For developers
Developer guide
Accept crypto with one API call and one webhook. All amounts are integers in the currency's minor units (cents for USD).
Keys come from the MaxPay team
In the private beta, the MaxPay team opens your store account, sets its webhook URL, and gives you its API key and webhook signing secret. Sign in to follow payments, balances and withdrawals.
Sign in1. Create a payment request
Use your store API key, which the MaxPay team issues with your store account. orderReference is your order id. Sending the same request again returns the same payment request, so retries are safe.
curl https://<your-maxpay-host>/v1/payment-requests \
-H "Authorization: Bearer $MAXPAY_KEY" \
-H "Content-Type: application/json" \
-d '{
"orderReference": "order-1001",
"amount": { "amountMinor": 2500, "currency": "USD" },
"description": "Order #1001",
"returnUrl": "https://shop.example/thanks"
}'
The response includes the hosted checkout URL and the widget token:
{
"id": "pr_01J…",
"orderReference": "order-1001",
"status": "OPEN",
"amount": { "amountMinor": 2500, "currency": "USD" },
"checkoutUrl": "https://<your-maxpay-host>/c/…",
"widgetToken": "…",
"expiresAt": "…"
}
2. Send the shopper to checkout
Redirect to checkoutUrl, or embed the widget on your own page:
<div id="maxpay"></div>
<script src="https://<your-maxpay-host>/embed.v1.js"></script>
<script>MaxPay.mount('#maxpay', { token: WIDGET_TOKEN });</script>
Never mark an order paid because the shopper came back to returnUrl or because the widget said so. Wait for the signed webhook.
3. Handle signed webhooks
MaxPay POSTs a JSON event to your webhook URL with the header MaxPay-Signature. Verify it on the raw body before trusting it. Events carry a sequence per order: ignore one older than the last you applied. Each event has an id: apply it once.
import { createHmac, timingSafeEqual } from 'node:crypto';
// header: "t=<unix seconds>,v1=<hex>" (two v1 values while a secret is rotated)
export function verify(rawBody, header, secret, toleranceSeconds = 300) {
const parts = header.split(',').map((p) => p.trim());
const t = Number(parts.find((p) => p.startsWith('t='))?.slice(2));
if (!Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
return parts
.filter((p) => p.startsWith('v1='))
.some((p) => {
const got = Buffer.from(p.slice(3), 'hex');
return got.length === expected.length && timingSafeEqual(got, expected);
});
}
| Type | Meaning |
|---|---|
payment_request. | A payment was seen on chain and is waiting for confirmations. |
payment_request. | Part of the amount arrived. The order stays open for the rest. |
payment_request. | The order is paid in full. Fulfil it. |
payment_request. | More than the amount arrived. Choose to keep it as credit or refund it. |
payment_request. | A payment was flagged by screening and is under review. |
payment_request. | A held payment was cleared after review. |
payment_request. | A held payment was rejected after review. |
payment_request. | A payment arrived after the window closed. Review it in the dashboard. |
payment_request. | You declined a late payment. |
payment_request. | The order expired unpaid. |
payment_request. | The order was cancelled. |
Respond with a 2xx status within 10 seconds. Failed deliveries are retried after 10 s, 30 s, 2 min, 10 min, 30 min, then hourly.
WooCommerce
- Copy the
maxpay-woocommerceplugin intowp-content/plugins/and activate it. - In WooCommerce → Settings → Payments → MaxPay, enter the API URL, your store API key and the webhook signing secret.
- Ask the MaxPay team to set your store’s webhook URL to
https://your-shop/wp-json/maxpay/v1/webhook.
Orders move to processing on paid, go on hold when underpaid, held or late, and are cancelled when an unpaid request expires.
More
- Payment links, invoices and subscriptions:
/v1/payment-links,/v1/invoices,/v1/subscriptions, or the Billing page in the dashboard. - Balances and withdrawals:
/v1/balances,/v1/withdrawals. Withdrawals need approval from several MaxPay operators. - Exports:
/v1/exports/accounting.xlsxand/v1/exports/maxaccounting.jsonfor a date range.