Asynchronous checks
POST https://checksharecode.co.uk/api/check/async queues a check and answers at once with its id. We run it, retry it if gov.uk fails, then post the result to your callback URL, or keep it for you to fetch with GET /api/check/async/:id. Same request body, same result and same error codes as POST /api/check.
Use it when you would rather not hold a request open while gov.uk answers, when you check many applicants at once, or when you want us to retry a check gov.uk failed. It works on every plan, and with sandbox keys too.
Headers
POST /api/check.Bearer rtw_live_…200, so a retry after a network error never runs or charges a second check.applicant-4411-check-1Body
https://api.acme.example/hooks/rtw?applicant=4411applicant-4411curl https://checksharecode.co.uk/api/check/async \
-H "Authorization: Bearer $CHECKSHARECODE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: applicant-4411-check-1" \
-d '{
"share_code": "AB1CD2EF3",
"date_of_birth": "1990-01-01",
"company_name": "Acme Ltd",
"callback_url": "https://api.acme.example/hooks/rtw?applicant=4411",
"client_reference": "applicant-4411"
}'{
"id": "chk_5f2a8c1e9b7d4a6f8e3c2b1a0d9f8e7c",
"status": "queued",
"mode": "live",
"client_reference": "applicant-4411",
"callback_url": "https://api.acme.example/hooks/rtw?applicant=4411",
"attempts": 0,
"result": null,
"error": null,
"result_expires_at": null,
"result_expired": false,
"created_at": "2026-09-28T10:00:00.000Z",
"completed_at": null
}The 202 has a Location header with the check’s URL. Bad input, a bad key, an exhausted quota and rate limits come back straight away with the usual error, so you never wait for a webhook to learn a request was wrong.
Get a check
GET /api/check/async/:id with the same key returns the check as it stands. If you set a callback URL you don’t need to poll: the webhook carries this same object.
{
"id": "chk_5f2a8c1e9b7d4a6f8e3c2b1a0d9f8e7c",
"status": "succeeded",
"mode": "live",
"client_reference": "applicant-4411",
"callback_url": "https://api.acme.example/hooks/rtw?applicant=4411",
"attempts": 1,
"result": { …the same object POST /api/check returns… },
"error": null,
"result_expires_at": "2026-10-05T10:00:14.000Z",
"result_expired": false,
"created_at": "2026-09-28T10:00:00.000Z",
"completed_at": "2026-09-28T10:00:14.000Z"
}| Field | Type | Meaning |
|---|---|---|
| id | string | The check’s id, chk_ and 32 characters. |
| status | "queued" | "running" | "succeeded" | "failed" | Where the check is. succeeded and failed are final. |
| mode | "live" | "test" | Whether a live or a sandbox key queued it. |
| result | object | null | When succeeded: exactly what POST /api/check returns, photo and PDF included. |
| error | { code, message } | null | When failed: the same code and message POST /api/check would have returned. |
| attempts | integer | How many times we ran it. More than 1 means we retried. |
| callback_url | string | null | Where the result is posted. null means poll only. |
| client_reference | string | null | Your id for the check, as you sent it. |
| result_expires_at | date-time | null | When we delete the result: 7 days after the check ends. |
| result_expired | boolean | true once the result is deleted. status and error stay readable. |
| created_at, completed_at | date-time | When it was queued, and when it ended. |
Outcomes and retries
- Same outcomes as the sync API. What
POST /api/checkanswers with200ends assucceeded. What it answers with an error ends asfailedwith that error code, soNOT_FOUNDandDOB_MISMATCHarefailedchecks. Each is charged the wayPOST /api/checkcharges it. - We retry for you.
TIMEOUT,BUSYandINTERNALare run again, up to 3 attempts in all, after about 30 seconds and then 2 minutes.GOVUK_UNEXPECTEDis run once more. Only the final outcome is charged. - Retries add time. A check that needs every retry takes a few minutes to end.
How long we keep the result
The result, photo and PDF included, is kept encrypted for 7 days after the check ends, so we can deliver it to you. Then it is deleted, with your client_reference and callback_url: result becomes null and result_expired becomes true. Save what you need when it arrives. The check’s status and error code stay readable for 30 days.
Limits and errors
- Checks in progress count. A queued or running live check counts against your monthly allowance, so a free account can’t queue more checks than it has left (
402 QUOTA_EXCEEDED). - 100 in progress at once. Past that,
POSTanswers429 RATE_LIMITEDwithRetry-After. - Unknown ids.
GETanswers404 CHECK_NOT_FOUNDwhen no check with that id belongs to this key’s account and mode. A sandbox key can’t read a live check, and the other way round. - Sandbox keys run the same flow with the test codes, so you can build your webhook handler before you spend a live check. A sandbox key your agent got without an account can poll, but can’t use
callback_urluntil it is claimed.