Right To Work Checker

Developer documentation

One endpoint. Bearer-token auth. Sandbox mode for free. The OpenAPI 3.1 spec lives at /openapi.json if you'd rather drive everything off that.

1. Authentication

Every request to /api/check requires a bearer API key. Keys are created in the dashboard at /app/keys and come in two modes:

  • rtw_live_… — calls real gov.uk and counts toward your quota.
  • rtw_test_… — returns deterministic sandbox fixtures (see Sandbox below). Never touches gov.uk. Not billed.
Authorization: Bearer rtw_live_AbCdEfGhIjKlMnOp…
2. Endpoints

POST /api/check

Verify a share code. Returns the structured gov.uk response (outcome, name, photo, PDF, conditions, reference, expiry).

{
  "share_code": "AB1CD2EF3",
  "date_of_birth": "1990-01-01",
  "company_name": "Acme Ltd"
}

GET /health

Liveness probe. Returns 200 ok. No auth required.

Dashboard API

Routes under /api/dash/* (keys, usage, billing) use a Supabase JWT in the bearer header and are documented in the OpenAPI spec.

3. Error codes

Every 4xx and 5xx response is JSON of the form { "error": { "code", "message" } }. The HTTP status and error code are stable parts of the contract — switch on code, not the message.

CodeHTTPMeaning
INVALID_INPUT400Request body failed validation (zod errors echo).
UNAUTHENTICATED401Authorization header missing or malformed.
INVALID_KEY401Key not found, revoked, or wrong format.
NOT_FOUND404gov.uk reported "Share code not found".
DOB_MISMATCH422gov.uk rejected the date of birth for that share code.
PAYMENT_REQUIRED402Subscription is past_due or unpaid. Update payment in the portal.
QUOTA_EXCEEDED402Free tier exceeded its included quota. Upgrade or wait for the period reset.
RATE_LIMITED429Per-key RPS exceeded or soft throttle at 1.5× quota. Honour Retry-After.
BUSY503No browser slot free. Retry after the indicated Retry-After window.
TIMEOUT504gov.uk did not respond in time. Safe to retry.
GOVUK_UNEXPECTED502gov.uk's HTML shape doesn't match the parser — file a bug.
INTERNAL500Unhandled error. Open an issue with the X-Request-Id header value.
4. Sandbox mode

Test keys (rtw_test_…) return deterministic fixtures, dispatched by the share code in your request. They never call gov.uk and never count toward your quota.

Share codeResponse
AA1AA1AA1ACCEPTED — skilled-worker visa
BB2BB2BB2REJECTED
CC3CC3CC3404 NOT_FOUND
DD4DD4DD4422 DOB_MISMATCH
EE5EE5EE5502 GOVUK_UNEXPECTED (simulated)
(any other)ACCEPTED — indefinite-leave fixture

The wire shape is byte-identical to live mode. Build against sandbox, swap to a live key when you're confident, no surprises.

5. Quotas and rate limits

Live keys are quota-gated and rate-limited per the tier on your subscription. Every successful response includes:

  • X-RateLimit-Limit — your tier's included quota
  • X-RateLimit-Remaining — checks left in the current period
  • X-RateLimit-Reset — unix timestamp when the period resets
  • X-Request-Id — for cross-referencing with support
TierIncludedSoft throttlePer-key RPS
Free10Hard cap5/sec
Pro1001.5× included20/sec
Scale5001.5× included50/sec
EnterpriseCustomNoneCustom

Hitting a rate limit returns 429 RATE_LIMITED with a Retry-After header. Read Quota & billing for the full request-flow diagram and overage maths.