Two endpoints. USDC in your wallet.
POST creates a hosted checkout. We GET your callback when paid. That's it.
Quickstart
The whole integration in three lines: create the link, redirect, handle the callback. Copy below, replace the wallet + key, and you're live.
POST /v1/wallet
We return a checkout_url.
Redirect
Send the customer to checkout_url.
Receive callback
We GET your URL with status=paid.
Copy & run
curl -X POST https://paylio.org/api/v1/wallet \
-H "Authorization: Bearer plio_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"address": "0xYourPolygonWallet",
"callback": "https://example.com/orders/123/paylio-callback",
"amount": "49.99",
"currency": "USD"
}'Authentication
Every request needs an API key. Generate one in dashboard › API Keys. Send it in either header — never both:
Authorization: Bearer plio_live_YOUR_KEY
# or
X-API-Key: plio_live_YOUR_KEYTreat keys like passwords. We only store a SHA-256 hash. If a key leaks, revoke it and create a new one.
Create checkout link
Generates a hosted-checkout page and returns a ready-to-redirect URL plus an ipn_token for tracking.
/api/v1/walletCard-funded payments that settle as USDC on Polygon. For direct-crypto flows use the dashboard or the WooCommerce / WHMCS modules.
addressreqstring | Your Polygon USDC payout wallet (0x…). Funds land here. |
callbackrequrl | Where PayLio GETs once the payment completes. See Callback. |
amountreqstring | number | Order total. Decimal string preferred (e.g. "49.99"). |
currencystring | ISO code — USD, EUR, GBP, CAD. Default USD. |
emailstring | Customer email. Pre-fills the checkout, included in the callback. |
notestring | Free-form note shown in your dashboard. Hidden from the customer. |
Request
curl -X POST https://paylio.org/api/v1/wallet \
-H "Authorization: Bearer plio_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"address": "0xYourPolygonWallet",
"callback": "https://example.com/orders/123/paylio-callback",
"amount": "49.99",
"currency": "USD"
}'Response · 200 OK
{
"address_in": "0xa1B2c3...derived",
"polygon_address_in": "0x32e854bD1270670C832634CA87858fFd9F3e2c78",
"ipn_token": "f7e9d3a1-4b8e-4a2f-9c6e-1234567890ab",
"callback_url": "https://example.com/orders/123/paylio-callback",
"payment_id": "clx9k2m3a0001a8w0b3v4r5g6",
"short_code": "a8wB3v4R",
"short_url": "https://paylio.org/p/a8wB3v4R",
"checkout_url": "https://paylio.org/pay/clx9k2m3a0001a8w0b3v4r5g6",
"payment_type": "card",
"status": "unpaid"
}Response field reference▾
checkout_urlurl | Redirect the customer here. |
ipn_tokenstring | Save on your order row. Use it to verify the callback. |
payment_idstring | PayLio internal ID. Alternative input for status checks. |
short_urlurl | Branded short link to the checkout (good for SMS / email). |
address_instring | Deposit address embedded in checkout_url. |
polygon_address_instring | Decrypted Polygon address — for internal reconciliation. |
payment_typestring | Always "card" for API-created payments. |
statusstring | Always "unpaid" at creation. |
Check payment status
Server-to-server verification. Always call this before fulfilling an order — query strings on your callback can be spoofed.
/api/v1/payment-statusipn_tokenstring | The token from /wallet. Either this or payment_id is required. |
payment_idstring | PayLio payment ID. |
Request
curl "https://paylio.org/api/v1/payment-status?ipn_token=f7e9d3a1-..." \
-H "Authorization: Bearer plio_live_YOUR_KEY"Response · 200 OK
{
"status": "paid",
"value_coin": "49.4",
"txid_in": "0xa22a82b4...",
"txid_out": "0x94c2c3e8...",
"coin": "polygon_usdc",
"address_in": "0x32e854bD1270670C832634CA87858fFd9F3e2c78",
"payment_id": "clx9k2m3a0001a8w0b3v4r5g6",
"amount": "49.99",
"currency": "USD",
"forward_status": "completed",
"forwarded_amount": "49.4",
"paid_at": "2026-04-28T13:01:42.000Z",
"created_at": "2026-04-28T12:59:11.000Z"
}Response field reference▾
statusstring | unpaid · paid · canceled. |
forward_statusstring | pending · processing · completed · failed. Treat completed as final. |
value_coinstring | Amount received in the settlement coin. |
forwarded_amountstring | Final amount delivered to your wallet (after fees). |
txid_instring | Hash of the customer's deposit tx. |
txid_outstring | Hash of the payout to your wallet. |
coinstring | Settlement coin ticker (e.g. polygon_usdc). |
Webhook callback
On payment completion, PayLio appends data to your callback URL and GETs it. Treat callbacks as untrusted hints — always re-verify with /payment-status.
// Express · Node.js
app.get("/orders/:id/paylio-callback", async (req, res) => {
// 1. Re-verify — query strings can be spoofed.
const verify = await fetch(
`https://paylio.org/api/v1/payment-status?ipn_token=${req.query.ipn_token}`,
{ headers: { Authorization: `Bearer ${process.env.PAYLIO_API_KEY}` } },
).then((r) => r.json());
if (verify.status !== "paid") return res.status(400).send("not paid");
// 2. Mark the order paid (idempotent).
await markOrderPaid(req.params.id, { txid: verify.txid_out });
// 3. Reply 200 within 10 s.
res.status(200).send("ok");
});- Re-verify with
/payment-statusbefore fulfilling. - Make your handler idempotent — we retry on non-2xx responses.
- Reply
200within 10 s; do heavy work async.
Errors
All errors return JSON: { "error": "...", "code": "..." } (the code field appears when actionable).
| HTTP | Cause | What to do |
|---|---|---|
| 400 | Validation failed (missing field, bad wallet, low amount). | Read error, fix input, retry. |
| 401 | Missing, invalid, or revoked API key. | Generate a new key. |
| 404 | Payment not found, or owned by a different user. | Verify ipn_token / payment_id. |
| 429 | Too many requests in a short window. | Honour Retry-After; back off with jitter. |
| 500 | Server error (upstream / RPC unreachable). | Retry with exponential backoff. |
Ship your first payment today.
Generate a key, copy a sample, watch USDC land in your wallet. No KYC, no SDK.