Skip to Content
Single Payments

Single Payments

Not every charge needs a group. The payments API charges one payer a one-off amount with the same hosted checkout: create a payment, share the returned checkout_url, get webhooks when it’s paid. Under the hood a single payment is a one-slot group payment, so it inherits the whole engine - provider cascade, state machine, reminders and expiry handling - without a second integration.

Full request/response shapes live in the interactive API Reference .

Create a payment

Amounts are in currency units (e.g. 50.00), not cents. expires_at defaults to 24h from now and is capped at 7 days. The optional customer pre-assigns the payer - Payylo can then email them reminders before the payment expires, and the checkout is smoother because the payer is already known.

curl https://api.payylo.com/v1/payments \ -H "Authorization: Bearer $PAYYLO_SECRET_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{ "amount": 50.00, "currency": "USD", "description": "Consulting - June", "customer": { "email": "payer@example.com", "name": "Alice" }, "metadata": { "invoice": "INV-042" } }'

description (max 80 chars) is shown to the payer at checkout. Add an Idempotency-Key header to make POSTs safe to retry.

Understand the response

{ "payment": { "id": "eda0165c-7c2f-4b1e-9a3d-1f2e3d4c5b6a", "merchant_id": "…", "amount": 50.0, "currency": "USD", "status": "pending", "description": "Consulting - June", "expires_at": "2026-06-21T18:00:00Z", "metadata": { "invoice": "INV-042" }, "created_at": "2026-06-20T18:00:00Z", "updated_at": "2026-06-20T18:00:00Z" }, "checkout_url": "https://checkout.payylo.com/g/eda0165c-…" }

Send checkout_url to the payer - by email, WhatsApp, a QR code, or a redirect from your site. They open it, pick their payment method and pay; you’re notified via webhooks.

Payment statuses

The group state machine is mapped to a simple status:

StatusMeaning
pendingCreated, awaiting payment.
authorizedFunds held (card preauthorisation), not yet captured.
paidCaptured - the money is yours.
expiredexpires_at passed without payment (holds released).
cancelledCancelled before completion.
refundedCaptured money was refunded (fully or partially).
failedA capture or refund failed and needs attention.

Retrieve and list

# Retrieve one payment curl https://api.payylo.com/v1/payments/eda0165c-… \ -H "Authorization: Bearer $PAYYLO_SECRET_KEY" # → { "payment": { … }, "checkout_url": "…" } # List, most recent first curl "https://api.payylo.com/v1/payments?limit=20&offset=0" \ -H "Authorization: Bearer $PAYYLO_SECRET_KEY" # → { "payments": [...], "pagination": { "limit", "offset", "total", "has_more" } }

Webhooks for single payments

A single payment is a group payment, so the webhook events are the same - group_payment.paid fires when it’s paid, and data.group_payment_id equals the payment id:

{ "type": "group_payment.paid", "data": { "group_payment_id": "eda0165c-…", "state": "paid" } }

Expiry works the same way too: a daily sweep closes unpaid payments past expires_at - see Group expiry and automatic refunds.

Next Steps

Last updated on