The screening logic, watchlists, and matching quality are the same across both
versions. Migration is almost entirely about how you authenticate and how you
read the response — the request body is largely backward compatible.
Why migrate
Standard response envelope
Every endpoint now returns a consistent
status / data / meta structure, so
error handling and parsing are uniform across the platform.Unified authentication
A single
Authorization: Bearer scheme (API key or JWT) replaces the legacy
per-endpoint auth, with role-based permissions.Value-first identifier matching
Document and ID matching now keys on the value, not the document-type label —
you no longer need to send the exact
document_type to get an exact ID hit.Multi-list in one call
Screen against many lists in a single request with a consolidated
summary and
per-list results.At a glance
| Aspect | Legacy | v2 |
|---|---|---|
| Base URL | Legacy gateway host | https://kyc.legaltalent.ai (prod) · https://stg.kyc.legaltalent.ai (staging) |
| Auth header | Legacy credential | Authorization: Bearer <api_key | jwt> |
| Endpoint | Legacy screening path | POST /kyc |
| Response envelope | Job object at the top level (job_id, status, …) | { "status", "data", "meta" } |
| Request identifier | job_id in body | meta.request_id in response |
| Top-level status | "COMPLETED" / "FAILED" | "success" / "error" |
| Per-list match flag | has_matches | is_match |
| Matched entity | matches[].matched_entity | matches[].entity (single list) / matches[].match_data |
| Per-match risk | matches[].risk_level + confidence_score | matches[].confidence_score (derive level from score, or use summary.overall_risk_level) |
| Aggregate risk | screening_summary | data.summary |
Migration in 5 steps
Switch the base URL and endpoint
Point your client at
https://stg.kyc.legaltalent.ai/kyc for integration testing,
then https://kyc.legaltalent.ai/kyc for production. The method stays POST.Switch to Bearer authentication
Replace the legacy credential with an
Authorization: Bearer header using your
API key (sk_...) or a JWT. See Authentication.
You no longer pass tenant_id in the body — it is derived from the token.Keep your request body (with minor tweaks)
The
subject object is backward compatible. If you used match_type, send
search_type instead (both accept composite, exact, fuzzy, token,
llm_enhanced).Update your response parser
Read results from the new envelope:
data for results, meta.request_id for the
correlation id, data.summary for the aggregate risk. See the field mapping below.Re-point your risk/decision logic
Use
summary.overall_risk_level + summary.recommended_action for the aggregate
decision, and matches[].confidence_score for per-match intensity. If you relied
on per-match risk_level, derive it from confidence_score (see
Risk and decisioning).Authentication
The legacy integration used a dedicated credential on the legacy gateway. The v2 API uses a single Bearer scheme for both user (JWT) and machine-to-machine (API key) access.POST /kyc requires the kyc:create permission. The token also scopes the request
to your tenant, so remove any tenant_id you previously sent in the request body.Request changes
The request body is largely unchanged. The main adjustments:| Legacy field | v2 field | Notes |
|---|---|---|
match_type | search_type | Same accepted values; search_type is the canonical name. |
tenant_id (body) | — | Removed. Derived from the Bearer token. |
subject.* | subject.* | Backward compatible (see below). |
Identifier matching improvement
In v2, identifier matching is value-first: an exact ID/document number matches a list entry regardless of how the document-type label is named on either side (CI, DNI, National ID, document_id, numeric id, etc.). Values are normalized
(non-alphanumeric characters stripped, case-insensitive) before comparison.
- Recommended (v2)
- Still supported
You no longer need This matches a list entry whether the number is stored under
document_type to get an exact ID hit:ci, document_id,
a numeric id, or inside an identifiers[] array.Response changes
The biggest change is the envelope. Below is the same multi-list screening in both formats, side by side.Field mapping
| Legacy path | v2 path |
|---|---|
status == "COMPLETED" | status == "success" |
job_id | meta.request_id |
completed_at | meta.timestamp |
screened_entity.name | data.subject.full_name |
results[list].has_matches | data.results[list].is_match |
results[list].match_count | data.results[list].match_count |
results[list].matches[].matched_entity | data.results[list].matches[].entity |
results[list].matches[].confidence_score | data.results[list].matches[].confidence_score |
results[list].matches[].match_type | data.results[list].matches[].match_type |
results[list].matches[].risk_level | (derive from confidence_score) |
screening_summary | data.summary |
screening_summary.overall_risk_level | data.summary.overall_risk_level |
screening_summary.recommended_action | data.summary.recommended_action |
Single-list responses put the result fields directly under
data
(data.is_match, data.matches, data.matched_field) instead of under
data.results[list]. Multi-list responses use data.results keyed by list name.
See List Check for full schemas.Risk and decisioning
The v2 API exposes risk at two layers:- Per match —
confidence_score(0.0–1.0): the intensity of an individual hit. An exact identifier match is always1.0. Name matches are scored by the search engine and refined bynationality/birth_date. - Aggregate —
summary.overall_risk_level+summary.recommended_action: a consolidated assessment across all checked lists, plus a suggested action.
risk_level, that field is not returned
per match in v2. Either consume the aggregate summary.overall_risk_level, or derive a
per-match level from confidence_score using thresholds that fit your risk appetite:
The thresholds above mirror the platform defaults, but you own the final decision
policy (block / review / proceed). Tune the cutoffs to your compliance requirements.
Error handling
Errors also move into the standard envelope.| Situation | Legacy | v2 |
|---|---|---|
| Success flag | status == "COMPLETED" | status == "success" |
| Failure flag | status == "FAILED" | status == "error" |
| Error detail | error_message (string) | error.code + error.message |
| Auth failure | gateway error | 401 (missing/invalid token) / 403 (insufficient permission) |
Migration checklist
Re-map the response
Read
data / meta; switch has_matches → is_match,
matched_entity → entity, job_id → meta.request_id.Re-point risk logic
Use
summary.overall_risk_level / recommended_action, and derive per-match level
from confidence_score if needed.FAQ
Do I have to change my request body?
Do I have to change my request body?
Minimally. The
subject object is backward compatible. The only common changes are
renaming match_type to search_type and removing any tenant_id from the body.Will the same input produce the same matches?
Will the same input produce the same matches?
Yes — the screening engine and lists are the same. Identifier matching is more
forgiving (value-first), so you may see exact ID hits that previously required the
correct
document_type. Name-based scoring is unchanged.What happened to per-match risk_level?
What happened to per-match risk_level?
The aggregate risk now lives in
summary.overall_risk_level and
summary.recommended_action. Each match exposes confidence_score; derive a
per-match level from it if your UI needs one.Can I run both versions during migration?
Can I run both versions during migration?
Yes. Point a copy of your traffic at the v2 staging endpoint, compare outputs, and
cut over once parity is confirmed. There is no forced switch on the request side.
Do I need to re-issue credentials?
Do I need to re-issue credentials?
You need a v2 API key (or JWT) for Bearer auth. Contact your account administrator
to provision an API key with the
kyc:create permission.Next steps
List Check reference
Full v2 request/response schemas, lists, and examples.
Authentication
Bearer tokens, API keys, and the permission model.
API Overview
Environments, rate limits, and platform basics.
Validate a Person or Entity
End-to-end screening walkthrough on v2.