POST /api/ingestion/customers/{customerId}/kyb-runs starts a KYB run for a business Customer that
your ingestion source already created. Use it when the Customer and its documents are already in
Karsa and you want a fresh evaluation, for example after uploading a replacement document. To submit
a complete snapshot with related parties and provider evidence, use
KYB dossiers instead.
Address the customer
Every KYB run route accepts either form of customer reference. Both resolve only Customers owned by the calling ingestion source.Start a run
AnIdempotency-Key header is required. The body is optional.
AVAILABLE
version of every ingested document linked to it or cited by its latest KYB dossier. Related parties
and provider evidence carry forward from that latest dossier. To choose the documents yourself, list
them with a KYB document role:
subtype (for example CERTIFICATE_OF_INCORPORATION_OR_FORMATION,
UTILITY_BILL, or SHAREHOLDER_OR_MEMBER_REGISTER, as in a KYB dossier) and language (a BCP 47
tag such as en or pt-BR; und is not accepted). A document cited by the Customer’s latest KYB
dossier in the same role reuses that dossier’s subtype and languages. Karsa does not guess: on a
first run, or for a document no dossier has cited, supply subtype and language in documents,
otherwise the request is refused with 422 KYB_DOCUMENT_METADATA_REQUIRED. Each entry in its
issues has the documentVersionId as path and names what is missing.
Karsa answers 202 Accepted with a Location header for the run:
202 without starting another run. Reusing the key
with a different body, or for a different customer reference, returns 409 IDEMPOTENCY_CONFLICT.
A Customer can have one active run at a time.
Poll the run
GET on the same customer path. Pass limit (1–100,
default 20) and the returned nextCursor as cursor to read the next page.
Status lifecycle
status is derived from the run and its Case.
A finished run has
result.outcome, result.openIssueCount, and result.caseId. Karsa
evaluations report ATTENTION_REQUIRED or NO_ATTENTION; prepared cases report APPROVED or
REVIEW_REQUIRED; runs from the earlier KYB investigation keep RFI_REQUIRED,
RESEARCH_REQUIRED, or HUMAN_REVIEW_REQUIRED. A failed run has failure.code, for example
KYB_EXECUTION_FAILED. New statuses and outcomes may be added; treat an unknown value as not yet
terminal and keep polling or wait for a webhook.
Errors
Errors useapplication/problem+json with a stable code. A trigger checks the Customer first, so
CUSTOMER_NOT_FOUND and CUSTOMER_NOT_BUSINESS are returned even while KYB evaluation is
unavailable.
Webhooks
Subscribe an endpoint tokyb.evaluation.queued, kyb.evaluation.completed, and
kyb.evaluation.failed as described in Set up outbound webhooks. Each KYB
event’s data.kybRun is the run exactly as GET /api/ingestion/kyb-runs/{id} returned it when the
event was recorded, so you can act on the webhook without polling. Events are delivered only to
endpoints that are active when they occur; to catch up after downtime or before an endpoint was
verified, list them with GET /api/ingestion/webhook-events.
kyb.evaluation.queued event carries kybRun.status pending. A kyb.evaluation.failed event
carries kybRun.status failed and the same code in failureCode and kybRun.failure.code.
Deliveries are retried with the same event ID, timestamp, and signature, so deduplicate on the
signed body’s id. The Karsa-Webhook-Id header is not signed: after verifying, reject a delivery
whose header ID or type differs from the body’s id or type.
Verify the signature
Karsa signs the UTF-8 bytestimestamp + "." + rawBody with Ed25519. Verify with the public key
for the delivery’s Karsa-Webhook-Key-Version before parsing the JSON: