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

# Cookbook: Onboard, verify, and provision merchants

> Create merchant organisations, run KYC or KYB, handle verification results, and track account provisioning.

Onboard a merchant under your partner account through the API. You create the organisation, the merchant is verified (KYC for an individual, KYB for a company), you handle the verification result, and ZBX provisions the merchant's crypto and EUR accounts.

## End-to-end flow

```mermaid theme={null}
flowchart LR
  A(["Create the org"]) --> B(["Complete KYC/KYB"])
  B --> C(["Verification result"])
  C --> D(["Accounts provisioned"])
```

## Authentication

Signed requests use these headers:

```
X-API-KEY: <API_KEY>
X-API-Nonce: <NONCE>
X-API-Signature: <HMAC_SIGNATURE>
```

Calculate the signature using `SIGNING_SECRET`. See [Authentication](/authentication).

Use the partner credentials for `/partners/orgs`. After onboarding, use the new merchant organisation's credentials for account, deposit, swap, and withdrawal requests.

ZBX will provide test credentials separately. Credentials must not be committed to source control or shared through an unsecured channel.

Retrieve the signing secret when credentials are first configured or after the secret is rotated:

```
GET https://mapi.zbx.com/v1/orgs/signing-secret
```

This request is authenticated with the organisation API key. Do not sign it: the signing secret is not available yet.

## Choose a verification path

