@usethrottle/checkout-sdk
v2.2.0
Published
<p align="left"> <img src="https://raw.githubusercontent.com/Epic-Design-Labs/app-throttle/main/packages/brand/assets/throttle-logo.png" alt="Throttle" height="56" /> </p>
Readme
@usethrottle/checkout-sdk
Production checkout SDK for Throttle storefront integrations.
Use the server entrypoint from backend routes to create sessions, mint embed tokens,
and read orders/payments. Use the React wrapper in the browser when you want
idempotent terminal callbacks, telemetry, and brand theming on top of
@usethrottle/checkout-react.
Install
npm install @usethrottle/checkout-sdkQuickstart
import { ThrottleCheckout } from '@usethrottle/checkout-sdk';
<ThrottleCheckout
sessionId="sess_abc"
parentOrigin="https://shop.example.com"
theme={{ primary: '#ff6600', logo: 'https://shop.example.com/logo.png' }}
onSucceeded={({ orderId }) => router.push(`/orders/${orderId}`)}
onTelemetry={(event) => analytics.track(event.type, event)}
/>;Server quickstart
Use the server export from backend routes only. It keeps your Throttle API key
out of the browser and unwraps both { data } envelopes and direct responses.
import {
buildCheckoutEmbedUrl,
buildCheckoutHostedUrl,
createCheckoutClient,
} from '@usethrottle/checkout-sdk/server';
const checkout = createCheckoutClient({
apiKey: process.env.THROTTLE_API_KEY!,
baseUrl: process.env.THROTTLE_BASE_URL,
});
const session = await checkout.createSession({
applicationId: process.env.THROTTLE_APPLICATION_ID!,
externalCartId: 'cart_123',
returnUrl: 'https://shop.example.com/checkout/success',
cancelUrl: 'https://shop.example.com/cart',
allowedMethods: ['net30'],
paymentTerms: { netN: 45 },
collect: { shippingAddress: true, billingAddress: false },
});
const embedUrl = buildCheckoutEmbedUrl({
checkoutOrigin: 'https://checkout.usethrottle.dev',
sessionId: session.sessionId,
parentOrigin: 'https://shop.example.com',
mode: 'payment-only',
});
const hostedUrl = buildCheckoutHostedUrl({
checkoutOrigin: 'https://checkout.usethrottle.dev',
sessionId: session.sessionId,
});
const ordersPage = await checkout.listOrders({
customerId: '11111111-1111-4111-8111-111111111111',
limit: 20,
});
const nextCursor = ordersPage.pagination?.cursor;Server methods
| Method | Endpoint | Description |
| ----------------------------- | --------------------------------------------- | --------------------------------------------------------- |
| createSession(input) | POST /api/v1/checkout/sessions | Creates a cart-backed hosted/embed checkout session. |
| completeSession(id, input) | POST /api/v1/checkout/sessions/:id/complete | Completes a checkout session from server-side proxy mode. May return {status: 'requires_action'} when the card needs a 3-D Secure challenge — narrow with isRequiresAction() before reading orderId. |
| getSession(id) | GET /api/v1/checkout/sessions/:id | Reads a session back, including its current status. |
| cancelSession(id) | DELETE /api/v1/checkout/sessions/:id | Cancels an in-flight session. Idempotent. |
| createEmbedToken(input) | POST /api/v1/checkout-sessions/embed-token | Mints an embed token for proxy-mode card capture. |
| getOrder(id) | GET /api/v1/orders/:id | Reads public-safe order totals/status. |
| listOrders(options) | GET /api/v1/orders | Lists public-safe orders with optional filters. |
| listOrderPayments(id) | GET /api/v1/orders/:id/payments | Lists payments for an order. |
| listPaymentTransactions(id) | GET /api/v1/payments/:id/transactions | Lists transactions for a payment. |
| getOrderWithPayments(id) | Combined reads | Fetches an order, payments, and transactions together. |
Net-N invoice terms
Use paymentTerms.netN when creating a checkout session to stamp a cart-level
Invoice Terms override. Customer-level netN still wins when the attached
customer has an override; otherwise checkout falls back to the cart override and
then DEFAULT_NET_N.
customer.netN ?? cart.netN ?? DEFAULT_NET_NallowedMethods remains only a method filter, for example ['net30']; the
Net-N day count belongs in paymentTerms.netN.
Props
| Prop | Type | Required | Description |
| -------------- | ----------------- | -------- | ------------------------------------------------------------------------------ |
| sessionId | string | Yes | Throttle checkout session id (cs_*) |
| parentOrigin | string | No | Origin of the page mounting the embed |
| baseUrl | string | No | Override the hosted checkout URL (default: https://checkout.usethrottle.dev) |
| theme | BrandTheme | No | Brand colour + logo forwarded to hosted page |
| onSucceeded | (args) => void | No | Called once on successful payment |
| onFailed | (args) => void | No | Called once on terminal payment failure |
| onCancelled | () => void | No | Called when the user cancels |
| onTelemetry | (event) => void | No | Receives every lifecycle event |
Telemetry events
| event.type | Additional payload | Description |
| -------------- | ------------------------------------------------ | ------------------------------------------ |
| mounted | sessionId, timestamp | Component mounted in the DOM |
| ready | sessionId, timestamp | Hosted iframe fully loaded |
| processing | sessionId, timestamp | Payment authorization in-flight |
| succeeded | sessionId, orderId, paymentId, timestamp | Payment completed successfully |
| failed | sessionId, code, message, timestamp | Terminal payment failure |
| cancelled | sessionId, timestamp | User cancelled checkout |
| step_changed | sessionId, step, timestamp | Checkout step navigation (full embed only) |
Money
Amounts are integers in the record's minor unit. Show them with
formatMoney(amount, currency): this package re-exports
@usethrottle/money as money and formatMoney by name, plus the
CurrencyCode and MoneyValue types.
Idempotency
onSucceeded and onFailed are terminal events — the underlying iframe can occasionally emit duplicate postMessages on network hiccups or React strict-mode double-renders. ThrottleCheckout maintains a settledRef that ensures only the first terminal event fires the callback. All subsequent duplicates are silently dropped.
Brand theming
theme.primary (a CSS colour string) and theme.logo (an absolute HTTPS URL) are forwarded as ?primary=...&logo=... query params on the hosted checkout iframe src. The hosted page (apps/checkout-web) reads these to apply the merchant's brand.
Build
pnpm --filter @usethrottle/checkout-sdk buildEmits CJS, ESM, and TypeScript declarations for both the browser entrypoint and
@usethrottle/checkout-sdk/server.
