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

# Onboarding a user

> Take a user from sign-up to an active account: KYC profile, terms, identity verification, source of funds, and account creation.

Onboarding takes a user from sign-up to an active account, ready for cards and money movement. You run it in five steps:

1. Create a KYC profile
2. Collect terms acceptance
3. Complete identity verification
4. Collect source of funds
5. Create an account

> [!NOTE]
>
> The Partner API doesn't return one combined onboarding state. Your backend owns the workflow: it decides which step comes next and stores the IDs returned at each step.

## Steps

**1. Create a KYC profile**

Call [`POST /kyc/profiles`](https://docs.gnosispay.com/api-reference/partner-api/kyc/create-a-kyc-profile) with your stable reference for the user and their email address.

If you already know the address that will own the user's Safe, include it as `safe_owner_address`. Use the same address later when you create the account.

```bash cURL theme={null}
curl --request POST "$PARTNER_API_BASE_URL/kyc/profiles" \
  --header "Authorization: Bearer $PARTNER_API_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "email": "hello@example.com",
    "reference": "customer_12345",
    "safe_owner_address": "0xC0FFEE254729296a45a3885639AC7E10F9d54979"
  }'
```

Store the returned `profile_id` against your user record. You use it as `{kyc_profile_id}` in every later onboarding call.

> [!TIP]
>
> Profile creation is idempotent for the same `reference` and email, so a retry returns the existing profile. Reusing a reference with a different email returns a conflict.

> [accordion] Already verified the user on your own Sumsub account? Reuse their KYC
>
> If your user has already completed KYC on your Sumsub account, you can reuse that verification instead of asking them to verify again. Gnosis Pay creates an applicant on its own Sumsub account and copies the user's verified data into it. If Gnosis Pay needs checks your verification didn't cover, only those missing steps are triggered in step 3.
>
> **1. Generate a share token.** On your Sumsub account, call Sumsub's [generate share token](https://docs.sumsub.com/reference/generate-share-token) endpoint for the user's applicant, with `forClientId` set to Gnosis Pay's Sumsub client ID. Contact Gnosis Pay to get this client ID.
>
> **2. Add it to the profile request.** Include a `reuse_kyc` object when you create the profile:
>
> ```bash cURL theme={null}
> curl --request POST "$PARTNER_API_BASE_URL/kyc/profiles" \
>   --header "Authorization: Bearer $PARTNER_API_TOKEN" \
>   --header 'Content-Type: application/json' \
>   --data '{
>     "email": "hello@example.com",
>     "reference": "customer_12345",
>     "safe_owner_address": "0xC0FFEE254729296a45a3885639AC7E10F9d54979",
>     "reuse_kyc": {
>       "provider": "sumsub",
>       "data": {
>         "share_token": "<your-share-token>"
>       }
>     }
>   }'
> ```
>
> | Field | Description |
> | - | - |
> | `reuse_kyc.provider` | The KYC provider. Currently only `sumsub`. |
> | `reuse_kyc.data.share_token` | The share token you generated for Gnosis Pay's client ID. |
>
> > [!WARNING]
> >
> > A share token is **single-use** and expires after its TTL (Sumsub's default is 1,200 seconds). Generate a new token right before each attempt.
>
> Then continue with the remaining steps as usual.

**2. Collect terms acceptance**

1. Call [`GET /kyc/terms-of-service`](https://docs.gnosispay.com/api-reference/partner-api/kyc/list-current-terms-of-service) to get the current terms and their versions.
2. Show those terms to the user.
3. Call [`POST /kyc/profiles/{kyc_profile_id}/terms`](https://docs.gnosispay.com/api-reference/partner-api/kyc/accept-terms-for-a-profile) with every type and version the user accepted.

To recover or display the current acceptance state, call `GET /kyc/profiles/{kyc_profile_id}/terms`.

> [!WARNING]
>
> Always submit the versions the API returns. Don't hard-code a terms version in your application, because terms can change.

**3. Complete identity verification**

1. Call [`GET /kyc/profiles/{kyc_profile_id}/checks`](https://docs.gnosispay.com/api-reference/partner-api/kyc/list-kyc-profile-checks)  and select the current `basic` check.
2. Call [`GET /kyc/profiles/{kyc_profile_id}/checks/{check_id}`](https://docs.gnosispay.com/api-reference/partner-api/kyc/get-a-kyc-check) and request the credential your client needs, such as `include_credentials=web_sdk_url`.
3. Open the returned hosted verification session in your application.
4. Listen for KYC [webhook events](https://docs.gnosispay.com/platform-integration/webhook/webhooks), then confirm the latest state with `GET /kyc/profiles/{kyc_profile_id}`.

If you reused KYC in step 1, check the profile first. The user may already be approved, or may only need to complete the missing checks.

Handle each profile status like this:

| Status | What to do |
| - | - |
| `pending` | If the basic check is waiting for the user, open the current verification session. Otherwise, wait for the next event. |
| `requires_action` | Tell the user their verification is under review. There's nothing for them to do yet. |
| `resubmission_requested` | Get fresh credentials for the check and ask the user to resubmit. |
| `approved` | Continue to source of funds, then account creation. |
| `rejected` or `blocked` | Stop automated onboarding and show the user how to contact support. |

See [KYC Statuses](https://docs.gnosispay.com/concepts/kyc/kyc-statuses.md) for full definitions.

**4. Collect source of funds**

1. Call [\`GET /kyc/source-of-funds-questions](https://docs.gnosispay.com/api-reference/partner-api/kyc/get-source-of-funds-questions.md) to get the current questionnaire.
2. Show the questions and allowed answers exactly as returned. Don't change their text or identifiers.
3. Submit the complete set of answers to [`POST /kyc/profiles/{kyc_profile_id}/source-of-funds`](https://docs.gnosispay.com/api-reference/partner-api/kyc/accept-terms-for-a-profile).

To recover the submitted state, call [`GET /kyc/profiles/{kyc_profile_id}/source-of-funds`](https://docs.gnosispay.com/api-reference/partner-api/kyc/get-profile-source-of-funds-answers).

**5. Create an account**

Once the profile is `approved` and the previous steps are complete, call [`POST /accounts`](https://docs.gnosispay.com/api-reference/partner-api/accounts/create-an-account) with the approved `kyc_profile_id`, your external reference for the account, and a funding configuration. Don't create the account before then.

```bash cURL theme={null}
curl --request POST "$PARTNER_API_BASE_URL/accounts" \
  --header "Authorization: Bearer $PARTNER_API_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "kyc_profile_id": "019cbf57-758a-7589-8676-835804fa8c44",
    "external_reference": "account_customer_12345",
    "funding": {
      "type": "safe_wallet",
      "config": {
        "chain_config": {
          "chain": "gnosis"
        },
        "safe_owner_address": "0xC0FFEE254729296a45a3885639AC7E10F9d54979"
      }
    }
  }'
```

If you set `safe_owner_address` when creating the KYC profile, use the same address here. Store the returned `account_id` against your user record, next to their `profile_id`.

Account provisioning is asynchronous. Wait for an account status [webhook event](https://docs.gnosispay.com/platform-integration/webhook/webhooks), or check the account with [`GET /accounts/{account_id}`](https://docs.gnosispay.com/api-reference/partner-api/accounts/get-an-account). The account is ready when **both** are true:

* `status` is `active`
* `funding.config.safe_address` is present

Don't issue cards or move money until then.

> [!NOTE]
>
> The account response groups funding-specific fields under `funding`, with a `type` field that says which kind of funding the account uses (today, `safe_wallet`). Read `funding.type` before reading anything inside `funding.config`, so your integration keeps working when new funding types are added.

See [Account Overview](https://docs.gnosispay.com/concepts/accounts/account.md) and [Account Status](https://docs.gnosispay.com/concepts/accounts/account-status.md) for how accounts work.

## When onboarding is complete

Onboarding is complete when the profile is `approved`, terms are accepted, identity is verified, source of funds is submitted, and the account is `active` with a `safe_address`.

> [!TIP]
>
> Store each user's onboarding progress in your own database, such as the `profile_id`, `account_id`, the last known statuses, and which steps are done. That way you can resume onboarding after a dropped session or a missed webhook without repeating steps.

## Next step

> [card] [Create a cardholder and card](https://docs.gnosispay.com/platform-integration/cards/cards.md)
>
> Register the user as a cardholder and issue their first card.


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