API documentation
Create payment links from your server, then send customers to the hosted checkout. Payments are detected on-chain automatically and confirmed once they reach the required depth.
Authentication
Send your secret key as a bearer token. Keys start with sk_live_. Keep them on your server.
Authorization: Bearer sk_live_...
Create a payment link
POST https://monifyd.com/api/v1/payment-links. Send an Idempotency-Key header so retries never create duplicates. API request limits use a separate API subscription from Dashboard plans. Customers currently pay the requested amount with no added transaction fee.
{
"amount": 500,
"currency": "USD",
"description": "Website development",
"accepted_payments": [
{ "asset": "USDC", "networks": ["base", "solana"] },
{ "asset": "BTC", "networks": ["bitcoin"] }
],
"metadata": { "order_id": "ORDER-123" },
"success_url": "https://example.com/success"
}
201 { "id": "plink_...", "status": "ACTIVE", "checkout_url": "https://monifyd.com/pay/plink_..." }Invoices
Create an invoice in draft state, then send it to the customer. Invoice amounts are in major currency units; checkout currently charges the requested amount without an added transaction fee.
POST https://monifyd.com/api/v1/invoices
Idempotency-Key: invoice-order-123
{
"amount": 125,
"currency": "USD",
"customer_email": "customer@example.com",
"title": "Design work",
"due_date": "2026-10-20",
"accepted_payments": [{ "asset": "USDC", "networks": ["base"] }]
}
POST https://monifyd.com/api/v1/invoices/:id/send
POST https://monifyd.com/api/v1/invoices/:id/cancel
GET https://monifyd.com/api/v1/invoices
GET https://monifyd.com/api/v1/invoices/:id
GET https://monifyd.com/api/v1/payment-links List your payment links
GET https://monifyd.com/api/v1/payments List payments
GET https://monifyd.com/api/v1/payments/:id Get one paymentInvoices with due dates are emailed a reminder three days before the due date and on the due date. Configure Resend to send invoice emails; the regular cron job also processes reminders.
Errors
Errors share one shape.
{ "error": { "code": "UNSUPPORTED_ASSET_NETWORK", "message": "USDT is not supported on base." } }Webhooks
Add an endpoint in Dashboard, Webhooks. Monifyd sends a POST with a JSON body. Reply with any 2xx status within 8 seconds. Anything else is retried after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 24 hours, then marked failed. You can replay any event from the dashboard.
Events: payment.created, payment.detected, payment.confirming, payment.paid,
payment.partial, payment.underpaid, payment.overpaid, payment.expired, payment.failed,
invoice.created, invoice.sent, invoice.paid, invoice.underpaid, invoice.overpaid, invoice.cancelled
Headers:
X-Monifyd-Event-Id evt_... (use it to ignore duplicates)
X-Monifyd-Timestamp unix seconds
X-Monifyd-Signature hex HMAC-SHA256 of "<timestamp>.<raw body>" with your signing secret
Body:
{ "id": "evt_...", "type": "payment.paid", "created": 1760000000,
"data": { "id": "pay_...", "status": "PAID", "amount_cents": 50000, "reference": "ORDER-123", ... } }Verify the signature against the raw request body before you trust an event. Mark an order as paid only on payment.paid or invoice.paid.
import crypto from "node:crypto";
export function verify(rawBody, headers, secret) {
const ts = headers["x-monifyd-timestamp"];
const sig = headers["x-monifyd-signature"] ?? "";
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; // too old
const expected = crypto.createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex");
return sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}Wrong-amount payments
If a customer sends the wrong amount, the payment ends as UNDERPAID or OVERPAID once the transfer is confirmed. The payload carries received_amount, shortfall and excess. Do not fulfil an payment.underpaid order. Treat payment.overpaid as paid in full, and refund the extra yourself if you choose. The merchant can accept an underpayment or close it from the dashboard, and an accepted underpayment then sends payment.paid.
Node.js integration
You can call the REST API directly from your server with Node.js. Save your API key and Monifyd URL as server-side environment variables; never expose the key in browser code. Get a key from Settings, Developer settings.
// .env.local (keep this file out of source control)
MONIFYD_API_KEY=sk_live_...
MONIFYD_BASE_URL=https://monifyd.com
// Server-side Node.js code
const response = await fetch(`${process.env.MONIFYD_BASE_URL}/api/v1/payment-links`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MONIFYD_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "order-123"
},
body: JSON.stringify({
amount: 500,
currency: "USD",
accepted_payments: [{ asset: "USDC", networks: ["base"] }]
})
});
const paymentLink = await response.json();
if (!response.ok) throw new Error(paymentLink.error?.message ?? "Request failed");
console.log(paymentLink.checkout_url);The JavaScript SDK source is included in the Monifyd project repository, but the example above works without installing a separate package.