PovitoDevelopers

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.

bash
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" }
  }'
json
{
  "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:

json
{ "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:

json
{
  "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.

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.