Pay a UK account by Faster Payments

Save a UK sort code and account number as a Faster Payments payee and send a GBP payout from a wallet-backed account.

Use this recipe to save a UK sort code and account number as a Faster Payments payee and send a GBP payout from a wallet-backed account.

Who it is for. A US marketplace that pays a UK seller's sterling account.

Status. Available from wallet-backed accounts to GB, if Gravv has enabled Faster Payments for your business. Not supported from bank-held USD accounts. Gravv does not support CHAPS or BACS.

Money example

  1. The marketplace's wallet-backed USD account holds 3,000.00 USD.
  2. The marketplace sends 800.00 USD to Oliver Bennett's UK account.
  3. At an example rate of 0.75 GBP per USD, the response shows 600.00 GBP for Oliver in local_amount. Gravv debits the account 800.00 USD plus the fee on your plan.

Before you start

You need the same as for SEPA:

  • A wallet-backed source account.
  • Faster Payments enabled for your business.
  • The seller's sort code, account number, name and address.

Find out what is required

  • Payee rules. Set payee_type to fps and currency to GBP, the only currency allowed. Put the 6-digit sort code in routing_number. Send account_number as 4 to 34 letters or digits with no spaces. Also send account_owner_type, bank_name and address.
  • Always send payee_type fps. Without it, Gravv guesses the payee type from the details, and a mistyped routing number can turn the payee into a US payee.
  • Indicative rate. Call GET /v1/transfer/rates?currency=GBP and read the item with direction USD_GBP.

Steps

1. Save the Faster Payments payee

curl --request POST \
 --url https://api.gravv.xyz/v1/external-accounts \
 --header 'Api-Key: <API_KEY>' \
 --header 'Content-Type: application/json' \
 --header 'Idempotency-Key: 70145bba-a8e7-4f2f-8700-4160600e6cbe' \
 --data '
{
"customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"payee_type": "fps",
"currency": "GBP",
"account_name": "Oliver Bennett",
"routing_number": "601613",
"account_number": "31926819",
"account_owner_type": "individual",
"bank_name": "NatWest",
"address": {
"address_line1": "221 Baker Street",
"city": "London",
"postal_code": "NW1 6XE",
"country": "GB"
}
}
'
const response = await fetch("https://api.gravv.xyz/v1/external-accounts", {
method: "POST",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Content-Type": "application/json",
"Idempotency-Key": "70145bba-a8e7-4f2f-8700-4160600e6cbe",
},
body: JSON.stringify({
"customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"payee_type": "fps",
"currency": "GBP",
"account_name": "Oliver Bennett",
"routing_number": "601613",
"account_number": "31926819",
"account_owner_type": "individual",
"bank_name": "NatWest",
"address": {
  "address_line1": "221 Baker Street",
  "city": "London",
  "postal_code": "NW1 6XE",
  "country": "GB"
}
}),
});
console.log(response.status, await response.json());
import os

import requests

response = requests.post(
"https://api.gravv.xyz/v1/external-accounts",
headers={
    "Api-Key": os.environ["GRAVV_API_KEY"],
    "Content-Type": "application/json",
    "Idempotency-Key": "70145bba-a8e7-4f2f-8700-4160600e6cbe",
},
json={
    "customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "payee_type": "fps",
    "currency": "GBP",
    "account_name": "Oliver Bennett",
    "routing_number": "601613",
    "account_number": "31926819",
    "account_owner_type": "individual",
    "bank_name": "NatWest",
    "address": {
        "address_line1": "221 Baker Street",
        "city": "London",
        "postal_code": "NW1 6XE",
        "country": "GB",
    },
},
)
print(response.status_code, response.json())
{
  "data": {
    "account_name": "OLIVER BENNETT",
    "account_number": "31926819",
    "account_owner_type": "individual",
    "address": {
      "address_line1": "221 Baker Street",
      "city": "London",
      "country": "GB",
      "postal_code": "NW1 6XE"
    },
    "currency": "GBP",
    "customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "date_created": "2026-10-13T22:41:25.016918Z",
    "id": "7b1a2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
    "institution_name": "NatWest",
    "payee_type": "fps",
    "routing_number": "601613",
    "status": "pending"
  },
  "error": null
}

