sondahub

sondahub / Bank API / Transfers

Fake transfers API

800 transfers from the Bank API, a fake banking API. Money moving between two accounts. POST {"from_account_id","to_account_id","amount","description"} and the hub checks the funds, debits, credits, and writes both transactions. Insufficient funds answers 422.

Reads with filters, sorting, search and relations; writes that answer like a real server and stay in your session token. Same ids on every build. Free, no key, CORS open.

Connect

List
https://api.sondahub.com/v1/bank/transfers
One record
https://api.sondahub.com/v1/bank/transfers/{id}
OpenAPI 3
https://api.sondahub.com/v1/bank/openapi.json
GraphQL
https://api.sondahub.com/v1/bank/graphql
JSON file
https://api.sondahub.com/data/bank/transfers.json
MCP
https://api.sondahub.com/mcp · list_records
The first three transfers
curl "https://api.sondahub.com/v1/bank/transfers?limit=3"

Sample records

Records 1 to 3 of 800, exactly as GET /v1/bank/transfers/{id} answers them. The data file holds all of them.

[
  {
    "id": 1,
    "created_at": "2026-06-04T13:02:16Z",
    "updated_at": "2026-06-04T13:02:16Z",
    "from_account_id": 578,
    "to_account_id": 599,
    "amount": 1265.87,
    "currency": "USD",
    "description": "Gift",
    "status": "pending",
    "debit_transaction_id": null,
    "credit_transaction_id": null,
    "scheduled_for": "2026-06-11",
    "executed_at": null
  },
  {
    "id": 2,
    "created_at": "2026-07-01T09:30:56Z",
    "updated_at": "2026-07-01T09:30:56Z",
    "from_account_id": 139,
    "to_account_id": 553,
    "amount": 594.35,
    "currency": "USD",
    "description": "Rent",
    "status": "completed",
    "debit_transaction_id": null,
    "credit_transaction_id": null,
    "scheduled_for": null,
    "executed_at": "2026-07-01T09:31:56Z"
  },
  {
    "id": 3,
    "created_at": "2026-08-03T05:40:58Z",
    "updated_at": "2026-08-03T05:40:58Z",
    "from_account_id": 430,
    "to_account_id": 39,
    "amount": 2498.73,
    "currency": "USD",
    "description": "Invoice 1042",
    "status": "completed",
    "debit_transaction_id": null,
    "credit_transaction_id": null,
    "scheduled_for": null,
    "executed_at": "2026-08-03T05:40:58Z"
  }
]

Fields

FieldTypeNotes
idread-onlyintAssigned by the server. Seed records keep their ids across restarts; records you create continue after the seed.
created_atread-onlydatetimeWhen the record was created (ISO 8601, UTC).
updated_atread-onlydatetimeWhen the record last changed.
from_account_idrequiredint → accounts
to_account_idrequiredint → accounts
amountrequiredfloatmin 0.01
currencystring
descriptionstring
statusread-onlyenumcompleted pending failed reversed
debit_transaction_idread-onlyint → transactions
credit_transaction_idread-onlyint → transactions
scheduled_fordate
executed_atread-onlydatetime

Relations: from_account → one account through from_account_id; to_account → one account through to_account_id. Use ?expand=from_account,to_account to embed them, or the nested routes.

Endpoints

POST checks both accounts exist, are active, hold the same currency and that the amount is available, then debits, credits and writes a transaction on each side; the answer carries debit_transaction_id and credit_transaction_id. Anything wrong answers 422 with the reason.
GET/v1/bank/transfersA page, with every filter, sort, search, field and expand option.
POST/v1/bank/transfersCreate one: 201 with the record, its id, a Location header and the session token that keeps it; 422 names each field that is wrong.
GET/v1/bank/transfers/{id}One record, with an ETag; If-None-Match earns a 304.
PATCH/v1/bank/transfers/{id}Change the fields you send.
PUT/v1/bank/transfers/{id}Replace the record; required fields must all be there.
DELETE/v1/bank/transfers/{id}Answers 200 with what was removed (a real server’s 204 lives at /v1/utils/status/204); gone for the session.
GET/v1/bank/transfers/{id}/from_accountThe account this record points at.
GET/v1/bank/transfers/{id}/to_accountThe account this record points at.

Try it

List with a filter
curl "https://api.sondahub.com/v1/bank/transfers?status=pending&amount_gte=10&expand=from_account&limit=3"
One record
curl https://api.sondahub.com/v1/bank/transfers/1?expand=from_account
Create
curl -i -X POST https://api.sondahub.com/v1/bank/transfers \
  -H "Content-Type: application/json" \
  -d '{"from_account_id":1,"to_account_id":3,"amount":100,"description":"Rent"}'
Read it back: newest first (send the session token)
curl "https://api.sondahub.com/v1/bank/transfers?sort=-id&limit=3" \
  -H "X-Sondahub-Session: THE_TOKEN_FROM_THE_CREATE"
Change one field
curl -X PATCH https://api.sondahub.com/v1/bank/transfers/1 \
  -H "Content-Type: application/json" \
  -d '{"amount":42.5}'
Delete the one you created
curl -X DELETE https://api.sondahub.com/v1/bank/transfers/801 \
  -H "X-Sondahub-Session: THE_TOKEN_FROM_THE_CREATE"

Query recipes

Every list option works on transfers; these are ready to paste. All the options.

WhatRequest
Page 2, 50 at a time (of 800)/v1/bank/transfers?page=2&limit=50
Only status = completed/v1/bank/transfers?status=completed
Amount between two values, largest first/v1/bank/transfers?amount_gte=1&amount_lte=500&sort=-amount
Newest first by created at/v1/bank/transfers?sort=-created_at&limit=5
Currency contains “usd”/v1/bank/transfers?currency_like=usd
Full-text search/v1/bank/transfers?q=usd
Only some fields/v1/bank/transfers?fields=id,currency&limit=5
Embed the from account/v1/bank/transfers/1?expand=from_account
Just the count/v1/bank/transfers?limit=1&fields=id

GraphQL

The same transfers as the transfers query on https://api.sondahub.com/v1/bank/graphql, and one transfer as transfer(id: 1). Introspection is on. More on the GraphQL API.

{
  transfers(limit: 3, sort: "-id", filter: { status: completed }) {
    total
    data {
      id from_account_id to_account_id amount
      from_account { number }
    }
  }
}
Run it
curl https://api.sondahub.com/v1/bank/graphql -H "Content-Type: application/json" -d '{"query": "{ transfers(limit: 3, sort: \"-id\", filter: { status: completed }) { total data { id from_account_id to_account_id amount from_account { number } } } }"}'

From an AI agent (MCP)

The MCP server reaches the same rows with list_records, get_record, create_record, update_record and delete_record, and as the resource sondahub://bank/transfers.

tools/call
curl https://api.sondahub.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_records","arguments":{"api":"bank","collection":"transfers","filters":{"status":"completed"},"limit":3}}}'

More in the Bank API

customers (400) · accounts (640) · cards (505) · transactions (7,674) · fx rates (28)

The live streams, and the whole API on one page: Bank API. Other worlds: fake e-commerce API, fake IoT API, fake social media API, fake helpdesk API, fake flight booking API, fake user directory API.