Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developer.uphold.com/llms.txt

Use this file to discover all available pages before exploring further.

This guide walks you through the steps to support SEPA bank withdrawals using the REST API — from listing external accounts to monitoring for settlement.

Prerequisites

Walkthrough


Check available rails

Before creating a quote, verify the SEPA rail is available for withdrawals. Call List Rails for EUR to confirm the sepa network has the withdraw feature.
GET /core/rails?type=bank&network=sepa&asset=EUR
The rail always exists in the system, but the withdraw feature is only present if it’s enabled for the user.
{
  "rails": [
    {
      "type": "bank",
      "network": "sepa",
      "method": "bank-transfer",
      "asset": "EUR",
      "decimals": 2,
      "features": [
        "deposit",
        "withdraw"
      ]
    }
  ]
}

Select source account

SEPA withdrawals can be sourced from any account. If the selected account is not in EUR, the balance will be converted at the time of the transaction using Uphold’s prevailing rate. Make sure the origin asset has the necessary features enabled. Call List accounts to retrieve the user’s accounts and let them pick the one to withdraw from.
GET /core/accounts
{
  "accounts": [
    {
      "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
      "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a",
      "label": "My EUR account",
      "asset": "EUR",
      "balance": {
        "total": "500.00",
        "available": "500.00"
      }
    }
  ]
}

Select a bank account

SEPA bank accounts are registered automatically as external accounts when a user makes their first SEPA deposit — they cannot be added manually. If the user has no SEPA-linked accounts yet, direct them to complete a SEPA deposit first. Call List external accounts and filter for accounts with type: "bank".
GET /core/external-accounts
Make sure the selected account has status: "ok" and "withdraw" in features.
{
  "externalAccounts": [
    {
      "id": "cc8e8abc-0f95-4b9f-8490-2569a67bd80e",
      "type": "bank",
      "status": "ok",
      "network": "sepa",
      "label": "My EUR Account",
      "features": [
        "withdraw"
      ],
      "details": {
        "iban": "AT487954841229809844",
        "bic": "EXAAAT2K"
      }
    }
  ]
}

Create a quote

To initiate the withdrawal, call Create quote with the origin as the user’s account and the destination as the selected SEPA external account. Specify the amount and asset for the withdrawal.
POST /core/transactions/quote
{
  "origin": {
    "type": "account",
    "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8"
  },
  "destination": {
    "type": "external-account",
    "id": "cc8e8abc-0f95-4b9f-8490-2569a67bd80e"
  },
  "denomination": {
    "asset": "EUR",
    "amount": "250.00",
    "target": "origin"
  }
}
A successful response returns a quote object with details about the withdrawal, including fees and expiration.
{
  "quote": {
    "id": "623000c8-9bdf-4a2b-aa3d-6a6b44a7f6a0",
    "origin": {
      "amount": "250.00",
      "asset": "EUR",
      "node": {
        "type": "account",
        "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
      },
      "rate": "1"
    },
    "destination": {
      "amount": "250.00",
      "asset": "EUR",
      "node": {
        "type": "external-account",
        "id": "cc8e8abc-0f95-4b9f-8490-2569a67bd80e",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
      },
      "rate": "1"
    },
    "denomination": {
      "asset": "EUR",
      "amount": "250.00",
      "target": "origin",
      "rate": "1"
    },
    "fees": [],
    "expiresAt": "2024-07-24T15:22:39Z"
  }
}
Quotes typically expire quickly. Prompt for user confirmation within the expiry window and requote if needed.

Confirm and create transaction

After the user confirms the withdrawal, call Create transaction with the quote ID to execute the transfer.
POST /core/transactions
{
  "quoteId": "623000c8-9bdf-4a2b-aa3d-6a6b44a7f6a0"
}
In a successful SEPA withdrawal, the origin is the user’s account and the destination is the external-account representing the user’s bank. The transaction status is initially processing and updates to completed once the transfer settles.
{
  "transaction": {
    "id": "d3e4f5a6-1b2c-4d5e-9f8a-7b6c5d4e3f2a",
    "origin": {
      "asset": "EUR",
      "amount": "250.00",
      "node": {
        "type": "account",
        "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
      }
    },
    "destination": {
      "asset": "EUR",
      "amount": "250.00",
      "node": {
        "type": "external-account",
        "id": "cc8e8abc-0f95-4b9f-8490-2569a67bd80e",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a",
        "network": "sepa"
      }
    },
    "status": "processing",
    "quotedAt": "2025-01-10T14:22:15Z",
    "createdAt": "2025-01-10T14:22:45Z",
    "updatedAt": "2025-01-10T14:22:45Z",
    "denomination": {
      "asset": "EUR",
      "amount": "250.00",
      "target": "origin"
    }
  }
}

Monitor for settlement

Prefer webhooks for real-time updates, or fall back to polling if webhooks are not feasible.

Notify the user

Display an in-app confirmation when the transaction is completed, and send an email if applicable.
You now support SEPA bank transfer withdrawals via the REST API.