Document Intelligence Platform

PowerCred Document Intelligence APIs

Three composable services for lenders and onboarding teams — extract structured data from documents, verify their authenticity, and turn the result into ready-to-consume fraud signals.

Versionv1 Updated16 June 2026 FormatREST / JSON

Introduction

PowerCred Document Intelligence is a three-stage pipeline that takes a raw document (PDF or image) and returns a structured, scored, lender-ready verdict. Each stage is exposed as its own REST API and can be adopted independently.

1
OCR

Convert a payslip, employment certificate, ID, or bank statement into structured JSON fields.

2
Tamper Detection

Verify the source PDF matches a registered template for the document type using metadata, fonts, and layout.

3
Fraud Signals

Run arithmetic, credibility, cross-document and statutory checks. Emit categorised verdicts and lender signals.

Authentication

Each service has its own API key. Keep them separate — they map to different products in our backend.

OCR
?apikey=…

Pass the API key as a apikey query parameter on every request. Do not use the Authorization header.

Tamper Detection
Bearer token

Send the API key in the Authorization: Bearer <token> header. This is the only service that uses Bearer auth.

Fraud Signals
?apikey=…

Pass the API key as a apikey query parameter on every request.

Important: Treat all keys as production secrets even on staging. Never embed them in client-side code or commit them to source control.

Environments

Use staging during integration; promote to production once your verification flow is finalised. Tamper Detection currently runs on a single sandbox host.

ServiceStagingProduction
OCR https://mock.powercred.io/idp/v1 https://dev.powercred.io/idp/v1
Fraud Signals https://mock.powercred.io/cms/v1 https://dev.powercred.io/cms/v1
Tamper Detection https://fraud-sandbox.powercred.io — (sandbox only)

End-to-end workflow

A typical loan-onboarding flow chains all three services. The OCR id is the linchpin — once you have it, the same identifier is reused as a session reference by Fraud Signals.

PRIMARY FLOW PARALLEL CHECK LENDER / CLIENT SYSTEM Has a borrower's payslip PDF 1 Submit document POST /idp/v1/read file + document_type Returns: { id } original PDF parallel · optional 2 Verify authenticity POST /check file (original PDF) Returns: { matched, is_epdf, reasons[] } use { id } 3 Fetch structured data GET /idp/v1/get?id=… poll until 200 (or callback) Returns: { data } use { id } or { data } 4 Generate fraud + lender signals OPTION A · session lookup POST /cms/v1/fraud-detection/<type>/run-from-session body: { sessions: [{ session_id: id, product: "idp" }] } OPTION B · inline payload POST /cms/v1/fraud-detection/<type>/run body: { documents: [{ type, data }] } Returns: { run_id, overall_status, categories[], signals, metadata }
Why the two options at step 4? Option A is one round-trip simpler — the service fetches the OCR result for you using the id. Option B lets you score data you already hold (e.g. cached payloads or data extracted by a non-PowerCred OCR). Both produce an identical response shape.

1OCR

Asynchronous structured extraction from PDF, JPEG, and PNG documents. Submit once, poll for the result. Supports payslips, employment certificates, government IDs, and bank statements.

Async by design. Submission returns 202 immediately with an id. Use either polling (GET /get?id=…) or supply callback_url on submit to receive a webhook when extraction is complete.
POST /idp/v1/read Submit a document for extraction

Upload a document (or supply a public file_url) and start extraction. Validation rules are determined by document_type — your account is configured with the schemas you need.

Request — query parameters

NameTypeRequiredDescription
apikeystringrequiredYour OCR API key.
reference_idstringrequiredYour correlation ID for the end-user or loan application.
document_typestringrequiredDocument type — e.g. payslip, employment_certificate, national_id, bank_statement.
file_urlstringoptionalPublic URL of the document. Use instead of multipart file.
callback_urlstringoptionalWebhook to receive the final payload on completion.
tamper_checkbooloptionalRun lightweight inline tamper indicators on the document.
get_image_qualitybooloptionalInclude image quality assessment (blur, brightness, flash, DPI) for camera images.

Request — form data

