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

# Onboarding Lifecycle

> End-to-end onboarding flow for partners and customers. Covers customer creation, identification, status tracking, and activation.

Iron gives you full visibility into your customer onboarding — clear status at every stage, written feedback from our compliance team when something needs fixing, and real-time insight into your customer's payment abilities.

## Steps to Onboard and Activate a Customer

<Steps>
  <Step title="Create a new customer">
    `POST /customers`

    Create a customer record. The customer is created in `IdentificationRequired` status.

    <Accordion title="API Example">
      <CodeGroup>
        ```bash theme={null}
        curl --request POST \
             --header 'content-type: application/json; charset=utf-8' \
             --header 'idempotency-key: <unique-request-id>' \
             --header 'x-api-key: <your-api-key>' \
             --data '{"name": "new_amazing_customer", "email": "customer@example.com", "customer_type": "Person"}' \
             --url 'https://api.sandbox.iron.xyz/api/customers'
        ```
      </CodeGroup>
    </Accordion>
  </Step>

  <Step title="Verify the customer's identity">
    `POST /customers/{id}/identifications/v2`

    Create an identification using one of these methods:

    * Hosted Iron KYC link
    * SumSub token sharing
    * Outsourcing

    <Warning>
      This endpoint is not an upsert. Every call 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.

      Create one identification, then wait for it to reach a terminal status (`Approved`, `Declined`, or `Expired`) 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>

    <Accordion title="API Example">
      <CodeGroup>
        ```bash theme={null}
        curl --request POST \
             --header 'accept: application/json; charset=utf-8' \
             --header 'idempotency-key: <unique-request-id>' \
             --header 'x-api-key: <your-api-key>' \
             --url 'https://api.sandbox.iron.xyz/api/customers/<customer_id>/identifications/v2' \
             --data '{"type": "Link"}'
        ```
      </CodeGroup>
    </Accordion>
  </Step>

  <Step title="KYC is approved">
    Once approved, the customer status transitions to `SigningsRequired`.
  </Step>

  <Step title="Customer signs required documents">
    `GET /customers/{id}/required-signings`

    Retrieve the required documents and present them to your customer. Mark each as signed via `POST /customers/{id}/signings`.

    <Accordion title="API Example">
      <CodeGroup>
        ```bash Retrieve signings theme={null}
        curl --request GET \
             --header 'accept: application/json; charset=utf-8' \
             --header 'x-api-key: <your-api-key>' \
             --url 'https://api.sandbox.iron.xyz/api/customers/<customer_id>/required-signings'
        ```

        ```bash Sign a document theme={null}
        curl --request POST \
             --header 'accept: application/json; charset=utf-8' \
             --header 'idempotency-key: <unique-request-id>' \
             --header 'x-api-key: <your-api-key>' \
             --data '{
               "content_id": "<id_from_required_signings>",
               "content_type": "Url",
               "signed": true
             }' \
             --url 'https://api.sandbox.iron.xyz/api/customers/<customer_id>/signings'
        ```
      </CodeGroup>

      **Example response from required-signings:**

      <CodeGroup>
        ```json theme={null}
        [
          {
            "display_name": "Terms and Conditions",
            "id": "019ababb-ddd6-7f02-8f5d-7469a0e8afb6",
            "url": "https://example.com/terms-and-conditions"
          }
        ]
        ```
      </CodeGroup>

      Pass the `url` to your customer for review. When signing, always set `content_type` to `"Url"` in the signing request.
    </Accordion>
  </Step>

  <Step title="Customer is activated">
    Once all required signings are complete, the customer status becomes `Active`.
  </Step>

  <Step title="Check payout rail availability">
    Check `abilities.fiat_payout` to confirm payout rails are `Active` before initiating payouts.
  </Step>
</Steps>

<Note>
  A customer's status may revert from `Active` to `SigningsRequired` or `IdentificationRequired` if new compliance actions are required (e.g. updated terms and conditions, fraud review, enhanced due diligence).
</Note>

## Handling Missing Information

If an identification becomes incomplete, the customer's status moves back to `IdentificationRequired` and a `url` is returned on the Identification object. Redirect your customer to this URL — it opens a hosted step-up flow that collects only the missing data.

This occurs when:

* A data point is found to be invalid, expired, or inconsistent
* A limit triggers additional due diligence requirements

## Mapping Onboarding Statuses in Your App

Use `customerStatus` and `identificationStatus` together to drive a three-stage progress stepper.

| `customerStatus`         | `identificationStatus` | Stage             | What to show                                      |
| ------------------------ | ---------------------- | ----------------- | ------------------------------------------------- |
| `IdentificationRequired` | None                   | Submission        | Prompt customer to start KYC                      |
| `IdentificationRequired` | `Pending`              | Submission        | Prompt customer to complete KYC                   |
| `IdentificationRequired` | `Expired`              | Submission        | Previous attempt expired — prompt to restart      |
| `IdentificationRequired` | `Declined`             | Submission        | Show `review_comment`, prompt to retry            |
| `IdentificationRequired` | `Processed`            | Compliance Review | Show waiting state — no customer action needed    |
| `IdentificationRequired` | `PendingReview`        | Compliance Review | Show waiting state — under active review          |
| `SigningsRequired`       | `Approved`             | Activation        | KYC approved — present required documents to sign |
| `Active`                 | `Approved`             | Complete          | Fully onboarded — customer can transact           |

<Note>
  Typical compliance review turnaround is 24–48 hours. Customers can re-enter `SigningsRequired` at any time (e.g. updated terms). Use the `abilities` endpoint to confirm banking rails are active — that's when the customer is truly ready to transact.
