Skip to main content

Overview

Every per-feature report follows the V3 serializer shape defined in service-didit-verification. The same object appears in three places, so the schema you see here is the single source of truth across them:
  • GET /v3/session/{sessionId}/decision/ — each feature is returned as a plural array (id_verifications[], nfc_verifications[], liveness_checks[], face_matches[], poa_verifications[], phone_verifications[], email_verifications[], aml_screenings[], ip_analyses[], database_validations[], questionnaire_responses[], and the KYB equivalents registry_checks[], document_verifications[], key_people_checks[]).
  • Webhook payloads (status.updated, data.updated) — same shape inside the decision envelope.
  • Standalone APIs — single-object responses (Face Search, Age Estimation, Biometric Authentication) reuse the same field set.
V3 introduced multi-instance workflows: every feature object carries a node_id that pins the report to the workflow graph node that produced it. V2 endpoints (singular kyc, face, aml, etc.) remain backwards-compatible but only return the first instance.

Common fields

Every report object exposes the following:
FieldTypeDescription
statusstringFeature-level lifecycle status — one of the values in Status enum. Source: common/config/choices.py:FeatureStatusChoices (lines 343-348). The parent session’s top-level status uses the wider session enum (StatusChoices, lines 106-117).
node_idstring | nullWorkflow graph node identifier. Populated for V3 multi-instance workflows; null for legacy single-feature sessions.
warningsarray of warning objectsRisk signals filtered to this feature and node_id. Returned by Session.get_logs(...) (sessions/models/session.py:1611).
Media fields (portrait_image, front_image, document_file, …) are presigned URLs with a limited validity window — download them promptly rather than persisting the URL. Examples show them as https://<media-host>/....

Warning object

Returned in every warnings[] array. Schema from logs/serializers/log.py:8-65 (LogV3Serializer).
FieldTypeNullableDescriptionExample
featurestring (enum)NoWhich feature emitted the warning. Values from LogWarningChoices (common/config/choices.py:190-204): ID_VERIFICATION, NFC, LIVENESS, FACEMATCH, PROOF_OF_ADDRESS, PHONE, EMAIL, AML, LOCATION, DATABASE_VALIDATION, QUESTIONNAIRE, KYB_REGISTRY, KYB_DOCUMENTS, KYB_KEY_PEOPLE."ID_VERIFICATION"
riskstringNoStable risk code (e.g. DOCUMENT_EXPIRED, LOW_LIVENESS_SCORE). Values from logs/choices.py:RiskChoices. Used as the key into description tables."DOCUMENT_EXPIRED"
additional_dataobject | nullYesRisk-specific context (e.g. score thresholds, matched fields). Shape varies by risk code.{ "score": 42.1, "threshold": 70 }
log_typestring (enum)NoOne of error, warning, information. From LogTypeChoices (common/config/choices.py:207-210)."error"
short_descriptionstringNoHuman-readable label for the risk. From logs/choices.py:RISK_SHORT_DESCRIPTIONS."Document expired"
long_descriptionstringNoLonger human-readable explanation suitable for end-user-facing surfaces. From logs/choices.py:RISK_LONG_DESCRIPTIONS."The document's expiration date has passed, rendering it no longer valid for use."
node_idstring | nullYesWorkflow graph node the warning was raised against. null for legacy V2 logs without node_id."first_id_verification"
{
  "feature": "ID_VERIFICATION",
  "risk": "DOCUMENT_EXPIRED",
  "additional_data": null,
  "log_type": "error",
  "short_description": "Document expired",
  "long_description": "The document's expiration date has passed, rendering it no longer valid for use.",
  "node_id": "first_id_verification"
}

Report objects

The remaining sections cover each per-feature report object. The H3 heading text is intentionally stable so other docs can deep-link to it.

ID verification

