Skip to content

Core concepts

Everything in Tuppence belongs to one account, in one mode (test or live). The payment is central: links, invoices and saved cards create payments; refunds, disputes and events follow from them; payouts take their money to your bank.

Subscriptionsub_Payment linklink_Customercus_Saved methodpm_Invoiceinv_Paymentpay_BalanceGET /v1/balancePayoutpo_Refundrfnd_Disputedp_Eventevt_Webhook endpointwe_ · your URLbillspaid bycreateskeepscharge_savednetto your banksigned POST
ObjectWhat it isRead more
Payment pay_An amount to be paid, by a card (or, in the UK, Bacs Direct Debit). Paid on the hosted page (approval_url), in your checkout (client_secret), or from a saved cardTake a payment
Payment link link_A URL anyone can pay; each payment through it has payment_link setPayment links
Customer cus_Who pays: email, name, saved methodsSaved cards
Saved payment method pm_A card or bank account kept under a mandate (mdt_) the customer agreed to, charged with nobody thereSaved cards
Plan plan_, subscription sub_, invoice inv_What you sell on repeat; a customer paying for it; one invoice per chargeSubscriptions
Refund rfnd_Money back on a payment, whole or partRefunds
Dispute dp_A cardholder asking their bank for the money backDisputes
Event evt_, webhook endpoint we_What happened, delivered signed to your URLWebhooks
Balance, payout po_Money waiting to clear, then paid to your bankPayouts
Account acct_, connected accountYour business; on Connect, a business your platform runs, acted as with Tuppence-Account: acct_…Connect
API key key_What your code authenticates with (below)Going live
requires_payment_methodrequires_action3-D SecureprocessingBacs Direct Debitrequires_capturecapture_method: manualsucceededcanceledcard paidbank askspayer passesdebit~3 working daysapprovedcapturecancel · 6 dayscancel

A declined card leaves it requires_payment_method, payable again (payment.failed). Each move sends an event: payment.created, .requires_action, .requires_capture, .processing, .succeeded, .failed, .canceled. Statuses in full →

Base URLhttps://api.tuppence.ai/v1/…, JSON in and out
AuthAuthorization: Bearer sk_test_…
AmountsIntegers in the minor unit: 2000 is £20.00 or $20.00
IdempotencyIdempotency-Key: <uuid> on every POST; a retry returns the first result (Idempotent-Replayed: true). Kept 24 hours. Required on payments, refunds, payouts and credit top-ups; the SDKs send one for you. More →
VersionDated, pinned per account. Tuppence-Version: 2026-09-20 chooses one. More →
Acting for another accountTuppence-Account: acct_… (Connect)
Rate limitPer key: 100/s live, 25/s test. 429 carries Retry-After
{
"error": {
"type": "invalid_request_error",
"code": "amount_too_large",
"message": "Only 1500 is left to refund on this payment.",
"param": "amount",
"request_id": "req_01J8ZKF8G0H2J4K6M8N0P2Q4R6"
}
}

Branch on code (stable; never renamed), never on message. Quote request_id to support. Retry only network errors, 5xx, 429 and 409 idempotency_in_progress.

typeHTTP
invalid_request_error400, 404, 409, 410
authentication_error401
permission_error403
card_error402
idempotency_error409
rate_limit_error429
api_error5xx

Every code →

{ "object": "list", "data": [{ "id": "pay_01K…" }], "has_more": true }

Newest first. ?limit= 1–100 (default 10); page on with starting_after=<last id>, or back with ending_before=<first id>. The SDKs’ listAll() / list_all() walk every page for you.

<prefix>_<ULID>: 26 upper-case characters that sort by creation time, which is why an id works as a list cursor. The prefix says what it is: pay_, link_, cus_, pm_, mdt_, plan_, sub_, inv_, rfnd_, dp_, evt_, we_, po_, acct_, sets_ (setup session), tr_ (transfer), fee_ (application fee), req_ (request).

{
"id": "evt_…",
"object": "event",
"type": "payment.succeeded",
"livemode": false,
"created": 1790000000,
"api_version": "2026-09-20",
"request_id": "req_…",
"data": { "object": { "id": "pay_…", "object": "payment", "amount": 2000 } }
}

Signed with Tuppence-Signature; retried for 72 hours until you answer 2xx. Connect events add account. Webhooks →

KeyWhereCan
sk_test_… / sk_live_…Your server onlyEverything the account can
rk_test_… / rk_live_…A service or an agentOnly its scopes (payments:read, …), optionally from fixed IPs
pk_test_… / pk_live_…The browserPay one payment it holds the client_secret for
whsec_…Your webhook handlerVerify deliveries (not an API key)
Test modeLive mode
MoneyNone movesReal
KeysFrom sign-up, under Developers → API keysTake payments once your business is verified
CardsTest cardsReal cards
TimeTest clock and helpersReal time
DataNever sees live dataNever sees test data

Same API, same code: only the key changes. Going live →

Docs assistant

Open as a page
Loading the assistant…