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

# Hosted Identification

> The simplest identification method. Create an identification with type Link and receive a URL to pass to your customer for completing verification.

The returned URL is an interface hosted by Iron. Once the customer has completed the flow, Iron reviews the submission, performs verification, and decides on approval. Iron is fully responsible for all compliance obligations, including final verification and ongoing monitoring.

<Note>
  Present and sign the terms and conditions before creating the identification. Ask your customer for their country, fetch the terms via `GET /api/terms-and-conditions?country={ISO3}`, and record acceptance via `POST /api/customers/{id}/signings`. The terms contain the data sharing agreement, so they must be signed before Iron collects KYC data. See [Terms and Conditions](/onboarding#terms-and-conditions).
</Note>

## Create a Link Identification

`POST /api/customers/{id}/identifications/v2`

Full request and response schemas live in the [API reference](/reference-sandbox/customer/create-customer-identification-v2).

The request body must include `"type": "Link"` to select the hosted flow. This is the discriminator that tells the API which identification method to use.

| Field                      | Required | Description                                                                               |
| -------------------------- | -------- | ----------------------------------------------------------------------------------------- |
| `type`                     | Yes      | Must be `"Link"` for hosted identifications                                               |
| `with_edd`                 | No       | Set to `true` to start the full Enhanced Due Diligence process. Individual customers only |
| `Idempotency-Key` (header) | Yes      | Unique UUID per request. Requests without it return `400`                                 |

<Warning>
  `with_edd` works for Individual customers only. Setting it to `true` on a Business customer returns `400` with the message `"with_edd is not supported for business customers"`.
</Warning>

<CodeGroup>
  ```bash Bash theme={null}
  curl -X POST "https://api.sandbox.iron.xyz/api/customers/<customer_id>/identifications/v2" \
    -H "Content-Type: application/json; charset=utf-8" \
    -H "IDEMPOTENCY-KEY: <unique-request-id>" \
    -H "X-API-Key: <your-api-key>" \
    -d '{ "type": "Link" }'
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    "https://api.sandbox.iron.xyz/api/customers/<customer_id>/identifications/v2",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json; charset=utf-8",
        "Idempotency-Key": "<unique-request-id>",
        "X-API-Key": "<your-api-key>",
      },
      body: JSON.stringify({ type: "Link" }),
    },
  );

  const identification = await response.json();
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.sandbox.iron.xyz/api/customers/<customer_id>/identifications/v2",
      headers={
          "Content-Type": "application/json; charset=utf-8",
          "Idempotency-Key": "<unique-request-id>",
          "X-API-Key": "<your-api-key>",
      },
      json={"type": "Link"},
  )

  identification = response.json()
  ```
</CodeGroup>

<Note>
  `POST /api/customers/{id}/identifications/v2` requires an `Idempotency-Key` header. Requests without one return `400`. Retrying with the same key returns the original response. Iron caches successful responses only, so a retry after an error executes the request again. Reusing a key with a different request body returns `409 Conflict`.
</Note>

<Warning>
  This endpoint is not an upsert. In the default flow, every call with a new idempotency key creates a new identification record, and the newest record drives the customer's status. If you create a new identification while another is in flight, the customer resets to `IdentificationRequired` and the older identification stops counting, even if it is approved later. One exception: if the customer's latest identification is Sumsub-based (every hosted-flow identification is), calling again with `with_edd: true` upgrades that record for EDD instead of creating a new one.

  Create one identification, then wait for it to reach a terminal status (`Approved`, `Declined`, `Expired`, or `Archived`) before creating another. To track progress, subscribe to the `identification_status` webhook or poll `GET /api/customers/{id}/identifications`. Never re-call this endpoint to refresh status.
</Warning>

**Example response (`201 Created`):**

<CodeGroup>
  ```json JSON theme={null}
  {
    "id": "c3d4e5f6-a7b8-9012-cdef-345678901234",
    "customer_id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
    "status": "Pending",
    "url": "https://api.sandbox.iron.xyz/verify?<encrypted_id>",
    "created_at": "2026-01-15T10:00:00Z",
    "updated_at": "2026-01-15T10:00:00Z"
  }
  ```
</CodeGroup>

Pass the `url` to your customer. They complete the verification flow in the hosted interface, and Iron handles the rest.

**Example errors:**

Most client errors (`400`, `401`, `403`, `404`, `429`) return a plain JSON string:

```json 404 Not Found theme={null}
"Create customer identification customer not found."
```

A `409` means the request matches an existing identification. The body includes the existing record's ids so you can reconcile the duplicate:

```json 409 Conflict theme={null}
{
  "message": "The identification payload matches an existing identification.",
  "existing_customer_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "existing_identification_id": "d4e5f6a7-b8c9-0123-def4-567890123456",
  "external_id": "cust-1042"
}
```

Server errors (`500`) return `{ "message": "...", "trace_id": "..." }`. Reference the `trace_id` when reporting issues.

<Note>
  In Sandbox, you can approve or reject the identification via `POST /api/sandbox/identification/{id}` instead of waiting for a manual review. See [Sandbox](/sandbox#update-identification-status).
</Note>