</Note>

### Tracking EDD Status

Each identification includes a `with_edd` field that indicates whether Enhanced Due Diligence was applied. This field is an optional boolean:

* `true` — EDD was triggered (either by the partner or automatically by Iron's AML checks)
* `false` — EDD was explicitly not required
* `null` — Identification was created before this feature was available

`with_edd` can be set in two ways:

1. **Partner-initiated** — Pass `with_edd: true` (Link flow) or include `edd_questionnaire` (Token/Person flow) when creating the identification. See [Proactively Increasing Customer Limits](/limits-and-minimum#proactively-increasing-customer-limits).
2. **Automatically by Iron** — If AML checks determine EDD is required (e.g. customer resides in a high-risk jurisdiction), Iron sets `with_edd` to `true` server-side.

Use `status` and `with_edd` together to understand where a customer is in the verification process:

| `status`        | `with_edd`       | Meaning                                                           |
| --------------- | ---------------- | ----------------------------------------------------------------- |
| `Pending`       | `null` / `false` | Standard KYC in progress                                          |
| `Pending`       | `true`           | EDD flow in progress                                              |
| `PendingReview` | `null` / `false` | Standard KYC under manual review                                  |
| `PendingReview` | `true`           | EDD complete at verification provider, awaiting compliance review |
| `Approved`      | `null` / `false` | Standard KYC approved, no EDD                                     |
| `Approved`      | `true`           | Approved through EDD                                              |
| `Declined`      | `null` / `false` | Standard KYC rejected                                             |
| `Declined`      | `true`           | Rejected after EDD review                                         |

### Edge Cases

| `customerStatus` | Meaning                                                                              |
| ---------------- | ------------------------------------------------------------------------------------ |
| `Suspended`      | Blocked — can happen at any stage. Contact support.                                  |
| `UserRequired`   | Partner-area user must be created first. Only applies if `requires_user` is enabled. |

### Displaying Onboarding Comments to Your Customer

If a customer's KYC submission is incomplete or needs correction, our onboarding team may provide written feedback explaining what needs to be improved. This feedback is available on the identification object via `review_comment` and `step_status.*.comment` fields. Display these comments to your customer so they know exactly what to fix before resubmitting.

Show these comments when `identificationStatus` is `Pending` or `Declined`.

<Warning>
  Do not display `step_status` results directly to the customer. The per-step breakdown (e.g. "identity: Declined, selfie: Approved") creates confusion and support tickets. Instead, extract the comment fields and combine them into a single message.
</Warning>

<Accordion title="Implementation example">
  **Example identification response with feedback:**

  <CodeGroup>
    ```json theme={null}
    {
      "id": "abc-123",
      "status": "Declined",
      "with_edd": false,
      "review_comment": "Please provide a clearer photo of your ID.",
      "step_status": {
        "identity": { "result": "Declined", "comment": "Document is blurry", "retry": true },
        "selfie": { "result": "Approved", "comment": null, "retry": false },
        "questionnaire": { "result": "Approved", "comment": null, "retry": false }
      }
    }
    ```
  </CodeGroup>

  **Extract and display all comments in a single message box:**

  <CodeGroup>
    ```typescript theme={null}
    function getVerificationMessages(identification: Identification): string[] {
      const messages: string[] = [];
      if (identification.step_status) {
        for (const step of Object.values(identification.step_status)) {
          if (step?.comment) { messages.push(step.comment); }
        }
      }
      if (identification.review_comment) {
        messages.push(identification.review_comment);
      }
      return messages;
    }
    ```
  </CodeGroup>
</Accordion>

***

## API Endpoints

| Endpoint                              | Purpose                                                                 |
| ------------------------------------- | ----------------------------------------------------------------------- |
| `GET /customers/{id}`                 | Customer object with `status` and `abilities`                           |
| `GET /customers/{id}/identifications` | Identifications with `status`, `step_status`, and `review_comment`      |
| `GET /customers/{id}/abilities`       | Customer capabilities including `fiat_deposit` and `fiat_payout` status |

## Status Reference

### Customer Status

Returned on the customer object.

| Status                   | Description                             |
| ------------------------ | --------------------------------------- |
| `IdentificationRequired` | Must complete KYC/KYB                   |
| `SigningsRequired`       | Must sign required documents            |
| `Active`                 | Fully onboarded — can transact          |
| `Suspended`              | Blocked for compliance or fraud reasons |
| `UserRequired`           | Partner-area user must be created first |

### Identification Status

Returned on each identification object.

| Status          | Description                          |
| --------------- | ------------------------------------ |
| `Pending`       | Customer has not started             |
| `Processed`     | Documents submitted, awaiting review |
| `PendingReview` | Under compliance review              |
| `Approved`      | Approved                             |
| `Declined`      | Rejected                             |
| `Expired`       | Expired due to inactivity            |

**Typical Flow:** `Pending` → `Processed` → `PendingReview` → `Approved` / `Declined`

The identification object also includes `with_edd` (boolean, nullable) to indicate whether EDD was applied. See [Tracking EDD Status](#tracking-edd-status) for the full interpretation table.

### Ability Status

Returned under `abilities.fiat_payout` and `abilities.fiat_deposit`.

| Status        | Description                   |
| ------------- | ----------------------------- |
| `Active`      | Available for use             |
| `Pending`     | Activation in progress        |
| `Unavailable` | Not offered for this customer |
| `Blocked`     | Blocked for this customer     |
| `Maintenance` | Temporarily unavailable       |
