Didit Standalone APIs API
The Standalone APIs API from Didit — 14 operation(s) for standalone apis.
The Standalone APIs API from Didit — 14 operation(s) for standalone apis.
openapi: 3.0.0
info:
version: 3.0.0
title: Didit Verification Billing Standalone APIs API
description: Identity verification API. Authenticate with x-api-key header.
servers:
- url: https://verification.didit.me
tags:
- name: Standalone APIs
paths:
/v3/id-verification/:
post:
summary: ID Verification (document OCR + fraud checks)
description: 'OCR an identity document and run document fraud checks in one call — returns the extracted holder fields, the parsed MRZ, an `Approved`/`Declined` `status`, and a `warnings` list explaining every issue found. Supports 14,000+ document types from 220+ countries and territories.
**How it works.** Send the document''s `front_image` (required) and, for two-sided documents, the `back_image`. Upload uncropped photos with all four corners of the document visible — the service detects, aligns, and crops the document itself, so do not pre-crop. The document is classified automatically (you never declare the country or document type), the visual zone is read with OCR, and the MRZ and any barcodes are decoded. Cross-checks then validate dates, number formats, and MRZ check digits, and compare the visual zone against the MRZ. With `perform_document_liveness=true`, the images are additionally screened for screen replays, printed copies, and portrait manipulation.
**Decision logic.** `status` is `Approved` unless at least one warning resolves to a decline. Fraud and hard-failure risks always decline: `DOCUMENT_EXPIRED`, `SCREEN_CAPTURE_DETECTED`, `PRINTED_COPY_DETECTED`, `PORTRAIT_MANIPULATION_DETECTED`, plus extraction failures (`NAME_NOT_DETECTED`, `DATE_OF_BIRTH_NOT_DETECTED`, `DOCUMENT_NUMBER_NOT_DETECTED`). (`PORTRAIT_IMAGE_NOT_DETECTED`, `COULD_NOT_DETECT_DOCUMENT_TYPE`, `INVALID_DATE`, and `MRZ_NOT_DETECTED` exist in workflow sessions but are never produced by this standalone endpoint.) Three risk groups are configurable per request via `invalid_mrz_action`, `inconsistent_data_action`, and `expiration_date_not_detected_action` (`DECLINE` or `NO_ACTION`). All other warnings (e.g. `POSSIBLE_DUPLICATED_USER`) are informational and never decline on their own. A document that cannot be processed at all returns `400` with `{"error": "COULD_NOT_RECOGNIZE_DOCUMENT"}`; a readable but problematic document returns `200` with `status: "Declined"` — always inspect `id_verification.status` and `id_verification.warnings`, not just the HTTP code.
**Billing.** Each `200` response consumes one ID Verification API credit (standalone APIs have no free tier). When the organization''s balance cannot cover the call, the endpoint returns `403` with the not-enough-credits error before any image processing.
**Session persistence (`save_api_request`, default `true`).** When `true`, the call is persisted as an API-type session: it appears in the Business Console, the returned `request_id` is a real session id you can pass to `GET /v3/session/{sessionId}/decision/`, the cropped document/portrait images are stored and returned as short-lived media URLs (`https://<media-host>/ocr/...`), and a `status.updated` webhook is emitted to your configured webhook endpoints. When `false`, nothing is stored, `request_id` is a one-off correlation UUID, and `portrait_image`/`front_image`/`back_image` are returned inline as base64-encoded JPEG strings.
**Sandbox.** Sandbox API keys skip all processing and billing: after request validation (malformed input still returns `400`), the endpoint returns a static `Approved` mock payload (a fictional "Sandbox User" USA identity card), no session is persisted, and no credits are consumed.
**Authentication.** Send your application''s API key in the `x-api-key` header. Missing or invalid credentials return `403` (`{"detail": "You do not have permission to perform this action."}`) — this API never returns `401`.
**Rate limit.** Shared write budget of 300 requests/min per API key across all POST/PATCH/DELETE endpoints; exceeding it returns `429`.'
operationId: post_v3id-verification
tags:
- Standalone APIs
parameters: []
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required:
- front_image
properties:
front_image:
type: string
format: binary
description: 'Front side of the identity document. Allowed extensions: `tiff`, `jpg`, `jpeg`, `png`, `webp`, `pdf`. Maximum upload size: **10 MB** (larger files are rejected with `400`). PDFs are rendered to an image before OCR; encrypted PDFs require `front_image_password`. Images are automatically compressed to ~0.5 MB and EXIF orientation is applied. Upload the full, uncropped capture with all four corners of the document visible.'
front_image_password:
type: string
description: Password to decrypt `front_image` when it is an encrypted PDF. Sending an encrypted PDF without (or with a wrong) password returns `400`.
writeOnly: true
back_image:
type: string
format: binary
description: Back side of the document — send it whenever the document has one (many ID cards carry the MRZ or a barcode on the back; omitting it simply leaves the MRZ and back-side fields empty in the response — this endpoint does not raise a missing-MRZ warning). Same format and size limits as `front_image`. When omitted, `back_image` and back-side fields are `null` in the response.
back_image_password:
type: string
description: Password to decrypt `back_image` when it is an encrypted PDF.
writeOnly: true
perform_document_liveness:
type: boolean
default: false
description: 'When `true`, also screens both images for presentation fraud: screen replays (`SCREEN_CAPTURE_DETECTED`), printed copies (`PRINTED_COPY_DETECTED`), and portrait manipulation (`PORTRAIT_MANIPULATION_DETECTED`). Any of these auto-declines. Adds latency, so enable it only when you need fraud screening.'
example: true
minimum_age:
type: integer
nullable: true
default: null
minimum: 1
maximum: 120
description: Accepted and validated (1–120) but **currently not applied** by this endpoint — it never produces a `MINIMUM_AGE_NOT_MET` warning from this field. Enforce age rules from the returned `date_of_birth`/`age`, or use a verification-session workflow with age restrictions.
expiration_date_not_detected_action:
type: string
enum:
- NO_ACTION
- DECLINE
default: NO_ACTION
description: 'What to do when no expiration date can be read (`EXPIRATION_DATE_NOT_DETECTED`). Default `NO_ACTION` because many identity documents print no expiry date. Note: a *detected and past* expiry date always declines (`DOCUMENT_EXPIRED`), regardless of this option.'
invalid_mrz_action:
type: string
enum:
- NO_ACTION
- DECLINE
default: DECLINE
description: What to do when the extracted MRZ fails check-digit validation (`MRZ_VALIDATION_FAILED`). A missing MRZ raises no warning on this endpoint. Only relevant for documents that carry an MRZ. `REVIEW` is not supported on this endpoint and returns `400`.
inconsistent_data_action:
type: string
enum:
- NO_ACTION
- DECLINE
default: DECLINE
description: 'What to do when extracted data is internally inconsistent: `DATA_INCONSISTENT`, `MRZ_AND_DATA_EXTRACTED_FROM_OCR_NOT_SAME` (visual zone disagrees with the MRZ), or `DOCUMENT_NAME_DIFFERENT_FROM_OTHER_APPROVED_DOCUMENTS`.'
preferred_characters:
type: string
enum:
- latin
- non_latin
default: latin
description: Preferred script for name/address fields on documents that print both Latin and non-Latin text (Arabic, Cyrillic, CJK, …). `latin` returns transliterated/Latin values; `non_latin` prefers the native script.
save_api_request:
type: boolean
default: true
description: When `true` (default), persists the call as an API-type session — visible in the Business Console, retrievable via `GET /v3/session/{sessionId}/decision/` using the returned `request_id`, announced through a `status.updated` webhook, and with document images returned as media URLs. When `false`, nothing is stored, `request_id` is a transient UUID, and images are returned inline as base64 JPEG strings.
example: true
vendor_data:
type: string
description: Optional opaque string (your internal user id, email, UUID…) stored on the persisted session and echoed back in the response. Use it to correlate API calls with your own records and to filter sessions later.
example: user-123
metadata:
type: object
additionalProperties: true
description: Optional JSON object stored with the session (when `save_api_request=true`) and echoed back in the response. In multipart requests, send it as a JSON-encoded string field (e.g. `metadata={"flow":"onboarding"}`) — it is parsed into an object.
example:
flow: onboarding
example:
front_image: (binary JPEG/PNG/PDF of the document front)
back_image: (binary JPEG/PNG/PDF of the document back)
perform_document_liveness: true
save_api_request: true
vendor_data: user-123
metadata:
flow: onboarding
responses:
'200':
description: 'Document processed. `id_verification.status` is `Approved` or `Declined`; every detected issue is itemized in `id_verification.warnings`. A problematic document still returns `200` with `status: "Declined"` — inspect the body, not just the HTTP code. When `save_api_request=true`, `request_id` is the persisted session id and image fields are short-lived media URLs; with `save_api_request=false` they are inline base64 JPEG strings.'
content:
application/json:
examples:
Approved:
summary: Two-sided ID card read cleanly (saved — images as media URLs)
value:
request_id: 11d219ed-d59c-4b1d-8d65-9b933f12d5b8
id_verification:
status: Approved
document_type: Identity Card
document_subtype: ID_CARD_GENERIC
document_number: CBX164224
personal_number: 20446581H
portrait_image: https://<media-host>/ocr/11d219ed-d59c-4b1d-8d65-9b933f12d5b8-portrait_image-8c2f.jpg?signature=...
front_image: https://<media-host>/ocr/11d219ed-d59c-4b1d-8d65-9b933f12d5b8-front_image-4a1e.jpg?signature=...
back_image: https://<media-host>/ocr/11d219ed-d59c-4b1d-8d65-9b933f12d5b8-back_image-77b0.jpg?signature=...
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: 78
brightness_score: 83.2
brightness_issue: ok
is_document_fully_visible: true
resolution_score: 40.7
overall_score: 70.2
back_image_quality_score:
focus_score: 100
brightness_score: 95.6
brightness_issue: ok
is_document_fully_visible: true
resolution_score: 43
overall_score: 84.4
date_of_birth: '1980-01-13'
age: 46
expiration_date: '2032-03-31'
date_of_issue: '2022-03-31'
issuing_state: ESP
issuing_state_name: Spain
first_name: Julio Francisco
last_name: Fores Sena
full_name: Julio Francisco Fores Sena
gender: M
address: Brda. Urb. El Cardonal 0052 52 Po3 B,Taco,San Cristobal De La Laguna,Santa Cruz De Tenerife
formatted_address: Av. el Cardonal, 52, b, 38108 La Laguna, Santa Cruz de Tenerife, Spain
place_of_birth: Valencia, Valencia
marital_status: UNKNOWN
nationality: ESP
extra_fields:
first_surname: Fores
second_surname: Sena
mrz:
surname: FORES SENA
name: JULIO FRANCISCO
country: ESP
nationality: ESP
birth_date: '800113'
expiry_date: '320331'
sex: M
document_type: ID
document_number: CBX164224
optional_data: 20446581H
optional_data_2: ''
birth_date_hash: '9'
expiry_date_hash: '8'
document_number_hash: '3'
final_hash: '3'
personal_number: 20446581H
warnings: []
errors: []
mrz_type: TD1
mrz_string: 'IDESPCBX164224320446581H<<<<<<
8001139M3203318ESP<<<<<<<<<<<3
FORES<SENA<<JULIO<FRANCISCO<<<'
mrz_key: CBX164224380011393203318
parsed_address:
street_1: Avenida el Cardonal 52
street_2: b
city: La Laguna
region: Canarias
country: ES
postal_code: '38108'
address_type: Avenida
formatted_address: Av. el Cardonal, 52, b, 38108 La Laguna, Santa Cruz de Tenerife, Spain
raw_results:
address_components:
- long_name: b
short_name: b
types:
- subpremise
- long_name: '52'
short_name: '52'
types:
- street_number
- long_name: Avenida el Cardonal
short_name: Av. el Cardonal
types:
- route
- long_name: La Laguna
short_name: La Laguna
types:
- locality
- political
- long_name: Spain
short_name: ES
types:
- country
- political
- long_name: '38108'
short_name: '38108'
types:
- postal_code
formatted_address: Av. el Cardonal, 52, b, 38108 La Laguna, Santa Cruz de Tenerife, Spain
geometry:
location:
lat: 28.4501161
lng: -16.3004407
location_type: ROOFTOP
types:
- street_address
- subpremise
document_location:
latitude: 28.4501161
longitude: -16.3004407
label: Spain Identity Card Address
is_verified: true
category: Residential
warnings: []
barcodes: []
vendor_data: user-123
metadata:
flow: onboarding
created_at: '2026-06-12T02:21:56.013573+00:00'
Declined - expired document:
summary: Front-only upload of an expired ID card
value:
request_id: f61681b8-9422-4378-ac3e-04c6a247fb45
id_verification:
status: Declined
document_type: Identity Card
document_subtype: ID_CARD_GENERIC
document_number: BNK123072
personal_number: 21771255F
portrait_image: https://<media-host>/ocr/f61681b8-9422-4378-ac3e-04c6a247fb45-portrait_image-1d9a.jpg?signature=...
front_image: https://<media-host>/ocr/f61681b8-9422-4378-ac3e-04c6a247fb45-front_image-5c2b.jpg?signature=...
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: 100
brightness_score: 95.7
brightness_issue: ok
is_document_fully_visible: true
resolution_score: 22.2
overall_score: 79.3
back_image_quality_score: null
date_of_birth: '1997-01-30'
age: 29
expiration_date: '2025-11-26'
date_of_issue: null
issuing_state: ESP
issuing_state_name: Spain
first_name: Lucia
last_name: Marin Castro
full_name: Lucia Marin Castro
gender: F
address: null
formatted_address: null
place_of_birth: null
marital_status: UNKNOWN
nationality: ESP
extra_fields:
first_surname: Marin
second_surname: Castro
mrz: {}
parsed_address: null
warnings:
- risk: DOCUMENT_EXPIRED
feature: ID_VERIFICATION
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.
barcodes: []
vendor_data: user-123
metadata: null
created_at: '2026-06-12T02:25:48.117204+00:00'
schema:
type: object
properties:
request_id:
type: string
format: uuid
description: Persisted session id when `save_api_request=true` (usable with `GET /v3/session/{sessionId}/decision/`); otherwise a transient correlation UUID.
id_verification:
type: object
properties:
status:
type: string
enum:
- Approved
- Declined
description: '`Approved` when no warning resolves to a decline; `Declined` otherwise — the `warnings` list explains why.'
document_type:
type: string
nullable: true
description: 'Detected document type display name: `Identity Card`, `Passport`, `Driver''s License`, `Residence Permit`, `Health Insurance Card`, or `Tax Card`. `null` when the document could not be classified.'
example: Identity Card
document_subtype:
type: string
nullable: true
description: Finer-grained subtype when available (e.g. `ID_CARD_GENERIC`, `EPASSPORT`).
example: ID_CARD_GENERIC
document_number:
type: string
nullable: true
example: CBX164224
personal_number:
type: string
nullable: true
description: Secondary personal/national number printed on some documents.
example: 20446581H
portrait_image:
type: string
nullable: true
description: Cropped portrait photo from the document. A short-lived media URL (`https://<media-host>/ocr/...`) when `save_api_request=true` (default); an inline base64-encoded JPEG string when `save_api_request=false`. `null` when no portrait was detected.
front_image:
type: string
nullable: true
description: Aligned crop of the document front. Media URL when saved, inline base64 JPEG otherwise.
back_image:
type: string
nullable: true
description: Aligned crop of the document back. `null` when no `back_image` was uploaded.
front_image_camera_front:
type: string
nullable: true
description: Always `null` on this endpoint (populated only in camera-capture verification sessions).
back_image_camera_front:
type: string
nullable: true
description: Always `null` on this endpoint.
front_image_camera_front_face_match_score:
type: number
nullable: true
description: Always `null` on this endpoint.
back_image_camera_front_face_match_score:
type: number
nullable: true
description: Always `null` on this endpoint.
front_image_quality_score:
type: object
nullable: true
description: Capture-quality diagnostics for the uploaded image (`null` when the side was not provided or scoring failed). All scores are 0–100.
properties:
focus_score:
type: number
format: float
description: Sharpness of the document crop (higher is sharper).
brightness_score:
type: number
format: float
description: Exposure quality (higher is better).
brightness_issue:
type: string
nullable: true
description: '`ok` when exposure is fine, otherwise the detected issue (e.g. too dark / too bright).'
is_document_fully_visible:
type: boolean
nullable: true
description: Whether all four corners of the document are inside the frame.
resolution_score:
type: number
format: float
description: Effective resolution of the document area.
overall_score:
type: number
format: float
description: Aggregate quality score.
back_image_quality_score:
type: object
nullable: true
description: Capture-quality diagnostics for the uploaded image (`null` when the side was not provided or scoring failed). All scores are 0–100.
properties:
focus_score:
type: number
format: float
description: Sharpness of the document crop (higher is sharper).
brightness_score:
type: number
format: float
description: Exposure quality (higher is better).
brightness_issue:
type: string
nullable: true
description: '`ok` when exposure is fine, otherwise the detected issue (e.g. too dark / too bright).'
is_document_fully_visible:
type: boolean
nullable: true
description: Whether all four corners of the document are inside the frame.
resolution_score:
type: number
format: float
description: Effective resolution of the document area.
overall_score:
type: number
format: float
description: Aggregate quality score.
date_of_birth:
type: string
format: date
nullable: true
example: '1980-01-13'
age:
type: integer
nullable: true
description: Holder age in years, computed from `date_of_birth`.
example: 46
expiration_date:
type: string
format: date
nullable: true
example: '2032-03-31'
date_of_issue:
type: string
format: date
nullable: true
example: '2022-03-31'
issuing_state:
type: string
nullable: true
description: Issuing country (ISO 3166-1 alpha-3).
example: ESP
issuing_state_name:
type: string
nullable: true
example: Spain
first_name:
type: string
nullable: true
example: Julio Francisco
last_name:
type: string
nullable: true
example: Fores Sena
full_name:
type: string
nullable: true
example: Julio Francisco Fores Sena
gender:
type: string
nullable: true
description: '`M`, `F`, or `null` when not printed/detected.'
example: M
address:
type: string
nullable: true
description: Address exactly as printed on the document.
formatted_address:
type: string
nullable: true
description: Geocoded, normalized version of `address`.
place_of_birth:
type: string
nullable: true
example: Valencia, Valencia
marital_status:
type: string
nullable: true
description: '`UNKNOWN` unless the document prints marital status.'
example: UNKNOWN
nationality:
type: string
nullable: true
description: Holder nationality (ISO 3166-1 alpha-3).
example: ESP
extra_fields:
type: object
nullable: true
additionalProperties: true
description: Document-specific extras that have no dedicated column (e.g. `first_surname`/`second_surname` on Spanish IDs, license classes on driving licenses).
mrz:
type: object
description: Parsed machine-readable zone. An **empty object** (`{}`) when the document has no MRZ or it could not be read — also check the `warnings` list in that case. Dates inside the MRZ use the raw `YYMMDD` format.
properties:
surname:
type: string
example: FORES SENA
name:
type: string
example: JULIO FRANCISCO
country:
type: string
description: Issuing country (ISO 3166-1 alpha-3).
example: ESP
nationality:
type: string
description: Holder nationality (ISO 3166-1 alpha-3).
example: ESP
birth_date:
type: string
description: Raw MRZ date of birth (`YYMMDD`).
example: '800113'
expiry_date:
type: string
description: Raw MRZ expiry date (`YYMMDD`).
example: '320331'
sex:
type: string
example: M
document_type:
type: string
description: MRZ document-type code (e.g. `ID`, `P`).
example: ID
document_number:
type: string
example: CBX164224
optional_data:
type: string
nullable: true
example: 20446581H
optional_data_2:
type: string
nullable: true
example: ''
birth_date_hash:
type: string
description: MRZ check digit for the birth date.
example: '9'
# --- truncated at 32 KB (418 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/didit/refs/heads/main/openapi/didit-standalone-apis-api-openapi.yml