GBP accounts

GBP account management

Create, query, and manage Sterling virtual IBANs for your clients. Full lifecycle from provisioning through to closure.

What you can do

The Sterling account endpoints let you provision GBP virtual IBANs, retrieve balances, pull statements, and control account status. Each client can hold one GBP account.

Provision

Create accounts

Provision a GBP virtual IBAN for any Active client. One account per client per currency.

Query

Balances and statements

List all accounts with real-time balances. Pull transaction statements with date filtering and pagination.

Control

Block, unblock, close

Freeze accounts to stop payments, reactivate them, or permanently close when no longer needed.

Endpoints at a glance

Method Path Description
POST /api/v1/sterling-account Create a GBP virtual account
GET/api/v1/sterling-accountList all GBP accounts
POST/api/v1/sterling-account/statementsGet transaction statements
POST.../{reference}/block/{iban}Block an account
POST.../{reference}/unblock/{iban}Unblock an account
POST.../{reference}/close/{iban}Close an account (irreversible)
GET /api/v1/client/{"{reference}"}/accounts Get all accounts for a client

Account lifecycle

GBP accounts move through a defined set of statuses. Blocking is reversible. Closing is permanent.

Processing
→
Active
→
Blocked
→
Active
From Active or Blocked:
→
Closed
(permanent)

Create an account

Provision a GBP virtual IBAN for a client. The client must have Active status and must not already have a GBP account.

Request body

Only one field required: clientReference. This is the Mercury-assigned reference returned when you onboarded the client via POST /api/v1/client.

Asynchronous

Returns a Processing status immediately. Listen for the Accounts.AccountCreated webhook to confirm the IBAN is ready.

{
  "clientReference": "CLIENT-001"
}
{
  "Response": {
    "Status": "Processing",
    "Message": "Your account request has been logged and is currently being processed",
    "RequestId": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
    "CreatedDate": "2026-02-23T15:26:37Z",
    "ClientReference": "CLIENT-001",
    "RequestedAccountDetails": {
      "AccountName": "Acme Ltd",
      "AccountType": "GB",
      "Currency": ["GBP"]
    }
  }
}
{
  "status": "Error",
  "message": "Request validation failed",
  "errors": [
    {
      "propertyName": "clientReference",
      "errorDescription": "The client already has a Virtual IBAN for the currency"
    }
  ]
}
import requests
import base64
import hashlib
import hmac
import uuid
import os

BASE_URL = os.getenv("MERCURY_BASE_URL")
API_KEY = os.getenv("MERCURY_API_KEY")
SECRET_KEY = os.getenv("MERCURY_SECRET_KEY")

nonce = str(uuid.uuid4())
method = "POST"
path = "/api/v1/sterling-account"
body = '{"clientReference":"CLIENT-001"}'

string_to_sign = "\n".join([API_KEY, method, path, body, nonce])
signature = base64.b64encode(
    hmac.new(SECRET_KEY.encode(), string_to_sign.encode(), hashlib.sha256).digest()
).decode()

headers = {
    "x-api-key": API_KEY,
    "x-nonce": nonce,
    "Authorization": f"HMACSHA256 {signature}",
    "Content-Type": "application/json"
}

response = requests.post(f"{BASE_URL}{path}", headers=headers, data=body.encode("utf-8"))
print(response.json())
const crypto = require("crypto");
const https = require("https");

const BASE_URL = process.env.MERCURY_BASE_URL;
const API_KEY = process.env.MERCURY_API_KEY;
const SECRET_KEY = process.env.MERCURY_SECRET_KEY;

const nonce = crypto.randomUUID();
const method = "POST";
const path = "/api/v1/sterling-account";
const body = JSON.stringify({ clientReference: "CLIENT-001" });

const stringToSign = [API_KEY, method, path, body, nonce].join("\n");
const signature = crypto
  .createHmac("sha256", SECRET_KEY)
  .update(stringToSign, "utf8")
  .digest("base64");

const url = new URL(path, BASE_URL);
const req = https.request(url, {
  method,
  headers: {
    "x-api-key": API_KEY,
    "x-nonce": nonce,
    "Authorization": `HMACSHA256 ${signature}`,
    "Content-Type": "application/json"
  }
}, (res) => {
  let data = "";
  res.on("data", (chunk) => data += chunk);
  res.on("end", () => console.log(JSON.parse(data)));
});

req.write(body);
req.end();
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.http.*;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.UUID;

