Supported Banks

The Supported Banks endpoint returns the banks currently available for payment selection. Use it to build a bank picker in your own checkout, then pass the selected bank's bank_id when creating a payment.

Some banks have a group, allowing related banks or account types to appear together. This guide shows how to display groups and individual banks in one alphabetical list, then drill down into a group to choose a bank.

Base URL: https://api.wonderful.one
Authentication: All API requests require an Authorization: Bearer {YOUR_AUTH_KEY} header. Obtain your token from your dashboard.


Bank selection flow

  1. Your server calls GET /v2/supported-banks.
  2. Collect banks with the same non-empty group into one group entry. Banks without a group remain individual entries.
  3. Sort the combined list of groups and individual banks alphabetically by the label shown to the customer: group for a group, or bank_name for an individual bank.
  4. Clicking an individual bank selects that bank immediately.
  5. Clicking a group opens a second list containing all banks in that group, sorted alphabetically by bank_name. Opening a group does not select a bank.
  6. Clicking a bank within the group selects that bank. Provide an “All banks” button so the customer can return to the first list.

Use the group value returned by the API rather than trying to infer groups from bank names. Treat a missing, null, empty, or whitespace-only group as an individual bank. Even if a group contains only one bank, the example below opens that group before selecting its bank.


Fetch supported banks

Request

GET /v2/supported-banks
curl --request GET \
    "https://api.wonderful.one/v2/supported-banks" \
    --header "Authorization: Bearer {YOUR_AUTH_KEY}" \
    --header "Accept: application/json"

Response

The following response is illustrative. Bank IDs and availability can change; always use the values returned by the endpoint.

{
    "data": [
        {
            "bank_id": "starling",
            "bank_name": "Starling",
            "bank_logo": "https://wonderful.co.uk/img/bank_logos/starling.png",
            "card_logo": null,
            "status": "online",
            "group": null,
            "tile_background": null
        },
        {
            "bank_id": "example-personal",
            "bank_name": "Example Bank Personal",
            "bank_logo": null,
            "card_logo": null,
            "status": "online",
            "group": "Example Bank",
            "tile_background": null
        },
        {
            "bank_id": "monzo",
            "bank_name": "Monzo",
            "bank_logo": "https://wonderful.co.uk/img/bank_logos/monzo.png",
            "card_logo": null,
            "status": "online",
            "group": null,
            "tile_background": null
        },
        {
            "bank_id": "example-business",
            "bank_name": "Example Bank Business",
            "bank_logo": null,
            "card_logo": null,
            "status": "issues",
            "group": "Example Bank",
            "tile_background": null
        }
    ]
}

Fields used in this guide

Field Description
bank_id Identifier of an individual bank. Keep this value when the customer selects a bank.
bank_name Display name for an individual bank.
bank_logo Bank logo URL, if available.
group Shared group label, or null for an individual bank.
status online or issues for banks returned by this endpoint. Banks with issues may have service problems; show a warning alongside them.

The first list for this response is Example Bank →, Monzo, Starling. Opening Example Bank shows Example Bank Business, then Example Bank Personal. Selecting Example Bank Business keeps example-business as the selected bank ID.

Server-side example (PHP)

Keep your API token on your server. For a browser-based picker, expose an endpoint in your application such as /api/banks that fetches the list and returns the JSON to your frontend. The JavaScript example below calls that application endpoint.

// Handler for your application's GET /api/banks route.
$client = new \GuzzleHttp\Client();
$response = $client->get('https://api.wonderful.one/v2/supported-banks', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('ONE_API_TOKEN'),
        'Accept' => 'application/json',
    ],
]);

header('Content-Type: application/json');
echo (string) $response->getBody();

Set ONE_API_TOKEN in your server environment. Handle upstream errors using your application's normal error handling.


Build the alphabetical list

This function returns two kinds of entries: a bank entry that selects directly, and a group entry containing its member banks. It sorts the combined first list as well as each group's bank list. It does not depend on the sequence of banks in the API response.

const alphabetically = new Intl.Collator("en", { sensitivity: "base" });

