> ## 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.

# FPS bank withdrawal via the REST API

> Send GBP Faster Payments (FPS) withdrawals using the Uphold REST API: list linked external accounts, generate and confirm a quote, and monitor for settlement.

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

## Prerequisites

* The user has [completed onboarding](/developer-guides/user-onboarding/overview) and has the required capabilities enabled.

## Walkthrough

```mermaid theme={null}
sequenceDiagram
  autonumber
  participant Usr as User
  participant U as Your App
  participant B as Your Backend
  participant A as Uphold
  participant F as Bank

  Usr->>U: Start withdrawal
  U->>B: Find bank account
  B->>A: GET /core/external-accounts
  A-->>B: { externalAccounts }
  B-->>U: { externalAccounts }
  Usr->>U: Select bank account
  Usr->>U: Choose source account and amount
  U->>B: Request quote
  B->>A: Create quote (account -> external account)
  A-->>B: { quote }
  B-->>U: { quote }
  Usr->>U: Confirm quote
  U->>B: Create transaction
  B->>A: Create transaction
  A-->>B: { transaction }
  A-->>B: webhook: transaction.created (processing)
  A->>F: Submit bank transfer
  F-->>A: Settlement confirmed
  A-->>B: webhook: transaction.status-changed (completed/failed)
  B-->>Usr: Notify the user
```

***

## Check available rails

Before creating a quote, verify the FPS rail is available for withdrawals. Call [List Rails](/rest-apis/core-api/assets/list-rails) for `GBP` to confirm the `fps` network has the `withdraw` feature.

```http theme={null}
GET /core/rails?type=bank&network=fps&asset=GBP
```

The rail always exists in the system, but the `withdraw` feature is only present if it's enabled for the user.

```json theme={null}
{
  "rails": [
    {
      "type": "bank",
      "network": "fps",
      "method": "bank-transfer",
      "asset": "GBP",
      "decimals": 2,
      "features": [
        "deposit",
        "withdraw"
      ]
    }
  ]
}
```

## Select source account

FPS withdrawals can be sourced from any account. If the selected account is not in GBP, 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](/rest-apis/core-api/assets/introduction#features-and-deposits-/-withdrawals).

Call [List accounts](/rest-apis/core-api/accounts/list-accounts) to retrieve the user's accounts and let them pick the one to withdraw from.

```http theme={null}
GET /core/accounts
```

```json theme={null}
{
  "accounts": [
    {
      "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
      "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a",
      "label": "My GBP account",
      "asset": "GBP",
      "balance": {
        "total": "500.00",
        "available": "500.00"
      }
    }
  ]
}
```

## Select a bank account

FPS bank accounts are registered automatically as external accounts when a user makes their first FPS deposit — they cannot be added manually. If the user has no FPS-linked accounts yet, direct them to complete an [FPS deposit](/developer-guides/bank-transfers/deposit/via-rest-api/fps) first.

Call [List external accounts](/rest-apis/core-api/external-accounts/list-external-accounts) and filter for `bank` type and `fps` network to retrieve the user's linked bank accounts available for withdrawal.

```http theme={null}
GET /core/external-accounts
```

Present the accounts to the user and make sure the selected one has `status: "ok"` and `"withdraw"` in `features`.

```json theme={null}
{
  "externalAccounts": [
    {
      "id": "aa6e6efa-8d73-497c-8278-0347f459bd68",
      "type": "bank",
      "status": "ok",
      "network": "fps",
      "label": "My GBP Account",
      "features": [
        "withdraw"
      ]
    }
  ]
}
```

## Create a quote

To initiate the withdrawal, call [Create quote](/rest-apis/core-api/transactions/create-quote) with the origin as the user's account and the destination as the selected FPS external account. Specify the amount and asset for the withdrawal.

```http theme={null}
POST /core/transactions/quote
{
  "origin": {
    "type": "account",
    "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8"
  },
  "destination": {
    "type": "external-account",
    "id": "aa6e6efa-8d73-497c-8278-0347f459bd68"
  },
  "denomination": {
    "asset": "GBP",
    "amount": "250.00",
    "target": "origin"
  }
}
```

A successful response returns a `quote` object with details about the withdrawal, including fees and expiration.

```json [expandable] theme={null}
{
  "quote": {
    "id": "623000c8-9bdf-4a2b-aa3d-6a6b44a7f6a0",
    "origin": {
      "amount": "250.00",
      "asset": "GBP",
      "node": {
        "type": "account",
        "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
      },
      "rate": "1"
    },
    "destination": {
      "amount": "250.00",
      "asset": "GBP",
      "node": {
        "type": "external-account",
        "id": "aa6e6efa-8d73-497c-8278-0347f459bd68",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
      },
      "rate": "1"
    },
    "denomination": {
      "asset": "GBP",
      "amount": "250.00",
      "target": "origin",
      "rate": "1"
    },
    "fees": [],
    "expiresAt": "2024-07-24T15:22:39Z"
  }
}
```

<Info>Quotes typically **expire** quickly. Prompt for user confirmation within the expiry window and requote if needed.</Info>

## Confirm and create transaction

After the user confirms the withdrawal, call [Create transaction](/rest-apis/core-api/transactions/create-transaction) with the quote ID to execute the transfer.

```http theme={null}
POST /core/transactions
{
  "quoteId": "623000c8-9bdf-4a2b-aa3d-6a6b44a7f6a0"
}
```

In a successful FPS 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.

```json [expandable] theme={null}
{
  "transaction": {
    "id": "d3e4f5a6-1b2c-4d5e-9f8a-7b6c5d4e3f2a",
    "origin": {
      "asset": "GBP",
      "amount": "250.00",
      "node": {
        "type": "account",
        "id": "a00507fe-628c-4f27-ae81-e1c40b2a8fb8",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a"
      }
    },
    "destination": {
      "asset": "GBP",
      "amount": "250.00",
      "node": {
        "type": "external-account",
        "id": "aa6e6efa-8d73-497c-8278-0347f459bd68",
        "ownerId": "e4ce04dc-67b7-4e9f-af91-482cb6f9fc4a",
        "network": "fps"
      }
    },
    "status": "processing",
    "quotedAt": "2025-01-10T14:22:15Z",
    "createdAt": "2025-01-10T14:22:45Z",
    "updatedAt": "2025-01-10T14:22:45Z",
    "denomination": {
      "asset": "GBP",
      "amount": "250.00",
      "target": "origin"
    }
  }
}
```

## Monitor for settlement

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

* Webhook events (recommended):
  * [core.transaction.created](/rest-apis/core-api/transactions/webhooks/transaction-created)
    * `status: processing` → payout submitted to the bank network
  * [core.transaction.status-changed](/rest-apis/core-api/transactions/webhooks/transaction-status-changed)
    * `status: completed` → funds delivered to the user's bank
    * `status: failed` → irrecoverable error
* Polling (fallback): [Get transaction](/rest-apis/core-api/transactions/get-transaction)

## Notify the user

Display an in-app confirmation when the transaction is `completed`, and send an email if applicable.

<Check>You now support FPS bank transfer withdrawals via the REST API.</Check>
