Payment links#
A payment link is a checkout you can share: a code, a title, an amount, and the methods you accept. Send it on WhatsApp, put it in an Instagram bio, print it as a QR on a receipt. Every payer who opens it gets their own checkout session, so a link reconciles through exactly the same objects — sessions, webhooks, refunds — as a full API integration.
Nothing about a link is a second payment path. It is a session factory.
https://checkout.povito.com/l/{code}Create one from the merchant portal without writing code, or from your own system with a secret key.
Create a link#
curl -sS https://api.checkout.povito.com/v1/links \
-H "Authorization: Bearer $POVITO_CHECKOUT_SECRET_KEY" \
-H "Idempotency-Key: link-eid-box-2026" \
-H "Content-Type: application/json" \
-d '{
"title": "Eid gift box",
"description": "A box of sweets and dates, delivered anywhere in Baghdad.",
"amount": 45000,
"currency": "IQD",
"collect": { "phone": "required", "name": "required", "shipping_address": "required" },
"success_message": "Thank you. We will call you to arrange delivery.",
"max_uses": 200,
"metadata": { "campaign": "eid-2026" }
}'{
"id": "pl_live_7QK2M8ZX4N1PB6R3TDVW",
"object": "payment_link",
"code": "K7M2QX9ZB4",
"url": "https://checkout.povito.com/l/K7M2QX9ZB4",
"livemode": true,
"title": "Eid gift box",
"amount": 45000,
"currency": "IQD",
"status": "active",
"uses": 0,
"paid_count": 0,
"paid_total": 0
}Share url. That is the whole integration.
Fixed or open amount#
Give either amount, or min_amount and max_amount for an amount the payer
types — tips, donations, part payments, an invoice whose total you agreed on
the phone. The floor is 250 minor units either way.
| Field | Fixed | Open |
|---|---|---|
amount |
required | omit |
min_amount / max_amount |
omit | both required, min below max |
| What the payer sees | the amount, and a pay button | an amount box, bounded, with the button following what they type |
line_items are optional and, on a fixed link, must add up to amount — the
same reconciliation rule as a session.
What the payer sees#
The link page is the hosted checkout page in the same clothes: your name, your logo, your accent colour, in Arabic, Kurdish or English. The payer confirms their phone with a one-time code, picks a method, and pays. The session behind them behaves exactly as one you created yourself.
Afterwards they land on your success_url if you set one, or on the link's own
success screen showing success_message if you did not.
Reference ids#
Each session opened from a link gets reference_id = {reference_prefix}-{n},
counting up from one, so a link's payments arrive in your books already
distinguishable. reference_prefix defaults to the link code. Set it to
something your accounting recognises:
{ "reference_prefix": "EID-2026" }The count is claimed when the page is opened, not when the payment succeeds, so numbering can skip where a payer abandoned. Two payers never share one.
Limits, pausing and expiry#
| Field | Effect |
|---|---|
max_uses |
Stops issuing sessions once that many have been opened; the page then says the link is fully used |
expires_at |
The link stops working at that moment; a later PATCH with a new date brings it back |
status |
PATCH to paused to stop it temporarily, archived to retire it. active resumes |
A refused link still renders — the payer is told the link is paused, expired or fully used rather than meeting a dead page.
Counters and the paid event#
| Field | Counts |
|---|---|
uses |
Sessions opened from the link |
paid_count |
Captures |
paid_total |
Money captured, in the link's currency |
A capture also emits payment_link.paid:
{
"id": "evt_live_…",
"type": "payment_link.paid",
"data": { "link_id": "pl_live_…", "session": { "…": "the full checkout session" } }
}Treat it the way you treat every Povito event: a prompt to read
GET /v1/checkout/sessions/{id} and act on what the session says. The session
carries link_id, so an ordinary checkout.session.completed handler already
knows the payment came from a link.
A cash-on-delivery order placed through a link moves neither counter and emits
no payment_link.paid, because no money has moved yet. It appears as a session
with payment_status: requires_offline_collection, and you collect on delivery.
Managing links#
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/links?status=&cursor=&limit= |
List |
GET |
/v1/links/{id} |
Detail with counters |
PATCH |
/v1/links/{id} |
Title, description, status, expiry, max_uses |
GET |
/v1/links/{id}/sessions |
Every session opened from this link |
Test mode#
A povito_ck_test_… key makes test links, which open on the same page and pay
through the simulated gateway. See testing.