KardXKardX

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

POST/api/gateway/create-sessionAPI key
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"
  }'
amountrequiredA decimal STRING, never a JSON number — "49.99".
returnUrlrequiredAbsolute URL the shopper lands on afterwards.
currencyoptionalDefaults to USDC.
orderIdoptionalYour reference, up to 120 characters. Returned in the webhook.
descriptionoptionalUp to 500 characters, shown on the checkout.
customerEmailoptionalPre-fills the checkout.
metadataoptionalFlat 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

GET/api/gateway/session/{id}public

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.