Developer docs
Hosted Checkout
After you create a deposit or withdrawal, redirect the customer to checkout_url. PeerPay renders a merchant-branded page with "Powered by PeerPay" secondary branding. You do not need to build first-version payment UI.
Checkout URLs
- Deposits:
https://checkout.peerpayment.org/c/{public_token} - Withdrawals:
https://checkout.peerpayment.org/w/{public_token}
Checkout links expire with the order (60 minutes). Expired links reject reference submission / confirmation. A withdrawal stays created until the customer confirms the destination on /w/{public_token}; that confirm is what starts agent assignment. Workspaces with Auto-Confirm Withdrawals on skip this page: the create call confirms the destination and returns no checkout_url.
An expired deposit link remains invalid. A workspace owner or administrator may reopen the expired deposit from the dashboard, which issues a new URL and deadline; it never reactivates the old token.
What customers see
For a deposit, the checkout is the customer's guided payment step: PeerPay shows the available payment option, the assigned receiving account and instructions, then accepts the external transfer reference. The customer never sends money through a PeerPay form; they transfer in their bank or wallet app and return to submit the reference.
- Available banks and wallets for the order
- Receiving account with copy controls (deposit)
- Min/max amount limits and method-specific instructions
- Reference submission and pending / retryable error states
- Success, failure, review-required, and expiry outcomes plus a support reference
The checkout status is a customer-facing view, not your settlement ledger. Reconcile server-side with a signed webhook or GET /v1/deposits/:id before crediting a wallet.
Public-token API (checkout only)
These routes live on the API host under /checkout-api. They are scoped to the public token — no merchant API key.
GET /checkout-api/c/{public_token}/state
POST /checkout-api/c/{public_token}/references
GET /checkout-api/c/{public_token}/events
GET /checkout-api/c/{public_token}/logo
GET /checkout-api/w/{public_token}/state
POST /checkout-api/w/{public_token}/confirm
GET /checkout-api/w/{public_token}/events
GET /checkout-api/w/{public_token}/logoDeposit reference submission body:
{
"payment_method": "telebirr",
"reference": "CHK7M2P9QX",
"supplementary_fields": {
"phone": "0911223344"
}
}Withdrawal destination confirmation (when the customer confirms or edits the destination on checkout):
{
"destination": {
"bank": "telebirr",
"account_number": "0933445566"
}
}Checkout events default to Server-Sent Events when Accept: text/event-stream. Use ?format=json for a JSON timeline. Resume with Last-Event-ID or ?after=.
Security boundaries
Never expose to checkout clients:
- Merchant API keys
- Webhook endpoint secrets
- Bank-verification secrets
- Provider raw responses
- Other merchants' receiving accounts or admin data
After checkout, reconcile server-side via Webhooks or deposit polling.