String baseUrl = System.getenv("MERCURY_BASE_URL");
String apiKey = System.getenv("MERCURY_API_KEY");
String secretKey = System.getenv("MERCURY_SECRET_KEY");

String nonce = UUID.randomUUID().toString();
String method = "POST";
String path = "/api/v1/sterling-account";
String body = "{\"clientReference\":\"CLIENT-001\"}";

String stringToSign = String.join("\n", apiKey, method, path, body, nonce);
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
String signature = Base64.getEncoder()
    .encodeToString(mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8)));

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create(baseUrl + path))
    .header("x-api-key", apiKey)
    .header("x-nonce", nonce)
    .header("Authorization", "HMACSHA256 " + signature)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

HttpResponse<String> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

List all accounts

Retrieve all GBP virtual accounts under your distributor. Returns account details, balances, and status for each account.

[
  {
    "ClientReference": "CLIENT-001",
    "ClientName": "Acme Ltd",
    "AccountName": "Acme Ltd",
    "Iban": "GB71CLRB04082700001159",
    "SortCode": "040827",
    "AccountNumber": "00001159",
    "Balance": {
      "CurrencyCode": "GBP",
      "Amount": 1000
    },
    "AvailableBalance": {
      "CurrencyCode": "GBP",
      "Amount": 1000
    },
    "Currency": "GBP",
    "Status": "Active",
    "ExternalReference": "EXT-REF-001",
    "CreatedDate": "2026-02-23T15:26:37Z"
  }
]
Balance

Total funds held in the account, including pending transactions.

Available balance

Funds available for immediate withdrawal or payment. May differ from Balance if transactions are pending.

Cross-currency

Use GET /api/v1/client/{reference}/accounts to retrieve both GBP and EUR accounts for a single client.

Get statements

Pull transaction history for all GBP accounts. All filter fields are optional. Omit the body entirely to retrieve all available transactions.

Date format

Dates use a {year, month, day} object, not an ISO string. Dates must not be in the future.

{
  "startDate": {
    "year": 2026,
    "month": 1,
    "day": 1
  },
  "endDate": {
    "year": 2026,
    "month": 3,
    "day": 31
  },
  "pageSize": 50
}
[
  {
    "ClientReference": "CLIENT-001",
    "ExternalClientReference": "EXT-REF-001",
    "Date": "2026-02-15",
    "TimeStamp": "2026-02-15T08:38:16Z",
    "EndToEndIdentifier": "E2E-20260215-001",
    "Detail": "Invoice GBP-2026-001",
    "Payments": 500,
    "Receipts": 0,
    "BankAccount": "GB71CLRB04082700001159",
    "BankReference": "Invoice GBP-2026-001",
    "TransactionType": "Debit"
  }
]
Debits

Payments field contains the amount. Receipts will be 0. TransactionType is "Debit".

Credits

Receipts field contains the amount. Payments will be 0. TransactionType is "Credit".

Block and unblock

Blocking an account prevents all payments in and out. Unblocking restores it to Active. Both require the client reference and the account IBAN as path parameters.

POST /api/v1/sterling-account/{reference}/block/{iban}
POST /api/v1/sterling-account/{reference}/unblock/{iban}
{
  "ClientReference": "CLIENT-001",
  "ClientName": "Acme Ltd",
  "AccountName": "Acme Ltd",
  "Iban": "GB71CLRB04082700001159",
  "SortCode": "040827",
  "AccountNumber": "00001159",
  "Balance": { "CurrencyCode": "GBP", "Amount": 1000 },
  "AvailableBalance": { "CurrencyCode": "GBP", "Amount": 1000 },
  "Currency": "GBP",
  "Status": "Blocked",
  "ExternalReference": "EXT-REF-001",
  "CreatedDate": "2026-02-23T15:26:37Z"
}
{
  "ClientReference": "CLIENT-001",
  "ClientName": "Acme Ltd",
  "AccountName": "Acme Ltd",
  "Iban": "GB71CLRB04082700001159",
  "SortCode": "040827",
  "AccountNumber": "00001159",
  "Balance": { "CurrencyCode": "GBP", "Amount": 1000 },
  "AvailableBalance": { "CurrencyCode": "GBP", "Amount": 1000 },
  "Currency": "GBP",
  "Status": "Active",
  "ExternalReference": "EXT-REF-001",
  "CreatedDate": "2026-02-23T15:26:37Z"
}

Close an account

Irreversible

Closing an account is permanent. The account balance must be zero across all currencies before you call this endpoint. Ensure all pending transactions have settled first.

