OCR KTP Check
Reads the fields printed on an Indonesian KTP (ID card) from an
uploaded photo. A completed extraction is billed (pricing=PAID).
Validation failures, an image the OCR engine cannot read as an ID
card, and service failures are not billed (pricing=FREE).
This feature must be enabled on your account. If it is not, the
API returns UNAUTHORIZED.
Outcomes
| Result | Response |
|---|---|
| Extraction succeeded | code=SUCCESS, pricing=PAID |
| Image isn’t a recognizable ID card (per the OCR engine) | code=CLIENT_ERROR, pricing=FREE |
Extracted id_number isn’t a valid 16-digit NIK | code=CLIENT_ERROR, pricing=FREE |
Missing request_id / image, or wrong image format | code=CLIENT_ERROR, pricing=FREE (HTTP 400) |
| Image exceeds 8MB | code=CLIENT_ERROR, pricing=FREE (HTTP 413) |
| Temporary service issue | code=SERVER_ERROR, pricing=FREE |
Same request_id reused after a completed extraction | code=DUPLICATE_REFERENCE, pricing=FREE (HTTP 409) — always, regardless of what image you send this time |
Same request_id reused after a failed attempt | Retried for real: the image you send this time is what actually gets processed and (if it succeeds) billed |
| Missing token, feature not enabled, or IP not allowlisted | code=UNAUTHORIZED, pricing=FREE |
| Prepaid balance too low | code=INSUFFICIENT_BALANCE, pricing=FREE |
Image requirements
JPEG or PNG only (checked against the actual bytes, not just the
declared Content-Type), 8MB maximum.
Idempotency
Use a unique request_id for each new extraction (UUID v4 is
recommended). Reusing a request_id that already resolved to a
completed extraction always returns DUPLICATE_REFERENCE,
regardless of what image you send this time — mint a new request_id
for every extraction attempt. Reusing a request_id whose prior
attempt failed retries for real — the image you send this time is
what actually gets processed and (if it succeeds) billed.
Authorizations
Access token from POST /api/v1/kyc/auth/get-auth-token.
Valid for one hour.
Body
Response
Extraction complete. code is SUCCESS. data holds the
extracted fields. pricing is PAID.
Always SUCCESS on this response.
SUCCESS "SUCCESS"
Always OK. Use code and data, not this field, to branch.
OK "OK"
Extracted KTP fields. Every value is a plain string, printed on
the card verbatim (uppercase, Indonesian). A field the OCR engine
could not read comes back as "", never omitted or null — this
is not a matching verdict like e-wallet/bank's VerifyData, so
there is no status / similarity / suggestion here.
The request_id you sent.
"c3d4e5f6-1a2b-3c4d-5e6f-7a8b9c0d1e2f"
Always PAID on this response.
PAID "PAID"
