{
  "markdown": "# Didit MCP Server\n\nThe official [Model Context Protocol](https://modelcontextprotocol.io) server for [Didit](https://didit.me) — bring KYC, KYB, AML screening, transaction monitoring, biometrics, and full workspace operations to Claude, Cursor, VS Code, Windsurf, Zed, and any MCP client.\n\n- **130+ tools** across sessions, workflows, vendor users/businesses, transactions, the standalone verification APIs, lists, cases, reports, webhooks, and billing.\n- **Auth is \"Log in with Didit\" (OAuth 2.1 + PKCE)** — the MCP acts as the signed-in **user** with their role's permissions. There is **no API-key mode**: every tool calls the user-scoped console endpoints, which only accept a Bearer token.\n- Every tool calls a single Didit REST endpoint and returns the JSON verbatim.\n\n> Full documentation: **https://docs.didit.me/integration/mcp/overview**\n\n## Quick start\n\n### Hosted (recommended)\n\nNo install, no API key — point your client at the hosted URL and sign in via the browser:\n\n```\nhttps://mcp.didit.me/mcp\n```\n\n**Claude Code**\n\n```bash\nclaude mcp add --transport http didit https://mcp.didit.me/mcp\n```\n\n**Cursor** (`~/.cursor/mcp.json`)\n\n```json\n{ \"mcpServers\": { \"didit\": { \"url\": \"https://mcp.didit.me/mcp\" } } }\n```\n\n**Windsurf / Zed** (via the `mcp-remote` bridge)\n\n```json\n{ \"mcpServers\": { \"didit\": { \"command\": \"npx\", \"args\": [\"-y\", \"mcp-remote@latest\", \"https://mcp.didit.me/mcp\"] } } }\n```\n\nSee [per-client setup](https://docs.didit.me/integration/mcp/installation) for Claude Desktop and VS Code.\n\n## Authentication\n\nThe MCP is an OAuth 2.1 **resource server**; the Didit console (`business.didit.me`) is the **authorization server**. On first connect your client opens a browser, you **Log in with Didit** and approve the scopes, and the MCP then acts as **you** — across every organization you belong to, with your role's permissions. Tokens are short-lived and refreshed automatically.\n\nScopes: `didit:management` (workspace operations) and `didit:verification` (running checks). Your console **role** is enforced server-side on every call.\n\n> **There is no API-key mode.** Every tool targets the user-scoped console endpoints (`/organization/{org}/application/{app}/…`), which authorize a Bearer token with per-role privileges and reject `x-api-key`. (For raw REST access with an application API key — e.g. creating sessions from your backend — use the [REST API](https://docs.didit.me) directly, not this server.)\n\nSee [Authentication](https://docs.didit.me/integration/mcp/authentication).\n\n## Tools\n\n130+ tools, grouped by area. The full catalogue with read/write/destructive markers is in [`docs/TOOLS.md`](docs/TOOLS.md) and at [docs.didit.me](https://docs.didit.me/integration/mcp/tools). Highlights:\n\n- **Discovery & cross-app:** `didit_context_get`, `didit_session_search`, `didit_transaction_search`, `didit_vendor_user_search`, `didit_analytics` — aggregate across every org/app in one call.\n- **Sessions:** create, list, get decision, update status, reviews, bulk import.\n- **Verification APIs:** `didit_verify_id`, `didit_verify_aml`, `didit_verify_face_match`, `didit_verify_kyb_search`, …\n- **Workflows (incl. branching graphs):** `didit_workflow_search`, `didit_workflow_get_graph`, `didit_workflow_edit_graph` — build conditional/branching workflows (fuzzy-match conditions, Document-AI steps) by sending small ops; large feature configs are kept server-side, never resent. `didit_workflow_get_id_verification_methods_catalog` and `didit_workflow_get_kyb_registry_catalog` answer the server-driven questions a config write depends on (which countries offer non-doc lookup / wallets, which KYB data tiers and monitoring a country's registries sell).\n- **Compliance:** transaction monitoring, custom and preset rule management with backtesting, lists/blocklist/allowlist, cases, reports, audit logs, alerts.\n- **Workspace:** questionnaires, webhooks, members, billing, branding.\n\n### File inputs\n\nTools that consume files (face upload, ID/PoA/liveness/face/age verification, branding) accept the file in one of two forms:\n\n- **`*_path`** — an absolute path on the machine running the MCP server. Only works for local/stdio runs (e.g. Claude Code with a local server), where your files and the server share a filesystem.\n- **`*_base64`** — the file content inline, as raw base64 or a `data:` URL. Use this against the hosted endpoint; it is how the Didit Console Copilot passes chat attachments (its agent resolves attachment references like `att_1` into base64 before the call reaches the MCP).\n\nBoth forms enforce the same 15MB cap and magic-bytes allow-list (png/jpg/jpeg/webp/gif/bmp/ico/pdf). The hosted transport's JSON body limit is 25MB (`MCP_JSON_BODY_LIMIT`).\n\n## Run it yourself\n\nThe hosted server above is the easy path — no install. To self-host, clone this repo and run it with **Docker** or Node. It authenticates the user the same way (OAuth, or a user Bearer token for headless runs); there is no API-key mode.\n\n```bash\ngit clone https://github.com/didit-protocol/mcp.git && cd mcp\n\n# Docker (recommended) — serves /mcp and /healthz on port 3000\ndocker build -t didit-mcp . && docker run -p 3000:3000 --env-file .env didit-mcp\n\n# …or with Node\nnpm install && npm run build\nnode dist/http.js                                          # hosted HTTP/OAuth\nDIDIT_ACCESS_TOKEN=<user-access-token> node dist/index.js  # stdio (headless)\n```\n\nAll Didit base URLs and OAuth endpoints are environment variables with public defaults (`verification.didit.me`, `apx.didit.me`, `business.didit.me`) — override them for a private deployment. See [`ARCHITECTURE.md`](ARCHITECTURE.md) and [`.env.example`](.env.example) for the full reference.\n\n## Workflow feature configuration\n\nEvery workflow feature node takes a `config` object. The tables below are the complete\ncontract - what `didit_workflow_create`, `didit_workflow_update`, `didit_workflow_validate_graph`,\n`didit_workflow_set_graph` and `didit_workflow_edit_graph` accept, and what the API stores.\nA key that is not listed here is not part of the contract and is dropped silently on save.\n\n`didit_workflow_get_feature_config_schema` returns the same data as JSON at runtime.\n\n<!-- BEGIN GENERATED FEATURE CONFIG REFERENCE -->\n\n_Generated from `schema/feature-config-schema.json` (contract `sha256:200a66d7054aaf6cdddd94d7bd9c62050912862bf6e291908b667b20436ef4cd`, schema version 1), which is a copy of the artifact `service-didit-verification` generates from its feature-config serializers. Do not edit by hand — run `npm run schema:readme`._\n\n### AGE_ESTIMATION\n\nConfiguration for Age Estimation feature.\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `borderline_maximum_age_threshold` | integer \\| null | integer >=1 <=100 |  |\n| `borderline_minimum_age_threshold` | integer \\| null | integer >=1 <=100 |  |\n| `enable_id_verification_fallback` | boolean \\| null | boolean |  |\n| `external_capture_device_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when an external capture device is detected. |\n| `face_audio_recording_enabled` | boolean \\| null | boolean | Record the microphone during the selfie capture, so a reviewer can hear the session. Off by default. |\n| `face_liveness_duplicated_face_name_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a duplicate face is found under a different name. |\n| `face_liveness_flash_mode` | string \\| null | string |  |\n| `face_liveness_max_attempts` | integer \\| null | integer >=1 <=3 |  |\n| `face_liveness_method` | string \\| null | 'ACTIVE_3D'\\|'FLASHING'\\|'PASSIVE' |  |\n| `face_liveness_multiple_faces_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when more than one face is present in the capture. |\n| `face_liveness_possible_duplicated_face_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when this face matches a previously seen user. |\n| `face_liveness_score_decline_threshold` | number \\| null | number |  |\n| `face_liveness_score_review_threshold` | number \\| null | number |  |\n| `face_luminance_max_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the selfie is brighter than `face_luminance_max_threshold`. |\n| `face_luminance_max_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `face_luminance_min_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the selfie is darker than `face_luminance_min_threshold`. |\n| `face_luminance_min_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `face_privacy_mode_enabled` | boolean \\| null | boolean |  |\n| `face_quality_decline_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `face_quality_review_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `frame_injection_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when injected video frames are detected. |\n| `minimum_age_threshold` | integer \\| null | integer >=1 <=100 |  |\n| `screen_capture_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the selfie is a photo of a screen. |\n| `status_rules` | array | array |  |\n| `virtual_camera_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a virtual camera feed is detected. |\n\n### AML\n\nConfiguration for AML feature (used for both KYC AML and KYB Company AML).\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `aml_country_weight` | integer \\| null | integer >=0 <=100 |  |\n| `aml_dob_weight` | integer \\| null | integer >=0 <=100 |  |\n| `aml_match_score_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `aml_name_weight` | integer \\| null | integer >=0 <=100 |  |\n| `aml_score_approve_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `aml_score_review_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `case_blueprint` | uuid \\| null | uuid | Which case blueprint the automatically-created case is built from. Only meaningful with `create_cases_on_hit`; the account default is used when unset. |\n| `create_cases_on_hit` | boolean \\| null | boolean | Open a case automatically when the screening returns a hit, instead of leaving the hit to be triaged from the session. Off by default. |\n| `fallback_to_native` | boolean \\| null | boolean |  |\n| `is_aml_ongoing_monitoring_enabled` | boolean \\| null | boolean | Keep screening the PERSON after the session is approved, raising a new hit when they later appear on a watchlist. Off by default. |\n| `kyb_company_aml_country_weight` | integer \\| null | integer >=0 <=100 |  |\n| `kyb_company_aml_dob_weight` | integer \\| null | integer >=0 <=100 |  |\n| `kyb_company_aml_match_score_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `kyb_company_aml_name_weight` | integer \\| null | integer >=0 <=100 |  |\n| `kyb_enable_ongoing_monitoring` | boolean \\| null | boolean | The same, for the COMPANY on a KYB workflow. The two switches are independent. |\n| `kyb_score_approve_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `kyb_score_review_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `provider_key` | string \\| null | string |  |\n| `status_rules` | array | array |  |\n\n### DATABASE_VALIDATION\n\nConfiguration for Database Validation feature.\n> The node is opt-in and does nothing while `database_validation_countries` is empty - the editor blocks publishing in that state and the compliance check reports it as a gap. Place it after the step that produces its inputs (usually OCR), and use `database_validation_field_sources` only for inputs no upstream step can fill.\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `database_validation_countries` | json \\| null | {\"<ISO3>\": {\"services\": [\"<service_id>\", ...]}} | The databases to check, per country - this node runs NOTHING until at least one country carries at least one service id. Service ids come from the country's live catalog (e.g. `bra_cpf` for BRA); ids that do not belong to the named country, and countries with no live service, are dropped on save. The legacy `{\"<ISO3>\": \"one_by_one\"\\|\"two_by_two\"\\|\"not_enabled\"}` shape is still accepted and auto-expanded to that country's live services. |\n| `database_validation_field_sources` | json \\| null | {\"<db_validation_input_field>\": {\"source\": \"document_ai\"\\|\"questionnaire\"\\|\"expected_data\", \"key\": \"<docai field key>\\|<questionnaire node id>\\|expected_details.<field>\\|metadata.<key>\"}} | Where to read a database input that no earlier step in the graph can fill. `source` names the producer and `key` names the value inside it: a Document AI field key for `document_ai`, a questionnaire node id for `questionnaire`, and `expected_details.<field>` or `metadata.<key>` for `expected_data`. Exact-key matches against an upstream step resolve automatically and are deliberately not persisted, so renaming a Document AI field never freezes a stale mapping into the config. A malformed entry is dropped on save rather than rejected, which un-satisfies its service and drops it from the selection. |\n| `database_validation_no_match_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the database returns no match at all. |\n| `database_validation_not_applicable_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when no selected database covers the holder's country or document. |\n| `database_validation_partial_match_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the database matches some, but not all, of the submitted fields. |\n| `status_rules` | array | array |  |\n\n### DOCUMENT_AI\n\nConfiguration for the Document AI feature.\n> At most 3 documents per node, field keys unique within a document, and at most one field per document may set `is_full_name` (it is optional - a document may mark none).\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `document_ai_document_tampering_action` | string \\| null | 'REVIEW'\\|'DECLINE' | Verdict when the document looks tampered with. |\n| `document_ai_documents` | array | array |  |\n| `document_ai_max_attempts_exceeded_action` | string \\| null | 'REVIEW'\\|'DECLINE' | Verdict when the user runs out of `document_ai_max_retry_attempts`. |\n| `document_ai_max_retry_attempts` | integer \\| null | integer >=2 <=5 |  |\n| `document_ai_missing_required_fields_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a field marked `required` could not be extracted. |\n| `document_ai_name_match_score_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `document_ai_name_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the field flagged `is_full_name` disagrees with the verified identity's full name, scored against `document_ai_name_match_score_threshold`. |\n| `document_ai_unreadable_document_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the uploaded document cannot be read at all. |\n| `document_ai_unsupported_file_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the uploaded file type is not supported. |\n| `status_rules` | array | array |  |\n\n### EMAIL_VERIFICATION\n\nConfiguration for Email Verification feature.\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `breached_email_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the address appears in a known credential breach. |\n| `cross_org_fraud_email_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when this address was flagged as fraudulent by another organization in the network. |\n| `disposable_email_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the address belongs to a disposable-mail provider. |\n| `duplicated_email_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the address was already verified for this application. |\n| `email_alphanumeric_code` | boolean \\| null | boolean |  |\n| `email_code_size` | integer \\| null | integer >=4 <=8 |  |\n| `email_enrichment_enabled` | boolean \\| null | boolean |  |\n| `email_intelligence_score_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the enrichment score is worse than `email_intelligence_score_threshold`. |\n| `email_intelligence_score_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `email_max_check_attempts` | integer \\| null | integer >=1 <=5 |  |\n| `email_max_retries` | integer \\| null | integer >=1 <=5 |  |\n| `frequent_email_breach_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the address appears in many breaches. |\n| `only_corporate_emails_allowed` | boolean \\| null | boolean |  |\n| `recent_email_breach_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the address appears in a recent breach. |\n| `status_rules` | array | array |  |\n\n### FACE_MATCH\n\nConfiguration for Face Match feature.\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `face_match_eyes_covered_action` | string | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when calibrated evidence says the eyes region is covered in the selfie. NO_ACTION records evidence without changing Face Match; REVIEW sends Face Match to review; DECLINE declines it. The signal remains shadow-only until the region reports calibrated=true. |\n| `face_match_face_covered_action` | string | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when calibrated evidence says the face region is covered in the selfie. NO_ACTION records evidence without changing Face Match; REVIEW sends Face Match to review; DECLINE declines it. The signal remains shadow-only until the region reports calibrated=true. |\n| `face_match_max_attempts` | integer \\| null | integer >=1 <=3 |  |\n| `face_match_mouth_covered_action` | string | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when calibrated evidence says the mouth region is covered in the selfie. NO_ACTION records evidence without changing Face Match; REVIEW sends Face Match to review; DECLINE declines it. The signal remains shadow-only until the region reports calibrated=true. |\n| `face_match_not_computed_action` | string \\| null | 'REVIEW'\\|'DECLINE' | Verdict when no face-match score could be produced (missing portrait or selfie). |\n| `face_match_score_decline_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `face_match_score_review_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `status_rules` | array | array |  |\n\n### IP_ANALYSIS\n\nConfiguration for Device & IP Analysis feature.\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `automation_detected_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the session looks driven by automation rather than a person. |\n| `cross_org_fraud_device_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when this device was flagged as fraudulent by another organization in the network. |\n| `cross_org_fraud_ip_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when this IP was flagged as fraudulent by another organization in the network. |\n| `device_app_tampered_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the host application binary looks tampered with. |\n| `device_blocklist_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the device is on the organization's block list. |\n| `device_debugger_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a debugger is attached to the host application. |\n| `device_emulator_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the device is an emulator rather than real hardware. |\n| `device_hooking_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when runtime hooking or instrumentation is detected. |\n| `device_integrity_missing_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when no platform device-integrity attestation was returned. |\n| `device_rooted_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the device is rooted or jailbroken. |\n| `duplicated_device_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when this device was already used by another verified user. |\n| `duplicated_ip_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when this IP was already used by another verified user. |\n| `expected_ip_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the IP disagrees with the expected IP sent on the session. |\n| `ip_geofencing_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the connecting IP's country is not allowed by `ip_geofencing_by_country`. |\n| `ip_geofencing_by_country` | json \\| null | {\"<ISO3>\": {\"allowed\": true\\|false, \"states\"?: {\"<state_code>\": {\"allowed\": true\\|false}} \\| null}} | Country allow/deny rules for the connecting IP address, applied only while `is_ip_geofencing_enabled` is true. `allowed` is required and must be a real boolean; `states` is optional and null when the country needs no per-state rule. Countries that are not valid ISO3 are dropped on save. |\n| `ip_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the IP country disagrees with the document's issuing country. |\n| `is_ip_geofencing_enabled` | boolean \\| null | boolean |  |\n| `multiple_devices_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the session was driven from more than one device. |\n| `recovered_device_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the device reports a recovered or restored state. |\n| `status_rules` | array | array |  |\n| `vpn_detection_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the connection comes through a VPN, proxy or Tor exit. |\n\n### KYB_DOCUMENTS\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `kyb_document_age_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a document is older than its configured freshness window. |\n| `kyb_document_critical_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a document contradicts the registry on a critical company detail. |\n| `kyb_document_max_attempts_exceeded_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the user runs out of `kyb_document_max_retry_attempts`. |\n| `kyb_document_max_retry_attempts` | integer \\| null | integer >=1 <=5 |  |\n| `kyb_document_non_critical_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a document contradicts the registry on a minor detail. |\n| `kyb_document_subtype_config` | json \\| null | {\"<KYB_DOCUMENT_GROUP\\|KYB_DOCUMENT_SUBTYPE>\": {\"enabled\": true\\|false, \"max_age_days\": <0-3650>\\|-1\\|null}} | Per-group or per-subtype switch and freshness window. Keys must be a known KYB document group or subtype code. `max_age_days` is null for the default window, -1 for unlimited, or an integer 0-3650; anything else is rejected. |\n| `kyb_document_tampering_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a company document looks tampered with. |\n| `kyb_required_document_groups` | json \\| null | [\"<KYB_DOCUMENT_GROUP>\", ...] | The company paperwork to collect, as a list of document-GROUP codes - each group is satisfied by any one of the document types it covers. The KYB Documents feature refuses to save with an empty list: a node that requires nothing is the same as not having the node. |\n| `status_rules` | array | array |  |\n\n### KYB_KEY_PEOPLE\n\n> The workflow ids here point at separate KYC workflows: a KYB graph verifies the company, and the people behind it are verified by the linked person workflows.\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `kyb_corporate_ubo_verification_workflow` | uuid \\| null | uuid |  |\n| `kyb_key_people_company_fields` | json \\| null | [{\"key\": \"<field key>\", \"label\": \"<label>\", \"type\": \"text\"\\|\"number\"\\|\"date\"\\|\"phone\"\\|\"email\", \"required\": true\\|false, \"custom\": true\\|false}] | Which company details are collected for a CORPORATE key person. Same list-of-descriptors shape and same rules as `kyb_key_people_person_fields`. |\n| `kyb_key_people_document_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a key person's document disagrees with the details declared for them. |\n| `kyb_key_people_ownership_required` | boolean \\| null | boolean |  |\n| `kyb_key_people_person_fields` | json \\| null | [{\"key\": \"<field key>\", \"label\": \"<label>\", \"type\": \"text\"\\|\"number\"\\|\"date\"\\|\"phone\"\\|\"email\", \"required\": true\\|false, \"custom\": true\\|false}] | Which personal details are collected for an individual key person, as an ORDERED LIST of field descriptors (not a map). `key` is required and non-empty; `type` must be one of text, number, date, phone or email; `custom` marks a field the customer added rather than one of the built-ins. |\n| `kyb_key_people_prefill_from_registry` | boolean \\| null | boolean | Pre-fill the key-people list from the company registry result, so the customer confirms and corrects rather than typing every officer and shareholder in. |\n| `kyb_notify_parties_by_email` | boolean \\| null | boolean |  |\n| `kyb_officer_verification_workflow` | uuid \\| null | uuid |  |\n| `kyb_reject_if_ubo_rejected` | boolean \\| null | boolean |  |\n| `kyb_require_corporate_ubo_kyb` | boolean \\| null | boolean |  |\n| `kyb_require_officer_kyc` | boolean \\| null | boolean |  |\n| `kyb_require_ubo_kyc` | boolean \\| null | boolean |  |\n| `kyb_reuse_verified_individuals` | boolean \\| null | boolean |  |\n| `kyb_role_config` | json \\| null | {\"<role_key>\": {\"enabled\"?: true\\|false, \"require_kyc\"?: true\\|false, \"verification_workflow\"?: \"<workflow uuid>\"\\|null, \"allow_skip\"?: true\\|false}} | Per-role rules for the people behind the company. Role keys come from the existing config - never invent one. A role with `require_kyc: true` MUST also carry a `verification_workflow` (the uuid of a separate KYC workflow) or the save is rejected. A list of `{\"role\": ..., ...}` entries is accepted as an alternative to the map. |\n| `kyb_shareholder_ownership_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `kyb_shareholder_verification_workflow` | uuid \\| null | uuid |  |\n| `kyb_ubo_ownership_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `kyb_ubo_verification_workflow` | uuid \\| null | uuid |  |\n| `kyb_wait_for_all_ubos` | boolean \\| null | boolean |  |\n| `status_rules` | array | array |  |\n\n### KYB_REGISTRY\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `kyb_accepted_countries` | json \\| null | [\"<ISO2>\", ...] | Which company-registry countries the business may be incorporated in, as a list of ISO-2 codes (note: ISO-2 here, unlike the ISO-3 used by the OCR and IP allow-lists). An empty list or null accepts every supported registry. |\n| `kyb_manual_company_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the company could not be found in a registry and was entered by hand. |\n| `kyb_registry_countries_config` | json \\| null | {\"<ISO2>\": {\"enabled\": true\\|false, \"tier\": \"basic\"\\|\"shareholders\"\\|\"ubo\"}} | Per-country registry routing configuration. Each enabled country selects the data tier charged when a company is selected. Only tiers marked available by the pricing endpoint can be enabled. At least one country must be enabled: a registry check that searches nowhere is rejected. Manual company entry does not use this configuration and is billed at its own flat fee of USD 0.75 per company. |\n| `kyb_registry_fields_config` | json \\| null | {\"<registry_field>\": {\"enabled\"?: true\\|false, \"required\"?: true\\|false}} | Per-registry-field overrides controlling which company details are collected and which of them are mandatory. Field keys come from the backend's configurable-field catalog (registration_number, incorporation_date, legal_address, vat_number, alternative_names, tax_number, company_type, legal_entity_identifier, location_of_registration, nature_of_business, registered_capital_amount, registered_capital_currency, website, email, phone, ...); an unknown key, or any sub-key other than `enabled` / `required`, is rejected. |\n| `kyb_registry_monitoring_enabled` | boolean \\| null | boolean | Keep the COMPANY's registry record under continuous monitoring after a Shareholders or UBO result: changes of status, officers, ownership or address move the session back to review and fire a webhook. Only where the registry provider offers monitoring; USD 2.00 per company per year, cancellable at any time. Off by default. |\n| `kyb_vat_invalid_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the VAT number is rejected by the tax authority. |\n| `kyb_vat_unverified_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the VAT number could not be checked at all. |\n| `status_rules` | array | array |  |\n\n### LIVENESS\n\nConfiguration for Liveness feature.\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `cross_org_fraud_face_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Deprecated and no longer applied. It treated a face as if it carried a fraud verdict. Use `cross_org_identity_claim_pattern_action`. |\n| `cross_org_identity_claim_pattern_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when other organizations in the network recorded identity-claim events for this same person in which the claimed identity did not match. Review or no action only - a decline set here is downgraded to review. |\n| `external_capture_device_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when an external capture device is detected. |\n| `face_audio_recording_enabled` | boolean \\| null | boolean | Record the microphone during the selfie capture, so a reviewer can hear the session. Off by default. |\n| `face_liveness_duplicated_face_name_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a duplicate face is found under a different name. |\n| `face_liveness_flash_mode` | string \\| null | string |  |\n| `face_liveness_max_attempts` | integer \\| null | integer >=1 <=3 |  |\n| `face_liveness_method` | string \\| null | 'ACTIVE_3D'\\|'FLASHING'\\|'PASSIVE' |  |\n| `face_liveness_mode` | string \\| null | string |  |\n| `face_liveness_multiple_faces_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when more than one face is present in the capture. |\n| `face_liveness_possible_duplicated_face_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when this face matches a previously seen user. |\n| `face_liveness_score_decline_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `face_liveness_score_review_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `face_luminance_max_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the selfie is brighter than `face_luminance_max_threshold`. |\n| `face_luminance_max_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `face_luminance_min_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the selfie is darker than `face_luminance_min_threshold`. |\n| `face_luminance_min_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `face_privacy_mode_enabled` | boolean \\| null | boolean |  |\n| `face_quality_decline_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `face_quality_review_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `frame_injection_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when injected video frames are detected. |\n| `race_map_similarity_thresholds` | json | {\"<race>\": {\"possible\": 0-100, \"high\": 0-100}} | Per-demographic overrides of the face-similarity bands used against the allow-list and duplicate-face sets, so match rates stay even across groups. `possible` is the lower band (defaults to 62) and `high` the upper (68); a group with no entry uses those defaults. |\n| `screen_capture_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the selfie is a photo of a screen. |\n| `status_rules` | array | array |  |\n| `virtual_camera_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a virtual camera feed is detected. |\n\n### NFC\n\nConfiguration for NFC/ePassport feature.\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `allow_nfc_skip` | boolean \\| null | boolean |  |\n| `skip_nfc_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the user skips the NFC chip read (only reachable with `allow_nfc_skip`). |\n| `status_rules` | array | array |  |\n| `trust_anchor_missing_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when chip data-group hashes are intact but the certificate chain cannot be verified because the issuing country's CSCA trust anchor is not loaded. |\n| `unverified_chip_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the chip is read but its signature cannot be verified. |\n\n### OCR\n\nConfiguration for OCR/ID Verification feature.\n> Omitting `documents_allowed` stores the full country/document catalog, so the node accepts everything. Put OCR before any feature that reads identity data from the document (FACE_MATCH, NFC, DATABASE_VALIDATION).\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `age_restrictions_by_country` | json \\| null | {\"<ISO3>\": {\"minimum_age\": 1-120, \"maximum_age\": 1-120\\|null, \"states\"?: {\"<STATE_CODE>\": {\"minimum_age\": 1-120, \"maximum_age\": 1-120\\|null}}}} | Per-country (and optionally per-state) age gate. `minimum_age` is required for every country listed; `maximum_age` may be null. |\n| `cross_org_fraud_document_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when this document was flagged as fraudulent by another organization in the network. |\n| `document_audio_recording_enabled` | boolean \\| null | boolean | Record the microphone during document capture, so a reviewer can hear the session. Off by default. |\n| `document_blur_fields_by_country` | json \\| null | {\"<ISO3>\": [\"<blur_field_name>\", ...]} | Fields to blur out of the stored document image, per country. Only fields the country's document layout supports are accepted. |\n| `document_liveness_portrait_replace_decline_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `document_liveness_portrait_replace_review_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `document_liveness_printed_copy_decline_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `document_liveness_printed_copy_review_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `document_liveness_screen_replay_decline_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `document_liveness_screen_replay_review_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `document_or_personal_number_format_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the document or personal number does not match the country's expected format. |\n| `document_selfie_portrait_match_decline_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `document_selfie_portrait_match_review_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `document_without_portrait_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the scanned document family carries no portrait on any side. Node-config only - there is no account-level setting; the runtime default is REVIEW. |\n| `documents_allowed` | json \\| null | {\"<ISO3>\": {\"<DOC_CODE>\": {\"enabled\": 0\\|1, \"sides\"?: 1\\|2, \"subtypes\"?: [\"<SUBTYPE_CODE>\", ...]}}} | Which identity documents are accepted, per issuing country. Omit the key entirely to accept the full catalog; an empty object means the same thing. At least one document must end up enabled or the save is rejected. |\n| `duplicated_user_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the identity was already verified for this application. |\n| `expected_details_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the extracted identity contradicts the `expected_details` sent with the session. |\n| `expiration_date_not_detected_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when no expiry date could be read from the document. |\n| `id_document_quality_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `id_verification_max_retry_attempts` | integer \\| null | integer >=2 <=5 |  |\n| `id_verification_name_match_score_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `image_capture_methods_allowed` | array \\| null | [\"CAMERA_SCAN\" \\| \"UPLOAD\", ...] | Capture methods the end user may use for the document photo. Declared as a list of free strings, so the vocabulary is not in the field itself: CAMERA_SCAN (live capture) and UPLOAD (pick an existing file). An empty list falls back to the account default. |\n| `image_quality_too_low_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when overall document image quality is below the bar. |\n| `image_too_blurry_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the captured document image is too blurry to trust. |\n| `image_too_bright_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the captured document image is overexposed. |\n| `image_too_dark_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the captured document image is underexposed. |\n| `inconsistent_data_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the document's own fields contradict each other. |\n| `invalid_code_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a document check digit or barcode fails validation. |\n| `invalid_mrz_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the machine-readable zone is missing or inconsistent. |\n| `invalid_validation_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when a document authenticity validation fails. |\n| `is_age_restrictions_enabled` | boolean \\| null | boolean |  |\n| `is_document_selfie_portrait_match_enabled` | boolean \\| null | boolean |  |\n| `is_image_capture_review_screen_enabled` | boolean \\| null | boolean | Show the user a review screen after each document capture, letting them retake the photo before it is submitted. Off by default. |\n| `is_ocr_id_verification_data_review_enabled` | boolean \\| null | boolean | Let the user review and correct the extracted identity data before the step completes. Off by default. A correction is scored against `ocr_id_verification_data_review_critical_fields`, and a disagreement takes the critical or the minor action accordingly. The review still runs when the workflow includes NFC - a later chip read simply supersedes it. |\n| `maximum_age` | integer \\| null | integer >=1 <=120 |  |\n| `maximum_age_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the holder is older than `maximum_age`. |\n| `methods` | json \\| null | {\"<ISO3>\": {\"document\": {\"enabled\": bool}, \"id_lookup\": {\"enabled\": bool, \"max_attempts\": 1-5, \"skip_liveness_and_face_match\": bool, \"on_partial_match\": \"fallback_to_document\"\\|\"decline\", \"on_no_match\": \"fallback_to_document\"\\|\"decline\", \"on_provider_error\": \"fallback_to_document\"\\|\"decline\", \"response_fields\"?: [\"<field_key>\", ...]}, \"wallet\": {\"enabled\": bool, \"providers\": [\"<wallet_id>\", ...], \"on_failure\": \"fallback_to_document\"\\|\"decline\"}}} | Which ID verification methods each country may use: document capture (today's behaviour), non-doc lookup against a government or other authoritative source, and digital identity wallets. Omit the key, or a country, or a method, and that country is document only. Every method must be available for the country in the capability catalog (GET workflow-graph/id-verification-methods-catalog/); wallets are an accept-list with no ordering. Each fallback is `fallback_to_document` or `decline`; `max_attempts` (1-5, default 1) counts only lookups the registry answered. |\n| `minimum_age` | integer \\| null | integer >=1 <=120 |  |\n| `minimum_age_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the holder is younger than `minimum_age`. |\n| `ocr_id_verification_data_review_critical_fields` | array \\| null | [\"first_name\" \\| \"last_name\" \\| \"date_of_birth\" \\| ...] | Which extracted identity fields count as critical when the user edits the OCR result, so a mismatch takes the critical action rather than the minor one. |\n| `ocr_id_verification_data_review_critical_mismatch_action` | string \\| null | 'REVIEW'\\|'DECLINE' | Verdict when the user's edit disagrees with OCR on a critical field. |\n| `ocr_id_verification_data_review_minor_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the user's edit disagrees with OCR on a non-critical field. |\n| `status_rules` | array | array |  |\n| `unparsed_address_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the document address could not be parsed into components. |\n\n### PHONE_VERIFICATION\n\nConfiguration for Phone Verification feature.\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `code_size` | integer \\| null | integer >=4 <=8 |  |\n| `cross_org_fraud_phone_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when this number was flagged as fraudulent by another organization in the network. |\n| `disposable_number_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the number belongs to a disposable-number provider. |\n| `duplicated_phone_number_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the number was already verified for this application. |\n| `fallback_to_native` | boolean \\| null | boolean |  |\n| `high_risk_phone_action` | string \\| null | 'REVIEW'\\|'DECLINE' | Verdict when the number carries a high risk signal. |\n| `low_phone_trust_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the trust index is below `phone_trust_index_threshold`. |\n| `phone_enrichment_enabled` | boolean \\| null | boolean |  |\n| `phone_intelligence_score_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the enrichment score is worse than `phone_intelligence_score_threshold`. |\n| `phone_intelligence_score_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `phone_max_check_attempts` | integer \\| null | integer >=1 <=5 |  |\n| `phone_max_retries` | integer \\| null | integer >=1 <=5 |  |\n| `phone_shared_device_mode` | boolean \\| null | boolean |  |\n| `phone_trust_index_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `phone_type_risk_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the line type itself is considered risky. |\n| `phone_verification_countries` | json \\| null | {\"<ISO2>\": {\"<channel: sms\\|whatsapp\\|telegram\\|rcs\\|viber\\|zalo>\": {\"enabled\": true\\|false, \"max_retries\": <int>} \\| true\\|false}} | Which countries and delivery channels the one-time code may be sent through. It is a WHITELIST: a country absent from the map is not offered at all, and a channel absent from a listed country is skipped. `max_retries` overrides the node-level retry cap for that one channel. A bare boolean is the legacy form and still means enabled/disabled with the node-level cap. |\n| `provider_key` | string \\| null | string |  |\n| `recent_port_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the number was ported to a new carrier recently. |\n| `status_rules` | array | array |  |\n| `voip_number_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the number is VoIP rather than a real subscriber line. |\n\n### PROOF_OF_ADDRESS\n\nConfiguration for Proof of Address feature.\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `poa_document_authenticity_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the document fails authenticity checks. |\n| `poa_document_issues_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the document is damaged, cropped or otherwise unusable. |\n| `poa_documents_allowed` | json \\| null | {\"<ISO3>\": {\"<DOC_CODE>\": {\"enabled\": 0\\|1, \"sides\"?: 1\\|2, \"subtypes\"?: [\"<SUBTYPE_CODE>\", ...]}}} | Which proof-of-address documents are accepted, per issuing country. Same shape as OCR's `documents_allowed`; omit to accept the full catalog. |\n| `poa_issue_date_not_detected_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when no issue date could be read from the document. |\n| `poa_issuer_not_identified_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the issuing company or authority cannot be identified. |\n| `poa_languages_allowed` | json \\| null | {\"<language_code>\": 0\\|1} | Languages the proof-of-address document may be written in, as a flag per language code. Omit to accept every supported language. |\n| `poa_max_attempts_exceeded_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the user runs out of `poa_max_retry_attempts`. |\n| `poa_max_retry_attempts` | integer \\| null | integer >=2 <=5 |  |\n| `poa_name_match_score_threshold` | integer \\| null | integer >=0 <=100 |  |\n| `poa_name_or_address_mismatch_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the name or address on the document disagrees with the verified identity. |\n| `poa_unparsable_or_invalid_address_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the address on the document cannot be parsed or is not a real address. |\n| `poa_unsupported_document_type_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the uploaded document is not one of `poa_documents_allowed`. |\n| `poa_unsupported_language_action` | string \\| null | 'NO_ACTION'\\|'REVIEW'\\|'DECLINE' | Verdict when the document language is not one of `poa_languages_allowed`. |\n| `status_rules` | array | array |  |\n\n### QUESTIONNAIRE\n\nConfiguration for Questionnaire feature.\n\n| Key | Type | Accepts | Meaning |\n| --- | --- | --- | --- |\n| `questionnaire_uuid` | uuid \\| null | uuid |  |\n| `review_questionnaire_manually` | boolean \\| null | boolean |  |\n| `status_rules` | array | array |  |\n\n<!-- END GENERATED FEATURE CONFIG REFERENCE -->\n\n## Contributing\n\nThe feature-config contract above is generated - never hand-write a config key into a tool description. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the regeneration workflow and the checks that enforce it.\n\nIssues and PRs welcome — see [`CONTRIBUTING.md`](CONTRIBUTING.md). Run the hosted server at [`mcp.didit.me/mcp`](https://mcp.didit.me/mcp), or self-host from this repo (Docker / Node) — see [**Run it yourself**](#run-it-yourself).\n\n## License\n\n[MIT](LICENSE) © Didit Protocol\n",
  "bytes": 46978,
  "sha": "8cf13baa27c3ac55b4fc086b5a811769628860a79a478136f9801addc82d2f84",
  "repo_slug": "didit-protocol/mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_me_didit_mcp_5dc72ef4/readme"
}