npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

checkout-client

v1.0.0

Published

Unofficial Production-grade TypeScript client for the Checkout.com API — all 168 endpoints, OAuth 2.0, retry, idempotency, webhook verification, zero runtime dependencies.

Readme

checkout-client

npm CI License: MIT

Production-grade TypeScript client for the Checkout.com API.

All 168 endpoints · OAuth 2.0 · Full-jitter retry · Idempotency · Webhook verification · Zero runtime dependencies


Features

| | | | ----------------------------- | --------------------------------------------------------------------------------- | | 100% API coverage | All 168 endpoints, 43 typed service namespaces | | Zero runtime dependencies | Only Node.js built-ins (node:crypto, node:http) | | Dual-module | ESM + CommonJS, full TypeScript declarations | | Deep imports | checkout-client/payments, /vault, /disputes, /issuing, /webhook, /errors | | OAuth 2.0 | Singleflight token fetch, in-memory cache, proactive refresh 90s before expiry | | Idempotency | UUID v4 auto-injected on all eligible endpoints; override per-request | | Full-jitter retry | Exponential backoff on 429 + 5xx; configurable attempts and delays | | AbortSignal | Pass signal to any request for cancellation and timeout control | | Webhook verification | HMAC-SHA256 constant-time signature checking | | AWS PrivateLink | privateLink: truepl-{prefix}.api.checkout.com | | Typed errors | CheckoutError with status predicates and full response metadata | | Structured logging | Bring your own logger via the Logger interface | | 68 tests | Vitest, mock fetch only — zero live API calls |


Requirements

Node.js ≥ 18 (uses native fetch and crypto.randomUUID).


Installation

npm install checkout-client

Quick start

import { CheckoutClient } from "checkout-client";

const client = new CheckoutClient({
  prefix: process.env.CHECKOUT_PREFIX!, // first 8 chars of client_id
  environment: "sandbox",
  accessKeyId: process.env.CHECKOUT_ACCESS_KEY_ID,
  accessKeySecret: process.env.CHECKOUT_ACCESS_KEY_SECRET,
});

// Request a payment
const payment = await client.payments.request({
  amount: 10_000, // GBP £100.00 in minor units
  currency: "GBP",
  source: { type: "token", token: "tok_..." },
  reference: "ORD-001",
});

// Capture it
await client.payments.capture(payment.id);

// Partial refund (£25)
await client.payments.refund(payment.id, { amount: 2_500 });

Authentication

OAuth 2.0 (recommended)

new CheckoutClient({
  prefix: "vkuhvk4v",
  accessKeyId: "ack_...",
  accessKeySecret: "...",
});

Tokens are fetched once, cached in-memory, and proactively refreshed 90 s before expiry. Concurrent requests coalesce onto a single in-flight token fetch.

Static secret key

new CheckoutClient({ prefix: "vkuhvk4v", secretKey: "sk_..." });

Configuration

import type { CheckoutConfig } from "checkout-client";

const config: CheckoutConfig = {
  prefix: "vkuhvk4v", // required
  environment: "production", // "production" | "sandbox"
  accessKeyId: "ack_...", // OAuth 2.0
  accessKeySecret: "...",
  secretKey: "sk_...", // static key (alternative to OAuth)
  publicKey: "pk_...", // tokenization only
  privateLink: false, // AWS PrivateLink
  idempotencyKeyPrefix: "myapp", // auto-key prefix: "myapp-{uuid}"
  timeoutMs: 30_000, // per-request timeout
  retry: {
    maxAttempts: 4, // 1 initial + 3 retries
    baseDelayMs: 500,
    maxDelayMs: 30_000,
  },
  fetch: customFetch, // injectable for testing/proxies
  logger: {
    debug: (msg, meta) => console.log(msg, meta),
    warn: (msg, meta) => console.warn(msg, meta),
  },
};

Error handling

import { CheckoutError } from "checkout-client";
// or: import { CheckoutError } from "checkout-client/errors";

try {
  await client.payments.request({ currency: "GBP" });
} catch (err) {
  if (err instanceof CheckoutError) {
    // HTTP status predicates
    err.isNotFound(); // 404
    err.isRateLimited(); // 429 — already retried maxAttempts times
    err.isConflict(); // 409 — idempotency key collision
    err.isUnauthorized(); // 401
    err.isForbidden(); // 403
    err.isValidationError(); // 422
    err.isServerError(); // 5xx

    // Rich metadata
    err.statusCode; // number
    err.requestId; // string — include in Checkout.com support tickets
    err.errorType; // e.g. "request_invalid"
    err.errorCodes; // e.g. ["amount_invalid", "currency_required"]
    err.apiMessage; // human-readable summary
    err.rawBody; // complete response body for debugging
  }
}

Idempotency

Cko-Idempotency-Key (UUID v4) is auto-injected on all eligible endpoints: POST /payments (and all action sub-paths), POST /payment-contexts, POST /transfers.

// Custom key — safe to retry with the same value
await client.payments.request(req, { idempotencyKey: "order-42-attempt-1" });

// Prefix auto-generated keys
new CheckoutClient({ idempotencyKeyPrefix: "myapp" });
// → "myapp-550e8400-e29b-41d4-..."

Retry

Full-jitter exponential backoff: delay = random(0, min(base × 2^attempt, max))

new CheckoutClient({
  retry: {
    maxAttempts: 4, // 1 initial + 3 retries
    baseDelayMs: 500,
    maxDelayMs: 30_000,
  },
});

