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 field | Default | Purpose |
|---|---|---|
image | required | Front image of a MyKad |
mask_sensitive | true | Mask 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.
Other endpoints
| Endpoint | Purpose |
|---|---|
POST /documents/mykad/parse | Synchronous MyKad parsing for compatibility and testing |
POST /ocr | Synchronous generic OCR; returns unmasked text |
GET /documents | Supported document types (API key required) |
GET /languages | OCR language profiles (API key required) |
GET /health | Service 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.