# Bulk participant import

Source: https://docs.settlemint.com/docs/concepts/compliance-and-identity/participant-import
Import participant rows in a background batch keyed by an organisation-scoped external reference.

An Identity manager calls `POST /api/v2/participants/import-batches` with `{ rows, walletVerification }`: up to 500 rows and one wallet step-up for the whole batch. The call answers `202 Accepted` with a `batchId`, a `statusUrl` and a matching `Location` header. Read `GET /api/v2/participants/import-batches/{batchId}` until `state` is `completed`. Send `Prefer: wait=<seconds>` to wait for the batch inside the request. The wait is held between 5 and 99 seconds. When it finishes in time, or every row already fails its row rules, the call answers `200` with the completed batch instead.

A session caller first requests a step-up challenge from `POST /api/v2/step-up-challenges` with the `operation` `POST /api/v2/participants/import-batches`, a `target` and a `payloadDigest`. The `target` is `null` when the import sends none of the `X-Chain-Id`, `X-Network-Id`, `X-Executor` and `X-Custody-Account-Id` headers. When it sends any of them, the `target` is the JSON text of an array holding `null` and then those four header values in that order, with a missing header as `null`. The digest is the lowercase hex SHA-256 of the import body's canonical JSON, with object keys sorted, absent fields dropped and the top-level `walletVerification` left out. The import then carries the challenge id in the `X-Step-Up-Challenge` header. A challenge works for one request and expires after five minutes. An API key caller sends no challenge and no `walletVerification`. A missing wallet step-up or challenge answers `400` and a caller without the Identity manager role answers `403`, before any row runs. Reading a batch needs the Identity manager role too. When the organisation's [approval settings](https://docs.settlemint.com/docs/console/organisation-settings/general#approvals) require a second person for the "System administration" group of the Administration family, the import waits for approval and runs once it is approved. Send an `Idempotency-Key` header to make a retried call safe: the same key from the same caller with the same rows answers the batch it already started, and the same key with different rows answers `409`.

Each row carries `externalRef`, `name`, `email`, `providerConfigurationId`, `nationality`, `residence` and `kyc` (`firstName`, `lastName`, `dob`, `residencyStatus`, `nationalId`). `nationality` and `residence` are ISO 3166-1 alpha-2 codes. `residence` becomes the KYC profile country.

Each row that does not fail opens a pending registration request for the participant, or refreshes one still pending, with `nationality` as the proposed identity registry country. An Identity manager accepts the registration as usual and sees that country prefilled. The import never accepts a registration itself.

A row can carry an optional `classification`: `retail`, `institutional` or `proprietary`. A batch that uses it also needs the claim issuer role. A caller without that role answers `403` before any row runs. The organisation's identity issues the class as a claim on `participantClassRetail`, `participantClassInstitutional` or `participantClassProprietary`, and only when the participant holds no class yet. A venue reads the class through its own class topic mapping. A row naming a different class from one the participant already holds fails with `classification-change-refused` and writes no claim, because a class change needs the holder of the participant identity's key. The row's other fields are already saved when it fails. A classified row whose reference is still pending in another batch writes no claim and fails with `classification-not-issued`. Send it again once that batch has finished.

The import does not take extra wallets. Each participant gets its custody provider's wallet. Register further wallets through the registration routes after the import.

`externalRef` is unique within the organisation. Sending a reference again updates that participant's name and KYC data instead of creating a second one. The import never changes a login email: a re-sent reference with a different email fails with `email-change-refused`. A reference that appears twice in one batch fails both rows. A reference whose creation failed is created afresh on its next send.

The batch answers one row per input row, in input order, with `status` `pending`, `created`, `updated`, `unchanged` or `failed`. A failed row carries a `code` and the field `issues` that caused it. A `created` or `updated` row carries `dependency-unavailable` when a later step, such as the KYC submission, did not finish. Send it again to finish it.

| Code | Meaning |
| --- | --- |
| `row-invalid` | A field broke its rule. `issues` names the field. |
| `external-ref-duplicate` | The reference appears more than once in the batch. |
| `email-in-use` | The email belongs to an existing user. The import does not adopt existing members. |
| `email-change-refused` | The reference is already imported with another login email. Change it through the user. |
| `participant-create-refused` | The user, wallet or identity could not be created. |
| `kyc-fields-rejected` | The KYC profile refused a field, or a field the organisation's profile sections require is missing. `issues` names it. The participant is already created. |
| `kyc-transition-refused` | The KYC version could not be submitted for review. |
| `kyc-version-refused` | A new KYC version could not be started. |
| `kyc-draft-open` | An operator has a KYC draft open for this participant. Finish or discard it, then retry. |
| `classification-not-issued` | The class claim could not be written. `issues` says why. Send the row again to retry it, unless `issues` says the outcome is unknown. Check the participant's claims first. |
| `classification-change-refused` | The participant already holds another class. A change needs the holder of the participant identity's key. |
| `dependency-unavailable` | A platform dependency was down. Send the row again later. |

A failed row never stops the other rows. KYC data follows the normal provider and review flow: the import submits it for review as the importing operator and never approves it.