NameTypeRequiredDescription
filebinaryconditionalPDF, JPEG or PNG. Required if file_url is not provided.

Response — 202 Accepted

{
  "message": "Document parsing started",
  "id": "3b41c2e0-9d2a-4e5e-bb37-2b8e0c0fbb12"
}

Common errors

CodeReason
400File is not PDF/JPEG/PNG.
422Missing required field, or document_type not configured on your account.
401Missing or invalid apikey.
GET /idp/v1/get Retrieve extraction result

Poll with the id returned by /read. The same response shape is returned when the extraction completes via callback.

Request — query parameters

NameTypeRequiredDescription
apikeystringrequiredYour OCR API key.
idstringrequiredThe id returned by POST /read.
return_jsonbooloptionalReturn the raw structured JSON instead of the formatted response.
image_qualitybooloptionalInclude the image quality assessment block when available.

Response — 200 OK (payslip example)

{
  "id": "3b41c2e0-9d2a-4e5e-bb37-2b8e0c0fbb12",
  "document_type": "payslip",
  "status": "COMPLETED",
  "data": {
    "employee_name": "Juan Dela Cruz",
    "employee_id": "EMP-00123",
    "employer_name": "Acme Corporation",
    "pay_period_start": "2026-05-01",
    "pay_period_end": "2026-05-15",
    "pay_date": "2026-05-20",
    "gross_pay": 35000.00,
    "basic_pay": 30000.00,
    "allowances": 5000.00,
    "total_deductions": 4750.00,
    "net_pay": 30250.00,
    "contributions": {
      "sss": 1125.00,
      "philhealth": 875.00,
      "pagibig": 100.00
    },
    "withholding_tax": 2650.00
  }
}

Status semantics

CodeMeaningAction
200Extraction complete; payload returned.Consume data.
202Extraction still in progress.Retry after 2–3 seconds.
404Document was unreadable.Resubmit a clearer copy.
500Extraction failed.Resubmit; if persistent, contact support.

2Document Tamper Detection

Register reference PDFs for each document type your organisation accepts. Incoming PDFs are then verified against the stored metadata fingerprint, font set, and layout signature. Doctored or fabricated ePDFs are caught before they reach scoring.

How it works