| Path | Use it when | Add to the request | Response |
| - | - | - | - |
| [KYC with a verification link](#option-a-kyc-with-a-verification-link) | The merchant is an individual who verifies with ZBX | Nothing extra | `kyc_next_action` is `kyc_required:<url>` |
| [KYC with a share token](#option-b-kyc-with-a-sumsub-share-token) | You already verified the individual in your own Sumsub account | `share_token` and `kyc_questionnaire` | No `kyc_next_action` |
| [KYB with a verification link](#option-c-kyb-for-a-company) | The merchant is a company | `user_type: "CORP"` and `legal_name` | `kyc_next_action` is `kyb_required:<url>` |

All three paths return `kyc_status: "pending"`. Whether `kyc_next_action` is present tells you if the merchant still has something to do.

## 1. Create the organisation

Create the organisation in one call. You can submit the merchant's KYC in the same request.

```
POST https://mapi.zbx.com/v1/partners/orgs
```

### Request fields

| Field | Required | Notes |
| - | - | - |
| `external_reference` | Yes | Your own reference for the merchant. Repeating it returns the existing org (`200`) instead of creating a second one, and ignores any `share_token`. |
| `name` | Yes | Display name. |
| `owner.email` | Yes | Merchant contact email. Must not already belong to another org. |
| `owner.name` | Yes | Contact person. |
| `owner.phone` | Yes | E.164 format: `+` then 2–15 digits, no leading zero (for example `+4915112345678`). Must be a real mobile number: it is needed later to issue the EUR account. |
| `user_type` | KYB only | `"CORP"` for a company. Omit it, or send `"IND"`, for an individual. |
| `legal_name` | KYB only | Registered company name. Must be unique and at most 50 characters. |
| `end_user_ip` | No | The merchant's IP address at signup, used for risk assessment. If omitted, the IP of the server making the call is used. |
| `webhook_url` | No | HTTPS URL that receives this merchant's webhooks, such as `Org.Updated`. |
| `share_token` | Share token path only | Sumsub share token from your own Sumsub account. Requires `kyc_questionnaire`. Not accepted when `user_type` is `"CORP"`. |
| `kyc_questionnaire` | With `share_token` | The merchant's due-diligence answers. Only accepted together with `share_token`. See [`kyc_questionnaire` reference](#questionnaire-reference). |
| `settlement_accounts` | Not accepted | Rejected with `400`. Accounts are provisioned after verification ([step 4](#4-account-provisioning)). |

### Option A: KYC with a verification link

ZBX returns a Sumsub verification link for the merchant to complete.

```mermaid theme={null}
sequenceDiagram
  autonumber
  participant You
  participant API as ZBX

  You->>API: POST /partners/orgs (owner.email, ...)
  API->>API: Check whether an org already exists for this email
  alt Email already has an org
    API-->>You: 409 Conflict - use a different owner email
  else New email
    API->>API: Create the org and prepare the verification link
    API-->>You: 201 Created - org_id and kyc_next_action
  end
```

```bash theme={null}
curl -X POST "https://mapi.zbx.com/v1/partners/orgs" \
  -H "X-API-KEY: sk_test_xxx" \
  -H "Content-Type: application/json" \
  -H "X-API-Nonce: ${NONCE}" \
  -H "X-API-Signature: ${SIG}" \
  -d '{
    "external_reference": "merchant-001",
    "name": "Acme Ops Ltd",
    "owner": {
      "email": "ops-1@acme.example",
      "name": "Acme Ops",
      "phone": "+4915112345678"
    }
  }'
```

Response (`201 Created`):

```json theme={null}
{
  "data": {
    "org_id": "3IDieTi1aMaCafUfmlotbHyDeSP",
    "owner": {
      "email": "ops-1@acme.example",
      "name": "Acme Ops",
      "phone": "+4915112345678"
    },
    "kyc_status": "pending",
    "kyc_next_action": "kyc_required:https://in.sumsub.com/websdk/p/...",
    "created_at": "2026-08-21T09:47:14Z"
  }
}
```

Send the URL after the `kyc_required:` prefix to the merchant ([step 2](#2-the-merchant-completes-verification)).

### Option B: KYC with a Sumsub share token

If you already verified the merchant in your own Sumsub account, share that KYC with ZBX. The merchant does not upload documents again and no verification link is returned.

```mermaid theme={null}
sequenceDiagram
  autonumber
  participant You
  participant API as ZBX

  You->>API: POST /partners/orgs (owner.email, share_token, kyc_questionnaire, ...)
  API->>API: Check whether an org already exists for this email
  alt Email already has an org
    API-->>You: 409 Conflict - use a different owner email
  else New email
    API->>API: Import the KYC from share_token and record the questionnaire answers
    alt Token or answers refused
      API-->>You: 424 - share_token_rejected or kyc_questionnaire_rejected, no org created
    else Accepted
      API-->>You: 201 Created - org_id, kyc_status pending
    end
  end
```

The token and the answers are submitted together: either both are accepted, or the call fails and no org is created.

**1. Create the share token in Sumsub.** This request goes to Sumsub, not to ZBX. Authenticate it the way Sumsub's API requires.

```bash theme={null}
curl -X POST "https://api.sumsub.com/resources/accessTokens/shareToken?levelName=basic-kyc-level" \
  -H "Content-Type: application/json" \
  -H "X-App-Token: $SUMSUB_APP_TOKEN" \
  -d '{
    "applicantId": "<your-sumsub-applicant-id>",
    "forClientId": "<sumsub-client-id-from-us>",
    "ttlInSecs": 1200
  }'
```

* `levelName`: the verification level in your Sumsub account.
* `forClientId`: the ZBX Sumsub client ID. ZBX gives you separate sandbox and production values.
* `ttlInSecs`: how long the token stays valid. Create the org before it expires.

**2. Create the org with the share token and questionnaire answers.**

```bash theme={null}
curl -X POST "https://mapi.zbx.com/v1/partners/orgs" \
  -H "X-API-KEY: sk_test_xxx" \
  -H "Content-Type: application/json" \
  -H "X-API-Nonce: ${NONCE}" \
  -H "X-API-Signature: ${SIG}" \
  -d '{
    "external_reference": "merchant-002",
    "name": "Acme Ops Ltd",
    "owner": {
      "email": "ops-2@acme.example",
      "name": "Acme Ops",
      "phone": "+4915112345678"
    },
    "share_token": "shr_xxx",
    "kyc_questionnaire": {
      "sdd_country_select": "MT",
      "investment_citizenship": "82",
      "employment_type_or_status": "15",
      "industry": "51",
      "employment_jurisdiction": "MT",
      "acting_capacity": "156",
      "annual_income": "75",
      "expected_deposit_one_year": "83",
      "source_of_funds": "66,70",
      "source_of_funds_of_country": "MT,DE",
      "source_of_wealth_of_country": "MT",
      "hnwi_str": "79"
    }
  }'
```

Response (`201 Created`). There is no `kyc_next_action`, because the merchant has nothing left to do:

```json theme={null}
{
  "data": {
    "org_id": "3IDieTi1aMaCafUfmlotbHyDeSP",
    "owner": {
      "email": "ops-2@acme.example",
      "name": "Acme Ops",
      "phone": "+4915112345678"
    },
    "kyc_status": "pending",
    "created_at": "2026-08-21T09:47:14Z"
  }
}
```

#### Questionnaire reference

The answers to the merchant's due-diligence questions. Every value is a string holding a fixed option ID, not free text.

| Field | Required | Value and meaning |
| - | - | - |
| `sdd_country_select` | Yes | Country of residence, 2-letter code (`MT`, `DE`). |
| `investment_citizenship` | Yes | Citizenship or residency obtained through an investor immigration programme (golden visa): `81` yes, `82` no. |
| `employment_type_or_status` | Yes | `15` employed (part-time or full-time), `16` self-employed or business owner, `17` unemployed, `18` pensioner or retired, `19` full-time student, family carer, or receiving social benefits. |
| `industry` | Yes | Industry or occupation, `20`–`53`. See [Industry option IDs](#industry-option-ids). |
| `employment_jurisdiction` | Unless `employment_type_or_status` is `17` | Country of employment, 2-letter code, or `N/A` if there is none. Send `N/A` for `18` and `19`. |
| `acting_capacity` | Yes | `156` acting as principal or on own behalf, `157` acting through an agent, power of attorney, or on behalf of another person. |
| `annual_income` | Yes | Annual gross income in EUR: `74` up to 10,000, `75` 10,000–50,000, `76` 50,000–300,000, `77` more than 300,000. |
| `expected_deposit_one_year` | Yes | Planned deposits over one year in EUR: `83` up to 10,000, `84` 10,000–150,000, `85` more than 150,000. |
| `source_of_funds` | Yes | Where the funds come from: one or more option IDs, comma-separated (`66,70`). See [Source of funds option IDs](#source-of-funds-option-ids). |
| `source_of_funds_of_country` | Yes | Countries the funds come from, 2-letter codes, comma-separated (`MT,DE`). |
| `source_of_wealth_of_country` | Yes | Countries the wealth was built in, 2-letter codes, comma-separated (`MT`). |
| `hnwi_str` | Yes | Approximate total net worth in EUR: `78` under 100,000, `79` 100,000–1,000,000, `80` 1,000,000 or more. |

* Country codes are ISO 3166-1 alpha-2. A list may not repeat a code or a value.
* A request with invalid answers returns `400` listing every problem, each naming its field.

##### Industry option IDs

<AccordionGroup>
  <Accordion title="Show all industry values (20–53)">
    | Value | Industry |
    | - | - |
    | `20` | Affiliate marketing |
    | `21` | Agriculture or fisheries services |
    | `22` | Architects or draftsmen |
    | `23` | Auctioneers or dealing in arts or antiques |
    | `24` | Aviation |
    | `25` | Banks or other regulated financial services |
    | `26` | Cash-intensive business |
    | `27` | Cleaning services |
    | `28` | Consultancy services |
    | `29` | Crypto-asset services or mining |
    | `30` | Dealing in luxury goods or precious commodities |
    | `31` | Energy or mining of natural resources |
    | `32` | Entertainment, tourism, or hospitality |
    | `33` | Fuel stations |
    | `34` | Government, military, or law enforcement |
    | `35` | Health professionals |
    | `36` | Healthcare, chemicals, or pharmaceuticals |
    | `37` | Import or export |
    | `38` | Legal or corporate services |
    | `39` | Manual (blue-collar) sector |
    | `40` | Manufacturing industry |
    | `41` | Marine services |
    | `42` | Marketing or journalism |
    | `43` | Non-profit organisations or charities |
    | `44` | Not applicable (for example student, pensioner, or unemployed) |
    | `45` | Private security services |
    | `46` | Professional sports |
    | `47` | Real estate or construction |
    | `48` | Regulated gambling and betting |
    | `49` | Retail, transportation, or logistics |
    | `50` | Retired |
    | `51` | Technology, software, or IT services |
    | `52` | Trade finance or unregulated financial services |
    | `53` | Other. May be sent as `53:<free text>` (up to 100 characters). |
  </Accordion>
</AccordionGroup>

##### Source of funds option IDs

<AccordionGroup>
  <Accordion title="Show all source of funds values (54–73)">
    | Value | Source |
    | - | - |
    | `54` | Bank credit or financing |
    | `55` | Bank loan |
    | `56` | Crowdfunding |
    | `57` | Crypto mining or ICO proceeds |
    | `58` | Dependent on a spouse or equivalent |
    | `59` | Dividends, investment, or rental income |
    | `60` | Divorce settlement |
    | `61` | Gambling winnings |
    | `62` | Gift or donations from family |
    | `63` | Inheritance or gift |
    | `64` | Loan or other financing |
    | `65` | Maturity of an insurance policy |
    | `66` | Salary, pension, or self-employment |
    | `67` | Sale of assets or business |
    | `68` | Sale of immovable property |
    | `69` | Sale of movable property |
    | `70` | Savings |
    | `72` | Virtual financial assets |
    | `73` | Other |
  </Accordion>
</AccordionGroup>

<Note>
  `71` (third-party funding) is not accepted with a share token. Onboard that merchant without `share_token` to get a verification link instead.
</Note>

### Option C: KYB for a company

Same flow as [option A](#option-a-kyc-with-a-verification-link), but `user_type` must be `"CORP"` and `legal_name` is required. The response carries a KYB link instead of a KYC link.

`share_token` and `kyc_questionnaire` are not accepted for a company and are rejected with `400`.

```bash theme={null}
curl -X POST "https://mapi.zbx.com/v1/partners/orgs" \
  -H "X-API-KEY: sk_test_xxx" \
  -H "Content-Type: application/json" \
  -H "X-API-Nonce: ${NONCE}" \
  -H "X-API-Signature: ${SIG}" \
  -d '{
    "external_reference": "merchant-003",
    "name": "Acme Holdings",
    "user_type": "CORP",
    "legal_name": "Acme Holdings Ltd",
    "owner": {
      "email": "ops-3@acme.example",
      "name": "Acme Ops",
      "phone": "+4915112345678"
    },
    "end_user_ip": "203.0.113.7",
    "webhook_url": "https://merchant.example/webhooks"
  }'
```

Response (`201 Created`):

```json theme={null}
{
  "data": {
    "org_id": "3IDieTi1aMaCafUfmlotbHyDeSP",
    "owner": {
      "email": "ops-3@acme.example",
      "name": "Acme Ops",
      "phone": "+4915112345678"
    },
    "kyc_status": "pending",
    "kyc_next_action": "kyb_required:https://in.sumsub.com/websdk/p/...",
    "created_at": "2026-10-13T09:47:14Z"
  }
}
```

### Errors when creating the org

| Status | Reason | Meaning | What to do |
| - | - | - | - |
| `200` | — | `external_reference` already used. The existing org is returned. | Nothing. No second org is created. |
| `400` | — | Invalid request, for example invalid questionnaire answers, `settlement_accounts` sent, or `share_token` sent with `user_type: "CORP"`. | Fix the fields listed in the error. |
| `409` | — | The owner email already has an org. | Use a different owner email. |
| `424` | `share_token_rejected` | Sumsub refused the share token. No org is created. | Create a new token, or onboard without `share_token`. |
| `424` | `kyc_questionnaire_rejected` | The questionnaire answers were refused. No org is created. | Correct the answers and retry. |

Error bodies follow the standard envelope. See [Response patterns](/api/response-patterns).

## 2. The merchant completes verification

**Verification link (options A and C).** The merchant opens the URL after the `kyc_required:` or `kyb_required:` prefix and uploads their documents on a Sumsub-hosted page. No login is required.

```mermaid theme={null}
sequenceDiagram
  autonumber
  participant M as Merchant
  participant S as Sumsub

  M->>S: Open the verification link and upload documents
  Note over S: Documents are reviewed
```

* The merchant usually opens the link, but if you already hold their documents, you can use it to submit on their behalf.
* The merchant can also submit documents from the ZBX merchant dashboard, which embeds the same Sumsub flow.

**Share token (option B).** Nothing to do. You already sent the share token and questionnaire answers when you created the org.

## 3. Handle the verification result

When the verification result arrives, ZBX updates `kyc_status` and sends an `Org.Updated` webhook to the `webhook_url` you registered. [Verify the webhook signature](/webhooks/verify-signatures) before you act on it.

You can also read the current state at any time:

```
GET https://mapi.zbx.com/v1/partners/orgs/{orgId}
```

```mermaid theme={null}
sequenceDiagram
  autonumber
  participant API as ZBX
  participant You

  Note over API: The verification result arrives (all paths)

  alt Approved
    API->>API: kyc_status = accepted, provisioning starts
    API->>You: Org.Updated - kyc_status accepted
  else More information needed
    API->>API: kyc_status stays pending, org not tradeable yet
    API->>You: Org.Updated - kyc_status pending, kyc_next_action, reason
  else Rejected
    API->>API: kyc_status = rejected, org permanently blocked
    API->>You: Org.Updated - kyc_status rejected, reason
  end
```

The `Org.Updated` webhook carries `kyc_status`, `kyc_next_action`, and `reason`. For example, when a tax identification number is needed:

```json theme={null}
{
  "kyc_status": "pending",
  "kyc_next_action": "tin_required",
  "reason": "tin missing",
  "updated_at": "2026-09-24T08:57:28Z",
  "org_id": "3IDieTi1aMaCafUfmlotbHyDeSP",
  "org": {
    "id": "3IDieTi1aMaCafUfmlotbHyDeSP",
    "name": "Acme Ops Ltd"
  },
  "event": "Org.Updated"
}
```

When the merchant has to verify again:

```json theme={null}
{
  "kyc_status": "pending",
  "kyc_next_action": "kyc_required:https://in.sumsub.com/websdk/p/...",
  "reason": "KYC submission was declined and needs to be resubmitted",
  "updated_at": "2026-09-24T08:57:27Z",
  "org_id": "3IDieTi1aMaCafUfmlotbHyDeSP",
  "org": {
    "id": "3IDieTi1aMaCafUfmlotbHyDeSP",
    "name": "Acme Ops Ltd"
  },
  "event": "Org.Updated"
}
```

Only an approval sets `kyc_status` to `"accepted"` and starts provisioning. Any other result leaves the org linked, in `"pending"` or `"rejected"`:

| Verification result | `kyc_status` | `kyc_next_action` | What you do |
| - | - | - | - |
| Approved | `accepted` | — | Nothing. The merchant can trade, and [provisioning](#4-account-provisioning) starts. |
| The merchant must verify again | `pending` | `kyc_required:<url>` | Send the new link to the merchant so they can resubmit. |
| Tax identification number needed | `pending` | `tin_required` | [Provide the TIN](#provide-a-tax-identification-number). |
| Enhanced due diligence needed | `pending` | `edd_required` | [Provide EDD information](#provide-enhanced-due-diligence-information). |
| Under review or on hold | `pending` | — | Nothing. Wait for the next webhook. |
| Rejected | `rejected` | — | Nothing. This is terminal: no retry is offered and the org is permanently blocked. |

`tin_required` and `edd_required` can appear at any point in the merchant's lifetime, not only during onboarding. Submit the information through the endpoints below whenever `kyc_next_action` asks for it.

### Provide a tax identification number

```
POST https://mapi.zbx.com/v1/partners/orgs/{orgId}/kyc/tin
```

Returns `200` with the resulting `kyc_status`.

```bash theme={null}
curl -X POST "https://mapi.zbx.com/v1/partners/orgs/$ORG_ID/kyc/tin" \
  -H "X-API-KEY: sk_test_xxx" \
  -H "Content-Type: application/json" \
  -H "X-API-Nonce: ${NONCE}" \
  -H "X-API-Signature: ${SIG}" \
  -d '{
    "tax_residency": "DE",
    "tin": "123456789"
  }'
```

If the merchant has no tax number, send the reason instead:

```json theme={null}
{
  "tax_residency": "DE",
  "tin_not_available": "YES",
  "tin_not_available_reason": "TIN_NOT_ISSUED"
}
```

| Field | Required | Value and meaning |
| - | - | - |
| `tax_residency` | Yes | Country of tax residency, 2-letter code (`DE`, `MT`). |
| `tin` | Yes, unless `tin_not_available` is `YES` | The merchant's tax identification number. |
| `tin_not_available` | No | `YES` if the country issues no tax number, `NO` otherwise. |
| `tin_not_available_reason` | No | Why there is no number: `TIN_COUNTRY_NOT_ISSUE` the country issues none, `TIN_NOT_REQUIRED` not required, `TIN_NOT_ISSUED` none issued to the merchant, `TIN_OTHER` any other reason. |
| `tin_not_available_reason_desc` | Yes, if the reason is `TIN_OTHER` | Explanation of the other reason. |

### Provide enhanced due diligence information

```
POST https://mapi.zbx.com/v1/partners/orgs/{orgId}/kyc/edd
```

Returns `202`. The submission is reviewed manually and the outcome arrives as an `Org.Updated` webhook.

```bash theme={null}
curl -X POST "https://mapi.zbx.com/v1/partners/orgs/$ORG_ID/kyc/edd" \
  -H "X-API-KEY: sk_test_xxx" \
  -H "Content-Type: application/json" \
  -H "X-API-Nonce: ${NONCE}" \
  -H "X-API-Signature: ${SIG}" \
  -d '{
    "professional_salary": {
      "name_of_employer": "Acme Ops Ltd",
      "occupation": "Director",
      "address_of_employer": "Unter den Linden 1, Berlin",
      "no_of_years_in_employment": "6",
      "gross_annual_income": "120000"
    },
    "other": "Dividends from a family holding company",
    "file_urls": ["https://files.example.com/edd/payslip.pdf"]
  }'
```

Send at least one field. All values are free text.

| Field | Required | Value and meaning |
| - | - | - |
| `capital_of_company` | No | Company capital, or dividends or income from the business. |
| `gift_or_inheritance` | No | Gift or inheritance. |
| `professional_salary` | No | Employment income, an object with the five fields below. |
| `professional_salary.name_of_employer` | No | Name of the employer. |
| `professional_salary.occupation` | No | Occupation. |
| `professional_salary.address_of_employer` | No | Address of the employer. |
| `professional_salary.no_of_years_in_employment` | No | Number of years in employment. |
| `professional_salary.gross_annual_income` | No | Gross annual income. |
| `profit_from_sold_or_maturing_investments` | No | Profit from sold or maturing investments. |
| `profits_from_property_sale` | No | Profits from a property sale. |
| `profits_from_sale_of_company` | No | Profits from the sale of a company. |
| `compensation_payment` | No | Compensation payment. |
| `pension` | No | Pension. |
| `other` | No | Any other source of funds. |
| `file_urls` | No | Links to supporting documents, at most 10. Each must be an `https` URL without credentials, and must stay valid until ZBX has fetched it. |

## 4. Account provisioning

Once `kyc_status` becomes `"accepted"`, ZBX provisions the merchant's accounts automatically. You do not call anything.

* **Crypto deposit addresses** are created right away and are typically ready within moments.
* **EUR account** is requested at the same time. The IBAN is issued separately, typically a few seconds to minutes later.

```mermaid theme={null}
sequenceDiagram
  autonumber
  participant API as ZBX
  participant You

  Note over API: Starts as soon as kyc_status becomes accepted

  API->>API: Create crypto deposit addresses
  API->>You: Webhook - crypto account ready
  API->>API: Request the EUR account
  Note over API: The IBAN is issued, typically within seconds to minutes
  API->>You: Webhook - EUR account ready
```

To confirm the merchant's accounts are open, read the org:

```
GET https://mapi.zbx.com/v1/partners/orgs/{orgId}
```

The response has the same shape as the create response, plus a `settlement_accounts` array. An entry in that array does not by itself mean the account is ready:

```json theme={null}
{
  "data": {
    "org_id": "3IDieTi1aMaCafUfmlotbHyDeSP",
    "kyc_status": "accepted",
    "settlement_accounts": [
      {
        "reference": "...",
        "chain_id": 1,
        "address": "0x...",
        "currencies": ["USDT"]
      },
      {
        "reference": "...",
        "chain_id": 0,
        "address": "",
        "currencies": ["EUR"]
      }
    ]
  }
}
```

Once the IBAN is issued, the same EUR entry has `account_number` and `bank` filled in:

```json theme={null}
{
  "reference": "...",
  "chain_id": 0,
  "address": "",
  "account_number": "DE89370400440532013000",
  "bank": {
    "name": "...",
    "bic": "...",
    "country": "DE",
    "address": "...",
    "account_holder_name": "Acme Ops Ltd"
  },
  "currencies": ["EUR"]
}
```

<Note>
  Check each entry's own field, not whether the array is non-empty. A crypto entry is ready when `address` is set, which happens almost immediately. The EUR entry is ready when `account_number` (the IBAN) is set, typically a few seconds to minutes later.
</Note>

## What is ready when

The EUR account is not a way to receive EUR. It is where EUR lands after a crypto-to-EUR exchange, on the way to a bank payout.

| Capability | Ready when |
| - | - |
| Trading (crypto to EUR and back) | `kyc_status` is `"accepted"`. Does not depend on settlement accounts. |
| Withdraw crypto | `kyc_status` is `"accepted"`. The destination address is supplied per request. |
| Receive crypto deposits | A crypto deposit address exists (typically moments after approval). |

`kyc_status: "accepted"` alone is enough for the merchant to start trading. `settlement_accounts` only tells you when the merchant can receive crypto deposits.

| Milestone | `kyc_status` | Crypto account | EUR account |
| - | - | - | - |
| Org created ([step 1](#1-create-the-organisation)) | `pending` | — | — |
| Verification approved ([steps 2–3](#3-handle-the-verification-result)) | `accepted` | Not ready yet | Not ready yet |
| Provisioning runs automatically | `accepted` | **Ready** (has a deposit address) | Requested, not ready yet |
| IBAN issued, a few seconds to minutes later | `accepted` | Ready | **Ready** (has an IBAN) |

## Next steps

* [Cookbook: Deposit, convert, and withdraw fiat](/deposits/cookbook-deposit-to-fiat): use the provisioned accounts for deposits, swaps, and EUR withdrawals.
* [Verify webhook signatures](/webhooks/verify-signatures): check `Org.Updated` deliveries before you act on them.
* [Authentication](/authentication): partner API keys and request signing.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.