INTEGRATION GUIDE

Live in five steps

From API keys to your first settled payment. Most merchants integrate AssetPay in under a day — one endpoint to create payments, one redirect, one webhook.

Get your API keys

Apply for a merchant account. Once KYB review is complete (typically 3 business days), you'll receive two keys:

KeyWhere it lives
sk_live_…Your server. Used to create payments and access account data. Treat it like a password.
pk_live_…The browser. Used by the hosted checkout — you rarely touch it directly.
Store the secret key in an environment variable — never commit it to source control. You can rotate it any time from the dashboard or via POST /merchant/keys/rotate-secret.

Create a payment from your server

When a customer checks out, call POST /payments with the USD amount. Use an Idempotency-Key so network retries never create duplicates.

Node.js
const res = await fetch('https://api.assetpay.io/payments', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.ASSETPAY_SECRET_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': `order-${order.id}`,
  },
  body: JSON.stringify({
    amountUsd: '149.99',
    orderId: order.id,
    successUrl: 'https://yourstore.com/thanks',
    cancelUrl: 'https://yourstore.com/cart',
  }),

const payment = await res.json();
// => { id, status: 'CREATED', checkoutUrl, expiresAt, ... }

Redirect to the hosted checkout

Send the customer to payment.checkoutUrl. The hosted page handles everything — crypto network selection (TRON USDT, Base USDC, Polygon USDC), card entry with 3-D Secure, live confirmation tracking, and the final redirect back to your successUrl.

// Express example
res.redirect(303, payment.checkoutUrl);

No iframe, no card data on your servers — keeps you out of PCI scope.

Handle the webhook

Set your webhook URL in the dashboard (or via PATCH /merchant/settings). Fulfil orders on payment.treasury_received — that's when funds are final. Always verify the signature first.

Express webhook handler
app.post('/webhooks/assetpay', express.raw({ type: '*/*' }), (req, res) => {
  const ok = verifyWebhook(
    process.env.ASSETPAY_WEBHOOK_SECRET,
    req.body.toString(),
    req.headers['x-assetpay-signature'],
  );
  if (!ok) return res.status(401).end();

  const event = JSON.parse(req.body);
  switch (event.type) {
    case 'payment.treasury_received':
      fulfillOrder(event.data.orderId);   // funds are final
      break;
    case 'payment.expired':
    case 'payment.failed':
      releaseInventory(event.data.orderId);
      break;
  }
  res.json({ received: true });
});

The verifyWebhook implementation is in the API docs — HMAC-SHA256 over timestamp.body with a 5-minute replay window.

Test, then go live

Run an end-to-end test before launch:

CheckWhat to verify
Create & payPayment reaches TREASURY_RECEIVED; customer lands on your successUrl.
WebhooksYour endpoint receives events, verifies signatures, and responds 2xx within 10s.
ExpiryAn unpaid payment transitions to EXPIRED and your inventory is released.
RefundsPOST /payments/:id/refund creates a PENDING refund visible in your dashboard.
IdempotencyReplaying the same Idempotency-Key returns the original payment, not a duplicate.

Settlement runs T+7 for your first four weeks, then automatically upgrades to T+3. Stablecoins settlement (USDC/USDT) is available for qualifying merchants — see settlement terms.