Documentation
Developer reference

Build with TandemPay

Create hosted checkout sessions from your server, redirect customers to pay, and confirm orders from signed webhooks.

API operationalREST + JSONVersion 1
Start here

Overview

The TandemPay API is organized around checkout sessions and payments. Create sessions from your server, mount checkout in the browser, then use webhooks as the source of truth for payment and settlement state.

Production

https://api.tandempay.io/v1

Sandbox

https://api.sandbox.tandempay.io/v1
01

Create a session

Initialize the amount and return URLs on your server.

02

Redirect to checkout

Send the customer to the hosted checkout URL.

03

Listen for events

Fulfill orders from signed payment webhooks.

W

WooCommerce plugin

Merchant access

Add TandemPay checkout to an existing WooCommerce store without building a custom integration. The plugin handles session creation, order status syncing, and webhook verification.

Available in the merchant dashboard after approval.

Apply for access
Security

Authentication

Authenticate server requests with a secret API key issued in the merchant dashboard after approval. Keys are scoped to one merchant and never expose operator credentials.

Authorization header
Authorization: Bearer tp_live_sk_••••••••••••••••

Secret key · server only

Creates checkout sessions, retrieves payments, and lists payment history.

Test vs live

Use tp_test_sk_* in sandbox and tp_live_sk_* in production.

A merchant ID identifies your account; it does not authorize a request. Never expose a secret key in browser code, mobile apps, logs, or source control.

Five minutes

Quickstart

1. Create a checkout session

Server
const response = await fetch(
  "https://api.tandempay.io/v1/checkout/sessions",
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.TANDEMPAY_SECRET_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": crypto.randomUUID()
    },
    body: JSON.stringify({
      amount: 114.00,
      currency: "USD",
      order_id: "order_1842",
      customer_email: "customer@example.com",
      success_url: "https://yourstore.com/order/success",
      cancel_url: "https://yourstore.com/cart"
    })
  }
);

const session = await response.json();

2. Redirect to hosted checkout

Browser
window.location.assign(session.checkout_url);

3. Confirm fulfillment from a webhook

Wait for payment.succeeded before fulfilling the order. Redirects improve customer experience, but are not a reliable payment confirmation channel.

Checkout

Checkout sessions

POST/checkout/sessionsSecret key

Create a checkout session and receive a hosted checkout URL. Amounts are decimal USD values.

amountnumber · requiredTotal amount in USD (e.g. 114.00).
currencystring · optionalPresentment currency. Defaults to USD.
order_idstring · optionalYour unique order reference.
customer_emailstring · optionalCustomer email for receipts.
success_urlURL · requiredReturn URL after successful payment.
cancel_urlURL · requiredReturn URL when checkout is canceled.
metadataobject · optionalString key-value pairs attached to the payment.
201 response
{
  "id": "clxyz123",
  "object": "checkout.session",
  "status": "open",
  "amount": 114.00,
  "currency": "USD",
  "reference_id": "tp_a1b2c3d4e5f6",
  "checkout_url": "https://checkout.tandempay.io/pay/tp_a1b2c3d4e5f6",
  "success_url": "https://yourstore.com/order/success",
  "cancel_url": "https://yourstore.com/cart",
  "created": 1726128000
}
Payments

Track payment status

GET/payments/{reference_id}Secret key

Retrieve payment status by reference ID. Re-fetches provider state when available.

200 response
{
  "id": "clxyz123",
  "object": "payment",
  "reference_id": "tp_a1b2c3d4e5f6",
  "status": "succeeded",
  "provider_status": "FILLED",
  "amount": 114.00,
  "amount_received": 114.00,
  "currency": "USDC",
  "network": "BASE",
  "customer_email": "customer@example.com",
  "order_id": "order_1842",
  "created": 1726128000,
  "updated": 1726128300
}
GET/payments?limit=20&status=succeededSecret key

List payments with cursor pagination. Filter by status.

openCheckout session created, awaiting payment.
processingPayment is being confirmed.
partially_paidPartial amount received.
succeededPayment completed successfully.
overpaidCustomer paid more than requested.
cancelledPayment was cancelled.
Rates

Ticker

GET/tickerSecret key

Normalized asset prices with 60-second server-side caching.

200 response
{
  "object": "ticker",
  "data": [
    { "blockchain": "BASE", "currency": "USDC", "price_usd": 1.0 }
  ]
}
Events

Webhooks

POSTyour-server.com/webhooks/tandempayYour endpoint

Receive signed payment events. Verify the TandemPay-Signature header before fulfilling orders.

Signature header
TandemPay-Signature: t=1726128000,v1=5d8f9a...
payment.processingPayment is open or partially filled.
payment.succeededPayment completed.
payment.overpaidCustomer overpaid.
payment.cancelledPayment cancelled.
Conventions

Errors and idempotency

Errors use stable machine-readable codes. The request ID is included in both the response body andtandempay-request-id header for support and tracing.

Error response
{
  "error": {
    "type": "invalid_request",
    "code": "amount_too_small",
    "message": "Amount must be at least 100 usd.",
    "param": "amount",
    "request_id": "req_01J8YA2B8FQP"
  }
}
200 / 201The request completed successfully.
400Parameters are missing or invalid.
401The API key is missing or invalid.
402The payment could not be completed.
404The requested resource does not exist.
409The request conflicts with current resource state.
429Too many requests; retry after the supplied delay.
5xxA TandemPay service error occurred; retry safely.

Send a unique Idempotency-Key with every POST request. Reusing the key with the same payload returns the original response; reusing it with different parameters returns HTTP 409.

Developer support

Need help integrating?

Send your request ID, environment, and a sanitized request example. Never email secret keys or raw card data.

contact@tandempay.io