{"openapi":"3.1.0","info":{"title":"Blinc Public API","version":"2026-09-11","description":"Programmatic access to Blinc compliance checks: AML (virtual invitations and in-person), Land Registry searches and PRS name-on-title checks, with signed webhooks as checks progress.\n\n## Quick start\n1. A company admin creates a **test key** (`blinc_test_…`) at **Company → API** in the Blinc dashboard.\n2. `POST /v1/aml-checks` with `type: \"virtual\"` and subject surname `INSTANT` — the check completes immediately in test mode. Only `type`, `first_name`, `last_name`, `email` and `customer_type` are required; leave the optional fields out rather than sending them empty.\n3. Register a webhook endpoint (`POST /v1/webhook-endpoints`), send a ping (`POST /v1/webhook-endpoints/{id}/test`), verify the signature, then re-run step 2 and watch the lifecycle events arrive.\n4. Swap to a live key when you go to production. **Live keys create real, billed checks.**\n\n## Authentication\n`Authorization: Bearer blinc_live_…` (or `blinc_test_…`). Keys are company-scoped; test and live are fully isolated.\n\n## Versioning\nA version is a **date** (`2026-09-11` is current). **Every key is pinned** to the version current when it was created and keeps it until you upgrade it in the dashboard — nothing we ship afterwards changes what that key sees. The path (`/v1`) never changes.\n\n- To try a newer version before upgrading a key, send `Blinc-Version: YYYY-MM-DD` on a request. Every response carries `Blinc-Version` with the version that was applied.\n- Webhook endpoints are pinned separately, to the version of the key that registered them, so upgrading a key never changes the shape arriving at a consumer built against the old one.\n- **Additive changes** (new endpoints, new optional fields, new event types) ship to every version. **Breaking changes** — renaming, removing or retyping a field, a new required request field, a new value in a response enum such as `result.flags[].code` — ship under a new dated version; pinned callers are unaffected.\n- No version is retired less than **12 months** after the next one ships. A retiring version carries `Deprecation` and `Sunset` headers, key owners are emailed at 90, 30 and 7 days, and after the date requests on it return 410 `api_version_sunset`.\n- `GET /v1/changelog.json` lists every version with what it changed.\n\n## Branches\nEvery check is recorded against one of your branches. `GET /v1/branches` lists them; the one flagged `is_primary` is what a request uses when it omits `branch_id`, so most integrations never need to send it. Pass `branch_id` only to record a check against a specific branch. A key can be restricted to a subset of branches when it is created — it then sees and may use only those.\n\n## Addresses: current vs transaction\nAn AML check can involve two addresses, and it matters which is which:\n\n- The **current address** is where the subject lives. It identifies and locates the person, and drives identity verification and data intelligence. For a virtual check the subject enters it in their invitation; for an in-person check you supply it as `current_address`.\n- The **transaction address** is the property being transacted — the let property for a landlord, the property being sold for a vendor. It is read by exactly one thing: the PRS name-on-title check (`prs_addon`), which confirms the subject's name appears on the Land Registry title *at that address*.\n\nFor a sale the two are usually the same, so `transaction_address` is optional: omit it and the PRS check runs against the current address. **For a landlord they usually differ — send `transaction_address` or the ownership check runs against the landlord's home, not the let property.** The address in use appears on the check as `transaction_address` once known. Sending `transaction_address` without `prs_addon` is rejected, because nothing would read it.\n\n## In-person checks: the sequence\nAn in-person check is **two calls**, and the check does not complete until both have happened:\n\n1. `POST /v1/aml-checks` with `type: \"in_person\"` and `skip_id_document: false` → `201`, `status: \"in_progress\"` (`aml_check.created`). The data-intelligence and screening step starts automatically; when it finishes, `aml_check.submitted` fires, the check is `processing` and reports `next_action: \"upload_id_document\"`.\n2. `POST /v1/aml-checks/{id}/documents` with the document images → `202`. `aml_check.document_received` confirms receipt and `next_action` clears. The identity provider's verdict arrives as `aml_check.document_decision`.\n3. The check completes: `aml_check.completed` fires and `result` is populated. Fetch the certificate with `GET /v1/aml-checks/{id}/report`.\n\nUntil step 2 the check stays `processing` — it will not complete, and no `aml_check.completed` is sent, on the strength of the automatic step alone. The one exception is an adverse screening match, which surfaces immediately so it is never held back by a missing document.\n\n## Virtual checks: nothing before Submit\nA virtual check runs its identity, data-intelligence and screening steps *inside* the subject's invitation flow, but none of that is reported until the subject presses Submit. Until then the check is `in_progress` with `result: null`, `GET /v1/aml-checks/{id}/report` answers `409`, and no `aml_check.completed` is sent — the same rule the Blinc dashboard applies to the agent, so that no decision is made on an unfinished application. At Submit, `aml_check.submitted` fires and, when the outcome is already known, `aml_check.completed` follows immediately.\n\n`skip_id_document: true` is for the case where the agent has verified the document in person and will not upload it: the check completes after the automatic step, and an upload is refused with 409. Choose it deliberately — the identity leg of the check then rests on the agent's word rather than a provider decision.\n\n## Storing the certificate\n`GET /v1/aml-checks/{id}/report` is available once a check is `completed` (409 `report_not_ready` before that). Pick the delivery shape that suits your stack — all three return the same file:\n\n| Shape | Request | Response |\n|---|---|---|\n| Signed URL (default) | `GET …/report` | `{ url, expires_at }` — fetch the URL within 10 minutes; never store the URL itself |\n| Bytes | `GET …/report` with `Accept: application/pdf` | The PDF, `Content-Disposition: attachment`, plus `ETag` |\n| Inline base64 | `GET …/report?encoding=base64` | `{ filename, content_type, size_bytes, sha256, content }` — decode `content`; `sha256` is the file's hash and the response `ETag` |\n\nUse the bytes or base64 shape when you want to file the PDF in your own system automatically; the base64 shape is the one for low-code platforms that cannot follow a binary download.\n\n**The certificate is a living document.** It is regenerated whenever the check changes after completion — a compliance decision, a screening match review, an ongoing-monitoring change or a re-evaluation — and every such change fires `aml_check.report_updated`. If you store the certificate, re-fetch it on that event. Send your stored `ETag` as `If-None-Match` and a `304` tells you the copy you hold is still current. Sandbox checks serve a watermarked sample through exactly the same shapes and headers, so you can prove your download and re-fetch code end to end with a `blinc_test_` key.\n\n## Errors\nAll failures are RFC 9457 `application/problem+json`. Code against the stable machine `code`, never the HTTP status or prose.\n\n## Rate limits and quotas\nPer-key fixed window, advertised on every response via `RateLimit-Limit` / `RateLimit-Remaining` / `RateLimit-Reset`. A 429 carries `Retry-After`.\n\n**Billed requests have separate daily quotas.** Creating a live AML check, uploading an ID document for one, running a PRS check and extracting a register each raise a charge, so each live key has a per-day cap across those four operations (default 100) **and** a per-day cap per operation sized to its cost (register extract 10, PRS check 25, AML create 50, document upload 50). Both reset at 00:00 UTC. Exceeding either returns 429 `quota_exceeded` with `Retry-After`, `Quota-Limit`, `Quota-Remaining`, `Quota-Reset` and `Quota-Scope` (which cap was hit) headers. A rejected request still counts. Test keys are never billed and have no quota. Contact Blinc to raise a cap — per key, or per operation for your account.\n\n**An account may also have a monthly spend budget.** When set, billed requests return 429 `budget_exceeded` (with `Budget-Limit`, `Budget-Spent` in pence, and `Retry-After` to the 1st) once the month's billed spend reaches it. Dashboard usage is never blocked by it.\n\nJSON request bodies are limited to 64 KB (413 `payload_too_large`); an `Idempotency-Key` is limited to 255 characters.\n\n## Idempotency\nSend an `Idempotency-Key` header (any unique string up to 255 characters, e.g. a UUID) on POSTs to make retries safe: the stored response is replayed with `Idempotent-Replay: true`. Reusing a key with a different body returns 409. Multipart uploads (document upload) do not support idempotency; the server de-duplicates in-flight provider checks instead.\n\n## Webhooks (Standard Webhooks)\nDeliveries carry `webhook-id`, `webhook-timestamp` and `webhook-signature` headers, signed per the [Standard Webhooks](https://www.standardwebhooks.com) spec — verify with the `standardwebhooks` library:\n\n```js\nimport { Webhook } from \"standardwebhooks\";\nconst wh = new Webhook(endpointSecret); // whsec_…\nconst event = wh.verify(rawBody, headers); // throws if invalid\n```\n\nRetries: 12 attempts over ~3 days with backoff. Endpoints failing repeatedly are auto-disabled.\n\n### Events — reference\nEvery change to a check's state has an event. `data` is always the full check exactly as `GET /v1/aml-checks/{id}` would return it at that moment, so the event **type** tells you what happened and the payload tells you where the check now stands — no follow-up read is needed. Events apply to both virtual and in-person checks unless the description says otherwise.\n\n| Event | Fires when | Repeats? |\n|---|---|---|\n| `aml_check.created` | The check row exists — for checks created in the Blinc dashboard as well as via the API, before any invitation is sent | no |\n| `aml_check.invited` | **Virtual only.** Only when the email provider accepted the invitation send — never on a failed send. Again on every resend from the dashboard | per email |\n| `aml_check.reminder_sent` | **Virtual only.** An automatic reminder email was sent to a subject who has not completed the invitation | per reminder |\n| `aml_check.started` | **Virtual only.** The subject opened the invitation flow | no |\n| `aml_check.submitted` | Virtual: the subject finished the flow. In-person: the automatic data-intelligence and screening step finished (fires even if a provider call failed). The check is now `processing` | no |\n| `aml_check.document_received` | **In-person only.** The ID document upload was stored | on re-upload |\n| `aml_check.document_decision` | The identity provider decided on the ID document — the subject's own upload for a virtual check, the agent's for an in-person one | on re-submission |\n| `aml_check.completed` | The check has its first outcome — `result` is populated. For a virtual check this never precedes `aml_check.submitted`: the outcome is withheld until the subject finishes the flow, and fires at Submit when it is already known | **once** |\n| `aml_check.result_updated` | A later re-evaluation (ongoing monitoring, a re-score) changed `result.outcome` or `result.flags`. **A check that was clear can become `attention`** | yes |\n| `aml_check.review_completed` | A compliance officer accepted or rejected the check on the Blinc platform — `result.review.decision` is set. (Escalation to the MLRO shows as `review.decision: under_review` on a read.) | rarely |\n| `aml_check.report_updated` | The certificate PDF changed after completion — a compliance decision, a screening match review, a monitoring change or a re-evaluation was recorded. Re-fetch `GET /v1/aml-checks/{id}/report` if you store it (`If-None-Match` → `304` when unchanged) | yes |\n| `aml_check.declined` | **Virtual only.** The subject declined the invitation. Terminal — contact the subject; this is not a compliance finding | no |\n| `aml_check.cancelled` | The check was cancelled by the agent, from the dashboard or the API. Terminal | no |\n| `aml_check.subject_updated` | The subject's contact details were changed — re-read `subject` | yes |\n| `aml_check.monitoring_updated` | Ongoing monitoring was switched on or off — re-read `ongoing_monitoring` | yes |\n\nLand-registry and PRS events (`land_registry.extract_completed`, `prs_check.completed`, `prs_check.failed`) carry the matching object in the same way.\n\n**Delivery contract.** Delivery is at-least-once — de-duplicate on the `webhook-id` header. Order across events is **not** guaranteed: sort by the envelope's `created_at`, never by arrival, and treat the check in the latest `data` as authoritative. Failed deliveries are retried 12 times over ~3 days; an endpoint that exhausts three deliveries is disabled until you re-enable it in the dashboard. **An endpoint registered with an explicit event list does not receive event types added later** — subscribe to `*` unless you have a reason not to.\n\n### Building a status indicator\nThe common integration is a traffic light per landlord or applicant. Derive it from `data` alone, so the same function is correct whether it runs on a webhook or on a `GET`:\n\n| Colour | Rule on `data` | Meaning |\n|---|---|---|\n| 🟢 **Green** | `status = \"completed\"` and `result.outcome = \"clear\"` — **or** `result.outcome = \"attention\"` and `result.review.decision = \"accepted\"` | Clear, or a compliance officer has reviewed the finding and signed it off: the transaction may proceed. This matches what the Blinc platform shows. |\n| 🟠 **Amber** | `status` is `invited`, `in_progress` or `processing` | Underway. Show the stage from the most recent event: `invited` → \"Invitation sent\", `reminder_sent` → \"Reminder sent\", `started` → \"Opened the check\", `submitted` → \"Finished — checks running\", `document_decision` → \"ID document assessed\". |\n| 🔴 **Red** | `status = \"completed\"` and `result.outcome = \"attention\"` and `result.review.decision` is `null`, `\"under_review\"` or `\"rejected\"` | A hard stop or a finding that needs a compliance officer. `null` — nobody has reviewed it yet; `under_review` — escalated to the MLRO; `rejected` — reviewed and the transaction must not proceed. `result.flags[]` say why. **Send your staff member to `dashboard_url`** to review and action it on the Blinc platform. |\n| ⚪ **Needs your action** | `status = \"declined\"` | The subject declined the invitation. Contact them or start a new check — not a compliance matter. |\n| ⚪ **None** | `status = \"cancelled\"` | The check was withdrawn. |\n\n```js\nfunction trafficLight(check) {\n  const { status, result } = check;\n  if (status === \"declined\") return \"needs_action\";\n  if (status === \"cancelled\") return \"none\";\n  if (status !== \"completed\") return \"amber\";\n  if (result.outcome === \"clear\") return \"green\";\n  if (result.review?.decision === \"accepted\") return \"green\";\n  return \"red\"; // attention: not reviewed, under review, or rejected\n}\n```\n\nTwo things to build in from the start. First, **green is not permanent**: with ongoing monitoring, `aml_check.result_updated` can move a clear check to `attention` months later — re-run the rule on every event, and on `review_completed` (which can move red to green). Second, **`dashboard_url` is on every check**, not only red ones; it opens the check for any signed-in user of your company, so it is safe to show as a link everywhere.\n\nThree abridged payloads:\n\n```json\n{ \"type\": \"aml_check.completed\", \"data\": { \"id\": \"aml_…\", \"status\": \"completed\",\n  \"result\": { \"outcome\": \"clear\", \"flags\": [], \"review\": null },\n  \"dashboard_url\": \"https://app.blinc-uk.com/amls/aml_…\" } }   → green\n```\n```json\n{ \"type\": \"aml_check.started\", \"data\": { \"id\": \"aml_…\", \"status\": \"in_progress\",\n  \"result\": null, \"dashboard_url\": \"https://app.blinc-uk.com/amls/aml_…\" } }   → amber, \"Opened the check\"\n```\n```json\n{ \"type\": \"aml_check.completed\", \"data\": { \"id\": \"aml_…\", \"status\": \"completed\",\n  \"result\": { \"outcome\": \"attention\",\n    \"flags\": [{ \"code\": \"sanctions_match\", \"label\": \"Sanctions match\" }], \"review\": null },\n  \"dashboard_url\": \"https://app.blinc-uk.com/amls/aml_…\" } }   → red, send staff to dashboard_url\n```\n\n## Test mode (sandbox)\nTest keys exercise the full API with deterministic outcomes and no billed provider calls. Magic values:\n\n| Input | Effect |\n|---|---|\n| subject surname `ATTENTION` | completes with outcome `attention` (flag `screening_adverse_media`) |\n| subject surname `REJECT` | completes with outcome `attention` (flag `identity_rejected`) |\n| subject surname `INSTANT` | lifecycle completes immediately (default: over a few minutes) |\n| search postcode `TE57 7ST` | two titles (freehold + leasehold) |\n| search postcode `TE57 0NF` | no titles found |\n| PRS address line 1 containing `NO MATCH` | `verified: false` |\n\nSandbox webhooks are signed and delivered identically to live ones."},"servers":[{"url":"https://app.blinc-uk.com/api/v1"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"AML checks"},{"name":"Land registry"},{"name":"PRS checks"},{"name":"Branches"},{"name":"Webhook endpoints"}],"paths":{"/branches":{"get":{"tags":["Branches"],"summary":"List your branches","description":"The branches this key may record checks against — the source of every `branch_id`. Not paginated: the full list is returned (at most 200). Retired branches are included with `is_active: false` so a stored id can still be explained; filter with `is_active=true` for only the branches new requests may use.","parameters":[{"name":"is_active","in":"query","schema":{"type":"boolean"},"description":"Omit for every branch; `true` for only those usable on new requests."}],"responses":{"200":{"description":"All branches, primary first","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Branch"}}}}}}},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/aml-checks":{"post":{"tags":["AML checks"],"summary":"Create an AML check","description":"**There are two kinds of check, chosen by `type`.** Pick **`virtual`** when you do not have the subject in front of you: Blinc emails them an invitation and they complete identity and details themselves. Pick **`in_person`** when you already hold the subject's details and their ID document: supply everything up front, the data-intelligence step runs automatically, and you upload the document separately. The request body below is a *One of* — select the variant matching your `type` to see its fields.\n\n`branch_id` and `transaction_address` are optional — see the field descriptions and the *Branches* and *Addresses* sections of the guide. Sending `transaction_address` without `prs_addon` in `services` is rejected.","requestBody":{"required":true,"content":{"application/json":{"examples":{"virtual":{"summary":"Virtual — minimal (test mode completes instantly)","value":{"type":"virtual","first_name":"Ada","last_name":"INSTANT","email":"ada@example.com","customer_type":"buyer"}},"virtual_landlord_prs":{"summary":"Virtual landlord with PRS — a distinct transaction address","value":{"type":"virtual","first_name":"Ada","last_name":"Lovelace","email":"ada@example.com","customer_type":"landlord","services":["standard","prs_addon"],"transaction_address":{"line1":"12 Let Property Road","town":"Manchester","postcode":"M1 1AA"}}},"in_person":{"summary":"In person — full subject details up front","value":{"type":"in_person","first_name":"Ada","last_name":"Lovelace","customer_type":"vendor","date_of_birth":"1984-10-25","nationality":"British","current_address":{"line1":"1 Home Street","town":"London","postcode":"SW1A 1AA"},"skip_id_document":false}}},"schema":{"discriminator":{"propertyName":"type","mapping":{"virtual":"#/components/schemas/CreateAmlCheckVirtual","in_person":"#/components/schemas/CreateAmlCheckInPerson"}},"oneOf":[{"$ref":"#/components/schemas/CreateAmlCheckVirtual"},{"$ref":"#/components/schemas/CreateAmlCheckInPerson"}]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AmlCheck"}}}},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"tags":["AML checks"],"summary":"List AML checks","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"starting_after","in":"query","schema":{"type":"string"},"description":"An `aml_…` id from a previous page."},{"name":"type","in":"query","schema":{"type":"string","enum":["virtual","in_person"]}},{"name":"status","in":"query","schema":{"type":"string","enum":["completed","cancelled","declined"]},"description":"Transient statuses are not filterable — consume webhooks instead."}],"responses":{"200":{"description":"A page of checks, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/AmlCheck"}},"has_more":{"type":"boolean"}}}}}},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/aml-checks/{id}":{"get":{"tags":["AML checks"],"summary":"Retrieve an AML check","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AmlCheck"}}}},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/aml-checks/{id}/cancel":{"post":{"tags":["AML checks"],"summary":"Cancel an AML check","description":"Idempotent when already cancelled. A completed check cannot be cancelled (409).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The cancelled check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AmlCheck"}}}},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Completed checks cannot be cancelled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/aml-checks/{id}/documents":{"post":{"tags":["AML checks"],"summary":"Upload the subject's ID document (in-person checks)","description":"The second step of an in-person check — see *In-person checks* in the guide. multipart/form-data: `front` (required), `back` (required for two-sided types), `document_type` (passport | driving_licence | national_identity_card | residence_permit). jpeg/png/webp only — HEIC is rejected; convert before uploading. Not idempotent (multipart); in-flight provider checks are de-duplicated server-side. Refused with 409 for virtual checks, for cancelled or declined checks, and for a check created with `skip_id_document: true`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["front"],"properties":{"front":{"type":"string","format":"binary"},"back":{"type":"string","format":"binary"},"document_type":{"type":"string"}}}}}},"responses":{"202":{"description":"Accepted — the provider decision arrives via `aml_check.document_decision`, and the check then completes (`aml_check.completed`)"},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Not an in-person check, a terminal check, or a check created with `skip_id_document: true`","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/aml-checks/{id}/report":{"get":{"tags":["AML checks"],"summary":"Get the certificate PDF (completed checks only)","description":"Three delivery shapes, chosen per request. **Default:** a JSON body with a short-lived signed URL — download promptly, do not store the URL. **`Accept: application/pdf`:** the PDF bytes, as an attachment. **`?encoding=base64`:** the PDF inline as base64 JSON, for platforms that cannot follow a binary download. The bytes and base64 shapes carry an `ETag` (the SHA-256 of the file) and honour `If-None-Match` with `304`. The certificate is regenerated whenever the check changes; subscribe to `aml_check.report_updated` to know when to re-fetch. See *Storing the certificate* in the guide.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"encoding","in":"query","required":false,"schema":{"type":"string","enum":["base64"]},"description":"`base64` returns the PDF inline in the JSON body instead of a signed URL. Cannot be combined with `Accept: application/pdf`."},{"name":"Accept","in":"header","required":false,"schema":{"type":"string","enum":["application/json","application/pdf"]},"description":"`application/pdf` returns the file bytes instead of JSON."},{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"},"description":"The `ETag` from a previous bytes or base64 response. A `304` means your stored copy is current."}],"responses":{"200":{"description":"The certificate — as a signed URL (default), inline base64 (`encoding=base64`), or the PDF bytes (`Accept: application/pdf`)","headers":{"ETag":{"description":"Bytes and base64 shapes only: the quoted SHA-256 of the PDF. Send it back as `If-None-Match`.","schema":{"type":"string"}},"Content-Disposition":{"description":"Bytes shape only: `attachment; filename=\"aml-certificate-{id}.pdf\"`.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","required":["object","id"],"properties":{"object":{"const":"aml_check_report"},"id":{"type":"string","description":"The check's public id."},"url":{"type":"string","format":"uri","description":"Default shape only. Short-lived signed URL for the PDF."},"expires_at":{"type":"string","format":"date-time","description":"Default shape only. When `url` stops working."},"filename":{"type":"string","description":"base64 shape only. Suggested filename, `aml-certificate-{id}.pdf`."},"content_type":{"type":"string","const":"application/pdf","description":"base64 shape only."},"size_bytes":{"type":"integer","description":"base64 shape only. Decoded size of `content`."},"sha256":{"type":"string","description":"base64 shape only. Hex SHA-256 of the decoded PDF — also the response `ETag`, unquoted."},"content":{"type":"string","format":"byte","description":"base64 shape only. The PDF, base64-encoded."}}}},"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"304":{"description":"Not modified — the certificate matches `If-None-Match`. Bytes and base64 shapes only."},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Report not ready","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/land-registry/searches":{"post":{"tags":["Land registry"],"summary":"Search the register by property address","description":"Synchronous. A `202 { status: \"retry\" }` with `Retry-After` means the registry acknowledged the request asynchronously — re-post the same body.","requestBody":{"required":true,"content":{"application/json":{"examples":{"search":{"summary":"Search by address (test mode: TE57 7ST returns two titles)","value":{"address_line1":"10 Downing Street","town_city":"London","postcode":"TE57 7ST"}}},"schema":{"type":"object","examples":[{"address_line1":"10 Downing Street","town_city":"London","postcode":"TE57 7ST"}],"required":["address_line1","postcode"],"properties":{"address_line1":{"type":"string"},"town_city":{"type":"string"},"postcode":{"type":"string"},"branch_id":{"type":"string","format":"uuid","description":"Optional. The branch to record this against — an `id` from `GET /v1/branches`. Defaults to your primary branch (for a branch-restricted key, the first active branch it may use). A retired branch, or one that is not yours, is rejected with 404."}}}}}},"responses":{"201":{"description":"The search with its titles","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LandRegistrySearch"}}}},"202":{"description":"Registry acknowledged asynchronously — retry shortly"},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/land-registry/searches/{id}":{"get":{"tags":["Land registry"],"summary":"Retrieve a search","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The search","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LandRegistrySearch"}}}},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/land-registry/searches/{id}/extract":{"post":{"tags":["Land registry"],"summary":"Fetch the official register for a title","description":"Billed per call, including re-extracts of a different title on the same search. `title_number` must come from this search's results.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title_number"],"properties":{"title_number":{"type":"string"},"include_title_plan":{"type":"boolean","default":false}}}}}},"responses":{"200":{"description":"The search with the register populated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LandRegistrySearch"}}}},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/land-registry/searches/{id}/documents":{"get":{"tags":["Land registry"],"summary":"Get signed URLs for the official-copy PDFs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Short-lived signed URLs — download promptly, do not store them","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"const":"list"},"data":{"type":"array","items":{"type":"object","required":["object","type","filename","url","expires_at"],"properties":{"object":{"type":"string","const":"land_registry_document"},"type":{"type":"string","enum":["official_copy","title_plan"]},"filename":{"type":"string"},"url":{"type":"string","format":"uri"},"expires_at":{"type":"string","format":"date-time"}}}}}}}}},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/prs-checks":{"post":{"tags":["PRS checks"],"summary":"Run a name-on-title (PRS) check","description":"Synchronous — the verdict is in the response.","requestBody":{"required":true,"content":{"application/json":{"examples":{"check":{"summary":"Name-on-title check","value":{"first_name":"Ada","last_name":"Lovelace","address":{"line1":"10 Downing Street","town":"London","postcode":"SW1A 2AA"}}}},"schema":{"type":"object","examples":[{"first_name":"Ada","last_name":"Lovelace","address":{"line1":"10 Downing Street","town":"London","postcode":"SW1A 2AA"}}],"required":["first_name","last_name","address"],"properties":{"first_name":{"type":"string"},"middle_name":{"type":"string"},"last_name":{"type":"string"},"dob":{"type":"string","format":"date"},"address":{"type":"object","description":"The property whose title is checked, in the API's one address shape.","required":["line1","postcode"],"properties":{"line1":{"type":"string"},"line2":{"type":"string"},"town":{"type":"string"},"county":{"type":"string"},"postcode":{"type":"string"}}},"branch_id":{"type":"string","format":"uuid","description":"Optional. The branch to record this against — an `id` from `GET /v1/branches`. Defaults to your primary branch (for a branch-restricted key, the first active branch it may use). A retired branch, or one that is not yours, is rejected with 404."}}}}}},"responses":{"201":{"description":"The completed check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrsCheck"}}}},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/prs-checks/{id}":{"get":{"tags":["PRS checks"],"summary":"Retrieve a PRS check","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrsCheck"}}}},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/webhook-endpoints":{"get":{"tags":["Webhook endpoints"],"summary":"List webhook endpoints","responses":{"200":{"description":"Endpoints for the key's mode (secrets never included)"},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Webhook endpoints"],"summary":"Register a webhook endpoint","description":"Public https URLs only. The signing secret is returned ONCE, here. The one exception is an idempotent replay: repeating this request with the same `Idempotency-Key` within 24 hours returns the stored response, secret included — so treat that key as sensitive for as long as it is valid.","requestBody":{"required":true,"content":{"application/json":{"examples":{"endpoint":{"summary":"Subscribe to everything","value":{"url":"https://integrator.example.com/webhooks/blinc","description":"Production"}}},"schema":{"type":"object","examples":[{"url":"https://integrator.example.com/webhooks/blinc","description":"Production"}],"required":["url"],"properties":{"url":{"type":"string","format":"uri"},"event_types":{"type":"array","items":{"type":"string","enum":["*","aml_check.created","aml_check.invited","aml_check.reminder_sent","aml_check.started","aml_check.submitted","aml_check.document_received","aml_check.document_decision","aml_check.completed","aml_check.result_updated","aml_check.review_completed","aml_check.report_updated","aml_check.declined","aml_check.cancelled","aml_check.subject_updated","aml_check.monitoring_updated","land_registry.extract_completed","prs_check.completed","prs_check.failed","ping"]},"default":["*"],"description":"Which events this endpoint receives. Omit, or send `[\"*\"]`, to receive every event type — including types added after registration (recommended; treat an unrecognised `type` as ignorable). An explicit list is FROZEN at registration: event types added later are never delivered to it, silently, and there is no update call — you would have to register a new endpoint (with a new secret) to receive them."},"description":{"type":"string"}}}}}},"responses":{"201":{"description":"The endpoint, including its one-time secret"},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/webhook-endpoints/{id}":{"post":{"tags":["Webhook endpoints"],"summary":"Rotate the signing secret","description":"The previous secret keeps signing alongside the new one until the next rotation, so consumers can switch over without dropping deliveries.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The new secret (shown once)"},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Webhook endpoints"],"summary":"Delete a webhook endpoint","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted"},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/webhook-endpoints/{id}/test":{"post":{"tags":["Webhook endpoints"],"summary":"Send a signed ping through the real delivery pipeline","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"202":{"description":"Queued — delivery usually lands within a minute"},"400":{"description":"Malformed request","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"API access not enabled","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limited — honour Retry-After","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"webhooks":{"aml_check.created":{"post":{"summary":"aml_check.created","description":"The check now exists. Fired for checks created in the Blinc dashboard as well as via the API, before any invitation is sent.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_created"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.invited":{"post":{"summary":"aml_check.invited","description":"The invitation email to the subject was accepted by the email provider. Never fired for a failed send; fired again on every resend, so the number of `invited` events is the number of invitation emails sent. Virtual checks only.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_invited"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.reminder_sent":{"post":{"summary":"aml_check.reminder_sent","description":"An automatic reminder email was sent to a subject who has not completed the invitation. Virtual checks only; repeats once per reminder window.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_reminder_sent"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.started":{"post":{"summary":"aml_check.started","description":"The subject opened the invitation flow. Virtual checks only.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_started"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.submitted":{"post":{"summary":"aml_check.submitted","description":"Virtual: the subject finished the invitation flow. In-person: the automatic data-intelligence and screening step finished (fired even when a provider call failed). The check is now `processing`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_submitted"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.document_received":{"post":{"summary":"aml_check.document_received","description":"The ID document upload for an in-person check was stored. Fired again on a re-upload.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_document_received"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.document_decision":{"post":{"summary":"aml_check.document_decision","description":"The identity provider decided on the ID document — the subject's own upload for a virtual check, the agent's for an in-person one. Can fire more than once when a resubmission is requested.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_document_decision"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.completed":{"post":{"summary":"aml_check.completed","description":"The check has its first outcome and `result` is populated. Fired exactly once per check.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_completed"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.result_updated":{"post":{"summary":"aml_check.result_updated","description":"A later re-evaluation (ongoing monitoring, a re-score) changed `result.outcome` or `result.flags`. Re-read `result`: a check that was clear can now require attention.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_result_updated"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.review_completed":{"post":{"summary":"aml_check.review_completed","description":"A compliance officer accepted or rejected the check on the Blinc platform; `result.review.decision` is `accepted` or `rejected`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_review_completed"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.report_updated":{"post":{"summary":"aml_check.report_updated","description":"The certificate PDF for a completed check changed — a compliance decision, a screening match review, an ongoing-monitoring change or a re-evaluation was recorded. If you store the certificate, re-fetch `GET /v1/aml-checks/{id}/report` (send `If-None-Match` with your stored ETag to skip an unchanged file).","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_report_updated"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.declined":{"post":{"summary":"aml_check.declined","description":"The subject declined the invitation. Terminal. Contact the subject — this is not a compliance finding.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_declined"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.cancelled":{"post":{"summary":"aml_check.cancelled","description":"The check was cancelled by the agent, from the dashboard or the API. Terminal.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_cancelled"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.subject_updated":{"post":{"summary":"aml_check.subject_updated","description":"The subject's contact details were changed on the Blinc platform. Re-read `subject`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_subject_updated"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"aml_check.monitoring_updated":{"post":{"summary":"aml_check.monitoring_updated","description":"Ongoing monitoring was switched on or off. Re-read `ongoing_monitoring`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_aml_check_monitoring_updated"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"land_registry.extract_completed":{"post":{"summary":"land_registry.extract_completed","description":"An official register extract finished for one of the search's titles; `data` is the search with its results.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_land_registry_extract_completed"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"prs_check.completed":{"post":{"summary":"prs_check.completed","description":"The name-on-title check finished; `data.verified` says whether the subject's name appears on the title.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_prs_check_completed"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"prs_check.failed":{"post":{"summary":"prs_check.failed","description":"The name-on-title check could not be completed; `data.error` says why.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_prs_check_failed"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}},"ping":{"post":{"summary":"ping","description":"A test delivery requested from the dashboard or `POST /v1/webhook-endpoints/{id}/test`. `data` carries a message only.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent_ping"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge. Non-2xx responses are retried with backoff for ~3 days."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Your `blinc_live_…` or `blinc_test_…` API key."}},"schemas":{"Problem":{"type":"object","description":"RFC 9457 problem+json. `code` is the stable machine contract.","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string","x-extensible-enum":["unauthorized","invalid_api_key","api_access_not_enabled","rate_limited","invalid_request","not_found","idempotency_key_reused","conflict","internal_error","service_unavailable","report_not_ready","livemode_required","payload_too_large","quota_exceeded","budget_exceeded","api_version_sunset"],"description":"Stable machine code. The set grows over time — handle an unknown value as a generic error of its HTTP status. See the changelog for additions."},"detail":{"type":"string"}},"required":["type","title","status","code"]},"AmlCheck":{"type":"object","properties":{"object":{"type":"string","const":"aml_check"},"id":{"type":"string","description":"Opaque id, `aml_` + 32 hex."},"type":{"type":"string","enum":["virtual","in_person"]},"status":{"type":"string","enum":["invited","in_progress","processing","completed","declined","cancelled"],"description":"Where the check is. `invited` → `in_progress` → `processing` → `completed` is the normal path; `declined` (the subject refused) and `cancelled` are terminal. `result` is populated only at `completed`. A virtual check stays `in_progress` until the subject SUBMITS the invitation flow, even though the identity, data-intelligence and screening steps run inside that flow — nothing about their outcome is reported before the subject finishes. See *Building a status indicator* in the guide."},"customer_type":{"type":["string","null"],"enum":["landlord","vendor","buyer","tenant","other",null]},"subject":{"type":"object","properties":{"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"email":{"type":["string","null"]},"phone":{"type":["string","null"]}}},"services":{"type":"array","items":{"type":"string","enum":["standard","prs_addon","sof_addon"]},"description":"Which checks to run. `standard` is always required — the add-ons extend it and cannot run alone.\n\n- `standard` — the extensive AML check: identity verification, data intelligence and PEP/sanctions screening.\n- `prs_addon` — Property Register (PRS) name-on-title check: confirms the subject's name appears on the Land Registry title at the **transaction address** (see `transaction_address`).\n- `sof_addon` — Source of Funds via Open Banking."},"ongoing_monitoring":{"type":"boolean"},"transaction_address":{"type":["object","null"],"description":"The transaction address on record, or null when none distinct from the subject's current address has been captured. Every key is always present.","required":["line1","line2","town","county","postcode","country"],"properties":{"line1":{"type":["string","null"]},"line2":{"type":["string","null"]},"town":{"type":["string","null"]},"county":{"type":["string","null"]},"postcode":{"type":["string","null"]},"country":{"type":["string","null"]}}},"branch_id":{"type":["string","null"],"format":"uuid","description":"The branch this check is recorded against — see `GET /v1/branches`."},"skip_id_document":{"type":["boolean","null"],"description":"In-person checks only (null for virtual): the value given at create. `false` means the ID document is uploaded separately and the check waits for its decision."},"next_action":{"type":["string","null"],"enum":["upload_id_document",null],"description":"What you must do before the check can progress. `upload_id_document`: an in-person check created with `skip_id_document: false` has not received its document yet — `POST /v1/aml-checks/{id}/documents`. Null once the document is in, when none is expected, and on every terminal status."},"result":{"type":["object","null"],"description":"Populated only at status `completed`. Can change after that: `aml_check.result_updated` fires when a re-evaluation (for example ongoing monitoring) moves it.","properties":{"outcome":{"type":"string","enum":["clear","attention"],"description":"`clear`: no finding. `attention`: a hard stop or a finding that a compliance officer must review on the Blinc platform — go to `dashboard_url`. The reasons are in `flags`; an accepted `review` supersedes it."},"flags":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["address_er_not_current","address_not_verified","bank_match_failed","ccj_found","company_inactive","deceased_match","document_liveness_failed","document_photocopy_detected","driving_licence_invalid","email_elevated_risk","email_very_high_risk","identity_attention","identity_check_not_clear","identity_not_verified_insufficient","identity_not_verified_lexid","identity_rejected","identity_review_recommended","insolvency_found","lexid_no_match","ni_number_invalid","passport_invalid","pep_match","remote_check_failed","sanctions_match","screening_adverse_media","screening_disqualified_entity"],"description":"Published vocabulary. A new value is a versioned change — pinned callers never see one they were not built for."},"label":{"type":"string"}}}},"review":{"type":["object","null"],"description":"The compliance decision recorded on the platform, or null while none has been. `accepted`: the transaction may proceed despite `attention`. `rejected`: it must not. `under_review`: escalated to the MLRO, decision pending.","properties":{"decision":{"type":"string","enum":["accepted","rejected","under_review"]}}}}},"created_at":{"type":["string","null"],"format":"date-time"},"dashboard_url":{"type":["string","null"],"format":"uri","description":"The check on the Blinc platform, e.g. `https://app.blinc-uk.com/amls/aml_…`. Opens for any signed-in user of your company. Present on every check; it is where to send a staff member when `result.outcome` is `attention`. Null for sandbox checks, which have no dashboard page."}}},"LandRegistrySearch":{"type":"object","properties":{"object":{"type":"string","const":"land_registry_search"},"id":{"type":"string","description":"Opaque id, `lrs_` + 32 hex."},"status":{"type":"string","enum":["searched","extracted"]},"address":{"type":"object","properties":{"line1":{"type":["string","null"]},"town_city":{"type":["string","null"]},"postcode":{"type":["string","null"]}}},"titles":{"type":"array","items":{"type":"object","properties":{"title_number":{"type":"string"},"tenure":{"type":"string"},"addresses":{"type":"array","items":{"type":"string"}}}}},"register":{"type":["object","null"],"description":"The official register for the extracted title. Populated after an extract; null on a search-only result.","properties":{"title_number":{"type":"string"},"tenure":{"type":["string","null"]},"class_of_title":{"type":["string","null"]},"edition":{"type":["string","null"]},"edition_date":{"type":["string","null"]},"official_copy_at":{"type":["string","null"]},"proprietors":{"type":"array","items":{"type":"object","properties":{"name":{"type":["string","null"]},"company_registration_number":{"type":["string","null"]},"address":{"type":["string","null"]}}}},"entries":{"type":"array","items":{"type":"object","properties":{"number":{"type":["string","null"]},"date":{"type":["string","null"]},"type":{"type":["string","null"]},"text":{"type":"string"}}}},"address_lines":{"type":"array","items":{"type":"string"}}}},"include_title_plan":{"type":"boolean"},"document_count":{"type":"integer"},"created_at":{"type":["string","null"],"format":"date-time"},"branch_id":{"type":["string","null"],"format":"uuid","description":"The branch this search is recorded against — see `GET /v1/branches`."}}},"PrsCheck":{"type":"object","properties":{"object":{"type":"string","const":"prs_check"},"id":{"type":"string","description":"Opaque id, `prs_` + 32 hex."},"status":{"type":"string","enum":["pending","completed","failed"]},"verified":{"type":["boolean","null"]},"subject":{"type":"object","properties":{"first_name":{"type":["string","null"]},"middle_name":{"type":["string","null"]},"last_name":{"type":["string","null"]}}},"address":{"type":["object","null"],"description":"The property address the name was checked against — the request's `address`, echoed with every key present.","required":["line1","line2","town","county","postcode"],"properties":{"line1":{"type":["string","null"]},"line2":{"type":["string","null"]},"town":{"type":["string","null"]},"county":{"type":["string","null"]},"postcode":{"type":["string","null"]}}},"created_at":{"type":["string","null"],"format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"},"branch_id":{"type":["string","null"],"format":"uuid","description":"The branch this check is recorded against — see `GET /v1/branches`."}}},"Branch":{"type":"object","required":["object","id","name","is_primary","is_active","address","created_at"],"properties":{"object":{"type":"string","const":"branch"},"id":{"type":"string","format":"uuid","description":"Use as `branch_id` on create requests."},"name":{"type":"string"},"is_primary":{"type":"boolean","description":"The branch requests default to when `branch_id` is omitted."},"is_active":{"type":"boolean","description":"Retired branches stay listed so a stored id can be explained, but are rejected on new requests."},"address":{"type":"object","required":["line1","line2","town","county","postcode"],"properties":{"line1":{"type":["string","null"]},"line2":{"type":["string","null"]},"town":{"type":["string","null"]},"county":{"type":["string","null"]},"postcode":{"type":["string","null"]}}},"created_at":{"type":["string","null"],"format":"date-time"}}},"CreateAmlCheckVirtual":{"type":"object","title":"Virtual","description":"**Virtual** (`type: \"virtual\"`) — you do not have the subject with you. Blinc emails them an invitation; they verify their identity and enter their own details (including their current address) in a guided flow. Progress arrives as webhooks. Requires the subject's email.","examples":[{"type":"virtual","first_name":"Ada","last_name":"INSTANT","email":"ada@example.com","customer_type":"buyer"},{"type":"virtual","first_name":"Ada","last_name":"Lovelace","email":"ada@example.com","customer_type":"landlord","services":["standard","prs_addon"],"transaction_address":{"line1":"12 Let Property Road","town":"Manchester","postcode":"M1 1AA"}}],"required":["type","first_name","last_name","email","customer_type"],"properties":{"type":{"const":"virtual"},"first_name":{"type":"string","examples":["Ada"]},"last_name":{"type":"string","examples":["INSTANT"],"description":"In test mode the surname `INSTANT` completes the check immediately."},"email":{"type":"string","format":"email","examples":["ada@example.com"]},"phone":{"type":"string"},"customer_type":{"type":"string","enum":["landlord","vendor","buyer","tenant","other"]},"services":{"type":"array","items":{"type":"string","enum":["standard","prs_addon","sof_addon"]},"default":["standard"],"description":"Which checks to run. `standard` is always required — the add-ons extend it and cannot run alone.\n\n- `standard` — the extensive AML check: identity verification, data intelligence and PEP/sanctions screening.\n- `prs_addon` — Property Register (PRS) name-on-title check: confirms the subject's name appears on the Land Registry title at the **transaction address** (see `transaction_address`).\n- `sof_addon` — Source of Funds via Open Banking."},"ongoing_monitoring":{"type":"boolean","default":false},"branch_id":{"type":"string","format":"uuid","description":"Optional. The branch to record this against — an `id` from `GET /v1/branches`. Defaults to your primary branch (for a branch-restricted key, the first active branch it may use). A retired branch, or one that is not yours, is rejected with 404."},"transaction_address":{"type":"object","description":"The property being transacted — the let property for a landlord, the property being sold for a vendor. Read ONLY by the PRS name-on-title check, so it is accepted only when `services` includes `prs_addon` (400 otherwise). Omit it when the transaction address is the subject's current address — the common case for a sale; the PRS check then runs against the current address (for a virtual check, the one the subject enters in their invitation) and it appears on the check as `transaction_address` once known.","required":["line1","town","postcode"],"properties":{"line1":{"type":"string"},"line2":{"type":"string"},"town":{"type":"string"},"county":{"type":"string"},"postcode":{"type":"string"},"country":{"type":"string","description":"Defaults to \"United Kingdom\"."}}}}},"CreateAmlCheckInPerson":{"type":"object","title":"In person","description":"**In person** (`type: \"in_person\"`) — you have the subject and their ID document with you. Supply their full details up front (date of birth, nationality, current address); the data-intelligence and screening step runs automatically. **Then upload the ID document via `POST /v1/aml-checks/{id}/documents` — the check stays `processing` and does not complete until the document decision arrives** (see *In-person checks* in the guide). `skip_id_document` is required: send `false` when the document will follow, `true` only when the agent verified it in person and no upload will be made. No email is required.","examples":[{"type":"in_person","first_name":"Ada","last_name":"Lovelace","customer_type":"vendor","date_of_birth":"1984-10-25","nationality":"British","current_address":{"line1":"1 Home Street","town":"London","postcode":"SW1A 1AA"},"skip_id_document":false}],"required":["type","first_name","last_name","customer_type","date_of_birth","nationality","current_address","skip_id_document"],"properties":{"type":{"const":"in_person"},"first_name":{"type":"string"},"middle_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string","format":"email"},"customer_type":{"type":"string","enum":["landlord","vendor","buyer","tenant","other"]},"date_of_birth":{"type":"string","format":"date","description":"Subject's date of birth (YYYY-MM-DD). The subject must be at least 18 years old; an under-18 date is rejected with a validation error."},"nationality":{"type":"string"},"current_address":{"type":"object","required":["line1","town","postcode"],"properties":{"line1":{"type":"string"},"line2":{"type":"string"},"town":{"type":"string"},"county":{"type":"string"},"postcode":{"type":"string"},"country":{"type":"string","description":"Defaults to \"United Kingdom\"."}}},"document_number":{"type":"string"},"skip_id_document":{"type":"boolean","description":"Required. `false` — you will upload the ID document via `POST /v1/aml-checks/{id}/documents`; the check reports `next_action: \"upload_id_document\"` and waits for the provider decision before completing. `true` — the document was verified in person and no upload will follow; an upload to such a check is refused with 409."},"services":{"type":"array","items":{"type":"string","enum":["standard","prs_addon","sof_addon"]},"default":["standard"],"description":"Which checks to run. `standard` is always required — the add-ons extend it and cannot run alone.\n\n- `standard` — the extensive AML check: identity verification, data intelligence and PEP/sanctions screening.\n- `prs_addon` — Property Register (PRS) name-on-title check: confirms the subject's name appears on the Land Registry title at the **transaction address** (see `transaction_address`).\n- `sof_addon` — Source of Funds via Open Banking."},"ongoing_monitoring":{"type":"boolean","default":false},"branch_id":{"type":"string","format":"uuid","description":"Optional. The branch to record this against — an `id` from `GET /v1/branches`. Defaults to your primary branch (for a branch-restricted key, the first active branch it may use). A retired branch, or one that is not yours, is rejected with 404."},"transaction_address":{"type":"object","description":"The property being transacted — the let property for a landlord, the property being sold for a vendor. Read ONLY by the PRS name-on-title check, so it is accepted only when `services` includes `prs_addon` (400 otherwise). Omit it when the transaction address is the subject's current address — the common case for a sale; the PRS check then runs against the current address (for a virtual check, the one the subject enters in their invitation) and it appears on the check as `transaction_address` once known.","required":["line1","town","postcode"],"properties":{"line1":{"type":"string"},"line2":{"type":"string"},"town":{"type":"string"},"county":{"type":"string"},"postcode":{"type":"string"},"country":{"type":"string","description":"Defaults to \"United Kingdom\"."}}}}},"WebhookEvent":{"description":"Webhook delivery body — a tagged union on `type`. `data` is the SAME projection the matching GET returns, snapshotted when the event occurred; `ping` carries a message only.","oneOf":[{"$ref":"#/components/schemas/WebhookEvent_aml_check_created"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_invited"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_reminder_sent"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_started"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_submitted"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_document_received"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_document_decision"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_completed"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_result_updated"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_review_completed"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_report_updated"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_declined"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_cancelled"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_subject_updated"},{"$ref":"#/components/schemas/WebhookEvent_aml_check_monitoring_updated"},{"$ref":"#/components/schemas/WebhookEvent_land_registry_extract_completed"},{"$ref":"#/components/schemas/WebhookEvent_prs_check_completed"},{"$ref":"#/components/schemas/WebhookEvent_prs_check_failed"},{"$ref":"#/components/schemas/WebhookEvent_ping"}],"discriminator":{"propertyName":"type","mapping":{"aml_check.created":"#/components/schemas/WebhookEvent_aml_check_created","aml_check.invited":"#/components/schemas/WebhookEvent_aml_check_invited","aml_check.reminder_sent":"#/components/schemas/WebhookEvent_aml_check_reminder_sent","aml_check.started":"#/components/schemas/WebhookEvent_aml_check_started","aml_check.submitted":"#/components/schemas/WebhookEvent_aml_check_submitted","aml_check.document_received":"#/components/schemas/WebhookEvent_aml_check_document_received","aml_check.document_decision":"#/components/schemas/WebhookEvent_aml_check_document_decision","aml_check.completed":"#/components/schemas/WebhookEvent_aml_check_completed","aml_check.result_updated":"#/components/schemas/WebhookEvent_aml_check_result_updated","aml_check.review_completed":"#/components/schemas/WebhookEvent_aml_check_review_completed","aml_check.report_updated":"#/components/schemas/WebhookEvent_aml_check_report_updated","aml_check.declined":"#/components/schemas/WebhookEvent_aml_check_declined","aml_check.cancelled":"#/components/schemas/WebhookEvent_aml_check_cancelled","aml_check.subject_updated":"#/components/schemas/WebhookEvent_aml_check_subject_updated","aml_check.monitoring_updated":"#/components/schemas/WebhookEvent_aml_check_monitoring_updated","land_registry.extract_completed":"#/components/schemas/WebhookEvent_land_registry_extract_completed","prs_check.completed":"#/components/schemas/WebhookEvent_prs_check_completed","prs_check.failed":"#/components/schemas/WebhookEvent_prs_check_failed","ping":"#/components/schemas/WebhookEvent_ping"}}},"WebhookEvent_aml_check_created":{"type":"object","description":"The check now exists. Fired for checks created in the Blinc dashboard as well as via the API, before any invitation is sent.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.created"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_invited":{"type":"object","description":"The invitation email to the subject was accepted by the email provider. Never fired for a failed send; fired again on every resend, so the number of `invited` events is the number of invitation emails sent. Virtual checks only.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.invited"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_reminder_sent":{"type":"object","description":"An automatic reminder email was sent to a subject who has not completed the invitation. Virtual checks only; repeats once per reminder window.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.reminder_sent"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_started":{"type":"object","description":"The subject opened the invitation flow. Virtual checks only.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.started"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_submitted":{"type":"object","description":"Virtual: the subject finished the invitation flow. In-person: the automatic data-intelligence and screening step finished (fired even when a provider call failed). The check is now `processing`.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.submitted"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_document_received":{"type":"object","description":"The ID document upload for an in-person check was stored. Fired again on a re-upload.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.document_received"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_document_decision":{"type":"object","description":"The identity provider decided on the ID document — the subject's own upload for a virtual check, the agent's for an in-person one. Can fire more than once when a resubmission is requested.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.document_decision"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_completed":{"type":"object","description":"The check has its first outcome and `result` is populated. Fired exactly once per check.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.completed"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_result_updated":{"type":"object","description":"A later re-evaluation (ongoing monitoring, a re-score) changed `result.outcome` or `result.flags`. Re-read `result`: a check that was clear can now require attention.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.result_updated"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_review_completed":{"type":"object","description":"A compliance officer accepted or rejected the check on the Blinc platform; `result.review.decision` is `accepted` or `rejected`.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.review_completed"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_report_updated":{"type":"object","description":"The certificate PDF for a completed check changed — a compliance decision, a screening match review, an ongoing-monitoring change or a re-evaluation was recorded. If you store the certificate, re-fetch `GET /v1/aml-checks/{id}/report` (send `If-None-Match` with your stored ETag to skip an unchanged file).","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.report_updated"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_declined":{"type":"object","description":"The subject declined the invitation. Terminal. Contact the subject — this is not a compliance finding.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.declined"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_cancelled":{"type":"object","description":"The check was cancelled by the agent, from the dashboard or the API. Terminal.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.cancelled"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_subject_updated":{"type":"object","description":"The subject's contact details were changed on the Blinc platform. Re-read `subject`.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.subject_updated"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_aml_check_monitoring_updated":{"type":"object","description":"Ongoing monitoring was switched on or off. Re-read `ongoing_monitoring`.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"aml_check.monitoring_updated"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/AmlCheck"}}},"WebhookEvent_land_registry_extract_completed":{"type":"object","description":"An official register extract finished for one of the search's titles; `data` is the search with its results.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"land_registry.extract_completed"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/LandRegistrySearch"}}},"WebhookEvent_prs_check_completed":{"type":"object","description":"The name-on-title check finished; `data.verified` says whether the subject's name appears on the title.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"prs_check.completed"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/PrsCheck"}}},"WebhookEvent_prs_check_failed":{"type":"object","description":"The name-on-title check could not be completed; `data.error` says why.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"prs_check.failed"},"created_at":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/PrsCheck"}}},"WebhookEvent_ping":{"type":"object","description":"A test delivery requested from the dashboard or `POST /v1/webhook-endpoints/{id}/test`. `data` carries a message only.","required":["id","type","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Also the `webhook-id` header."},"type":{"type":"string","const":"ping"},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}}}}}}}