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

# Proof of address warnings

> Every proof-of-address warning: name and address mismatches, expired or unsupported documents, overlay manipulation, extraction failures, and configurable actions.

export const WarningTypes = () => <div style={{
  display: "flex",
  flexDirection: "column",
  gap: "12px",
  margin: "16px 0"
}}>
    {WARNING_TYPES.map(w => <div key={w.type} style={{
  display: "flex",
  alignItems: "flex-start",
  gap: "12px",
  padding: "12px 16px",
  borderRadius: "8px",
  background: w.bg
}}>
        <span style={{
  fontSize: "16px",
  lineHeight: "24px"
}}>{w.icon}</span>
        <div>
          <div style={{
  fontWeight: 600,
  color: w.color,
  marginBottom: "2px"
}}>
            <code style={{
  background: "transparent",
  color: w.color,
  fontWeight: 600,
  padding: 0
}}>
              {w.type}
            </code>
          </div>
          <div style={{
  fontSize: "14px",
  lineHeight: "20px",
  color: "#374151"
}}>
            {w.description}
          </div>
        </div>
      </div>)}
  </div>;

## Overview

Proof-of-address (POA) verification emits warnings on `poa_verifications[].warnings[]` for every quality, authenticity, or matching issue detected during extraction and forensic analysis. Each warning is a [Warning object](/reference/data-models#warning-object) with `feature` set to `"PROOF_OF_ADDRESS"`. A handful of risks always force `Declined`; the rest follow a per-risk action (`DECLINE` / `REVIEW` / `NO_ACTION`) configured on your workflow.

Every risk below is verified against the live decision pipeline; the exact short and long description strings are reproduced verbatim in the tables.

<Note>
  POA extraction introduces a **5–15 second** latency per document. Warnings are written only when the workflow step completes; do not poll faster than every 5 s.
</Note>

## Two production paths

POA warnings are produced on two different paths, and the risk set differs between them:

* **Workflow sessions** (the POA step inside a verification session) — the upload endpoint first runs blocking validation with a retry loop (see [Retry behavior](#retry-behavior-workflow-sessions)), then the final stored warnings are computed by `check_poa_risks` plus the multi-document name check.
* **Standalone API** (`POST /v3/poa/`) — warnings come from `check_poa_risks` only. There is no retry loop, no verified-ID context, and only one document, so `NAME_MISMATCH_ID_VERIFICATION`, `POA_NAME_MISMATCH_BETWEEN_DOCUMENTS`, `POA_MAX_ATTEMPTS_EXCEEDED`, and `FUTURE_ISSUE_DATE` are **never** produced by the standalone API. The pre-extraction validation errors are discarded on this path.

`POOR_DOCUMENT_QUALITY` is defined in the risk enum and reserved in the action mapping, but **no code path in the POA pipeline produces it** — it never appears in `warnings[]` on either path. Do not branch on it.

## Auto-decline warnings (always force `Declined`)

These risks are in `AUTO_DECLINE_RISKS`; when logged, the POA status is `Declined` regardless of configuration, and `log_type` is always `error`.

| Risk                              | Cause                                                                                                                                                                                                                                                                                                                                                                | Recommended remediation                                                       |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `MISSING_ADDRESS_INFORMATION`     | No address could be extracted from the document.                                                                                                                                                                                                                                                                                                                     | Ask the user to resubmit a document that clearly shows their address.         |
| `POA_DOCUMENT_EXPIRED`            | The document is older than the configured maximum age for its type. Defaults: **3 months** for `UTILITY_BILL` and `BANK_STATEMENT`, **12 months** for `GOVERNMENT_ISSUED_DOCUMENT` and `OTHER_POA_DOCUMENT` (a month counts as 30 days; `-1` disables the check). `additional_data` carries `max_age_months`, `document_type`, `document_subtype`, and `issue_date`. | Ask the user for a more recent document, or raise `age_months` for that type. |
| `INVALID_DOCUMENT_TYPE`           | The document could not be classified into any supported POA type (`document_type` falls back to `UNKNOWN`).                                                                                                                                                                                                                                                          | Ask the user to resubmit; check the file is not corrupted.                    |
| `UNABLE_TO_VALIDATE_DOCUMENT_AGE` | The document-age check itself failed (error while computing the expiration from the issue date).                                                                                                                                                                                                                                                                     | Ask the user for a document with a clearly readable issue date.               |

`FUTURE_ISSUE_DATE` is also listed in `AUTO_DECLINE_RISKS`, but it has a single producer in pre-extraction validation (an issue date more than 7 days in the future) whose errors only feed the **workflow retry loop** — it surfaces as a blocking upload error there, is never produced by the standalone API, and is not written to `warnings[]`. See [Retry behavior](#retry-behavior-workflow-sessions).

## Configurable warnings

Each of these follows an action knob on the workflow's POA node (`DECLINE` / `REVIEW` / `NO_ACTION`). The warning's `log_type` mirrors the configured action: `error` for Decline, `warning` for Review, `information` for No action.

| Risk                                         | Cause                                                                                                                                                                                                                                                                                                                 | Action knob                                        | Default     |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ----------- |
| `NAME_MISMATCH_WITH_PROVIDED`                | The name on the document scores below `poa_name_match_score_threshold` (default 86) against the name supplied at session creation (`expected_details`).                                                                                                                                                               | `poa_name_or_address_mismatch_action`              | Review      |
| `NAME_MISMATCH_ID_VERIFICATION`              | The name on the document scores below the threshold against the verified ID document. `additional_data`: `{ poa_name, kyc_name, match_score }`. Workflow sessions only.                                                                                                                                               | `poa_name_or_address_mismatch_action`              | Review      |
| `ADDRESS_MISMATCH_WITH_PROVIDED`             | The extracted address differs from the address supplied via API, or either address could not be verified as a residential address.                                                                                                                                                                                    | `poa_name_or_address_mismatch_action`              | Review      |
| `POA_COUNTRY_MISMATCH_WITH_PROVIDED`         | The document's country does not match the country supplied via API (ISO-3 normalised). `additional_data`: `{ expected_country, extracted_country }`.                                                                                                                                                                  | `poa_name_or_address_mismatch_action`              | Review      |
| `POA_NAME_MISMATCH_BETWEEN_DOCUMENTS`        | Two or more POA documents in the same session carry different names. `additional_data` includes both node IDs, both names, and the match score. Workflow sessions only.                                                                                                                                               | `poa_name_or_address_mismatch_action`              | Review      |
| `DOCUMENT_METADATA_MISMATCH`                 | The file is empty (`file_size` 0) or its EXIF dates are malformed.                                                                                                                                                                                                                                                    | `poa_document_issues_action`                       | Review      |
| `SUSPECTED_DOCUMENT_MANIPULATION`            | Forensics found manipulation evidence — modification after digital signing (`is_tampered`), overlay-text manipulation (with `additional_data.manipulated_regions` rectangles), a known PDF editor, inconsistent EXIF dates, or a suspicious re-export. `additional_data.detection_method` names the check that fired. | `poa_document_authenticity_action`                 | **Decline** |
| `UNSUPPORTED_DOCUMENT_LANGUAGE`              | The document's language is not in `poa_languages_allowed`.                                                                                                                                                                                                                                                            | `poa_unsupported_language_action`                  | **Decline** |
| `POA_DOCUMENT_NOT_SUPPORTED_FOR_APPLICATION` | The detected document type is not enabled in `poa_documents_allowed` for the document's country, or its subtype is explicitly disabled.                                                                                                                                                                               | `poa_unsupported_document_type_action`             | **Decline** |
| `ISSUER_NOT_IDENTIFIED`                      | The issuing institution could not be identified from the document.                                                                                                                                                                                                                                                    | `poa_issuer_not_identified_action`                 | Review      |
| `UNABLE_TO_EXTRACT_ISSUE_DATE`               | No valid issue date could be located on the document.                                                                                                                                                                                                                                                                 | `poa_issue_date_not_detected_action`               | Review      |
| `POA_NAME_NOT_DETECTED`                      | No name was detected on the document.                                                                                                                                                                                                                                                                                 | `poa_issue_date_not_detected_action` (shared knob) | Review      |
| `UNPARSABLE_OR_INVALID_ADDRESS`              | An address was extracted but could not be parsed and geocoded into a valid residential address.                                                                                                                                                                                                                       | `poa_unparsable_or_invalid_address_action`         | Review      |
| `POA_MAX_ATTEMPTS_EXCEEDED`                  | The user exhausted `poa_max_retry_attempts` (default 2) in the workflow retry loop. `additional_data`: `{ attempts }`. Workflow sessions only.                                                                                                                                                                        | `poa_max_attempts_exceeded_action`                 | **Decline** |

<Note>
  There is **one shared action** for all name and address mismatches: `poa_name_or_address_mismatch_action` covers both name risks, both address risks, and the cross-document name check — you cannot configure name and address mismatch behavior separately. On the standalone API the same group follows the `poa_address_mismatch_action` request option (the `poa_name_mismatch_action` option is accepted but never read).
</Note>

## Standalone API differences (`POST /v3/poa/`)

The standalone endpoint builds the same risk-to-action mapping but with request-level options that only accept `DECLINE` or `NO_ACTION` (all defaulting to `DECLINE`):

* `UNABLE_TO_EXTRACT_ISSUE_DATE` and `POA_NAME_NOT_DETECTED` are **hard-coded to Decline** on this endpoint.
* `POA_DOCUMENT_NOT_SUPPORTED_FOR_APPLICATION` and `UNPARSABLE_OR_INVALID_ADDRESS` are **informational** here — their actions default to No action and are not configurable per request.
* `FUTURE_ISSUE_DATE`, `POOR_DOCUMENT_QUALITY`, `NAME_MISMATCH_ID_VERIFICATION`, `POA_NAME_MISMATCH_BETWEEN_DOCUMENTS`, and `POA_MAX_ATTEMPTS_EXCEEDED` are never produced — a future-dated document is **not** auto-declined on this endpoint.

See the [POST /v3/poa/ API reference](/standalone-apis/proof-of-address) for the request options.

## Retry behavior (workflow sessions)

In a verification session, the POA upload step runs blocking validation before the document is accepted. When it finds a blocking error — `INVALID_DOCUMENT_TYPE`, `UNABLE_TO_EXTRACT_ISSUE_DATE`, `FUTURE_ISSUE_DATE`, `POA_NAME_NOT_DETECTED`, `MISSING_ADDRESS_INFORMATION`, `POA_COUNTRY_MISMATCH_WITH_PROVIDED`, `POA_DOCUMENT_NOT_SUPPORTED_FOR_APPLICATION`, `UNSUPPORTED_DOCUMENT_LANGUAGE`, or `POA_DOCUMENT_EXPIRED` — the upload is rejected with `400` and the risk code as the message, and the user can try again with a better document.

Once the user has burned `poa_max_retry_attempts` attempts (default 2, configurable 2–5), the submission is accepted anyway: the stored warnings are recomputed from the saved document, `POA_MAX_ATTEMPTS_EXCEEDED` is appended, and the status is resolved from the full risk set. This is why `FUTURE_ISSUE_DATE` can block an upload yet never appears in `warnings[]`.

## Configurable settings

The workflow's POA node exposes these knobs (matching `VerificationSettings` fields):

| Setting                                    | Controls                                                                                                                                                                      | Default                                                                           |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `poa_name_or_address_mismatch_action`      | `NAME_MISMATCH_WITH_PROVIDED`, `NAME_MISMATCH_ID_VERIFICATION`, `ADDRESS_MISMATCH_WITH_PROVIDED`, `POA_COUNTRY_MISMATCH_WITH_PROVIDED`, `POA_NAME_MISMATCH_BETWEEN_DOCUMENTS` | Review                                                                            |
| `poa_document_issues_action`               | `DOCUMENT_METADATA_MISMATCH`                                                                                                                                                  | Review                                                                            |
| `poa_document_authenticity_action`         | `SUSPECTED_DOCUMENT_MANIPULATION`                                                                                                                                             | Decline                                                                           |
| `poa_unsupported_language_action`          | `UNSUPPORTED_DOCUMENT_LANGUAGE`                                                                                                                                               | Decline                                                                           |
| `poa_unsupported_document_type_action`     | `POA_DOCUMENT_NOT_SUPPORTED_FOR_APPLICATION`                                                                                                                                  | Decline                                                                           |
| `poa_issuer_not_identified_action`         | `ISSUER_NOT_IDENTIFIED`                                                                                                                                                       | Review                                                                            |
| `poa_issue_date_not_detected_action`       | `UNABLE_TO_EXTRACT_ISSUE_DATE`, `POA_NAME_NOT_DETECTED`                                                                                                                       | Review                                                                            |
| `poa_unparsable_or_invalid_address_action` | `UNPARSABLE_OR_INVALID_ADDRESS`                                                                                                                                               | Review                                                                            |
| `poa_max_attempts_exceeded_action`         | `POA_MAX_ATTEMPTS_EXCEEDED`                                                                                                                                                   | Decline                                                                           |
| `poa_documents_allowed`                    | Per-country accepted document types, each with `enabled` and `age_months` (`-1` = unlimited); per-subtype overrides via `document_subtypes_config`.                           | Utility bill and bank statement: 3 months; government-issued and other: 12 months |
| `poa_languages_allowed`                    | Accepted document languages.                                                                                                                                                  | All supported languages                                                           |
| `poa_name_match_score_threshold`           | Minimum name-match score (0–100) before the `NAME_MISMATCH*` risks fire.                                                                                                      | 86                                                                                |
| `poa_max_retry_attempts`                   | Upload attempts before the retry loop gives up (2–5).                                                                                                                         | 2                                                                                 |

## Name matching logic

POA name matching tolerates common variations:

* **Middle names and initials** are matched leniently (presence/absence is allowed).
* **Candidate names** — every name detected on the document (`name_on_document` plus `additional_names`) is scored, and the best-scoring candidate is kept.
* **Match threshold** — the default `poa_name_match_score_threshold` is **86**; a score below it fires the relevant `NAME_MISMATCH*` warning.

The numeric scores are exposed on the report as `name_match_score_expected_details` and `name_match_score_id_verification` (0–100). Score values are useful for fine-grained review even when no warning has been raised.

## Examples

### Overlay manipulation (Decline by default)

```json theme={null}
{
  "warnings": [
    {
      "feature": "PROOF_OF_ADDRESS",
      "risk": "SUSPECTED_DOCUMENT_MANIPULATION",
      "additional_data": {
        "reason": "Overlay-text manipulation detected: same base font embedded with multiple subset prefixes on 1 page(s).",
        "detection_method": "overlay_text_manipulation",
        "signals": ["duplicate_font_subset", "glyph_fragmentation"],
        "duplicate_font_subsets": [{ "page": 1, "base_font": "Helvetica" }],
        "fragmented_fonts": [],
        "manipulated_regions": [
          { "page": 1, "x": 102.4, "y": 318.1, "width": 187.0, "height": 18.0, "page_width": 595, "page_height": 842 }
        ]
      },
      "log_type": "error",
      "short_description": "Suspected document manipulation",
      "long_description": "The system detected signs of potential document manipulation or editing.",
      "node_id": "feature_poa_1"
    }
  ]
}
```

### Expired document + missing address (auto-decline)

```json theme={null}
{
  "warnings": [
    {
      "feature": "PROOF_OF_ADDRESS",
      "risk": "POA_DOCUMENT_EXPIRED",
      "additional_data": {
        "max_age_months": 3,
        "document_subtype": "ELECTRICITY_BILL",
        "document_type": "UTILITY_BILL",
        "issue_date": "2025-11-02"
      },
      "log_type": "error",
      "short_description": "Document expired",
      "long_description": "The submitted document is older than 90 days from its issue date, which exceeds the acceptable time period for validity.",
      "node_id": "feature_poa_1"
    },
    {
      "feature": "PROOF_OF_ADDRESS",
      "risk": "MISSING_ADDRESS_INFORMATION",
      "additional_data": null,
      "log_type": "error",
      "short_description": "Missing address information",
      "long_description": "The document does not contain complete or clear address information that can be extracted.",
      "node_id": "feature_poa_1"
    }
  ]
}
```

### Name mismatch (Review by default)

```json theme={null}
{
  "warnings": [
    {
      "feature": "PROOF_OF_ADDRESS",
      "risk": "NAME_MISMATCH_ID_VERIFICATION",
      "additional_data": {
        "poa_name": "JOHN B SMYTH",
        "kyc_name": "John A. Smith",
        "match_score": 60
      },
      "log_type": "warning",
      "short_description": "Name mismatch with ID verification",
      "long_description": "The full name on the document does not match the name from the user's verified identity documents.",
      "node_id": "feature_poa_1"
    }
  ]
}
```

## Related

* [Proof of address report](/core-technology/proof-of-address/report-proof-of-address) — full response shape, overlay-manipulation forensics, status semantics
* [Proof of address overview](/core-technology/proof-of-address/overview) — accepted document types
* [Data models — Proof of address](/reference/data-models#proof-of-address) — canonical schema and Warning object
* [Webhooks](/integration/webhooks) — `status.updated` carries POA warnings

### Warning types

<WarningTypes />
