POST /v1/kyc/verify returns the verdict for a client profile and the documents behind it. Scope: kyc:verify. It does not read files and it costs no document read. POST /v1/kyc/assess takes the same body, runs this same verdict, and adds a risk assessment.
Request
JSON body. Every field is optional, but an empty body verifies nothing.values
values is a free object. The engine reads the keys below and ignores the others. Send strings. Dates are YYYY-MM-DD.
The completeness check counts these keys as present when they are non-empty.
The required list comes from an engine that was first built for North American files. It asks for
province, postal_code and a sin or ssn, so a Moroccan individual can reach 27 of 28 at most (96 percent) and sin/ssn stays in missing. 80 percent or more is not flagged. The sample requests here use country MA, id_type National ID and a CIN number such as BK123456; province and postal_code take any text for a Moroccan address, and the Canadian postal format is checked only when country is CA.
Other keys the checks use:
Response
checks list above is shortened to three entries; a full answer has more. The example is the real output of the engine for fake data (a Moroccan national ID and a payslip for Test Client).
Each check has five keys.
Do not match on
label: it can change. Match on id, and treat the part after the first colon as a variable.
How to read the verdict
The file passes when no critical check failed. A file with 30 warnings still passes, so look at
flags as well as passed.
The three layers
- Per document: the same checks
/extractalready returned for each file (type, readable, expiry, adult, MRZ, recency, provenance, specimen). - Cross-document and profile: the name, date of birth and address agree across documents and with
values; the formats of numbers; the bank details; the required identity document is among the uploads. - File level: sanctions and PEP screening, beneficial ownership for entities, registry checks, the policy’s own determinations, then completeness.
Checks
Ids are listed with the part after the first colon replaced by*. “Document” means the label of the step or the doc_type hint (for example passport, or Government photo ID when a step_key is sent).
Per document
Across documents and profile
File level
Screening
Every party on the file is screened by default (screen: true).
A sanctions hit is critical and blocks. A PEP hit is a warning. A clean result produces one
screening check that says what the party was screened against:
With
canadian_screening true (or the policy asking for it) and a Canadian client (country is CA, CAN or Canada), the parties the bundle found nothing on are also screened by the eID provider’s Canadian AML and PEP tables, when the workspace has an account. The screening:canchek check says how many parties were screened.
Policy and switches
Each call runs under your workspace’s KYC policy for the client kind (kyc for a person, kyb for any entity) and the environment. The answer’s policy says which one.
A request switch can add checks or be stricter. It cannot turn off an item the policy locks. A refused switch is not an error: the call runs with the stricter rule and the refusal is recorded.
overrides_refused is real, the values are an example.) A refusal also adds an info check policy:override_refused:screen.
What a policy can change:
Policy values are edited in the console, not through the API.
Periodic review
purpose: "periodic_review" is for a client already onboarded. It does not re-verify identity (PCMLTFR s.155(1)): the identity documents, the eID requirement and the slot checks are not applied. Screening, the determinations and every other lock still run.
- With a passed onboarding on file at Sahl for the same
referenceandenvironment, the review adds an info checkpolicy:periodic_review. - With none, or without a
reference, the review is honoured but adds a warningpolicy:periodic_review_unanchored: identity was skipped on your word alone.
Your own checks
extra_checks lets you fold a check you ran yourself, such as a duplicate client or a blocklist in your database, into the verdict so it can block it.
id, label, severity (critical, warning or info) and passed; detail is optional. An id that starts with eid: or policy: is Sahl’s alone: it comes back as partner:eid:... or partner:policy:..., shown and still able to block, but it never meets the policy’s eID requirement.
Corporations Canada registry
For acorporation the advisor says is federally incorporated (CBCA), and when the policy enables it (default on), Sahl looks the company up. registry then holds the normalised record, so you can pre-fill from it, and the registry: checks compare it with your data. In every other case registry is null.
Filing
With areference the verdict is filed on the case for (workspace, environment, reference). Documents whose document_id came from /extract are linked to it. A status a person set (approved, refused) is never undone by a new verdict. The kyc.case_verified webhook fires after the commit.
Examples
A blocked file
An expired national ID givespassed: false and two critical failures, one from the document and one from the profile: