> ## 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.

# Update Session Data

> Correct OCR-extracted KYC, POA, or KYB registry fields on existing sessions. Three PATCH endpoints, partial updates, webhook-emitting. Pay-per-call.

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>;
};

<AgentPromptAccordion
  title="Update Session Data Prompt"
  prompt={`Correct OCR-extracted fields on a finished Didit verification session — KYC identity, Proof of Address, or KYB company data.

There are THREE separate PATCH endpoints. Pick the one that matches the feature record you need to fix.

1) Update KYC identity data
PATCH https://verification.didit.me/v3/session/{session_id}/update-data/
- Auth: x-api-key (client) or user-auth token. Privilege: write:sessions.
- Session status must be one of Approved, Declined, In Review, Kyc Expired.
- Session must have a captured KYC feature record.
- Optional query / body param node_id targets a specific KYC instance in multi-step workflows (e.g. node_id=feature_ocr_2).
- Mutable fields: document_type ("P", "ID", "DL", "RP"), document_number, personal_number, date_of_birth (ISO date), date_of_issue, expiration_date, issuing_state (ISO 3166-1 alpha-3), first_name, last_name (full_name is auto-recomputed), gender ("M"|"F"|"X"), nationality, marital_status, place_of_birth, address (free-text — triggers re-geocoding), parsed_address (nested: address_type, city, region, street_1, street_2, postal_code, country [ISO 3166-1 alpha-2]), extra_fields (object — send null on a key to remove it).

2) Update Proof of Address (POA) data
PATCH https://verification.didit.me/v3/session/{session_id}/update-poa-data/
- Same auth + privilege + status gate as KYC.
- Session must have a captured POA record. node_id supported.
- Mutable fields: issuing_state (ISO-3), document_type ("utility_bill" | "bank_statement" | "lease_agreement"), document_language (ISO 639-1), issuer, issue_date (ISO date), poa_address (free-text — triggers re-geocoding), name_on_document, poa_parsed_address (same nested shape as KYC parsed_address), extra_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).

3) Update KYB company data
PATCH https://verification.didit.me/v3/session/{session_id}/kyb/{company_uuid}/update-data/
- Privilege: write:businesses (NOT write:sessions).
- No status gate — KYB company data can be corrected at any time.
- company_uuid must belong to that session_id (else 404).
- Mutable fields: company_name, registration_number, country_code (ISO-3), incorporation_date / registration_date / dissolution_date, tax_number, legal_address (lands on registered_address), company_type, registry_status ("active" | "dissolved" | "struck_off" | "inactive" | ...), verification_status ("verified" | "failed" | "unknown"), alternative_names, nature_of_business, registered_capital, website, email, phone, legal_entity_identifier, location_of_registration, control_scheme.
- Edits BOTH the canonical column and the raw registry_data JSON snapshot. user_provided_data is never touched.

Common contract for all three:
- PATCH semantics — only fields you send are updated. Omit a field to leave it as-is. Send null on an extra_fields key to remove it.
- A successful update fires a data.updated webhook (with session_kind: "user" or "business"). KYB company updates carry trigger: "console_registry_edit".
- The audit trail records changed fields, previous + new values, and (for user-auth) the actor email.

KYC curl example:
curl -X PATCH "https://verification.didit.me/v3/session/<SESSION_ID>/update-data/" \\
-H "x-api-key: <API_KEY>" \\
-H "Content-Type: application/json" \\
-d '{
"first_name": "John",
"last_name": "Doe",
"date_of_birth": "1990-01-01",
"issuing_state": "ESP",
"extra_fields": { "municipality": "Madrid" }
}'

Response: the updated record (KYC / POA / KYB company shape — same fields as in the session decision).

Failure modes:
- 401 — missing or invalid credentials.
- 403 — { "detail": "You do not have permission to perform this action." } — caller lacks write:sessions (KYC/POA) or write:businesses (KYB company).
- 404 — { "detail": "Not found." } — session, node_id, or company_uuid not found; OR the session does not carry the feature record you are patching (no KYC / no POA / no matching company).
- 400 — validation error: invalid country code, unknown parsed_address key, extra_fields not an object, etc. Returned as { "<field>": ["..."] }.

When NOT to use these endpoints:
- To ask the user to retake the document → use PATCH /v3/session/{id}/update-status/ with new_status: "Resubmitted" (see /sessions-api/update-status).
- To change entity-level data → use /v3/users/{vendor_data}/ or /v3/businesses/{vendor_data}/.
- To patch Key People — no public API; submitted through the hosted flow.

Side effects:
- Changes to KYC name / DOB / nationality can re-trigger AML if AML was still running.
- Changes to address / poa_address re-run geocoding asynchronously (failures swallowed — they never fail the update).

For end-to-end Didit integration, paste in the full prompt at /integration/integration-prompt.`}
/>