Retried: 429, 5xx, network errors. Not retried: 4xx except 429, 409 Conflict.


AbortSignal

Every service method accepts { signal } as its last options argument:

const controller = new AbortController();
setTimeout(() => controller.abort(), 5_000);

const payment = await client.payments.request(
  { amount: 10_000, currency: "GBP" },
  { signal: controller.signal },
);

AWS PrivateLink

new CheckoutClient({ prefix: "vkuhvk4v", privateLink: true });
// → https://pl-vkuhvk4v.api.checkout.com

Webhook verification

import {
  verifyWebhook,
  InvalidWebhookSignatureError,
} from "checkout-client/webhook";

app.post("/webhooks/checkout", express.raw({ type: "*/*" }), (req, res) => {
  try {
    const event = verifyWebhook(
      req.headers["cko-signature"],
      req.body, // Buffer or string
      process.env.CKO_WEBHOOK_KEY!,
    );
    console.log(event.type, event.id);
    res.sendStatus(200);
  } catch (err) {
    if (err instanceof InvalidWebhookSignatureError) {
      res.sendStatus(403);
    } else {
      res.sendStatus(500);
    }
  }
});

Or import directly from the root:

import { verifyWebhook, InvalidWebhookSignatureError } from "checkout-client";

Custom fetch (testing, proxies, OpenTelemetry)

// Inject a custom fetch for testing
import { CheckoutClient } from "checkout-client";

const client = new CheckoutClient({
  prefix: "testpfx1",
  secretKey: "sk_test",
  fetch: async (url, init) => {
    console.log("→", url);
    return globalThis.fetch(url, init);
  },
});

Deep imports

Each sub-module is independently importable with full tree-shaking support:

import type { PaymentRequest, PaymentResponse } from "checkout-client/payments";
import type { FXRatesResponse } from "checkout-client/vault";
import type { Dispute } from "checkout-client/disputes";
import type { CardResponse } from "checkout-client/issuing";
import { verifyWebhook } from "checkout-client/webhook";
import { CheckoutError } from "checkout-client/errors";

Complete API

| Namespace | Methods | | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | client.payments | request, list, get, getActions, incrementAuthorization, cancelRetry, capture, refund, reverse, void, search | | client.flow | createSession, submitSession, createAndSubmit | | client.paymentLinks | create, get | | client.hostedPayments | create, get | | client.paymentContexts | request, get | | client.paymentSetups | create, update, get, confirm | | client.paymentMethods | list | | client.tokens | create | | client.instruments | create, get, update, delete, getBankAccountFieldFormatting | | client.customers | create, get, update, delete | | client.transfers | create, get | | client.balances | get | | client.forex | getRates | | client.cardMetadata | get | | client.networkTokens | provision, get, requestCryptogram, delete | | client.accountUpdater | getUpdatedCredentials | | client.applePay | generateCSR, uploadCertificate, enrollDomain | | client.googlePay | enrollEntity, registerDomain, getRegisteredDomains, getEnrollmentState | | client.forward | sendRequest, getRequest, createSecret, listSecrets, updateSecret, deleteSecret | | client.sessions | create, get, update, complete, update3DSMethodCompletion | | client.compliance | get, respond | | client.agenticCommerce | createDelegatedToken | | client.reports | list, get, getFile | | client.financialActions | list | | client.disputes | list, get, accept, provideEvidence, getEvidence, submitEvidence, submitArbitrationEvidence, getSubmittedArbitrationEvidence, getSubmittedEvidence, getSchemeFiles, uploadFile, getFile | | client.workflows | list, create, get, patch, delete, addAction, updateAction, removeAction, addCondition, updateCondition, removeCondition, test, getEventTypes, getEvent, getActionInvocations, getSubjectEvents, reflowByEvent, reflowByEventAndWorkflow, reflow, reflowBySubject, reflowBySubjectAndWorkflow | | client.cardholders | create, get, update, listCards | | client.cardholderAccessTokens | request | | client.cards | create, get, update, getCredentials, activate, suspend, revoke, renew, scheduleRevocation, deleteScheduledRevocation, enrol3DS, get3DSEnrollment, update3DSEnrollment | | client.controls | create, listByTarget, get, update, delete | | client.controlProfiles | create, list, get, update, delete, addTarget, removeTarget | | client.controlGroups | create, listByTarget, get, delete | | client.issuingTransactions | list, get | | client.issuingDisputes | create, get, cancel, escalate | | client.issuingSandbox | simulateAuthorization, simulateIncrementalAuthorization, simulateClearing, simulateRefund, simulateReversal | | client.platformEntities | onboard, get, update, uploadFile, getFile, listMembers, reinviteMember | | client.platformInstruments | add, get, update, list | | client.payoutSchedules | get, update | | client.reserveRules | add, get, update, list | | client.identityApplicants | create, get, update, anonymize | | client.identityVerification | createAndStart, create, get, anonymize, createAttempt, listAttempts, getAttempt, getReport | | client.amlScreening | create, get | | client.faceAuth | create, get, anonymize, createAttempt, listAttempts, getAttempt | | client.idDocuments | create, get, anonymize, createAttempt, listAttempts, getAttempt, getReport |


Testing

npm test              # vitest run
npm run test:watch    # vitest watch mode
npm run test:coverage # coverage report

All 68 tests use mock fetch — no live API calls, no credentials needed.


Building

npm run build   # ESM + CJS + type declarations
npm run clean   # remove dist/

License

MIT — see LICENSE.