Returned from each KYC/ID document a user submits. Appears as id_verifications[] in GET /v3/session/{sessionId}/decision/ and inside the kyc field of V2 responses. Source: kyc/serializers/kyc.py:383-414 (IDVerificationV3Serializer, extends IDVerificationV2Serializer at kyc/serializers/kyc.py:320-380).
FieldTypeNullableDescriptionExample
statusstringNoSee Status enum."Approved"
document_typestringYesHuman-readable document class (Passport, Identity Card, Driver's License, Residence Permit, Health Insurance Card, Tax Card). Source: DOC_TYPE_MAPPING (common/config/choices.py:1132-1139)."Passport"
document_subtypestringYesAccepted document subtype code from the workflow document settings. Region-specific documents include the region."QUEENSLAND_DRIVER_LICENSE_GENERIC"
document_numberstringYesOCR-extracted document number."AB1234567"
personal_numberstringYesOCR-extracted personal/national identifier."99999999R"
portrait_imagestring (URL)YesPresigned URL to the face crop."https://<media-host>/.../portrait.jpg?..."
front_imagestring (URL)YesPresigned URL to the cleaned document front."https://<media-host>/.../front.jpg?..."
front_videostring (URL)YesPresigned URL to the front capture video (when available)."https://<media-host>/.../front.mp4?..."
back_imagestring (URL)YesPresigned URL to the cleaned document back."https://<media-host>/.../back.jpg?..."
back_videostring (URL)YesPresigned URL to the back capture video.null
full_front_imagestring (URL)YesUnclipped (full-frame) front capture."https://<media-host>/.../full_front.jpg?..."
full_back_imagestring (URL)YesUnclipped (full-frame) back capture.null
front_image_camera_frontstring (URL)YesFront-camera image taken at the same time as the document front.null
back_image_camera_frontstring (URL)YesFront-camera image taken at the same time as the document back.null
front_image_camera_front_face_match_scorefloat (0-100)YesSimilarity between the document portrait and the front-camera capture.null
back_image_camera_front_face_match_scorefloat (0-100)YesSame as above but for the back capture.null
front_image_quality_scoreobjectYesQuality metrics for the front image: scores 0-100 (focus_score, brightness_score, resolution_score, overall_score), plus brightness_issue (ok, too_dark, too_bright) and is_document_fully_visible (boolean).{ "focus_score": 91.0, "overall_score": 88.5 }
back_image_quality_scoreobjectYesSame shape as front_image_quality_score.null
date_of_birthstring (YYYY-MM-DD)YesOCR-extracted DOB."1990-05-12"
ageintegerYesComputed age in years at extraction time.35
expiration_datestring (YYYY-MM-DD)YesDocument expiration."2032-05-11"
date_of_issuestring (YYYY-MM-DD)YesDocument issue date."2022-05-11"
issuing_statestring (ISO 3166-1 alpha-3)YesIssuing country code."ESP"
issuing_state_namestringYesLocalized issuing country name."Spain"
first_namestringYesOCR-extracted given name(s)."María"
last_namestringYesOCR-extracted surname(s)."García López"
full_namestringYesFull normalized name (vendor-supplied)."María García López"
genderstringYesM, F, or other vendor-supplied value."F"
addressstringYesRaw OCR-extracted address line."Calle Mayor 1, 28001 Madrid"
formatted_addressstringYesGeocoded/formatted address (when parseable)."Calle Mayor 1, 28001 Madrid, Spain"
parsed_addressobjectYesStructured, geocoded address: street_1, street_2, city, region, country, postal_code, address_type, formatted_address, document_location ({latitude, longitude}), raw_results, is_best_match. Source: kyc/utils/address.py:147-197.{ "street_1": "Calle Mayor 1", "city": "Madrid", "postal_code": "28001", "country": "ES" }
place_of_birthstringYesOCR-extracted place of birth."Madrid"
marital_statusstringYesWhen extractable.null
nationalitystring (ISO 3166-1 alpha-3)YesOCR-extracted nationality."ESP"
extra_fieldsobjectYesDocument-type-specific fields not covered by the canonical schema (e.g. driver license categories).{ "DL Class": "B" }
mrzobjectYesParsed MRZ fields when present (document_number, birth_date, expiry_date, surname, given_names, …).{ "document_number": "AB1234567", "surname": "GARCIA", "given_names": "MARIA" }
extra_filesarray of strings (URL)NoPresigned URLs to any additional uploaded files.[]
matchesarray of objectsNoCross-session document matches. Each item: { session_id, session_number, vendor_data, verification_date, user_details: { name, document_type, document_number }, status, is_blocklisted, api_service, front_image_url }. front_image_url is presigned.[]
node_idstring | nullYesWorkflow node identifier (V3)."first_id_verification"
warningsarrayNoSee Warning object.[]
{
  "status": "Approved",
  "document_type": "Passport",
  "document_subtype": "PASSPORT_GENERIC",
  "document_number": "AB1234567",
  "personal_number": "99999999R",
  "portrait_image": "https://<media-host>/.../portrait.jpg?signature=...",
  "front_image": "https://<media-host>/.../front.jpg?signature=...",
  "front_video": null,
  "back_image": "https://<media-host>/.../back.jpg?signature=...",
  "back_video": null,
  "full_front_image": "https://<media-host>/.../full_front.jpg?signature=...",
  "full_back_image": null,
  "front_image_camera_front": null,
  "back_image_camera_front": null,
  "front_image_camera_front_face_match_score": null,
  "back_image_camera_front_face_match_score": null,
  "front_image_quality_score": {
    "focus_score": 91.0,
    "brightness_score": 88.0,
    "brightness_issue": "ok",
    "is_document_fully_visible": true,
    "resolution_score": 95.0,
    "overall_score": 88.5
  },
  "back_image_quality_score": null,
  "date_of_birth": "1990-05-12",
  "age": 35,
  "expiration_date": "2032-05-11",
  "date_of_issue": "2022-05-11",
  "issuing_state": "ESP",
  "issuing_state_name": "Spain",
  "first_name": "María",
  "last_name": "García López",
  "full_name": "María García López",
  "gender": "F",
  "address": "Calle Mayor 1, 28001 Madrid",
  "formatted_address": "Calle Mayor 1, 28001 Madrid, Spain",
  "parsed_address": { "street_1": "Calle Mayor 1", "street_2": null, "city": "Madrid", "region": "Madrid", "postal_code": "28001", "country": "ES", "address_type": "Calle" },
  "place_of_birth": "Madrid",
  "marital_status": null,
  "nationality": "ESP",
  "extra_fields": {},
  "mrz": {
    "document_number": "AB1234567",
    "surname": "GARCIA",
    "given_names": "MARIA",
    "birth_date": "900512",
    "expiry_date": "320511"
  },
  "extra_files": [],
  "matches": [],
  "node_id": "first_id_verification",
  "warnings": []
}

NFC verification

Returned for each ePassport chip read against an ID document. Appears as nfc_verifications[] in GET /v3/session/{sessionId}/decision/ (one per parent KYC record). Source: kyc/serializers/epassport.py:121-139 (NFCV3Serializer, extends NFCV2Serializer at kyc/serializers/epassport.py:83-118).
FieldTypeNullableDescriptionExample
statusstringNoSee Status enum."Approved"
portrait_imagestring (URL)YesPresigned URL to the chip-extracted face image."https://<media-host>/.../nfc_portrait.jpg?..."
signature_imagestring (URL)YesPresigned URL to the chip-extracted signature image (when stored on the chip).null
chip_dataobjectYesPersonal data parsed from the chip’s Data Groups, flattened (kyc/utils/epassport.py:165-212): dgs (Data Groups read), surname, name, country, nationality, birth_date (YYYY-MM-DD), expiry_date (YYYY-MM-DD), sex (M/F), document_type (MRZ document code), document_number, optional_data, MRZ check digits (birth_date_hash, expiry_date_hash, document_number_hash, optional_data_hash, final_hash), mrz_string, mrz_type (TD1/TD2/TD3); plus place_of_birth and address (and full_name / full_name_non_latin for non-Latin names) when the chip carries DG11 — those keys are absent otherwise. null when the NFC step was skipped.{ "document_number": "AB1234567", "name": "MARIA" }
authenticityobjectNo{ sod_integrity, dg_integrity }. sod_integrity validates that the Document Security Object (SOD) signature chains to a valid issuing-country CSCA (and the DSC is neither revoked nor expired); dg_integrity validates that each Data Group hashes match the SOD. Both true means the chip is genuine and untampered.{ "sod_integrity": true, "dg_integrity": true }
certificate_summaryobjectYesSummary of the document-signer certificate (kyc/utils/epassport.py:338-348): issuer, subject, serial_number (integer), not_valid_before, not_valid_after (YYYY-MM-DD HH:MM:SS), plus a validation object { csca_verified, dsc_revoked, dsc_expired, csca_expired } (kyc/views/epassport.py:86).{ "issuer": "Common Name: CSCA SPAIN, Country: ES", "not_valid_after": "2031-02-18 10:21:11" }
node_idstring | nullYesWorkflow node identifier (V3)."first_nfc"
warningsarrayNoSee Warning object.[]
{
  "status": "Approved",
  "portrait_image": "https://<media-host>/.../nfc_portrait.jpg?signature=...",
  "signature_image": null,
  "chip_data": {
    "dgs": ["DG1", "DG2", "DG11"],
    "surname": "GARCIA LOPEZ",
    "name": "MARIA",
    "country": "ESP",
    "nationality": "ESP",
    "birth_date": "1990-05-12",
    "expiry_date": "2032-05-11",
    "sex": "F",
    "document_type": "P",
    "document_number": "AB1234567",
    "optional_data": "",
    "birth_date_hash": "4",
    "expiry_date_hash": "7",
    "document_number_hash": "3",
    "optional_data_hash": "",
    "final_hash": "8",
    "mrz_string": "P<ESPGARCIA<LOPEZ<<MARIA<<<<<<<<<<<<<<<<<<<<AB1234567ESP9005124F3205117<<<<<<<<<<<<<<08",
    "mrz_type": "TD3",
    "place_of_birth": "MADRID",
    "address": "CALLE MAYOR 1, MADRID"
  },
  "authenticity": { "sod_integrity": true, "dg_integrity": true },
  "certificate_summary": {
    "issuer": "Common Name: CSCA SPAIN, Organization: DIRECCION GENERAL DE LA POLICIA, Country: ES",
    "subject": "Common Name: DS n-eID SPAIN 2, Organizational Unit: PASSPORT, Organization: DIRECCION GENERAL DE LA POLICIA, Country: ES",
    "serial_number": 118120836164494130086420187336801405660,
    "not_valid_before": "2020-11-18 10:21:11",
    "not_valid_after": "2031-02-18 10:21:11",
    "validation": {
      "csca_verified": true,
      "dsc_revoked": false,
      "dsc_expired": false,
      "csca_expired": false
    }
  },
  "node_id": "first_nfc",
  "warnings": []
}

Liveness check

Returned per liveness session. Appears as liveness_checks[] in GET /v3/session/{sessionId}/decision/. Source: face/serializers/face.py:301-320 (LivenessV3Serializer, extends LivenessV2Serializer at face/serializers/face.py:216-298).
FieldTypeNullableDescriptionExample
statusstringNoSee Status enum."Approved"
methodstring (enum)YesACTIVE_3D, FLASHING, or PASSIVE (LivenessMethodChoices, common/config/choices.py:514-517). Passive runs when desktop sessions are allowed and the user is on a desktop."PASSIVE"
scorefloat (0-100)YesLiveness confidence, rounded to 2 decimals.92.41
reference_imagestring (URL)YesPresigned URL to the user’s reference face crop."https://<media-host>/.../reference.jpg?..."
video_urlstring (URL)YesPresigned URL to the liveness video (active mode only)."https://<media-host>/.../liveness.webm?..."
age_estimationfloatYesEstimated age (in years) of the largest face in the reference image.34.2
matchesarray of objectsNoCross-session face matches. Each item: { session_id, session_number, similarity_percentage, vendor_data, verification_date, user_details: { full_name, document_type, document_number }, match_image_url, status, is_blocklisted, is_allowlisted, api_service, source }. source is session, imported, or list_entry; match_image_url is presigned.[]
face_qualityfloat (0-100)YesPassive-liveness face-quality score (normalized to a percentage).87.50
face_luminancefloat (0-100)YesPassive-liveness face-luminance score (normalized from 0-255 to a percentage).54.12
node_idstring | nullYesWorkflow node identifier (V3)."first_liveness"
warningsarrayNoSee Warning object.[]
{
  "status": "Approved",
  "method": "PASSIVE",
  "score": 92.41,
  "reference_image": "https://<media-host>/.../reference.jpg?signature=...",
  "video_url": null,
  "age_estimation": 34.2,
  "matches": [],
  "face_quality": 87.50,
  "face_luminance": 54.12,
  "node_id": "first_liveness",
  "warnings": []
}

Face match

Returned per face-match comparison (typically the user’s liveness face against the document portrait). Appears as face_matches[] in GET /v3/session/{sessionId}/decision/. Source: face/serializers/face.py:367-389 (FaceMatchV3Serializer, extends FaceMatchV2Serializer at face/serializers/face.py:323-364).
FieldTypeNullableDescriptionExample
statusstringNoSee Status enum."Approved"
scorefloat (0-100)YesSimilarity, rounded to 2 decimals. When the provider returns only an unmatched_faces[].Confidence, it’s converted to 100 - confidence.97.83
source_image_session_idstring (UUID)YesThe session whose stored portrait supplied the source (reference) image — set in portrait-based flows (biometric authentication, or a portrait supplied at session creation). null when the reference is the document portrait from the same session.null
source_imagestring (URL)YesPresigned URL to the source (reference) image — usually the document portrait, or the stored portrait in biometric-authentication flows."https://<media-host>/.../source.jpg?..."
target_imagestring (URL)YesPresigned URL to the target (live face) image captured during liveness."https://<media-host>/.../target.jpg?..."
node_idstring | nullYesWorkflow node identifier (V3)."first_face_match"
warningsarrayNoSee Warning object.[]
{
  "status": "Approved",
  "score": 97.83,
  "source_image_session_id": null,
  "source_image": "https://<media-host>/.../source.jpg?signature=...",
  "target_image": "https://<media-host>/.../target.jpg?signature=...",
  "node_id": "first_face_match",
  "warnings": []
}
Returned by the standalone Face Search API (POST /v3/face-search/). Face Search never appears as a plural array in /v3/session/{sessionId}/decision/ — when persisted with save_api_request=true the session surfaces there as a FACE_SEARCH entry in features[] plus a liveness_checks[] item carrying the stored matches. Sources: apis/serializers/face_search.py:8-79 (FaceSearchResponseSerializer wrapping FaceSearchDetailsSerializer); match dicts built in face/utils/utils.py:869-884. Top-level response:
FieldTypeNullableDescriptionExample
request_idstring (UUID)NoThe persisted session id when save_api_request=true (usable with GET /v3/session/{sessionId}/decision/); otherwise a transient correlation UUID."4a1c2c4e-8b1b-4d6a-91b5-ee9a1f3a2c7f"
face_searchobjectNoThe search-details payload — see fields below.
vendor_datastringYesEchoed vendor_data from the request.null
metadataobjectYesEchoed metadata from the request.null
created_atstring (ISO 8601)NoServer-side request timestamp."2026-06-12T01:04:42.763237+00:00"
face_search object:
FieldTypeNullableDescriptionExample
statusstringNoDeclined only when a FACE_IN_BLOCKLIST or POSSIBLE_FACE_IN_BLOCKLIST warning fired; Approved otherwise — duplicate matches alone never decline (apis/views/face_search.py:242-248)."Approved"
total_matchesintegerNoNumber of returned matches in matches[] (0–5).1
matchesarray of face-search match objectsNoUp to 5 matches above the similarity floor, sorted by descending similarity (blocklisted entries first with search_type=blocklisted_or_approved).[…]
user_imageobjectNoDetection result for the submitted image: { entities: [{ bbox, confidence }], best_angle } — one entity per detected face.{ "entities": [{ "bbox": [40, 40, 120, 120], "confidence": 0.73 }], "best_angle": 0 }
warningsarray of objectsNoReduced warning shape for this standalone API — no node_id. The serializer contract declares { risk, additional_data, log_type, short_description, long_description } (apis/serializers/face_search.py:49-54); the runtime payload also carries feature, always "LIVENESS" (apis/views/face_search.py:332-341).[]

Face-search match object

FieldTypeNullableDescriptionExample
session_idstring (UUID)YesThe matched verification session. null when source is imported or list_entry."a3f2a6f1-…"
session_numberintegerYesConsole-friendly number of the matched session; null for non-session matches.1024
similarity_percentagefloat (0-100)NoSimilarity between the submitted face and the matched face.96.42
sourcestring (enum)NoWhere the matched face was enrolled from: session (verification session or saved standalone call), imported (direct user-profile face upload), list_entry (face attached to a list)."session"
vendor_datastringYesThe matched session’s vendor_data (or the imported profile’s)."user-12345"
verification_datestring (ISO 8601)YesWhen the matched face was captured; null for list_entry matches."2024-11-04T09:14:02Z"
user_detailsobjectYes{ full_name, document_type, document_number } from the matched session’s document verification; for imported matches only full_name is set; null when no identity data exists.{ "full_name": "María García López", "document_type": "Passport", "document_number": "AB1234567" }
match_image_urlstring (URL)NoMatched user’s reference face — presigned URL when save_api_request=true, raw storage path otherwise."https://<media-host>/.../matched.jpg?..."
statusstringYesThe matched session’s verification status (see Status enum); null for non-session matches."Approved"
is_blocklistedbooleanNoWhether the matched face is in your face blocklist.false
is_allowlistedbooleanNoWhether the matched face is in one of your allowlists.false
api_servicestring (enum)YesUppercase standalone API type of the matched session (e.g. PASSIVE_LIVENESS, FACE_MATCH); null for workflow sessions and non-session matches.null
{
  "request_id": "4a1c2c4e-8b1b-4d6a-91b5-ee9a1f3a2c7f",
  "face_search": {
    "status": "Approved",
    "total_matches": 1,
    "matches": [
      {
        "session_id": "a3f2a6f1-1c1c-4eec-8b69-1c1c2f3a2c7f",
        "session_number": 1024,
        "similarity_percentage": 96.42,
        "source": "session",
        "vendor_data": "user-12345",
        "verification_date": "2024-11-04T09:14:02Z",
        "user_details": {
          "full_name": "María García López",
          "document_type": "Passport",
          "document_number": "AB1234567"
        },
        "match_image_url": "https://<media-host>/.../matched.jpg?signature=...",
        "status": "Approved",
        "is_blocklisted": false,
        "is_allowlisted": false,
        "api_service": null
      }
    ],
    "user_image": {
      "entities": [
        {
          "bbox": [40, 40, 120, 120],
          "confidence": 0.732973
        }
      ],
      "best_angle": 0
    },
    "warnings": []
  },
  "vendor_data": null,
  "metadata": null,
  "created_at": "2026-06-12T01:04:42.763237+00:00"
}

AML screening

Returned per screened entity. Appears as aml_screenings[] in GET /v3/session/{sessionId}/decision/ for both KYC and KYB sessions. Source: aml/serializers/aml.py:63-85 (AMLV3Serializer, extends AMLV2Serializer at aml/serializers/aml.py:28-60).
FieldTypeNullableDescriptionExample
statusstringNoSee Status enum."Approved"
total_hitsintegerNoNumber of screening hits (always present, defaults to 0).2
entity_typestring (enum)Yesperson or company (EntityTypeChoices, common/config/choices.py:675-677)."person"
hitsarray of objectsNoOne entry per hit. Key fields: id, caption, match (bool), target (bool | null — whether the entity is the direct target of the listing), match_score (float 0-100 identity confidence), risk_score (float 0-100 entity risk), score (deprecated 0-1 float), datasets[] (e.g. PEP, PEP Level 1-4, Sanctions, Adverse Media, Warnings and Regulatory Enforcement, Fitness and Probity), properties (names, aliases, dates of birth, …), features, url, first_seen, last_seen, rca_name, risk_view, score_breakdown, pep_matches, sanction_matches, warning_matches, adverse_media_matches, adverse_media_details, linked_entities, additional_information, and review_status (Unreviewed, Confirmed Match, False Positive, Inconclusive — editable via the update-AML-hit-status endpoint, AMLHitStatusChoices).[…]
scorefloat (0-100)YesOverall screening score — the highest risk_score among hits not marked False Positive (aml/services/aml.py:832-842); 0 when every hit is a false positive. null until computed.42.7
screened_dataobjectYesSnapshot of the data sent to screening: full_name, nationality, date_of_birth, document_number.{ "full_name": "María García López", "date_of_birth": "1990-05-12" }
is_ongoing_monitoring_enabledbooleanNoWhether the entity is subscribed to ongoing-monitoring re-screens.false
next_ongoing_monitoring_bill_datestring (YYYY-MM-DD)YesComputed as last_aml_bill_date + 365 days when ongoing monitoring is enabled.null
node_idstring | nullYesWorkflow node identifier (V3)."first_aml"
warningsarrayNoSee Warning object.[]
{
  "status": "In Review",
  "total_hits": 1,
  "entity_type": "person",
  "hits": [
    {
      "id": "Q7XW3-aml-hit-1",
      "caption": "Maria Garcia Lopez",
      "match": true,
      "target": true,
      "match_score": 86.4,
      "risk_score": 42.7,
      "datasets": ["PEP Level 2"],
      "properties": {
        "name": ["María García López", "M. García"],
        "alias": ["Maria Garcia"],
        "birthDate": ["1990-05-12"]
      },
      "url": "https://example.org/registry/entities/Q7XW3",
      "first_seen": "2023-11-02T00:00:00Z",
      "last_seen": "2026-05-01T00:00:00Z",
      "review_status": "Unreviewed"
    }
  ],
  "score": 42.7,
  "screened_data": {
    "full_name": "María García López",
    "date_of_birth": "1990-05-12",
    "nationality": "ES",
    "document_number": "AB1234567"
  },
  "is_ongoing_monitoring_enabled": false,
  "next_ongoing_monitoring_bill_date": null,
  "node_id": "first_aml",
  "warnings": []
}

IP analysis

Returned per captured network location. Appears as ip_analyses[] in GET /v3/session/{sessionId}/decision/ for both KYC and KYB sessions. Source: kyc/serializers/location.py:196-243 (IPAnalysisSerializerV3).
FieldTypeNullableDescriptionExample
statusstringNoSee Status enum."Approved"
node_idstring | nullYesWorkflow node identifier (V3)."first_ip_analysis"
device_brandstringYesUser-agent-derived device brand."Apple"
device_modelstringYesDevice model."iPhone"
browser_familystringYesBrowser family."Mobile Safari"
os_familystringYesOS family."iOS"
platformstringYesHigh-level platform (mobile, desktop, tablet)."mobile"
device_fingerprintstringYesStable per-device fingerprint hash."f2a3…"
ip_countrystringYesCountry name resolved from the IP."Spain"
ip_country_codestring (ISO 3166-1 alpha-2)YesCountry code resolved from the IP."ES"
ip_statestringYesRegion / state resolved from the IP."Comunidad de Madrid"
ip_citystringYesCity resolved from the IP."Madrid"
latitudefloatYesIP-derived latitude.40.4168
longitudefloatYesIP-derived longitude.-3.7038
ip_addressstringYesThe captured IP address."203.0.113.42"
ispstringYesISP name."Telefonica de Espana"
organizationstringYesOrganization name (often equal to ISP)."Telefonica de Espana"
is_vpn_or_torbooleanYestrue when the IP belongs to a VPN, proxy, or Tor exit node.false
is_data_centerbooleanYestrue when the IP belongs to a known hosting / data-center ASN.false
time_zonestringYesIANA time-zone name."Europe/Madrid"
time_zone_offsetstringYesUTC offset."+02:00"
ipobjectNo{ location, distance_from_id_document, distance_from_poa_document }. location = { latitude, longitude }. Distances in km, null when either side is missing.{ "location": { "latitude": 40.4168, "longitude": -3.7038 }, "distance_from_id_document": 3.4, "distance_from_poa_document": 1.1 }
id_documentobjectNo{ location, distance_from_ip, distance_from_poa_document }. ID document location resolved from issuing_state and parsed address.{ "location": { "latitude": 40.4165, "longitude": -3.7026 }, "distance_from_ip": 3.4, "distance_from_poa_document": 4.0 }
poa_documentobjectNo{ location, distance_from_ip, distance_from_id_document }. POA address geocoded.{ "location": { "latitude": 40.4170, "longitude": -3.7040 }, "distance_from_ip": 1.1, "distance_from_id_document": 4.0 }
matchesarray of objectsNoCross-session IP/device matches. Each item: { session_id, session_number, vendor_data, verification_date, match_type, match_source, matched_value, status, is_blocklisted, api_service, source, device_info, location_info, confidence, match_mode }. match_type is ip_address or device_fingerprint; match_source is ip_address, persistent_id, legacy_fp, or recovered_high (recovered matches also carry recovery_similarity, tls_ja4_corroborated, recovery_gate_reason). Capped at 5 IP + 5 device matches.[]
warningsarrayNoSee Warning object.[]
{
  "status": "Approved",
  "node_id": "first_ip_analysis",
  "device_brand": "Apple",
  "device_model": "iPhone",
  "browser_family": "Mobile Safari",
  "os_family": "iOS",
  "platform": "mobile",
  "device_fingerprint": "f2a3c1de8b994a3f9e4cdf3a02b1a7c9",
  "ip_country": "Spain",
  "ip_country_code": "ES",
  "ip_state": "Comunidad de Madrid",
  "ip_city": "Madrid",
  "latitude": 40.4168,
  "longitude": -3.7038,
  "ip_address": "203.0.113.42",
  "isp": "Telefonica de Espana",
  "organization": "Telefonica de Espana",
  "is_vpn_or_tor": false,
  "is_data_center": false,
  "time_zone": "Europe/Madrid",
  "time_zone_offset": "+02:00",
  "ip": {
    "location": { "latitude": 40.4168, "longitude": -3.7038 },
    "distance_from_id_document": 3.4,
    "distance_from_poa_document": 1.1
  },
  "id_document": {
    "location": { "latitude": 40.4165, "longitude": -3.7026 },
    "distance_from_ip": 3.4,
    "distance_from_poa_document": 4.0
  },
  "poa_document": {
    "location": { "latitude": 40.4170, "longitude": -3.7040 },
    "distance_from_ip": 1.1,
    "distance_from_id_document": 4.0
  },
  "matches": [],
  "warnings": []
}

Proof of address

Returned per submitted address document. Appears as poa_verifications[] in GET /v3/session/{sessionId}/decision/. Source: poa/serializers/poa.py:212-227 (POAV3Serializer, extends POAV2Serializer at poa/serializers/poa.py:173-209).
FieldTypeNullableDescriptionExample
statusstringNoSee Status enum."Approved"
issuing_statestring (ISO 3166-1 alpha-3)YesCountry code of the document issuer."ESP"
document_typestringNoHigh-level type from PoaDocumentTypeChoices (common/config/choices.py:868-873): UTILITY_BILL, BANK_STATEMENT, GOVERNMENT_ISSUED_DOCUMENT, OTHER_POA_DOCUMENT. Falls back to UNKNOWN — never null."UTILITY_BILL"
document_subtypestringNoSubtype code from PoaDocumentSubtypeChoices (e.g. ELECTRICITY_BILL, WATER_BILL, ACCOUNT_STATEMENT). Falls back to UNKNOWN — never null."ELECTRICITY_BILL"
issuerstringYesName of the issuing entity."Iberdrola"
issue_datestring (YYYY-MM-DD)YesDocument issue date."2026-04-15"
expiration_datestring (YYYY-MM-DD)YesExpiration date printed on the document, when present.null
poa_addressstringYesRaw OCR-extracted address."Calle Mayor 1, 28001 Madrid"
poa_formatted_addressstringYesGeocoded/formatted address."Calle Mayor 1, 28001 Madrid, Spain"
poa_parsed_addressobjectYesStructured address (street_1, street_2, city, region, postal_code, country (alpha-2), address_type, document_location, …).{ "street_1": "Calle Mayor 1", "city": "Madrid", "postal_code": "28001" }
document_filestring (URL)YesPresigned URL to the uploaded document."https://<media-host>/.../poa.pdf?..."
document_languagestringYesDetected document language (ISO 639-1)."es"
document_metadataobjectYesFiltered metadata: file_size, content_type, creation_date, modified_date, creator, producer, software, encryption, is_signed, is_tampered, signature_info, exif_original_date, exif_digitized_date, processed_by_known_editor, has_different_creation_mod_date, overlay_manipulation.{ "file_size": 184221, "content_type": "application/pdf", "is_tampered": false }
extra_fieldsobjectNoBank-account fields (bank_account_number, bank_iban, bank_sort_code, bank_routing_number, bank_swift_bic, bank_branch_name, bank_branch_address), document_phone_number, additional_names, plus any custom keys persisted on the record.{ "bank_iban": null, "additional_names": [] }
name_on_documentstringYesName as it appears on the POA."María García López"
expected_details_addressstringYesAddress the customer typed during signup (verbatim)."Calle Mayor 1, Madrid"
expected_details_formatted_addressstringYesGeocoded expected address."Calle Mayor 1, 28001 Madrid, Spain"
expected_details_parsed_addressobjectYesStructured expected address.{ "city": "Madrid", "postal_code": "28001" }
name_match_score_expected_detailsfloat (0-100)YesFuzzy match between name_on_document and the name supplied at session creation.94.0
name_match_score_id_verificationfloat (0-100)YesFuzzy match between name_on_document and the verified ID’s full_name.100.0
extra_filesarray of strings (URL)NoPresigned URLs to additional uploaded files.[]
node_idstring | nullYesWorkflow node identifier (V3)."first_poa"
warningsarrayNoSee Warning object.[]
{
  "status": "Approved",
  "issuing_state": "ESP",
  "document_type": "UTILITY_BILL",
  "document_subtype": "ELECTRICITY_BILL",
  "issuer": "Iberdrola",
  "issue_date": "2026-04-15",
  "expiration_date": null,
  "poa_address": "Calle Mayor 1, 28001 Madrid",
  "poa_formatted_address": "Calle Mayor 1, 28001 Madrid, Spain",
  "poa_parsed_address": { "street_1": "Calle Mayor 1", "city": "Madrid", "postal_code": "28001", "country": "ES" },
  "document_file": "https://<media-host>/.../poa.pdf?signature=...",
  "document_language": "es",
  "document_metadata": {
    "file_size": 184221,
    "content_type": "application/pdf",
    "creation_date": "2026-04-15T08:11:32Z",
    "modified_date": "2026-04-15T08:11:32Z",
    "creator": "Iberdrola Billing",
    "producer": "Adobe PDF Library 15.0",
    "software": null,
    "encryption": null,
    "is_signed": true,
    "is_tampered": false,
    "signature_info": { "signer_name": "Iberdrola Clientes", "date": "2026-04-15T08:11:32Z" },
    "exif_original_date": null,
    "exif_digitized_date": null,
    "processed_by_known_editor": false,
    "has_different_creation_mod_date": false,
    "overlay_manipulation": null
  },
  "extra_fields": {
    "bank_account_number": null,
    "bank_iban": null,
    "bank_sort_code": null,
    "bank_routing_number": null,
    "bank_swift_bic": null,
    "bank_branch_name": null,
    "bank_branch_address": null,
    "document_phone_number": null,
    "additional_names": []
  },
  "name_on_document": "María García López",
  "expected_details_address": "Calle Mayor 1, Madrid",
  "expected_details_formatted_address": "Calle Mayor 1, 28001 Madrid, Spain",
  "expected_details_parsed_address": { "city": "Madrid", "postal_code": "28001", "country": "ES" },
  "name_match_score_expected_details": 94.0,
  "name_match_score_id_verification": 100.0,
  "extra_files": [],
  "node_id": "first_poa",
  "warnings": []
}

Phone verification

Returned per phone-verification attempt. Appears as phone_verifications[] in GET /v3/session/{sessionId}/decision/ for both KYC and KYB sessions. Source: phone/serializers/phone.py:251-266 (PhoneV3Serializer, extends PhoneV2Serializer at phone/serializers/phone.py:103-248).
FieldTypeNullableDescriptionExample
statusstringNoSee Status enum."Approved"
phone_number_prefixstringNoE.164 country prefix (with +)."+34"
phone_numberstringNoSubscriber number without the prefix."612345678"
full_numberstringNoThe full E.164 number (phone_number_prefix + phone_number)."+34612345678"
country_codestring (ISO 3166-1 alpha-2)YesCountry of the number."ES"
country_namestringYesLocalized country name."Spain"
carrierobjectNo{ name, type } where type is a LineTypeChoices value (common/config/choices.py:648-667): mobile, fixed_line, voip, isp, vpn, toll_free, premium_rate, satellite, pager, payphone, voice_mail, unknown, and other line classes.{ "name": "Movistar", "type": "mobile" }
is_disposablebooleanNotrue when the carrier marks the number as temporary/disposable.false
is_virtualbooleanNotrue when carrier.type is one of voip, isp, vpn.false
verification_methodstringNoChannel used to deliver the OTP (whatsapp, sms, …). Reads from the last send attempt’s actual_channel (falls back to the requested channel, then sms)."whatsapp"
verification_attemptsintegerNoTotal OTP send attempts (initial send plus resends).1
verified_atstring (ISO 8601)YesTimestamp the OTP was successfully entered."2026-05-17T10:14:02Z"
lifecyclearray of objectsNoChronological events: send attempts, delivery callbacks, code checks, and the final status event. Each event is { type, timestamp, details, fee }. Event types come from PhoneEventChoices.[…]
matchesarray of objectsNoCross-session phone-number matches. Each item: { session_id, session_number, vendor_data, verification_date, phone_number, status, is_blocklisted, api_service, source }. source is session or list_entry.[]
node_idstring | nullYesWorkflow node identifier (V3)."first_phone"
warningsarrayNoSee Warning object.[]
{
  "status": "Approved",
  "phone_number_prefix": "+34",
  "phone_number": "612345678",
  "full_number": "+34612345678",
  "country_code": "ES",
  "country_name": "Spain",
  "carrier": { "name": "Movistar", "type": "mobile" },
  "is_disposable": false,
  "is_virtual": false,
  "verification_method": "whatsapp",
  "verification_attempts": 1,
  "verified_at": "2026-05-17T10:14:02Z",
  "lifecycle": [
    {
      "type": "PHONE_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2026-05-17T10:13:51Z",
      "details": { "status": "Success", "reason": null, "channel": "whatsapp", "actual_channel": "whatsapp" },
      "fee": 0.04
    },
    {
      "type": "PHONE_DELIVERY_DELIVERED",
      "timestamp": "2026-05-17T10:13:52Z",
      "details": { "channel": "whatsapp", "status": "delivered" },
      "fee": 0
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2026-05-17T10:14:02Z",
      "details": { "code_tried": "482917", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "PHONE_VERIFICATION_APPROVED",
      "timestamp": "2026-05-17T10:14:02Z",
      "details": null,
      "fee": 0
    }
  ],
  "matches": [],
  "node_id": "first_phone",
  "warnings": []
}

Email verification

Returned per email-verification attempt. Appears as email_verifications[] in GET /v3/session/{sessionId}/decision/ for both KYC and KYB sessions. Source: email_verification/serializers/email.py:149-164 (EmailV3Serializer, extends EmailV2Serializer at email_verification/serializers/email.py:38-146).
FieldTypeNullableDescriptionExample
statusstringNoSee Status enum."Approved"
emailstringNoThe submitted email address."maria.garcia@example.com"
is_breachedbooleanNotrue when the email appears in a known data breach.false
breachesarray of objectsNoPer-breach detail when is_breached is true: { name, domain, logo_path, breach_date, description, is_verified, data_classes, breach_emails_count }.[]
is_disposablebooleanNotrue when the email belongs to a disposable-mail provider.false
is_undeliverablebooleanNotrue when SMTP delivery probing shows the inbox doesn’t accept mail.false
verification_attemptsintegerNoTotal OTP check attempts.1
verified_atstring (ISO 8601)YesTimestamp the OTP was successfully entered."2026-05-17T10:15:22Z"
lifecyclearray of objectsNoChronological events: send attempts, code checks, and the final status event. Each event is { type, timestamp, details, fee }. Event types come from EmailEventChoices.[…]
matchesarray of objectsNoCross-session email matches. Each item: { session_id, session_number, vendor_data, verification_date, email, status, is_blocklisted, api_service, source }. source is session or list_entry.[]
node_idstring | nullYesWorkflow node identifier (V3)."first_email"
warningsarrayNoSee Warning object.[]
{
  "status": "Approved",
  "email": "maria.garcia@example.com",
  "is_breached": false,
  "breaches": [],
  "is_disposable": false,
  "is_undeliverable": false,
  "verification_attempts": 1,
  "verified_at": "2026-05-17T10:15:22Z",
  "lifecycle": [
    {
      "type": "EMAIL_VERIFICATION_MESSAGE_SENT",
      "timestamp": "2026-05-17T10:15:11Z",
      "details": { "status": "Success", "reason": null },
      "fee": 0.03
    },
    {
      "type": "VALID_CODE_ENTERED",
      "timestamp": "2026-05-17T10:15:22Z",
      "details": { "code_tried": "739204", "status": "Approved" },
      "fee": 0
    },
    {
      "type": "EMAIL_VERIFICATION_APPROVED",
      "timestamp": "2026-05-17T10:15:22Z",
      "details": null,
      "fee": 0
    }
  ],
  "matches": [],
  "node_id": "first_email",
  "warnings": []
}

Database validation

Returned per database lookup run against the user’s submitted data. Appears as database_validations[] in GET /v3/session/{sessionId}/decision/. Source: database_validation/serializers/database_validation.py:21-142 (DatabaseValidationV3Serializer, extends DatabaseValidationV2Serializer).
FieldTypeNullableDescriptionExample
issuing_statestring (ISO 3166-1 alpha-3)YesCountry whose registry was queried."ESP"
validation_typestring (enum)NoHow the result was corroborated: one_by_one (single-service outcome), two_by_two (two or more distinct services independently full-matched the identification number), or not_enabled (the validator was skipped or no provider responded — a definitive no_match still yields one_by_one). Never null. Source: DatabaseValidationChoices (common/config/choices.py:1097-1100)."one_by_one"
screened_dataobjectNoThe data submitted to the registry. File fields (selfie, cnh_qr_code_image, document_image) are presigned at read time.{ "document_number": "99999999R", "date_of_birth": "1990-05-12" }
validationsarray of objectsNoOne entry per catalog service that produced a match. Each entry can include service_id, service_name, validation (provider verdict object), outcome_code, outcome_detail, and source_data (cleaned citizen profile: full_name, gender, date_of_birth, photo (presigned URL), signature (presigned URL), …).[…]
errorsarray of objectsYesPer-service errors when a lookup failed; the key is omitted entirely when empty. Each entry is the upstream service’s error object plus the service_id that produced it.[]
match_typestring (enum)YesAggregate match verdict across queried services: full_match, partial_match, or no_match (DatabaseValidationMatchTypeChoices, common/config/choices.py:1103-1106). null until evaluated."full_match"
statusstringNoSee Status enum."Approved"
node_idstring | nullYesWorkflow node identifier (V3)."first_db_validation"
warningsarrayNoSee Warning object.[]
{
  "issuing_state": "ESP",
  "validation_type": "one_by_one",
  "screened_data": {
    "document_number": "99999999R",
    "date_of_birth": "1990-05-12",
    "first_name": "María",
    "last_name": "García López"
  },
  "validations": [
    {
      "service_id": "esp_dni",
      "service_name": "Spain - DNI/NIE verification",
      "validation": { "is_valid": true, "match_score": 100 },
      "outcome_code": "MATCH",
      "outcome_detail": "All identifiers match the registry record.",
      "source_data": {
        "full_name": "María García López",
        "gender": "F",
        "date_of_birth": "1990-05-12",
        "photo": "https://<media-host>/.../registry_photo.jpg?signature=...",
        "signature": null
      }
    }
  ],
  "match_type": "full_match",
  "status": "Approved",
  "node_id": "first_db_validation",
  "warnings": []
}

Questionnaire response

Returned per questionnaire submission. Appears as questionnaire_responses[] in GET /v3/session/{sessionId}/decision/ for both KYC and KYB sessions. Source: questionnaires/serializers/questionnaire.py:591-597 (QuestionnaireResponseV3Serializer, extends QuestionnaireResponseSerializer at questionnaires/serializers/questionnaire.py:520-588).
FieldTypeNullableDescriptionExample
questionnaire_idstring (UUID)NoIdentifier of the questionnaire version that was answered."6a0f1c2c-…"
titlestringNoQuestionnaire name, as set in the Console."Customer risk profile"
descriptionstringYesQuestionnaire description."Short risk-profile questions."
languagesarray of stringsNoLanguage codes the questionnaire is published in.["en", "es"]
default_languagestringNoFallback language code."en"
is_activebooleanNoWhether this questionnaire version is the active one.true
is_simple_questionnairebooleanNotrue when the questionnaire has no branching (flat list).true
questionnaire_group_idstring (UUID)NoIdentifier shared across versions of the same questionnaire."a7c2c2c2-…"
versionintegerNoVersion number of the active template.3
statusstringNoOne of Approved, In Review, Not Finished (a questionnaire-level decline maps to In Review)."Approved"
published_atstring (ISO 8601)YesWhen the template was published."2026-01-12T11:00:00Z"
sectionsarray of objectsNoOrdered sections after applying graph traversal and visibility filtering. Each section is { title, description, items[] } (title/description come from the opening SECTION_HEADER, pre-translated). Each item is a form element (uuid, value (node id), element_type, is_required, title, description, placeholder, choices, max_files, required_if, repeatable_config, plus an answer field — null when unanswered, omitted on HEADING/PARAGRAPH/SEPARATOR layout items). File answers contain { files: [<presigned URL>, …] }.[…]
node_idstring | nullYesWorkflow node identifier (V3)."first_questionnaire"
{
  "questionnaire_id": "6a0f1c2c-3b7d-4d2c-9eb6-fdc6c7c92ef9",
  "title": "Customer risk profile",
  "description": "Short risk-profile questions.",
  "languages": ["en", "es"],
  "default_language": "en",
  "is_active": true,
  "is_simple_questionnaire": true,
  "questionnaire_group_id": "a7c2c2c2-1111-4d2c-9eb6-fdc6c7c92ef9",
  "version": 3,
  "status": "Approved",
  "published_at": "2026-01-12T11:00:00Z",
  "sections": [
    {
      "title": "Source of funds",
      "description": null,
      "items": [
        {
          "uuid": "4f1d5e2c-aaaa-4d2c-9eb6-fdc6c7c92ef9",
          "value": "q_source_of_funds",
          "element_type": "SINGLE_CHOICE",
          "is_required": true,
          "title": "What is your main source of funds?",
          "description": null,
          "placeholder": null,
          "choices": [
            { "label": "Salary", "value": "salary" },
            { "label": "Business income", "value": "business" },
            { "label": "Investments", "value": "investments" }
          ],
          "max_files": 1,
          "required_if": null,
          "repeatable_config": null,
          "answer": { "value": "salary" }
        }
      ]
    }
  ],
  "node_id": "first_questionnaire"
}

Age estimation

Returned by the standalone Age Estimation API (POST /v3/age-estimation/). The response carries a subset of Liveness check’s shape under an age_estimation envelope — status, method, score, age_estimation, warnings — plus a standalone-only user_image face-detection block; it does not include reference_image, video_url, matches, face_quality, or face_luminance. In workflow sessions there is no separate array — the estimated age surfaces as liveness_checks[].age_estimation in GET /v3/session/{sessionId}/decision/. Source: apis/serializers/age_estimation.py:50-55 (AgeEstimationResponseSerializer), envelope assembled in apis/views/age_estimation.py:138-174.
FieldTypeNullableDescriptionExample
request_idstring (UUID)NoPersisted session id when save_api_request=true (the default); otherwise a transient correlation UUID."3b1f1e2c-…"
age_estimationobjectNoResult envelope: status (Approved / Declined), method (always PASSIVE), score (liveness 0-100, nullable), age_estimation (predicted age in years of the largest face, nullable), user_image (entities[] with per-face age, bbox [x_min, y_min, x_max, y_max], confidence, gender; plus best_angle), warnings[].{ … }
vendor_datastringYesEchoed vendor_data from the request.null
metadataobjectYesEchoed metadata from the request.null
created_atstring (ISO 8601)NoServer-side request timestamp."2026-05-17T10:22:13.512941+00:00"
{
  "request_id": "3b1f1e2c-7777-4d2c-9eb6-fdc6c7c92ef9",
  "age_estimation": {
    "status": "Approved",
    "method": "PASSIVE",
    "score": 94.10,
    "age_estimation": 28.7,
    "user_image": {
      "entities": [
        { "age": 28.7, "bbox": [40, 40, 100, 100], "confidence": 0.72, "gender": "male" }
      ],
      "best_angle": 0
    },
    "warnings": []
  },
  "vendor_data": null,
  "metadata": null,
  "created_at": "2026-05-17T10:22:13.512941+00:00"
}

Biometric authentication

Biometric authentication runs the same Liveness + Face Match pipeline used in standard KYC, but configured to compare the captured face against an existing user’s reference image instead of a freshly-OCR’d document portrait. There is no dedicated serializer — GET /v3/session/{sessionId}/decision/ returns the standard Liveness check and Face match objects under liveness_checks[] and face_matches[]. The session’s workflow is configured with workflow_type = "biometric_authentication" (WorkflowTypeChoices, common/config/choices.py:636).
FieldTypeNullableDescriptionExample
liveness_checksarray of Liveness checkNoLiveness result for the authentication attempt.[ { "status": "Approved", … } ]
face_matchesarray of Face matchNoMatch result against the enrolled reference. source_image_session_id is set to the session’s own session_id — the supplied portrait_image is stored under the authentication session itself (face/views/face.py:656-659).[ { "status": "Approved", "source_image_session_id": "…", … } ]
statusstringNoTop-level session status (see Status enum)."Approved"
{
  "session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
  "status": "Approved",
  "liveness_checks": [
    {
      "status": "Approved",
      "method": "PASSIVE",
      "score": 95.10,
      "reference_image": "https://<media-host>/.../reference.jpg?signature=...",
      "video_url": null,
      "age_estimation": null,
      "matches": [],
      "face_quality": 91.20,
      "face_luminance": 53.10,
      "node_id": "biometric_auth_liveness",
      "warnings": []
    }
  ],
  "face_matches": [
    {
      "status": "Approved",
      "score": 98.42,
      "source_image_session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
      "source_image": "https://<media-host>/.../source.jpg?signature=...",
      "target_image": "https://<media-host>/.../target.jpg?signature=...",
      "node_id": "biometric_auth_face_match",
      "warnings": []
    }
  ]
}

KYB registry

Returned per registry-confirmed company in a KYB workflow. Appears as registry_checks[] in GET /v3/session/{sessionId}/decision/ for business sessions. Source: kyb/serializers/kyb.py:939-964 (RegistryCheckV3Serializer).
FieldTypeNullableDescriptionExample
statusstringNoSee Status enum."Approved"
node_idstring | nullYesWorkflow node identifier (V3)."first_registry"
data_resolvedbooleanNotrue when the registry fetch has completed (or is_from_registry is false, meaning the data was entered manually).true
companyobjectNoFull company payload — see Company object below.{ … }
ownership_structureobjectYesProvider-supplied ownership graph (nodes, edges, percentages). Free-form JSON.{ "nodes": [...], "edges": [...] }
warningsarrayNoSee Warning object.[]

Company object

From kyb/serializers/kyb.py:220-321 (KYBCompanyResponseSerializer).
FieldTypeNullableDescription
uuidstring (UUID)NoInternal company identifier.
node_idstring | nullYesWorkflow node identifier.
statusstringNoFeature status (FeatureStatusChoices).
registry_statusstringYesCompany status from the registry (active, dissolved, …).
data_resolvedbooleanNoSame definition as on the parent object.
company_namestringYesRegistered company name.
registration_numberstringYesRegistry identifier.
country_codestring (ISO 3166-1 alpha-2)YesCountry of incorporation.
regionstringYesISO 3166-2 subdivision when applicable (e.g. US-CA).
company_typestringYesLegal form (LLC, SL, …).
incorporation_datestring (YYYY-MM-DD)YesDate of incorporation.
registered_addressstringYesRegistered legal address.
tax_numberstringYesTax / VAT identifier.
risk_levelstringYesProvider-supplied risk rating.
verification_statusstringYesInternal verification status enum.
is_from_registrybooleanNotrue when sourced from the registry (vs. manual entry).
fetch_statusstringYespending, resolved, failed.
alternative_namesstringYesComma-separated alternative trade names.
nature_of_businessstringYesFree-text business activity description.
registered_capitalstringYesRegistered capital as a human-readable string.
registered_capital_amountstring (decimal)YesParsed registered capital amount.
registered_capital_currencystring (ISO 4217)YesCurrency code.
websitestring (URL)YesCompany website.
emailstringYesPublic contact email.
phonestringYesPublic contact phone.
legal_entity_identifierstringYesLEI when available.
location_of_registrationstringYesRegistry office / region.
financial_summaryobjectYesSnapshot of latest financial highlights when supplied by the registry.
officersarray of objectsNoB2C-safe officer list: { uuid, name, designation, role, nationality, is_active, kyc_status, kyc_session_url }.
beneficial_ownersarray of objectsNoB2C-safe UBO list: { uuid, name, first_name, last_name, entity_type, roles, ownership_min_shares, ownership_max_shares, is_active, kyc_status, kyc_session_url, effective_ownership_percent }.
addressesarray of objectsYesPer-address detail from the registry.
industriesarray of objectsYesSIC/NAICS-style classifications.
accountsarray of objectsYesFiled accounts metadata.
registry_dataobjectYesRaw registry payload (vendor-specific).
user_provided_dataobjectYesSnapshot of user-edited fields.
confirmed_by_user_atstring (ISO 8601)YesTimestamp the user confirmed the extracted data.
last_console_edit_atstring (ISO 8601)YesTimestamp of the last console edit.
is_editablebooleanNotrue while registry-sourced data can still be edited by the end user.
{
  "status": "Approved",
  "node_id": "first_registry",
  "data_resolved": true,
  "company": {
    "uuid": "b1f1e2c2-9999-4d2c-9eb6-fdc6c7c92ef9",
    "node_id": "first_registry",
    "status": "Approved",
    "registry_status": "active",
    "data_resolved": true,
    "company_name": "Sante Clinics SL",
    "registration_number": "B12345678",
    "country_code": "ES",
    "region": null,
    "company_type": "SL",
    "incorporation_date": "2018-03-22",
    "registered_address": "Calle Mayor 1, 28001 Madrid, Spain",
    "tax_number": "B12345678",
    "risk_level": "low",
    "verification_status": "verified",
    "is_from_registry": true,
    "fetch_status": "resolved",
    "alternative_names": "Sante Clinics",
    "nature_of_business": "Medical clinic operations",
    "registered_capital": "EUR 50,000",
    "registered_capital_amount": "50000.00",
    "registered_capital_currency": "EUR",
    "website": "https://santeclinics.com",
    "email": "info@santeclinics.com",
    "phone": "+34911223344",
    "legal_entity_identifier": null,
    "location_of_registration": "Registro Mercantil de Madrid",
    "financial_summary": null,
    "officers": [
      {
        "uuid": "c1f1e2c2-aaaa-4d2c-9eb6-fdc6c7c92ef9",
        "name": "María García López",
        "designation": "Administrador único",
        "role": "Director",
        "nationality": "ESP",
        "is_active": true,
        "kyc_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…"
      }
    ],
    "beneficial_owners": [
      {
        "uuid": "d1f1e2c2-bbbb-4d2c-9eb6-fdc6c7c92ef9",
        "name": "María García López",
        "first_name": "María",
        "last_name": "García López",
        "entity_type": "person",
        "roles": ["UBO"],
        "ownership_min_shares": "75.00",
        "ownership_max_shares": "75.00",
        "is_active": true,
        "kyc_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…",
        "effective_ownership_percent": 75.0
      }
    ],
    "addresses": [],
    "industries": [],
    "accounts": [],
    "registry_data": {},
    "user_provided_data": {},
    "confirmed_by_user_at": "2026-05-17T10:11:02Z",
    "last_console_edit_at": null,
    "is_editable": false
  },
  "ownership_structure": null,
  "warnings": []
}

KYB document

Returned per node that collects KYB supporting documents. Appears as document_verifications[] in GET /v3/session/{sessionId}/decision/ for business sessions — one entry per node_id, with items[] listing each uploaded document. Source: kyb/serializers/kyb.py:1053-1068 (DocumentVerificationV3Serializer); each item follows kyb/serializers/kyb.py:811-851 (KYBDocumentResponseSerializer).
FieldTypeNullableDescriptionExample
statusstringNoAggregate status across this node’s documents: Approved only when every pipeline document is approved; Declined if any is declined; In Review otherwise; Not Finished while pending. See Status enum."Approved"
node_idstring | nullYesWorkflow node identifier (V3)."first_kyb_documents"
itemsarray of KYB document item objectsNoOne entry per uploaded or requested document.[…]
groupsobjectNoPer-document-group counts: { <group_name>: { total, approved, pending, declined, in_review, other, missing } }.{ "incorporation_certificate": { "total": 1, "approved": 1, "pending": 0, "declined": 0, "in_review": 0, "other": 0, "missing": 0 } }
required_groupsarray of stringsNoDocument groups required by the workflow configuration.["incorporation_certificate", "shareholder_register"]
warningsarrayNoSee Warning object.[]

KYB document item object

FieldTypeNullableDescription
uuidstring (UUID)NoInternal document identifier.
document_typestringYesHigh-level group (incorporation_certificate, shareholder_register, …).
document_subtypestringYesProvider-specific subtype.
document_groupstringYesMirror of document_type (alias kept for clarity).
file_urlstring (URL)YesPresigned URL to the cleaned file.
original_filenamestringYesFilename as uploaded.
file_sizeintegerYesFile size in bytes.
statusstringNoPer-document status (FeatureStatusChoices).
created_atstring (ISO 8601)NoUpload timestamp.
cross_check_resultobjectYesCross-check verdict against registry / other docs.
document_metadataobjectYesSame filtered metadata shape as POA’s document_metadata.
descriptionstringYesReviewer- or system-supplied description.
is_requestedbooleanNotrue when the workflow expected this document.
ocr_dataobjectYesOCR-extracted fields when available.
is_console_uploadbooleanNotrue when the document was uploaded by a console reviewer (excluded from the aggregate verdict).
is_confirmedbooleanNotrue when the reviewer has explicitly confirmed the document.
{
  "status": "Approved",
  "node_id": "first_kyb_documents",
  "items": [
    {
      "uuid": "e1f1e2c2-cccc-4d2c-9eb6-fdc6c7c92ef9",
      "document_type": "incorporation_certificate",
      "document_subtype": "registro_mercantil_extract",
      "document_group": "incorporation_certificate",
      "file_url": "https://<media-host>/.../incorporation.pdf?signature=...",
      "original_filename": "incorporation_certificate.pdf",
      "file_size": 256412,
      "status": "Approved",
      "created_at": "2026-05-17T10:08:00Z",
      "cross_check_result": { "matches_registry_name": true, "matches_registration_number": true },
      "document_metadata": {
        "file_size": 256412,
        "content_type": "application/pdf",
        "is_signed": true,
        "is_tampered": false
      },
      "description": null,
      "is_requested": true,
      "ocr_data": { "company_name": "Sante Clinics SL", "registration_number": "B12345678" },
      "is_console_upload": false,
      "is_confirmed": true
    }
  ],
  "groups": {
    "incorporation_certificate": { "total": 1, "approved": 1, "pending": 0, "declined": 0, "in_review": 0, "other": 0, "missing": 0 }
  },
  "required_groups": ["incorporation_certificate", "shareholder_register"],
  "warnings": []
}

KYB key person

Returned per Key People node in a KYB workflow. Appears as key_people_checks[] in GET /v3/session/{sessionId}/decision/ for business sessions. Source: kyb/serializers/kyb.py:967-1050 (KeyPeopleCheckV3Serializer).
FieldTypeNullableDescriptionExample
statusstringNoSee Status enum."Approved"
node_idstring | nullYesWorkflow node identifier (V3)."first_key_people"
registryobjectNo{ officers[], beneficial_owners[] } extracted from the registry. Officers follow KYBPersonResponseSerializer (kyb/serializers/kyb.py:533-645); beneficial owners follow KYBBeneficialOwnerResponseSerializer (kyb/serializers/kyb.py:648-788, which adds date_of_birth, country_of_birth, email, company_name, registration_number, entity_type, roles, ownership_min_shares, ownership_max_shares, child_beneficial_owners, effective_ownership_percent). Both include per-party AML + KYC enrichment (aml_status, kyc_status, kyc_session_url, kyc_session_id, verification_workflow_type, verification_workflow_id, verification_workflow_label, verification_workflow_features, didit_internal_id, kyc_document_type, kyc_nationality, kyc_liveness_passed, kyc_verified_at, kyc_aml_categories, kyc_notification_sent_at).{ "officers": [...], "beneficial_owners": [...] }
submittedobjectNo{ parties[] } — entries the business confirmed / submitted via the key-people flow (BusinessParty rows with source=USER). Each party follows BusinessPartySubmissionResponseSerializer (kyb/serializers/party.py:146-194): uuid, entity_type, source, name, first_name, last_name, company_name, registration_number, email, nationality, phone_number, date_of_birth, position, custom_fields, is_active, is_skipped, requires_verification, roles[] ({ role, ownership_percent, voting_percent }), kyc_session_id, kyc_session_status, kyc_session_url, kyb_sub_session_id, kyb_sub_session_status, kyb_sub_session_url, verification_workflow_type, verification_workflow_id, verification_workflow_label, verification_workflow_features, didit_internal_id.{ "parties": [...] }
ubo_kyc_summaryobjectYesCounts across active UBOs with linked KYC: { total, approved, flagged, pending }. null when no active UBOs have KYC linked.{ "total": 2, "approved": 2, "flagged": 0, "pending": 0 }
warningsarrayNoSee Warning object.[]
{
  "status": "Approved",
  "node_id": "first_key_people",
  "registry": {
    "officers": [
      {
        "uuid": "c1f1e2c2-aaaa-4d2c-9eb6-fdc6c7c92ef9",
        "name": "María García López",
        "designation": "Administrador único",
        "role": "Director",
        "nationality": "ESP",
        "appointment_date": "2018-03-22",
        "termination_date": null,
        "is_active": true,
        "address": "Calle Mayor 1, 28001 Madrid",
        "aml_status": "Approved",
        "kyc_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…",
        "kyc_session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
        "verification_workflow_type": "kyc",
        "verification_workflow_id": "11111111-1111-1111-1111-111111111111",
        "verification_workflow_label": "KYB officer KYC",
        "verification_workflow_features": [
          { "feature": "ID_VERIFICATION", "status": "Approved" },
          { "feature": "LIVENESS", "status": "Approved" },
          { "feature": "FACE_MATCH", "status": "Approved" }
        ],
        "didit_internal_id": "user-12345",
        "kyc_document_type": "Passport",
        "kyc_nationality": "ESP",
        "kyc_liveness_passed": true,
        "kyc_verified_at": "2026-05-17T10:10:11Z",
        "kyc_aml_categories": [],
        "kyc_notification_sent_at": "2026-05-15T08:00:00Z"
      }
    ],
    "beneficial_owners": []
  },
  "submitted": {
    "parties": [
      {
        "uuid": "d1f1e2c2-bbbb-4d2c-9eb6-fdc6c7c92ef9",
        "entity_type": "person",
        "source": "USER",
        "name": "María García López",
        "first_name": "María",
        "last_name": "García López",
        "company_name": null,
        "registration_number": null,
        "email": "maria.garcia@example.com",
        "nationality": "ESP",
        "phone_number": null,
        "date_of_birth": "1990-05-12",
        "position": "Administrador único",
        "custom_fields": {},
        "is_active": true,
        "is_skipped": false,
        "requires_verification": true,
        "roles": [
          { "role": "UBO", "ownership_percent": 75.0, "voting_percent": null }
        ],
        "kyc_session_id": "9b1f1e2c-8888-4d2c-9eb6-fdc6c7c92ef9",
        "kyc_session_status": "Approved",
        "kyc_session_url": "https://verify.didit.me/s/…",
        "kyb_sub_session_id": null,
        "kyb_sub_session_status": null,
        "kyb_sub_session_url": null,
        "verification_workflow_type": "kyc",
        "verification_workflow_id": "11111111-1111-1111-1111-111111111111",
        "verification_workflow_label": "KYB officer KYC",
        "verification_workflow_features": [
          { "feature": "ID_VERIFICATION", "status": "Approved" },
          { "feature": "LIVENESS", "status": "Approved" }
        ],
        "didit_internal_id": "user-12345"
      }
    ]
  },
  "ubo_kyc_summary": { "total": 1, "approved": 1, "flagged": 0, "pending": 0 },
  "warnings": []
}

Status enum reference

Two related value spaces share the status field name. Every per-feature report object on this page uses the feature-level enum; the parent session’s top-level status uses the wider session enum.

Feature-level statuses

Used by every report object’s status field. Source: common/config/choices.py:343-348 (FeatureStatusChoices).
ValueMeaning
Not FinishedThe feature has been provisioned but the user has not completed it yet.
ApprovedThe feature passed all checks.
DeclinedThe feature failed at least one hard check (see warnings[] with log_type: "error").
In ReviewThe feature triggered soft-fail signals and is awaiting manual review (see warnings[] with log_type: "warning").
Resub RequestedA reviewer requested the user resubmit this feature.
Phone, email, and ID verification can additionally surface Expired when their step times out (PhoneStatusChoices at common/config/choices.py:377-382, EmailStatusChoices at common/config/choices.py:434-439).

Session-level statuses

Used by the parent session’s top-level status. Source: common/config/choices.py:106-117 (StatusChoices).
ValueMeaning
Not StartedThe session has been created but the user has not begun it.
In ProgressThe user has started the flow; result not yet finalized.
ApprovedThe session passed all checks.
DeclinedThe session failed at least one hard check.
In ReviewThe session is awaiting manual review.
ExpiredThe session expired before completion.
AbandonedThe user left the flow without completing it.
Kyc ExpiredThe KYC’s validity window elapsed (used in re-verification flows).
ResubmittedThe user resubmitted after a prior decline; this session is superseded by a newer one.
Awaiting UserThe system is waiting on a user-side action (e.g. OTP entry).
Terminal session values are Approved, Declined, In Review, Expired, Kyc Expired, and Abandoned. A session can reach its overall decision while an individual feature stays In Review.