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

# EUR/GBP Offramp

> Sell stablecoin for Euros or Pounds Sterling, paid out directly to a EUR (IBAN) or GBP (sort code) bank account.

EUR/GBP offramp lets your users convert their stablecoin balance into Euros or Pounds Sterling, settled to a bank account. Every offramp flow follows the same four steps: **Create User → KYC → Bank Account Linkage → Transaction.**

<Info>
  Both USDT and USDC are supported for EUR/GBP offramp.
</Info>

<Steps>
  <Step title="Create User">
    ```http theme={null}
    POST /api/v2/user
    ```

    ```json theme={null}
    {
      "email": "user@example.com",
      "phone": "+491701234567"
    }
    ```

    Response:

    ```json theme={null}
    {
      "success": true,
      "data": {
        "user_id": "550e8400-e29b-41d4-a716-446655440000"
      }
    }
    ```

    Save `user_id` — every subsequent call needs it as the `X-User-Id` header.
  </Step>

  <Step title="KYC">
    EUR/GBP supports two KYC methods:

    <Tabs>
      <Tab title="KYC Sharing">
        ```http theme={null}
        POST /api/v2/user/kyc
        ```

        Headers: `X-User-Id: <user_id>`

        ```json theme={null}
        {
          "legal_name": "Hans Mueller",
          "poi": "<proof-of-identity-document-id>",
          "poa": "<proof-of-address-document-id>",
          "dob": "1990-01-31",
          "email": "user@example.com",
          "phone": "+491701234567",
          "country_iso3": "DEU"
        }
        ```

        Response:

        ```json theme={null}
        { "success": true, "data": {} }
        ```

        Use the ISO3 code for the user's country (e.g. `DEU` for Germany, `GBR` for the UK). Saber may request supporting KYC documents at any time — these must be shared within 72 hours of the request.
      </Tab>

      <Tab title="KYC Widget">
        Redirect the user to a signed URL:

        ```javascript theme={null}
        const sigString = clientId + timestamp + "sdk" + userId
        const secret = HmacSHA256(sigString, clientSecret).toString().toUpperCase()
        // redirect to: https://app.saber.money/kyc?client_id=...&user_id=...&timestamp=...&secret=...&redirect_url=<url-encoded-url>
        ```

        The URL is valid for **10 minutes** from generation. Append the optional `redirect_url` as the last query parameter (URL-encoded) to send the user back to your app when they exit the flow. See [KYC Hosted Widget](/user/kyc/widget) for the full parameter reference.
      </Tab>
    </Tabs>
  </Step>

  <Step title="Bank Account Linkage">
    There's no bank-code lookup step for EUR/GBP — banks are identified directly by IBAN (EUR) or sort code (GBP).

    ```http theme={null}
    POST /api/v2/user/bank_account
    ```

    Headers: `X-User-Id: <user_id>`

    <Tabs>
      <Tab title="EUR">
        ```json theme={null}
        {
          "bank_iban": "DE89370400440532013000",
          "account_holder_name": "Hans Mueller",
          "country": "DEU"
        }
        ```

        Mandatory: `bank_iban`, `account_holder_name`, `country`.
      </Tab>

      <Tab title="GBP">
        ```json theme={null}
        {
          "account_holder_name": "James Smith",
          "account_number": "12345678",
          "bank_code": "040004",
          "country": "GBR"
        }
        ```

        Mandatory: `account_holder_name`, `account_number` (max 8 digits), `bank_code` (sort code), `country`.
      </Tab>
    </Tabs>

    Response:

    ```json theme={null}
    {
      "success": true,
      "data": {
        "bank_id": "550e8400-e29b-41d4-a716-446655440000",
        "account_number": "12345678",
        "iban": "DE89370400440532013000",
        "bic": null,
        "account_holder_name": "Hans Mueller",
        "name": null,
        "validation_status": "PENDING",
        "routing_type": "IBAN",
        "country": "DEU",
        "is_nre": false,
        "created_at": "2024-01-01T00:00:00Z",
        "updated_at": "2024-01-01T00:00:00Z"
      }
    }
    ```

    <Note>
      This is the shared bank account response shape across corridors — `iban`/`bic` are populated for IBAN routing, `account_number` for GBP sort-code routing, with the unused identifier fields returned as `null`.
    </Note>

    Save `bank_id` for the sell step.
  </Step>

  <Step title="Transaction">
    Two variants, both requiring a quote first — a **Live Quote** (informational, executes at market rate regardless) or a **Locked Quote** (rate held \~30-60s, supplied as `quote_id` in the sell request):

    <Tabs>
      <Tab title="Pool Sell (recommended)">
        Get an informational quote:

        ```http theme={null}
        GET /api/v2/wallet/s/quote?from_currency=USDT&to_currency=EUR&from_amount=100
        ```

        Then create the sell:

        ```http theme={null}
        POST /api/v2/wallet/transaction/pool/sell
        ```

        ```json theme={null}
        {
          "source_id": "<bank_id>",
          "fiat_symbol": "EUR",
          "crypto_symbol": "USDT",
          "crypto_amount": 25,
          "payment_method": "bank_transfer"
        }
        ```
      </Tab>

      <Tab title="External Sell">
        Generate a locked quote (expires in \~30-60s):

        ```http theme={null}
        GET /api/v2/wallet/w/quote?from_currency=USDT&to_currency=GBP&network=BSC&from_amount=10
        ```

        Save `id` from the response as `quote_id`, then create the sell:

        ```http theme={null}
        POST /api/v2/wallet/transaction/crypto/sell
        ```

        ```json theme={null}
        {
          "payment_method": "bank_transfer",
          "network": "BSC",
          "destination_instrument_id": "<bank_id>",
          "quote_id": "<quote_id>",
          "sender_wallet_address": "0x318d2aae4c99c2e74f7b5949fa1c34df837789b8",
          "refund_wallet_address": "0x318d2aae4c99c2e74f7b5949fa1c34df837789b8"
        }
        ```

        Then fund `deposit_crypto_address` on-chain within the settlement expiry, and confirm it:

        ```http theme={null}
        POST /api/v2/wallet/transaction/crypto/sell/{id}/confirm-onchain-funding
        ```

        ```json theme={null}
        { "transaction_hash": "0x1234567890abcdef" }
        ```

        <Warning>
          This returns **202 Accepted**, not 200 — Saber verifies the deposit asynchronously.
        </Warning>
      </Tab>
    </Tabs>

    **Payment rails:** `payment_method: bank_transfer` resolves internally based on currency and recipient bank:

    | Currency | Rail                                                                     |
    | -------- | ------------------------------------------------------------------------ |
    | GBP      | Faster Payments                                                          |
    | EUR      | SEPA Instant if supported by the recipient bank, otherwise standard SEPA |

    <Info>
      There are no cut-off times for EUR/GBP payouts. Standard SEPA transfers (where SEPA Instant isn't supported by the recipient bank) are subject to normal weekend and banking-holiday delays.
    </Info>
  </Step>
</Steps>

## Checking status

```http theme={null}
GET /api/v2/wallet/transaction?transaction_type={POOL_SELL|EXTERNAL_SELL}&transaction_id={id}
```

| Transaction Type | Possible `status` values                                                                                                                                           |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Pool Sell        | `CREATED`, `PROCESSING`, `COMPLETED`, `FAILED`, `CANCELLED`, `APPROVAL_REQUIRED`, `SOURCE_INVALID`, `VERIFICATION_PENDING`, `REFUND_INITIATED`, `REFUND_COMPLETED` |
| External Sell    | `CREATED`, `PAYMENT_INITIATED`, `FUNDS_RECEIVED`, `COMPLETED`, `FAILED`, `REFUND_INITIATED`, `REFUND_COMPLETED`, `REFUND_FAILED`                                   |

Poll until the status reaches a terminal state, or configure a webhook URL to receive completion pushes instead — see [Order Lifecycle and Webhooks](/offramp/operations/lifecycle).

## User limits and EDD

Each user has a lifetime transaction limit (currently \$200,000 USD equivalent — this figure is suggestive and subject to change; confirm current limits with Saber). Once a user's limit is breached, no further transactions can be created until Enhanced Due Diligence (EDD) is completed to raise it.

EDD is completed via the [EDD Hosted Widget](/users/limits-edd/widget), with a turnaround time of 2-3 working days.

## Related pages

<CardGroup cols={2}>
  <Card title="Offramp Operations" icon="arrow-right-arrow-left" href="/offramp/available-flows" cta="View guide" arrow="true" />

  <Card title="User KYC" icon="id-card" href="/user/kyc/overview" cta="View guide" arrow="true" />

  <Card title="Bank Account" icon="building-columns" href="/user/bank-account/overview" cta="View guide" arrow="true" />
</CardGroup>


## Related topics

- [Overview](/user/bank-account/overview.md)
- [Available Flows](/offramp/available-flows.md)
- [EUR/GBP Onramp](/onramp/currencies/eur-gbp.md)
- [EUR/GBP Openbanking: Best Practices](/onramp/currencies/eur-gbp-best-practices.md)