You upload one or more clean reference PDFs per document type (e.g. an employer's payslip template). The service extracts a fingerprint composed of PDF metadata patterns, embedded fonts, and a layout signature, and stores it as the active version. Every incoming PDF is checked against the stored fingerprint, with regex-based pattern matching for metadata and a cosine similarity score for layout.

GET /documents List registered document types

Response fields

FieldTypeDescription
documentsstring[]All document type identifiers registered under your account.
countintegerLength of documents.

Example — 200 OK

{
  "documents": ["payslip", "national_id"],
  "count": 2
}
POST /templates/{document_id}/auto Auto-extract a template

Upload reference PDFs and let the service derive every validation rule automatically. Metadata patterns and font lists are taken directly from the PDFs:

  • Single unique value across all files → exact-match regex.
  • Multiple differing values → regex alternation (?:a|b|…).
  • Field absent in all files → omitted (not checked).

Path parameters

NameTypeDescription
document_idstringThe document type identifier you want to register (e.g. payslip).

Form-data fields

NameTypeRequiredDescription
filesbinary[]requiredOne or more PDFs, ≤ 5 MB each.
similarity_thresholdfloatoptionalLayout cosine-similarity threshold, default 0.85.

Response fields

FieldTypeDescription
version_idstringIdentifier of the newly created version (e.g. v1). This version becomes active immediately.
document_idstringEcho of the path parameter.
template_countintegerNumber of PDFs stored in the new version.
extracted_configobjectConfiguration derived from the uploaded PDFs.
extracted_config.metadata_configobject<string,string>Regex patterns per PDF metadata field (producer, title, author, creator, subject, keywords, creation_date). Fields absent from all uploads are omitted.
extracted_config.fontsstring[]Union of font family names found across the uploaded PDFs.
extracted_config.similarity_thresholdfloatLayout cosine-similarity threshold stored on the version.

Example — 201 Created

{
  "version_id": "v1",
  "document_id": "payslip",
  "template_count": 2,
  "extracted_config": {
    "metadata_config": {
      "producer": "Adobe\\ PDF\\ Library\\ 15\\.0",
      "creator": "Microsoft\\ Word"
    },
    "fonts": ["Arial", "TimesNewRoman"],
    "similarity_threshold": 0.85
  }
}
POST /templates/{document_id} Create a template with explicit rules

Use this when you want full control over the regex patterns and font list, rather than relying on auto-extraction.

Form-data fields

NameTypeRequiredDescription
filesbinary[]requiredOne or more PDFs, ≤ 5 MB each.
producer_patternstringoptionalRegex matched against the PDF producer field.
title_patternstringoptionalRegex for PDF title metadata.
author_patternstringoptionalRegex for PDF author metadata.
creator_patternstringoptionalRegex for PDF creator metadata.
subject_patternstringoptionalRegex for PDF subject metadata.
keywords_patternstringoptionalRegex for PDF keywords metadata.
creation_date_patternstringoptionalRegex for PDF creation date.
fontsstringoptionalJSON array of font families, e.g. ["Arial","Helvetica"].
similarity_thresholdfloatoptionalDefault 0.85.

Response fields

FieldTypeDescription
version_idstringNewly created version. Becomes active immediately.
document_idstringEcho of the path parameter.
template_countintegerNumber of PDFs stored in the new version.

Example — 201 Created

{
  "version_id": "v1",
  "document_id": "payslip",
  "template_count": 1
}
PUT /templates/{document_id} Update template configuration

Any field omitted is carried over from the currently active version. A new version is always created and becomes active immediately.

Form-data fields (all optional)

NameTypeDescription
filesbinary[]Additional PDFs.
file_modestringappend (default) keeps existing PDFs; overwrite replaces them with the newly uploaded set.
producer_pattern, title_pattern, …stringNew regex for that metadata field.
fontsstringJSON array of font families.
similarity_thresholdfloatUpdated threshold.

Response fields

FieldTypeDescription
version_idstringThe new version created by this update. Becomes active immediately.
document_idstringEcho of the path parameter.
template_countintegerTotal PDFs in the new version. With file_mode=append this equals existing + newly uploaded; with overwrite it equals only the newly uploaded set.

Example — 200 OK

{
  "version_id": "v2",
  "document_id": "payslip",
  "template_count": 3
}
GET /templates/{document_id} Get active template

Response fields

FieldTypeDescription
document_idstringDocument type identifier.
active_versionstringThe currently active version for this document type.
metadata_configobject<string,string>Regex patterns evaluated against the PDF's metadata fields. Keys: producer, title, author, creator, subject, keywords, creation_date. Only keys with rules are present.
fontsstring[]Font families that must appear in any matching PDF.
similarity_thresholdfloatLayout cosine-similarity minimum (0.0–1.0).
template_countintegerReference PDFs stored in the active version.
created_atstring (ISO-8601)When the active version was created.

Example — 200 OK

{
  "document_id": "payslip",
  "active_version": "v1",
  "metadata_config": {"producer": "Adobe PDF Library"},
  "fonts": ["Arial", "Helvetica"],
  "similarity_threshold": 0.85,
  "template_count": 2,
  "created_at": "2026-05-20T08:14:11Z"
}
GET /templates/{document_id}/versions List versions

Returns every version ever created for this document type, ordered by version number. Exactly one will have is_active: true.

Response fields

FieldTypeDescription
document_idstringDocument type identifier.
versionsobject[]One entry per version.
versions[].version_idstringStable identifier (e.g. v1).
versions[].version_numberintegerMonotonic counter, useful for ordering.
versions[].created_atstring (ISO-8601)Creation timestamp.
versions[].is_activebooleantrue for the version currently used by /check.
versions[].metadata_configobject<string,string>Regex patterns stored on this version.
versions[].fontsstring[]Required fonts on this version.
versions[].similarity_thresholdfloatLayout threshold on this version.
versions[].template_countintegerReference PDFs in this version.

Example — 200 OK

{
  "document_id": "payslip",
  "versions": [
    {
      "version_id": "v1",
      "version_number": 1,
      "created_at": "2026-05-20T08:14:11Z",
      "is_active": false,
      "metadata_config": {"producer": "Adobe PDF Library"},
      "fonts": ["Arial"],
      "similarity_threshold": 0.85,
      "template_count": 2
    },
    {
      "version_id": "v2",
      "version_number": 2,
      "created_at": "2026-06-04T11:02:55Z",
      "is_active": true,
      "metadata_config": {"producer": "Adobe PDF Library", "creator": "Microsoft Word"},
      "fonts": ["Arial", "Helvetica"],
      "similarity_threshold": 0.88,
      "template_count": 3
    }
  ]
}
PATCH /templates/{document_id}/versions/{version_id}/activate Activate a version

Response fields

FieldTypeDescription
messagestringHuman-readable confirmation.
document_idstringDocument type identifier.
active_versionstringThe version that is now active.

Example — 200 OK

{
  "message": "Version 'v2' is now active",
  "document_id": "payslip",
  "active_version": "v2"
}
DELETE /templates/{document_id}/files/{filename} Remove a reference PDF

Removes one PDF from the active version. A new version is created without that file and is set active.

Response fields

FieldTypeDescription
version_idstringThe new version created without the deleted file. Becomes active immediately.
document_idstringDocument type identifier.
template_countintegerRemaining reference PDFs in the new version.

Example — 200 OK

{
  "version_id": "v3",
  "document_id": "payslip",
  "template_count": 1
}
POST /check Verify a PDF

Run the authenticity checks. By default the PDF is checked against every registered document type; pass ?document_id=… to scope to a single type.

Query parameters

NameTypeRequiredDescription
document_idstringoptionalCheck against this document type only.

Form-data

NameTypeRequiredDescription
filebinaryrequiredThe PDF to verify (≤ 5 MB).

Response fields

FieldTypeDescription
matchedbooleanTop-level verdict — true if the PDF matched at least one registered document type.
is_epdfbooleantrue for digitally-generated PDFs, false for scanned/image-only PDFs. When false, no checks run.
messagestring · nullableOptional human-readable note (e.g. why checks were skipped).
resultsobject[]One entry per document type checked. Empty array for scanned PDFs.
results[].document_idstringThe document type checked against.
results[].matchedbooleanOverall match against this document type's active version.
results[].version_checkedstringVersion ID used for the check.
results[].reasons.metadata.matchedbooleanOverall metadata check result.
results[].reasons.metadata.details[]object[]Per-field results: field (string), pattern (regex), extracted_value (string·nullable), matched (boolean).
results[].reasons.fonts.matchedbooleanWhether every required font was present.
results[].reasons.fonts.details[]object[]Per-font results: required_font (string), found (boolean), extracted_fonts (string[]).
results[].reasons.layout.matchedbooleanWhether layout similarity met the threshold.
results[].reasons.layout.scorefloatCosine similarity against the closest reference (0.0–1.0).
results[].reasons.layout.thresholdfloatThreshold value used for the comparison.
results[].reasons.date_integrity.matchedbooleantrue when modification date is consistent with creation date.
results[].reasons.date_integrity.creation_datestring · nullablePDF creation timestamp, if present.
results[].reasons.date_integrity.mod_datestring · nullablePDF last-modified timestamp, if present.

Example — 200 OK (ePDF, matched)

{
  "matched": true,
  "is_epdf": true,
  "results": [
    {
      "document_id": "payslip",
      "matched": true,
      "version_checked": "v1",
      "reasons": {
        "metadata": {
          "matched": true,
          "details": [
            {
              "field": "producer",
              "pattern": "Adobe PDF Library",
              "extracted_value": "Adobe PDF Library 15.0",
              "matched": true
            }
          ]
        },
        "fonts": {
          "matched": true,
          "details": [
            {"required_font": "Arial", "found": true, "extracted_fonts": ["Arial", "Helvetica"]}
          ]
        },
        "layout": {"matched": true, "score": 0.94, "threshold": 0.85},
        "date_integrity": {"matched": true, "creation_date": "2026-05-15T10:22:01Z", "mod_date": "2026-05-15T10:22:01Z"}
      }
    }
  ]
}

Response — 200 OK (scanned/image PDF)

{
  "matched": false,
  "is_epdf": false,
  "message": "PDF appears to be scanned/image-based; tamper checks skipped.",
  "results": []
}
Reading the result. A top-level matched: true means the PDF matched at least one registered document type. The per-document reasons object explains which sub-checks passed or failed — useful for surfacing actionable feedback to operators.

3Fraud Signals

Take structured document data and emit categorised fraud verdicts plus lender-ready financial signals. Currently supports payslips and employment certificates.

What's evaluated

CategoryWhat it checks
Arithmetic IntegrityNet pay reconciliation, cross-field consistency, income stability across periods.
Document CredibilityTrust score, format reliability, employment formality, pay frequency cadence.
Cross-Document ChecksEmployer consistency and pay period continuity when multiple documents are submitted.
Statutory ComplianceRegion-specific contribution and tax compliance (SSS, PhilHealth, Pag-IBIG, withholding, minimum wage for region=ph).
POST /cms/v1/fraud-detection/{document_type}/run Evaluate from JSON payload

Use this when you already hold the structured document data (typically the response body from OCR).

Path parameters

NameTypeDescription
document_typestringpayslip or employment_certificate.

Query parameters

NameTypeRequiredDescription
apikeystringrequiredYour Fraud Signals API key.
regionstringoptionalRegion code for statutory rules. Defaults to ph.

Request body

{
  "documents": [
    {
      "type": "payslip",
      "document_id": "payslip_1",
      "data": { /* extracted JSON, typically from OCR */ }
    }
  ]
}
FieldTypeRequiredDescription
documentsarrayrequiredAt least one document. Every item's type must match the path.
documents[].typestringrequiredDocument type; must equal {document_type}.
documents[].document_idstringoptionalYour identifier. Defaults to doc_0, doc_1, …
documents[].dataobjectrequiredExtracted structured data for the document.

Response fields

All three Fraud Signals endpoints (/run, /run-from-session, GET /runs/{run_id}) return the same FraudDetectionResponse shape documented below.

FieldTypeDescription
run_idstring (UUID)Unique identifier for this evaluation. Persist this — you can refetch the result later with GET /runs/{run_id}.
document_typestringpayslip or employment_certificate. Echoes the path parameter.
timestampstring (ISO-8601)When the run was executed (UTC).
overall_statusenumWorst status across all categories: pass, warn, fail, or inconclusive.
categories[]object[]One entry per category evaluated. See Category below.
signalsobjectLender-ready summary derived from the document. See Signals below.
gcsobject<string,string>Internal storage references for the audit trail; safe to ignore in client code.
metadataobjectRequest context and processing details. See Metadata below.
session_dataobject[] · nullablePresent only for /run-from-session. Lists the upstream sessions resolved: session_id, product, document_type.

Category

FieldTypeDescription
namestringCategory label (e.g. Arithmetic Integrity, Document Credibility, Cross-Document Checks, Statutory Compliance).
descriptionstringWhat this category evaluates.
statusenumWorst status across this category's checks.
checks[]object[]Individual checks. See Check below.

Check

FieldTypeDescription
namestringStable check identifier (e.g. net_pay_reconciliation).
descriptionstringPlain-English explanation.
statusenumpass, warn, fail, or inconclusive.
checks_performedstring[]Sub-checks executed within this check.
findings[]object[]Issues raised by the check. Each finding has: severity (high/medium/low), code (stable identifier), message (description), evidence (object with relevant raw values).

Signals

FieldTypeDescription
signals.financial_summaryobjectNormalised financial figures pulled from the document. Each field is nullable.
financial_summary.gross_paynumberGross compensation for the period.
financial_summary.net_paynumberTake-home amount.
financial_summary.basic_paynumberBase salary component.
financial_summary.total_deductionsnumberSum of all deductions.
financial_summary.sss_contributionnumberSSS contribution (PH).
financial_summary.philhealth_contributionnumberPhilHealth contribution (PH).
financial_summary.pagibig_contributionnumberPag-IBIG contribution (PH).
financial_summary.withholding_taxnumberWithholding tax for the period.
financial_summary.takehome_rationumbernet_pay / gross_pay — useful for affordability scoring.
signals.lender_signals[]object[]Cards summarising the document for underwriting. Each entry has: name (identifier), value (any), status (pass/warn/fail/inconclusive), evidence (object · nullable).

Metadata

FieldTypeDescription
metadata.app_idstringYour application ID.
metadata.developer_emailstringDeveloper email tied to the API key.
metadata.app_namestringYour application name.
metadata.document_typestringEcho of the path parameter.
metadata.processing_time_msnumberEnd-to-end processing time in milliseconds.
metadata.request_ipstring · nullableOriginating IP, if available.
metadata.user_agentstring · nullableOriginating user agent, if available.

Example — 200 OK

{
  "run_id": "3f8c…",
  "document_type": "payslip",
  "timestamp": "2026-06-16T09:12:33Z",
  "overall_status": "pass",
  "categories": [
    {
      "name": "Arithmetic Integrity",
      "description": "Net pay calculations, cross-field consistency, and income stability",
      "status": "pass",
      "checks": [
        {
          "name": "net_pay_reconciliation",
          "description": "gross - deductions = net",
          "status": "pass",
          "checks_performed": ["sum_deductions", "net_pay_match"],
          "findings": []
        }
      ]
    },
    { "name": "Document Credibility",   "status": "pass", "checks": [] },
    { "name": "Cross-Document Checks",  "status": "pass", "checks": [] },
    { "name": "Statutory Compliance",   "status": "pass", "checks": [] }
  ],
  "signals": {
    "financial_summary": {
      "gross_pay": 35000.00,
      "net_pay": 30250.00,
      "basic_pay": 30000.00,
      "total_deductions": 4750.00,
      "sss_contribution": 1125.00,
      "philhealth_contribution": 875.00,
      "pagibig_contribution": 100.00,
      "withholding_tax": 2650.00,
      "takehome_ratio": 0.864
    },
    "lender_signals": [
      { "name": "income_stability",   "value": "stable",   "status": "pass" },
      { "name": "statutory_coverage", "value": "complete", "status": "pass" }
    ]
  },
  "metadata": {
    "app_id": "app_xxx",
    "developer_email": "dev@example.com",
    "app_name": "my-app",
    "document_type": "payslip",
    "processing_time_ms": 412.0
  }
}

Overall status values

StatusMeaning
passAll checks passed; document looks legitimate.
warnOne or more soft anomalies; review recommended.
failAt least one hard rule failed; treat as suspicious.
inconclusiveNot enough information to decide.
POST /cms/v1/fraud-detection/{document_type}/run-from-session Evaluate from an upstream session

Skip uploading data — point at an existing PowerCred session (e.g. the OCR id) and we fetch the document data for you.

Request body

{
  "sessions": [
    { "session_id": "3b41c2e0-9d2a-4e5e-bb37-2b8e0c0fbb12", "product": "idp" }
  ]
}
FieldTypeRequiredDescription
sessionsarrayrequiredAt least one upstream session reference.
sessions[].session_idstringrequiredThe upstream identifier — typically the OCR id.
sessions[].productstringrequiredThe upstream product key. Errors include the list of supported values.

Response fields

Same FraudDetectionResponse shape as POST /run, with the session_data field populated.

FieldTypeDescription
session_dataobject[]One entry per resolved upstream session.
session_data[].session_idstringThe session ID supplied in the request.
session_data[].productstringThe upstream product key (e.g. idp).
session_data[].document_typestringDocument type of the fetched record. Must match the path parameter.

All other fields (run_id, overall_status, categories, signals, metadata) are identical to the /run response.

Example — 200 OK

{
  "run_id": "3f8c…",
  "document_type": "payslip",
  "timestamp": "2026-06-16T09:14:02Z",
  "overall_status": "pass",
  "session_data": [
    {
      "session_id": "3b41c2e0-9d2a-4e5e-bb37-2b8e0c0fbb12",
      "product": "idp",
      "document_type": "payslip"
    }
  ],
  "categories": [ /* same shape as /run */ ],
  "signals":    { /* same shape as /run */ },
  "metadata":   { /* same shape as /run */ }
}
GET /cms/v1/fraud-detection/runs/{run_id} Fetch a past run

Refetch a previously executed run by run_id.

Path parameters

NameTypeDescription
run_idstring (UUID)The run_id returned by a previous /run or /run-from-session call under the same account.

Response fields

Returns the same FraudDetectionResponse shape as POST /run. If the original run was session-based, session_data will be populated as well.

Errors

CodeReason
404No run with that run_id exists under your account.

Workflow templates

Copy-paste starting points for the most common verification flows.

Payslip — verify, authenticate, score

Single-payslip flow that combines all three services. Each call is independent; you can fan out steps 2 and 3 in parallel.

# 1) Submit the payslip
curl -X POST "https://mock.powercred.io/idp/v1/read\
?apikey=$IDP_KEY&reference_id=ref-12345&document_type=payslip" \
  -F "file=@./payslip.pdf"
# → { "id": "OCR_ID", ... }

# 2) Poll for the structured payload
curl "https://mock.powercred.io/idp/v1/get?apikey=$IDP_KEY&id=$OCR_ID"
# → { "status": "COMPLETED", "data": { ... } }

# 3) Verify authenticity (run in parallel with step 2)
curl -X POST "https://fraud-sandbox.powercred.io/check?document_id=payslip" \
  -H "Authorization: Bearer $TAMPER_KEY" \
  -F "file=@./payslip.pdf"
# → { "matched": true, "is_epdf": true, ... }

# 4) Generate fraud + lender signals from the OCR session
curl -X POST "https://mock.powercred.io/cms/v1/fraud-detection/payslip/\
run-from-session?apikey=$CMS_KEY®ion=ph" \
  -H "Content-Type: application/json" \
  -d '{"sessions":[{"session_id":"'"$OCR_ID"'","product":"idp"}]}'
# → { "overall_status": "pass", "signals": {...}, ... }

Multi-payslip income stability check

Use multiple payslips in a single fraud-detection call to surface cross-period anomalies (employer mismatch, pay gaps, sudden income jumps).

curl -X POST "https://mock.powercred.io/cms/v1/fraud-detection/payslip/run\
?apikey=$CMS_KEY®ion=ph" \
  -H "Content-Type: application/json" \
  -d '{
    "documents": [
      {"type": "payslip", "document_id": "p_1", "data": { /* April */ }},
      {"type": "payslip", "document_id": "p_2", "data": { /* May */   }},
      {"type": "payslip", "document_id": "p_3", "data": { /* June */  }}
    ]
  }'

Tamper template lifecycle

# Initial template — let the service derive everything
curl -X POST "https://fraud-sandbox.powercred.io/templates/payslip/auto" \
  -H "Authorization: Bearer $TAMPER_KEY" \
  -F "files=@./payslip_v1.pdf" \
  -F "similarity_threshold=0.85"
# → { "version_id": "v1", ... }

# Employer changes payroll vendor → upload new reference, append to existing
curl -X PUT "https://fraud-sandbox.powercred.io/templates/payslip" \
  -H "Authorization: Bearer $TAMPER_KEY" \
  -F "files=@./payslip_v2.pdf" \
  -F "file_mode=append"
# → { "version_id": "v2", ... }

# Roll back to the previous version
curl -X PATCH "https://fraud-sandbox.powercred.io/templates/payslip/versions/v1/activate" \
  -H "Authorization: Bearer $TAMPER_KEY"

HTTP status codes

CodeMeaning
200Successful request. Payload included.
201Resource created (template versions).
202Accepted / processing not yet complete.
400Bad request — usually a malformed file or unsupported MIME type.
401Missing or invalid API key.
404Resource not found.
422Validation failed — missing required field, invalid document type, etc.
500Server error. Safe to retry idempotent calls.