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

# EEA onboarding

> Onboard European (EEA) users end to end: verification, terms, MiCA compliance, and SEPA payouts — all driven by capabilities.

Onboarding a user in the European Economic Area (EEA) uses the same capability-driven model as [any other user](/guides/onboarding) — you just have a couple of extra requirements to satisfy, because EEA ramps run under the EU's Markets in Crypto-Assets regulation (MiCA).

You never hard-code these steps. You read the user's **capabilities**, satisfy whatever requirements are outstanding, and re-read until the ramp is `active`. This guide walks the full EEA path for a SEPA off-ramp; the shape is identical for on-ramps.

<Info>
  New to the capability model? Read [Onboarding customers](/guides/onboarding) first — this guide assumes you've created the user and started identity verification.
</Info>

## The extra requirements

For an EEA user, a ramp capability (e.g. `crypto_to_fiat` / `sepa_credit_transfer`) can surface up to three requirements. Each tells you how to satisfy it:

| Requirement `type`      | How you satisfy it                                                                                                                                        |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `identity_verification` | Standard KYC (see [Onboarding](/guides/onboarding)). Usually already done; occasionally the provider asks for more — send the user to its `actionUrl`.    |
| `terms_acceptance`      | Send the user to its `actionUrl` (a hosted terms flow) → it returns a **signed agreement id** → `POST /v1/users/me/terms`.                                |
| `regional_compliance`   | Collect the MiCA fields and `POST /v1/users/me/compliance`. No `actionUrl` — you render the form. See [Regional compliance](/guides/regional-compliance). |

`terms_acceptance` and `regional_compliance` are the two that need you to **submit** something back — the rest of the model is the familiar "visit `actionUrl`, then re-fetch capabilities".

## The flow

<Steps>
  <Step title="Create and verify the user">
    Create the user and start identity verification exactly as in [Onboarding customers](/guides/onboarding). Verification produces the identity data the EEA path needs, so it comes first.
  </Step>

  <Step title="Read capabilities">
    `GET /v1/users/me`. The SEPA capability comes back `requirements_needed` with its outstanding requirements and a `nextRequirement`.

    ```json theme={null}
    {
      "product": "crypto_to_fiat",
      "method": "sepa_credit_transfer",
      "status": "requirements_needed",
      "nextRequirement": "terms_acceptance",
      "requirements": [
        { "type": "terms_acceptance", "actionUrl": "https://…", "status": "not_started" },
        { "type": "regional_compliance", "actionUrl": null, "status": "not_started" }
      ]
    }
    ```
  </Step>

  <Step title="Accept the terms">
    Send the user to the `terms_acceptance` requirement's `actionUrl` (a hosted terms page). When they accept, the flow returns a **signed agreement id**. Submit it:

    ```bash theme={null}
    curl -X POST https://platform.spritz.finance/v1/users/me/terms \
      -H "Content-Type: application/json" \
      # plus your integrator signing headers and the user's Authorization
      -d '{ "agreementId": "<signed agreement id>" }'
    ```

    ```json theme={null}
    { "termsAccepted": true }
    ```

    The `agreementId` is opaque — you just relay what the hosted flow gave you. Accepting the terms is what provisions the user's EEA account behind the scenes.
  </Step>

  <Step title="Submit MiCA compliance fields">
    Check what's outstanding, collect the fields, and submit them together:

    ```bash theme={null}
    curl https://platform.spritz.finance/v1/users/me/compliance/requirements
    ```

    ```bash theme={null}
    curl -X POST https://platform.spritz.finance/v1/users/me/compliance \
      -H "Content-Type: application/json" \
      -d '{
        "placeOfBirth": { "country": "DEU", "city": "Berlin" },
        "nationalities": ["DEU"],
        "accountPurpose": "personal_or_living_expenses"
      }'
    ```

    See [Regional compliance](/guides/regional-compliance) for the full field reference (ISO alpha-3 codes, the account-purpose list, and validation).
  </Step>

  <Step title="Finish identity verification (if asked)">
    Identity is normally satisfied by the verification from step 1. If the provider's own checks need more — for example an address that didn't match a registry — the `identity_verification` requirement stays with an `actionUrl`. Send the user there to complete it.
  </Step>

  <Step title="Re-read capabilities and transact">
    You don't need to poll for this. Subscribe to the `capabilities.updated` [webhook](/guides/webhooks) and re-fetch `GET /v1/users/me` when it fires — you'll be notified as each requirement is processed and cleared. Once every requirement clears, the SEPA capability flips to `active` and money movement unblocks. Until then, transactions are refused with the outstanding requirement.

    Add the destination bank account and create the off-ramp — see [Off-ramp: crypto to bank](/guides/use-cases/off-ramp).
  </Step>
</Steps>

<Tip>
  **Listen, don't poll.** Provider checks (KYC, the SEPA endorsement, database screens) resolve asynchronously, sometimes minutes apart. Rather than polling `GET /v1/users/me` on a timer, subscribe to the `capabilities.updated` [webhook](/guides/webhooks) — Spritz notifies you whenever a requirement or capability status changes, and you re-fetch only then.
</Tip>

<Warning>
  While a ramp capability is `requirements_needed`, money movement on it is **blocked** — the requirements are a hard gate, not a soft prompt. Drive your UI off `capabilities` so the user always sees exactly what's left.
</Warning>

## Endpoint reference

| Purpose                          | Endpoint                                   |
| -------------------------------- | ------------------------------------------ |
| Start identity verification      | `POST /v1/users/me/verification-sessions`  |
| Read capabilities / requirements | `GET /v1/users/me`                         |
| Accept terms                     | `POST /v1/users/me/terms`                  |
| Compliance — what's needed       | `GET /v1/users/me/compliance/requirements` |
| Compliance — submit              | `POST /v1/users/me/compliance`             |
| Add destination bank account     | `POST /v1/bank-accounts`                   |
| Off-ramp quote                   | `POST /v1/off-ramp-quotes`                 |

## Next

<CardGroup cols={2}>
  <Card title="Regional compliance" icon="shield-check" href="/guides/regional-compliance">
    The MiCA field reference — place of birth, nationalities, account purpose.
  </Card>

  <Card title="Onboarding customers" icon="user-plus" href="/guides/onboarding">
    The capability-driven model these steps build on.
  </Card>

  <Card title="Off-ramp: crypto to bank" icon="arrow-right-from-bracket" href="/guides/use-cases/off-ramp">
    Put the active SEPA capability to work.
  </Card>

  <Card title="Webhooks" icon="bell" href="/guides/webhooks">
    React to capabilities.updated instead of polling.
  </Card>
</CardGroup>
