Node.js — @tuppence/node
npm install @tuppence/nodeimport { Tuppence } from "@tuppence/node";
const tuppence = new Tuppence(process.env.TUPPENCE_SECRET_KEY);
const customer = await tuppence.customers.create({ name: "Ada Lovelace", email: "ada@example.com" });const payment = await tuppence.payments.create({ amount: 2000, currency: "gbp", customer: customer.id,});console.log(payment.id, payment.status, payment.approval_url);
// Every item of a list, page by page, fetched only as you reach it.for await (const c of tuppence.customers.listAll({ limit: 100 })) { console.log(c.id, c.email); break;}What it does for you
Section titled “What it does for you”- Types for every object and request, generated from the API’s contract — they cannot lag it.
- An
Idempotency-Keyon everyPOST, reused across that call’s retries; pass{ idempotencyKey }to choose it. - Retries — twice by default, with jittered backoff, honouring
Retry-After— on network errors, timeouts,5xx,429and a request still in flight. Never another4xx. - Typed errors:
CardError,InvalidRequestError,AuthenticationError,PermissionError,RateLimitError,IdempotencyError,ApiError,ConnectionError— allTuppenceError, withcode,param,declineCodeandrequestId. - Webhooks:
tuppence.webhooks.constructEvent(rawBody, signatureHeader, secret). - Anything else:
tuppence.request("GET", "/v1/…"), with the same auth, retries and idempotency.
Options
Section titled “Options”new Tuppence(key, { apiVersion: "2026-09-20", // pin a version (default: your account's) maxRetries: 4, timeoutMs: 10_000,});await tuppence.balance.retrieve({ maxRetries: 0, timeoutMs: 2_000 }); // per requestbaseUrl (or TUPPENCE_API_URL in the environment) points it at another API — a test
environment, say.