Developer API
Create checkout sessions from your server, send customers a payment link or embedded widget, and receive USDC when they pay via mobile money or Stepay wallet. Webhooks notify your backend when payment succeeds.
1. Sign up and open Dashboard → Merchant. Generate an API key — save sk_live_… and whsec_… immediately.
2. Create a checkout from your server:
curl -X POST https://stepay.pro/api/v1/checkouts \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 25,
"asset": "usdc",
"label": "School fees — Term 2",
"reference": "STU-1042",
"success_url": "https://yoursite.com/thank-you",
"webhook_url": "https://yoursite.com/hooks/stepay"
}'3. Redirect the customer to checkout_url from the response, or embed it (see below).
4. Listen for the checkout.paid webhook on your server to mark the order paid.
Send your secret API key on every request. Keys start with sk_live_.
Authorization: Bearer sk_live_... # or X-Stepay-Key: sk_live_...
Never expose your API key in browser JavaScript. Create checkouts from your backend only.
Create a one-time payment session.
Request body
{
"amount": 25, // required — min 1 USDC or 0.1 XLM
"asset": "usdc", // "usdc" (default) or "xlm"
"label": "Invoice #1042", // required — shown to payer
"description": "Optional longer text",
"reference": "INV-1042", // your order id (also accepts referenceId)
"metadata": { "order_id": "1042" },
"success_url": "https://yoursite.com/done", // HTTPS only
"cancel_url": "https://yoursite.com/cancel", // optional
"webhook_url": "https://yoursite.com/hooks/stepay",
"expires_in_minutes": 1440 // 15–10080, default 24h
}Response
{
"id": "uuid",
"checkout_token": "hex32",
"amount": 25,
"asset": "usdc",
"label": "Invoice #1042",
"status": "pending",
"expires_at": "2026-07-06T18:00:00.000Z",
"checkout_url": "https://stepay.pro/pay/checkout/{token}",
"embed_url": "https://stepay.pro/pay/checkout/{token}?embed=1"
}Poll checkout status by UUID.
curl https://stepay.pro/api/v1/checkouts/CHECKOUT_UUID \ -H "Authorization: Bearer sk_live_..."
Status values: pending, paid, expired, cancelled.
List your 30 most recent checkouts.
curl https://stepay.pro/api/v1/checkouts \ -H "Authorization: Bearer sk_live_..."
When a checkout is paid, Stepay POSTs to your webhook_url with event checkout.paid.
Payload
{
"event": "checkout.paid",
"checkoutId": "uuid",
"checkoutToken": "hex32",
"referenceId": "STU-1042",
"amount": 25,
"asset": "usdc",
"txHash": "stellar-transaction-hash",
"payerId": "user-uuid-or-null",
"paymentMethod": "wallet",
"paidAt": "2026-07-05T18:00:00.000Z",
"metadata": { "order_id": "1042" }
}Verify signature (Node.js)
import { createHmac, timingSafeEqual } from 'crypto';
function verifyStepayWebhook(rawBody, signatureHeader, secret) {
const parts = Object.fromEntries(
signatureHeader.split(',').map((p) => p.trim().split('='))
);
const timestamp = parts.t;
const expected = parts.v1;
if (!timestamp || !expected) return false;
const signed = `${timestamp}.${rawBody}`;
const actual = createHmac('sha256', secret).update(signed).digest('hex');
return timingSafeEqual(Buffer.from(actual), Buffer.from(expected));
}
// Express example:
app.post('/hooks/stepay', express.raw({ type: 'application/json' }), (req, res) => {
const raw = req.body.toString('utf8');
const sig = req.headers['stepay-signature'];
if (!verifyStepayWebhook(raw, sig, process.env.STEPAY_WEBHOOK_SECRET)) {
return res.status(401).send('invalid signature');
}
const event = JSON.parse(raw);
if (event.event === 'checkout.paid') {
// mark order paid using event.referenceId
}
res.sendStatus(200);
});Header format: Stepay-Signature: t=UNIX_SECONDS,v1=HEX_HMAC. Use the whsec_… secret from the same API key that created the checkout.
Add an inline payment widget to your site (iframe). Put the container before the script:
<div data-stepay-embed="https://stepay.pro/pay/checkout/CHECKOUT_TOKEN"></div> <script src="https://stepay.pro/embed.js" defer></script>
Or open checkout in a popup button:
<a href="https://stepay.pro/pay/checkout/TOKEN" data-stepay-checkout="https://stepay.pro/pay/checkout/TOKEN" class="stepay-pay-btn">Pay with Stepay</a> <script src="https://stepay.pro/embed.js" defer></script>
Errors return JSON { "error": "message" } with HTTP status:
const API_KEY = process.env.STEPAY_API_KEY;
const BASE = 'https://stepay.pro';
async function createCheckout(order) {
const res = await fetch(`${BASE}/api/v1/checkouts`, {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: order.totalUsdc,
asset: 'usdc',
label: order.title,
reference: order.id,
metadata: { order_id: order.id },
success_url: `https://shop.example.com/orders/${order.id}/thanks`,
webhook_url: 'https://shop.example.com/hooks/stepay',
}),
});
if (!res.ok) throw new Error((await res.json()).error);
return res.json();
}
// Usage:
// const { checkout_url } = await createCheckout({ id: '1042', title: 'Fees', totalUsdc: 25 });
// redirect customer to checkout_url