The payee starts as pending. Wait for the external_account.active webhook before you send the payout.

2. Send the payout

curl --request POST \
 --url https://api.gravv.xyz/v1/transfer \
 --header 'Api-Key: <API_KEY>' \
 --header 'Content-Type: application/json' \
 --header 'Idempotency-Key: c72fcd5c-b78d-4442-b1b3-c89df886eef9' \
 --data '
{
"customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"source": {
"source_type": "internal_account",
"id": "9b2d6f0e-3c1a-4e8b-a7d5-2f4c6e8a0b13"
},
"destination": {
"destination_type": "external_account",
"id": "7b1a2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"rail": "fps"
},
"amount": "800.00",
"description": "Marketplace payout order 5590",
"client_reference": "fps-ob-5590"
}
'
const response = await fetch("https://api.gravv.xyz/v1/transfer", {
method: "POST",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Content-Type": "application/json",
"Idempotency-Key": "c72fcd5c-b78d-4442-b1b3-c89df886eef9",
},
body: JSON.stringify({
"customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"source": {
  "source_type": "internal_account",
  "id": "9b2d6f0e-3c1a-4e8b-a7d5-2f4c6e8a0b13"
},
"destination": {
  "destination_type": "external_account",
  "id": "7b1a2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  "rail": "fps"
},
"amount": "800.00",
"description": "Marketplace payout order 5590",
"client_reference": "fps-ob-5590"
}),
});
console.log(response.status, await response.json());
import os

import requests

response = requests.post(
"https://api.gravv.xyz/v1/transfer",
headers={
    "Api-Key": os.environ["GRAVV_API_KEY"],
    "Content-Type": "application/json",
    "Idempotency-Key": "c72fcd5c-b78d-4442-b1b3-c89df886eef9",
},
json={
    "customer_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "source": {
        "source_type": "internal_account",
        "id": "9b2d6f0e-3c1a-4e8b-a7d5-2f4c6e8a0b13",
    },
    "destination": {
        "destination_type": "external_account",
        "id": "7b1a2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
        "rail": "fps",
    },
    "amount": "800.00",
    "description": "Marketplace payout order 5590",
    "client_reference": "fps-ob-5590",
},
)
print(response.status_code, response.json())
{
  "data": {
    "amount": "800",
    "amount_currency": "USD",
    "reference": "8e0a2c4e-6f8b-4a0c-b2e4-6a8c0e2f4b56",
    "date_created": "2026-10-13T11:20:00.000Z",
    "transfer_status": "pending",
    "transaction_id": "1c3e5a7c-9e1b-4c3e-a5c7-9e1b3d5f7a67",
    "local_amount": "600",
    "local_currency": "GBP",
    "fee": "2",
    "fee_currency": "USD",
    "requires_approval": false
  },
  "error": null
}

3. Follow it to the end

The transaction shows transaction_type global_remittance and channel bank_transfer. The webhooks carry workflow_type fps_transfer.

What can go wrong

Response Why Fix
400 routing number (sort code) required but missing for fps payee: invalid input The request has no sort code Send it in routing_number
400 account number must not contain spaces The account number has spaces Send 31926819, not 3192 6819
400 EUR not supported for fps external accounts: invalid input Faster Payments payees are GBP only Send "currency": "GBP"
A GBP payee saved with a 9-digit routing number becomes a US payee and fails the USD rule The request had no payee_type Always send "payee_type": "fps"
400 a recipient with the same account name, account number and bank already exists, with data.payee_id A payee with the same customer, name, account number and sort code already exists. 60-16-13 and 601613 count as the same sort code Use data.payee_id
400 account_number (UK sort code + account number) is required for FPS transfers The payee has no account number Fix the payee or save a new one
Source, country and rate errors The same errors as for SEPA, with GB/GBP See SEPA

Webhooks you will receive

You receive the same webhooks as for SEPA.

Testing in sandbox

Sandbox simulates Faster Payments payee setup, and the payee becomes active in a few seconds. Everything else works as for SEPA.

Reference

Was this page helpful?