Merchant integration

MyKad OCR API

Extract text and structured fields from the front of a Malaysian MyKad.

HTTPS API available   Base URL: https://ocr.orpheuscapitalmy.com

Call this API from your server using the merchant key supplied by the operator. Send it in the X-API-Key header. Do not put the key in client-side code, URLs, or logs.

1. Submit an asynchronous job

Ask the operator to register your public HTTPS callback URL and provide its one-time whsec_… signing secret. Then submit an image to POST /v1/jobs/mykad. The API returns HTTP 202 and a job ID immediately. Reuse the same Idempotency-Key and image when retrying a timed-out submission.

Form fieldDefaultPurpose
imagerequiredFront image of a MyKad
mask_sensitivetrueMask most digits of the ID number in the callback result

Supported formats: JPG, PNG, BMP, WebP, TIFF and PDF; maximum upload size 20 MiB. A MyKad request must contain one page.

curl --fail-with-body https://ocr.orpheuscapitalmy.com/v1/jobs/mykad \
  -H "X-API-Key: $OCR_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -F 'image=@./document.jpg' \
  -F 'mask_sensitive=true'

Response: {"job_id":"…","status":"queued","status_url":"/v1/jobs/…","callback_status":"awaiting_result",…}. Only the first submission with an idempotency key counts toward the merchant's monthly quota. Reusing that key with different content returns 409.

2. Receive and verify the callback

When processing finishes, the service sends an HTTPS POST to your registered URL. Its JSON body contains event_id, job_id, status, result, and error_code. For a completed MyKad job, result contains the same structured fields as the synchronous API: number, name, address, citizenship, religion and gender. Check result.success and result.warnings.

Verify X-MyKad-Signature: v1=<hex> against HMAC-SHA256(signing_secret, X-MyKad-Timestamp + "." + raw_request_body). Use a constant-time comparison, require a timestamp within five minutes, and deduplicate by event_id. Return 2xx quickly. Failed deliveries are retried up to eight total attempts.

You can recover a missed result with GET /v1/jobs/{job_id} using the same merchant key. Images and results are encrypted while queued and removed after 24 hours. Generic OCR also has an asynchronous route: POST /v1/jobs/ocr.

OCR confidence is not an accuracy guarantee. This service extracts printed text; it does not authenticate the card, check a government database, or match a person to the portrait. Route missing, ambiguous or important fields to human review. Masking the number does not hide the name or address.

Other endpoints

EndpointPurpose
POST /documents/mykad/parseSynchronous MyKad parsing for compatibility and testing
POST /ocrSynchronous generic OCR; returns unmasked text
GET /documentsSupported document types (API key required)
GET /languagesOCR language profiles (API key required)
GET /healthService status

Interactive API schema: Swagger UI · OpenAPI JSON.

Errors and limits

Authentication failures return 401 or 403; an unconfigured callback or conflicting idempotency key returns 409; oversized files return 413; unsupported formats return 415; invalid requests return 422. A 429 can indicate the merchant's monthly quota, a full queue or gateway traffic limit. Retry asynchronous submissions with the original idempotency key.

Upload a neutral filename such as document.jpg. Asynchronous jobs temporarily store encrypted images and results in the restricted GPU database for up to 24 hours; completed images are removed after processing. Clients must protect their own request and response logs.