> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Document AI Overview

> Collect up to 3 custom documents and extract the exact fields you define with AI, then cross-check them against other steps and your own rules.

export const AgentPromptAccordion = ({prompt, title = "AI Agent Integration Prompt"}) => {
  const [copied, setCopied] = React.useState(false);
  const handleCopy = e => {
    e.stopPropagation();
    if (!prompt) return;
    navigator.clipboard.writeText(prompt.trim()).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  };
  const agents = ["Claude Code", "Codex", "Cursor", "Devin", "Windsurf", "GitHub Copilot"];
  return <div className="didit-agent-card">
      {}
      <div className="didit-agent-titlebar">
        <div className="didit-agent-dots" aria-hidden="true">
          <span className="didit-agent-dot didit-agent-dot-red"></span>
          <span className="didit-agent-dot didit-agent-dot-yellow"></span>
          <span className="didit-agent-dot didit-agent-dot-green"></span>
        </div>
        <span className="didit-agent-filename">{title}</span>
        <button type="button" className={`didit-agent-copy ${copied ? "didit-agent-copy-copied" : ""}`} onClick={handleCopy} title="Copy prompt to clipboard" aria-label={copied ? "Copied!" : "Copy prompt to clipboard"}>
          {copied ? <>
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                <path d="M3 8.5l3.5 3.5L13 4" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
              <span>Copied</span>
            </> : <>
              <svg width="13" height="13" viewBox="0 0 16 16" fill="none">
                <rect x="5" y="5" width="9" height="9" rx="1.5" stroke="currentColor" strokeWidth="1.5" />
                <path d="M11 5V3.5A1.5 1.5 0 0 0 9.5 2h-6A1.5 1.5 0 0 0 2 3.5v6A1.5 1.5 0 0 0 3.5 11H5" stroke="currentColor" strokeWidth="1.5" />
              </svg>
              <span>Copy</span>
            </>}
        </button>
      </div>

      {}
      <pre className="didit-agent-body"><code>{prompt.trim()}</code></pre>

      {}
      <div className="didit-agent-footer">
        <span className="didit-agent-footer-label">Paste into</span>
        <div className="didit-agent-chips">
          {agents.map(name => <span key={name} className="didit-agent-chip">{name}</span>)}
        </div>
      </div>
    </div>;
};

Document AI lets you collect documents that don't fit a fixed template — proof of funds, payslips, source-of-wealth letters, tax statements, and anything else — and extract exactly the fields **you** define. You configure each document's on-screen title and description (automatically translated into every verification language) and the list of data points to read. Didit's AI extracts those fields, optionally cross-references them against other verification steps, and applies your rules to produce a status.

<AgentPromptAccordion
  title="Document AI Integration Prompt"
  prompt={`# Goal
Integrate Didit Document AI (configurable multi-document upload + AI field extraction + cross-checks) into your app.

# Setup (Business Console or POST /v3/workflows/)
Add the DOCUMENT_AI feature to your workflow and configure:
- document_ai_documents: up to 3 documents. Each has { document_key, title, description, fields[] }.
Each field is { key, name, instruction, type: "text" | "number" | "date", required, is_full_name }.
title and description are auto-translated into every verification language on save.
- is_full_name: optional boolean on a field. Marks the field whose value is compared automatically against the
verified subject: on a person (KYC) workflow the document holder's full name (the ID-verification name, or the
session's expected details), and on a business (KYB) workflow the verified company name (the registry-matched
company, or the session's expected company name). A low match below document_ai_name_match_score_threshold
triggers document_ai_name_mismatch_action. At most one field per document may set it, and it is optional — a
document may mark none (no name check runs).
- Basic rules (per-risk action DECLINE | REVIEW | NO_ACTION): document_ai_unreadable_document_action,
document_ai_missing_required_fields_action, document_ai_document_tampering_action,
document_ai_name_mismatch_action, document_ai_unsupported_file_action, document_ai_max_attempts_exceeded_action.
- document_ai_name_match_score_threshold (0-100), document_ai_max_retry_attempts (2-5).
- status_rules[]: custom rules on any extracted field. Reference an extracted field as document_ai.<field_key>
and cross-reference other steps with value_type:"field" (e.g. document_ai.account_holder equals kyc.full_name).

# Flow
1. Create a session — POST /v3/session/ with { workflow_id, vendor_data, callback }. See /sessions-api/create-session.
2. Open session.url for the user (or mount the Web/Mobile SDK). The user uploads each configured document.
3. The user uploads documents to POST /v3/document-ai/documents/ (handled by the hosted flow/SDK):
multipart/form-data with { document_key, document, locale? }, Session-Token auth.
Response: { valid?, next_step, document_ai_status, uploaded_document_keys[], required_document_keys[] }.
The step completes once every configured document_key is uploaded.
4. Fetch the decision — GET /v3/session/{sessionId}/decision/ or subscribe to session.status.updated.

# Decision surface
DOCUMENT_AI appears in the decision features[] array as { feature: "DOCUMENT_AI", node_id }.
Per-document statuses combine via precedence Declined > In Review > Approved.

# See also
- Report: /core-technology/document-ai/report-document-ai
- Rules & warnings: /core-technology/document-ai/warnings-document-ai
- Configure in the console: /console/workflows`}
/>

