Developers
Take payments on your site with one API key
Create a checkout session from your server, send the shopper to the hosted page, and get a signed webhook when they pay. The amount, less a 1.5% platform fee, lands in your KardX balance. Everything below runs exactly as written against the live API.
1 · Create
Your server calls create-session with your key and gets a checkout URL back.
2 · Pay
The shopper pays on the hosted checkout (or inline / modal via the drop-in script).
3 · Settle
The net amount is credited to your balance and checkout.paid is POSTed to your webhook, signed.
Authentication
Send your key as a bearer token. Keys start with kx_live_. Only a hash is stored on our side, so a lost key cannot be recovered — roll a new one from the gateway screen. The key never reaches a browser.
Authorization: Bearer kx_live_…Create a checkout session
curl -X POST https://kardx.io/api/gateway/create-session \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": "49.99",
"currency": "USDC",
"orderId": "order-1024",
"description": "Pro plan — annual",
"returnUrl": "https://your-store.com/thanks",
"customerEmail": "buyer@example.com"
}'| amount | required | A decimal STRING, never a JSON number — "49.99". |
| returnUrl | required | Absolute URL the shopper lands on afterwards. |
| currency | optional | Defaults to USDC. |
| orderId | optional | Your reference, up to 120 characters. Returned in the webhook. |
| description | optional | Up to 500 characters, shown on the checkout. |
| customerEmail | optional | Pre-fills the checkout. |
| metadata | optional | Flat string map, echoed back in the session and the webhook. |
Response
{
"sessionId": "e2e4a1d2-…",
"checkoutUrl": "https://kardx.io/pay/e2e4a1d2-…",
"expiresAt": "2026-09-02T21:57:49Z",
"amountMinor": "49990000",
"currency": "USDC"
}Read a session
Returns id, amountMinor, currency, description, orderId, status, expiresAt, returnUrl, merchantName, branding. Status is one of pending · processing · paid · expired. Poll this if you prefer not to run a webhook.
Webhooks
Set an HTTPS webhook URL on the gateway screen. When a checkout settles we POST a JSON event to it, signed with your webhook secret (shown once when you issue or roll a key).
POST https://your-store.com/kardx-webhook
X-KardX-Event: checkout.paid
X-KardX-Timestamp: 1756850000
X-KardX-Signature: v1=<hex HMAC-SHA256 of "<timestamp>.<raw body>" with your secret>
{
"id": "evt_…",
"type": "checkout.paid",
"created": 1756850000,
"data": {
"sessionId": "e2e4a1d2-…",
"orderId": "order-1024",
"amountMinor": "49990000",
"feeMinor": "749850",
"netMinor": "49240150",
"currency": "USDC",
"paidAt": "2026-09-02T21:59:12.000Z",
"metadata": { "cart": "abc" }
}
}Verify the signature (Node)
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyKardx(rawBody, headers, secret) {
const ts = headers['x-kardx-timestamp'];
const sig = headers['x-kardx-signature']; // "v1=…"
const expected = 'v1=' + createHmac('sha256', secret)
.update(ts + '.' + rawBody).digest('hex');
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
return fresh && sig.length === expected.length
&& timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}Drop-in button
<script src="https://kardx.io/embed.js" defer></script>
<button
data-kardx-checkout
data-amount="49.99"
data-currency="USDC"
data-description="Pro plan — annual"
data-return-url="https://your-store.com/thanks">
Pay with KardX
</button>On click the script posts to /api/kardx/checkout on YOUR server, which holds the key and calls create-session. Set the amount from your own order on the server — a data attribute is a value the shopper can edit.