function buildBankList(banks) {
    const groups = new Map();
    const entries = [];

    for (const bank of banks) {
        const groupName = bank.group?.trim();

        if (!groupName) {
            entries.push({ type: "bank", label: bank.bank_name, bank });
            continue;
        }

        if (!groups.has(groupName)) {
            const group = { type: "group", label: groupName, banks: [] };
            groups.set(groupName, group);
            entries.push(group);
        }

        groups.get(groupName).banks.push(bank);
    }

    for (const group of groups.values()) {
        group.banks.sort((a, b) => alphabetically.compare(a.bank_name, b.bank_name));
    }

    return entries.sort((a, b) => alphabetically.compare(a.label, b.label));
}

Banks within a group appear only inside that group. Keep the entry type explicit so a group and an unrelated individual bank can have the same display label without being combined.


Render the drill-down picker

Add this markup to your checkout page. The hidden input holds the selected bank ID for your checkout form.

<section aria-labelledby="bank-heading">
    <h2 id="bank-heading" tabindex="-1">Choose your bank</h2>
    <button id="all-banks" type="button" hidden>← All banks</button>
    <ul id="bank-list"></ul>
    <p id="bank-message" role="status">Loading banks…</p>
    <input id="bank-id" type="hidden" name="bank_id">
</section>

Place the following script after the markup, together with buildBankList above. Selecting either an individual bank or a bank within a group calls the same selectBank function. Group buttons only change the displayed list.

const heading = document.getElementById("bank-heading");
const list = document.getElementById("bank-list");
const backButton = document.getElementById("all-banks");
const message = document.getElementById("bank-message");
const bankIdInput = document.getElementById("bank-id");
let entries = [];
let selectedBank = null;

function selectBank(bank) {
    selectedBank = bank;
    bankIdInput.value = bank.bank_id;
    message.textContent = `Selected bank: ${bank.bank_name}`;
    // Continue your checkout using selectedBank.bank_id.
}

function addButton(label, onClick) {
    const item = document.createElement("li");
    const button = document.createElement("button");
    button.type = "button";
    button.textContent = label;
    button.addEventListener("click", onClick);
    item.append(button);
    list.append(item);
}

function bankLabel(bank) {
    return bank.bank_name + (bank.status === "issues" ? " (service issues)" : "");
}

function showGroup(group) {
    heading.textContent = group.label;
    backButton.hidden = false;
    list.replaceChildren();

    for (const bank of group.banks) {
        addButton(bankLabel(bank), () => selectBank(bank));
    }

    heading.focus();
}

function showAllBanks() {
    heading.textContent = "Choose your bank";
    backButton.hidden = true;
    list.replaceChildren();

    for (const entry of entries) {
        if (entry.type === "group") {
            addButton(`${entry.label} →`, () => showGroup(entry));
        } else {
            addButton(bankLabel(entry.bank), () => selectBank(entry.bank));
        }
    }
}

backButton.addEventListener("click", () => {
    showAllBanks();
    heading.focus();
});

async function loadBanks() {
    try {
        // Your server forwards the Supported Banks response from /api/banks.
        const response = await fetch("/api/banks", {
            headers: { "Accept": "application/json" },
        });

        if (!response.ok) {
            throw new Error("Unable to fetch supported banks");
        }

        const body = await response.json();
        entries = buildBankList(body.data);
        showAllBanks();
        message.textContent = entries.length ? "" : "No banks available. Please try again later.";
    } catch (error) {
        message.textContent = "Unable to load banks. Please try again later.";
    }
}

loadBanks();

The example uses text buttons to keep the selection flow clear. You can add each bank's bank_logo alongside its name when a logo is available.


Use the selected bank

Send the selected bank_id to your server when the customer continues. Your server can then include it in a POST /v2/quick-pay request, along with the other payment details described in the Quick Pay guide.

{
    "amount": 1000,
    "merchant_payment_reference": "ORDER-1234",
    "redirect_url": "https://mysite.com/success",
    "bank_id": "example-business"
}

Use the actual bank ID returned by the endpoint in place of the illustrative example-business value. A group label is only for navigation; always submit the selected individual bank's bank_id.

For the full endpoint reference, see Supported Banks.