POST /api/v1/sterling-account/{reference}/close/{iban}
{
  "ClientReference": "CLIENT-001",
  "ClientName": "Acme Ltd",
  "AccountName": "Acme Ltd",
  "Iban": "GB71CLRB04082700001159",
  "SortCode": "040827",
  "AccountNumber": "00001159",
  "Balance": { "CurrencyCode": "GBP", "Amount": 0 },
  "AvailableBalance": { "CurrencyCode": "GBP", "Amount": 0 },
  "Currency": "GBP",
  "Status": "A request to close the account has been logged and is currently being processed",
  "ExternalReference": "EXT-REF-001",
  "CreatedDate": "2026-02-23T15:26:37Z"
}
{
  "status": "Error",
  "message": "Request validation failed",
  "errors": [
    {
      "propertyName": "iban",
      "errorDescription": "Account with the provided Iban has a positive balance in one or more currencies. Cannot close account until balance is zero"
    }
  ]
}

Webhook events

Five webhook events cover the full account lifecycle. Listen for these to track account state changes in real time rather than polling.

Event Type field When it fires
AccountCreated AccountCreated IBAN provisioned and active
AccountCreationFailedAccountCreationFailedProvisioning failed. Check Errors object.
AccountBlockedAccountBlockedAccount frozen, payments stopped
AccountUnBlockedAccountBlockedAccount reactivated. Check Status field, not Type.
AccountClosed AccountClosed Account permanently closed
Gotcha: unblock webhook

The Accounts.AccountUnBlocked webhook has Type: "AccountBlocked" in the payload, not "AccountUnBlocked". You must check the Payload.Status field to distinguish between block and unblock events. Status will be "Blocked" or "UnBlocked".

{
  "Type": "AccountCreated",
  "Payload": {
    "OwnerReference": "CLIENT-001",
    "Owner": "Acme Ltd",
    "Currencies": ["GBP"],
    "Identifiers": [
      { "Identifier": "GB71CLRB04082700001159", "Kind": "Iban" }
    ],
    "Status": "Active",
    "TimestampCreated": "2026-02-23T15:26:37.5612949Z"
  },
  "Nonce": "VkPweAa3fHcJTAowEv3P1g=="
}
{
  "Type": "AccountCreationFailed",
  "Payload": {
    "OwnerReference": "CLIENT-001",
    "OwnerName": "Acme Ltd",
    "Currencies": ["GBP"],
    "AccountIdentifiers": { "Iban": null, "Bban": null },
    "Errors": {
      "FieldName": ["error description"]
    }
  },
  "Nonce": "XrNcCDMvPN3KvfcU4f+U9Q=="
}
{
  "Type": "AccountBlocked",
  "Payload": {
    "OwnerReference": "CLIENT-001",
    "Owner": "Acme Ltd",
    "Identifiers": [
      { "Identifier": "GB71CLRB04082700001159", "Kind": "Iban" }
    ],
    "Status": "Blocked"
  },
  "Nonce": "1BSubJoGnKN+uN2kVYx0bw=="
}
{
  "Type": "AccountBlocked",
  "Payload": {
    "OwnerReference": "CLIENT-001",
    "Owner": "Acme Ltd",
    "Identifiers": [
      { "Identifier": "GB71CLRB04082700001159", "Kind": "Iban" }
    ],
    "Status": "UnBlocked"
  },
  "Nonce": "1BSubJoGnKN+uN2kVYx0bw=="
}
{
  "Type": "AccountClosed",
  "Payload": {
    "OwnerReference": "CLIENT-001",
    "OwnerName": "Acme Ltd",
    "AccountIdentifiers": {
      "Iban": "GB71CLRB04082700001159",
      "Bban": "CLRB04082700001159"
    },
    "Status": "Closed"
  },
  "Nonce": "O/Brp8hOfXNOvDFuJ8p0vw=="
}

Common pitfalls

Client not Active

All account operations require the parent client to have Active status. If you get a 400 error, verify the client status first via GET /api/v1/client/{reference}.

One account per currency

Each client can hold one GBP virtual IBAN. Attempting to create a second returns a 400 error. Check existing accounts with GET /api/v1/sterling-account first.

Statement date format

The statements endpoint expects dates as {year, month, day} objects, not ISO 8601 strings. Future dates return a 400 error.

Close requires zero balance

You cannot close an account with a positive balance. Transfer or withdraw all funds first, wait for settlement, then close. The API will reject with a clear error message.

Next steps

Ready to provision accounts?

Open the API reference to try these endpoints in the sandbox.

Create GBP account

Did this page help you?