## How it works

<Steps>
  <Step title="Configure documents and fields" icon="sliders">
    In the workflow builder you define up to **3 documents**. For each document you set:

    | Setting                 | Description                                                                                                                                                                                                                                                                                                                                                                                              |
    | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | **Title & description** | Shown to the user on the upload screen. Entered once and **auto-translated** into every verification language.                                                                                                                                                                                                                                                                                           |
    | **Fields to extract**   | A list of typed fields — each with a name, an extraction instruction for the AI, a type (`text`, `number`, `date`), a required flag, and an optional **full name** marker.                                                                                                                                                                                                                               |
    | **Name field**          | Optionally mark one text field per document as the name to match. On a person (KYC) workflow it is the **full name**, compared against the verified identity; on a business (KYB) workflow it is the **company name**, compared against the verified company. `document_ai_name_mismatch_action` decides what happens on a mismatch. Optional — leave it unset to skip the name check for that document. |

    Start from a [template](#starter-templates) or build from scratch.
  </Step>

  <Step title="The user uploads documents" icon="cloud-arrow-up">
    The user uploads one file per configured document (PDF or image). Each upload is processed independently; the step completes once every required document has been provided.
  </Step>

  <Step title="AI extraction" icon="wand-magic-sparkles">
    Didit renders each document and runs a vision-language model with a schema built from your field definitions. Extracted values are returned typed (numbers as numbers, dates as `YYYY-MM-DD`) and stored per document. PDF/EXIF forensics run to detect manipulation.
  </Step>

  <Step title="Cross-reference & rules" icon="shield-check">
    Extracted fields can be cross-checked against other steps — for example, the document holder name against the verified ID, or any field against questionnaire answers — and against your **basic rules** and **custom status rules**. The resulting per-document statuses combine into the feature status.
  </Step>
</Steps>

## Starter templates

When you add a Document AI node you can start from a ready-made template that pre-fills the title, description, and typed fields. Customize anything afterward.

| Template                      | Typical fields                                        |
| ----------------------------- | ----------------------------------------------------- |
| **Proof of Funds**            | Account holder, balance, currency, statement date     |
| **Proof of Income (payslip)** | Employer, employee name, gross/net salary, pay period |
| **Source of Wealth**          | Source type, amount, date, institution                |
| **Tax Document**              | Taxpayer name, tax year, declared income, tax ID      |

## Cross-referencing other steps

Document AI fields are addressable as `document_ai.<field_key>` and can be compared against fields from other completed steps using a custom status rule with `value_type: "field"`. For example:

* `document_ai.account_holder` **equals** `kyc.full_name` — the document holder matches the verified identity.
* `document_ai.balance` **greater\_than** `50000` — flag high balances for review.

Matching rules fold into the decision using the platform precedence **Declined > In Review > Approved**, so a rule can raise severity but never override a stricter risk-driven status. See [Rules & warnings](/core-technology/document-ai/warnings-document-ai).

## Document requirements

| Requirement            | Detail                                                                     |
| ---------------------- | -------------------------------------------------------------------------- |
| **Documents per step** | Up to 3, each configured independently                                     |
| **Supported formats**  | PDF, JPG, JPEG, PNG, TIFF, WebP                                            |
| **Pages**              | Multi-page PDFs supported                                                  |
| **Quality**            | Original document or high-quality scan; no digital editing or manipulation |

<Note>
  Document AI performs unstructured-text reading, which introduces a few seconds of latency per document. Webhooks fire only when the entire workflow step completes — do not poll the decision endpoint faster than every 5 s during this window.
</Note>