Sometimes OCR misreads an ID, a utility bill, or a registry entry. Didit exposes three PATCH endpoints you can call to correct the extracted data without having to rerun the whole verification.

| Endpoint                                                                             | Use when                                                                                                             |
| ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| [`PATCH /v3/session/{id}/update-data/`](#update-kyc-identity-data)                   | Fix values extracted from an ID document on a **User Verification (KYC)** session                                    |
| [`PATCH /v3/session/{id}/update-poa-data/`](#update-proof-of-address-poa-data)       | Fix values extracted from a utility bill / bank statement / lease agreement on a **User Verification (KYC)** session |
| [`PATCH /v3/session/{id}/kyb/{company_uuid}/update-data/`](#update-kyb-company-data) | Fix registry-extracted fields on a **Business Verification (KYB)** session                                           |

All three accept your **client API key** or a **user authorization header**, and all three emit a `data.updated` webhook on success so your system and downstream analytics stay in sync.

## Shared requirements

* **Authorization** — client API key (standard `x-api-key` / `Authorization` bearer) or user-auth token.
* **Privilege** —
  * KYC and POA: `write:sessions`
  * KYB company: `write:businesses`
* **Session status** (KYC / POA only) — must be one of `APPROVED`, `DECLINED`, `IN_REVIEW`, or `KYC_EXPIRED`. Sessions that haven't reached a reviewable state cannot be patched. KYB company updates have no status gate.
* **Feature record must exist** — you can only patch KYC fields if the session captured a KYC, POA fields if it captured a POA, and KYB company fields if the session has a registry check.
* **Partial updates** — only fields you include are changed. Omit a field to leave it as-is. Send `null` to clear an `extra_fields` key.
* **Webhooks** — a successful update fires `data.updated` with `session_kind: "user"` or `"business"`, and the session's audit trail records which specific fields changed and who changed them.

## Update KYC identity data

**`PATCH /v3/session/{sessionId}/update-data/`**

Patch any field extracted from the ID document. Supports graph-based multi-instance workflows via an optional `node_id` query parameter or body field — target a specific KYC record when a single session has multiple KYC steps.

### Mutable fields

| Field                               | Notes                                                                                                        |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `document_type`                     | ISO document code — `P` (passport), `ID`, `DL`, `RP`.                                                        |
| `document_number`                   | The printed document number.                                                                                 |
| `personal_number`                   | Personal / tax ID number when printed on the document.                                                       |
| `date_of_birth`                     | ISO 8601 date.                                                                                               |
| `date_of_issue` / `expiration_date` | ISO 8601 dates.                                                                                              |
| `issuing_state`                     | Issuing country, ISO 3166-1 alpha-3.                                                                         |
| `first_name` / `last_name`          | `full_name` is auto-recomputed from these two.                                                               |
| `gender`                            | `M`, `F`, or `X` when present.                                                                               |
| `nationality`                       | Free text.                                                                                                   |
| `marital_status`                    | Free text.                                                                                                   |
| `place_of_birth`                    | Free text.                                                                                                   |
| `address`                           | Free-text address from the document. Triggers re-geocoding.                                                  |
| `parsed_address`                    | Structured address — see the nested shape below.                                                             |
| `extra_fields`                      | Arbitrary extra fields from the ID (e.g. `blood_group`, `municipality`). Send `null` for a key to remove it. |

`parsed_address` only accepts these nested keys: `address_type`, `city`, `region`, `street_1`, `street_2`, `postal_code`, `country` (ISO 3166-1 **alpha-2**).

### Example

```bash theme={null}
curl -X PATCH "https://verification.didit.me/v3/session/4c5c7f3a.../update-data/" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "John",
    "last_name": "Doe",
    "date_of_birth": "1990-01-01",
    "issuing_state": "ESP",
    "extra_fields": { "municipality": "Madrid" }
  }'
```

For a multi-instance graph workflow, add `?node_id=feature_ocr_2` to the URL (or pass `"node_id": "feature_ocr_2"` in the body) to target a specific KYC record.

## Update Proof of Address (POA) data

**`PATCH /v3/session/{sessionId}/update-poa-data/`**

Patch fields extracted from a proof-of-address document. Same status gates and privilege as KYC updates. Also supports `node_id` for multi-instance workflows.

### Mutable fields

| Field                | Notes                                                                                                                                                                                                                                             |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `issuing_state`      | Country that issued the document, ISO 3166-1 alpha-3.                                                                                                                                                                                             |
| `document_type`      | e.g. `utility_bill`, `bank_statement`, `lease_agreement`.                                                                                                                                                                                         |
| `document_language`  | ISO 639-1 language of the document.                                                                                                                                                                                                               |
| `issuer`             | Utility company, bank, landlord, etc.                                                                                                                                                                                                             |
| `issue_date`         | ISO 8601 date.                                                                                                                                                                                                                                    |
| `poa_address`        | Address as printed on the document (free-text). Triggers re-geocoding.                                                                                                                                                                            |
| `name_on_document`   | Full name printed on the document.                                                                                                                                                                                                                |
| `poa_parsed_address` | Structured address — same nested shape as KYC `parsed_address`.                                                                                                                                                                                   |
| `extra_fields`       | Document-specific fields — bank details (`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` (list or `null`). |

### Example

```bash theme={null}
curl -X PATCH "https://verification.didit.me/v3/session/4c5c7f3a.../update-poa-data/" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "document_type": "utility_bill",
    "issuer": "Iberdrola",
    "issue_date": "2026-03-15",
    "name_on_document": "Jane Doe",
    "poa_parsed_address": {
      "street_1": "Calle Mayor 10",
      "city": "Madrid",
      "postal_code": "28013",
      "country": "ES"
    }
  }'
```

## Update KYB company data

**`PATCH /v3/session/{sessionId}/kyb/{companyUuid}/update-data/`**

Correct registry-extracted fields on a KYB company. The endpoint edits **both** the canonical company columns and the raw `registry_data` snapshot, so the "Extracted from Registry" view in the console reflects your corrections. `user_provided_data` — what the end user confirmed in the hosted flow — is not modified. `last_console_edit_at` is stamped, and a `data.updated` webhook fires with `trigger: "console_registry_edit"`.

### Requirements

* **Privilege** — `write:businesses` (different from the KYC / POA privilege).
* The `companyUuid` in the URL must belong to the given `sessionId`, otherwise you get a 404.
* No session status gate — KYB company data can be corrected at any time.

### Mutable fields

| Field                                                           | Notes                                                                                |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `company_name`                                                  | Legal name.                                                                          |
| `registration_number`                                           | Official registration number.                                                        |
| `country_code`                                                  | Country of incorporation, ISO 3166-1 alpha-3.                                        |
| `incorporation_date` / `registration_date` / `dissolution_date` | ISO 8601 dates.                                                                      |
| `tax_number`                                                    | Tax identification number.                                                           |
| `legal_address`                                                 | Alias for `registered_address` — lands on the canonical `registered_address` column. |
| `company_type`                                                  | Ltd / LLC / PLC / SA / GmbH / SL etc.                                                |
| `registry_status`                                               | `active`, `dissolved`, `struck_off`, `inactive`, etc.                                |
| `verification_status`                                           | `verified`, `failed`, `unknown`.                                                     |
| `alternative_names`                                             | Trade names, former names, DBAs.                                                     |
| `nature_of_business`                                            | Short description.                                                                   |
| `registered_capital`                                            | Authorized / issued capital.                                                         |
| `website`, `email`, `phone`                                     | Contact details.                                                                     |
| `legal_entity_identifier`                                       | LEI.                                                                                 |
| `location_of_registration`                                      | City / subdivision.                                                                  |
| `control_scheme`                                                | Governance scheme when registry exposes it.                                          |

Any field you omit is left untouched. Any field you send is written to the canonical column (when one exists) and merged into the raw `registry_data` JSON. Dates are serialized as ISO 8601 strings when merged into `registry_data`.

### Example

```bash theme={null}
curl -X PATCH "https://verification.didit.me/v3/session/bs-01HJX1.../kyb/f7a9c1b2-4e6d.../update-data/" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "company_name": "Acme Corporation Limited",
    "registration_number": "12345678",
    "registry_status": "active",
    "legal_address": "1 Main Street, London EC1A 1AA, United Kingdom",
    "alternative_names": "Acme Ltd, Acme Group"
  }'
```

Response: the full KYB company object — same shape as `registry_checks[].company` in the [session decision](/sessions-api/retrieve-session#business-verification-kyb).

## What happens after an update

* **Webhook** — `data.updated` fires on the session, with the session's `session_kind` in the payload (`"user"` or `"business"`). Subscribe once at the destination level and route on `session_kind`.
* **Audit trail** — the session records exactly which fields changed, the previous and new values, and (for user-auth calls) the actor email. Visible in the console's Events tab.
* **Address re-geocoding** — for KYC and POA updates that change `address` / `poa_address`, Didit re-runs geocoding in the background. Failures are swallowed so the update never fails because of a geocoding issue.
* **AML re-evaluation** — KYC updates that change name / DOB / nationality can re-trigger AML screening if AML hadn't finished on the session. Results surface on the session decision.

## When not to use these endpoints

* **Rerunning the whole verification** — if the customer has to re-take their ID photo or re-upload a document, use [update-status](/sessions-api/update-status) to move the session to `Resubmitted` instead.
* **Changing profile fields on the User or Business entity** — use [`PATCH /v3/users/{vendor_data}/`](/management-api/users/update) or [`PATCH /v3/businesses/{vendor_data}/`](/management-api/businesses/update) — those endpoints update entity-level data, not session-level data.
* **Updating Key People** — there's no public API to patch key-people records; that data is submitted through the hosted flow.

## Errors

| Status | Meaning                                                                                                                   |
| ------ | ------------------------------------------------------------------------------------------------------------------------- |
| `401`  | Missing or invalid credentials.                                                                                           |
| `403`  | Caller lacks the required privilege (`write:sessions` or `write:businesses`).                                             |
| `404`  | Session not found, or the session doesn't carry the feature record you're patching (no KYC, no POA, no matching company). |
| `400`  | Validation error — invalid country code, unknown `parsed_address` key, `extra_fields` not an object, etc.                 |

## Next steps

<CardGroup cols={3}>
  <Card title="Retrieve session" icon="file-lines" href="/sessions-api/retrieve-session">
    Fetch the full decision to see the updated fields.
  </Card>

  <Card title="Update status" icon="pen-to-square" href="/sessions-api/update-status">
    Approve, decline, or re-open a session after a data correction.
  </Card>

  <Card title="Webhooks" icon="bolt" href="/integration/webhooks">
    Subscribe to `data.updated` events.
  </Card>
</CardGroup>
