Skip to content

Node.js — @tuppence/node

Terminal window
npm install @tuppence/node
import { 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;
}
  • Types for every object and request, generated from the API’s contract — they cannot lag it.
  • An Idempotency-Key on every POST, 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, 429 and a request still in flight. Never another 4xx.
  • Typed errors: CardError, InvalidRequestError, AuthenticationError, PermissionError, RateLimitError, IdempotencyError, ApiError, ConnectionError — all TuppenceError, with code, param, declineCode and requestId.
  • Webhooks: tuppence.webhooks.constructEvent(rawBody, signatureHeader, secret).
  • Anything else: tuppence.request("GET", "/v1/…"), with the same auth, retries and idempotency.
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 request

baseUrl (or TUPPENCE_API_URL in the environment) points it at another API — a test environment, say.