Payment Links
Payment links are reusable URLs that open a checkout page. Unlike one-time checkouts, a payment link can be shared and used by multiple customers.
Create a payment link
POST /api/v1/linkscurl -X POST https://api.inzilink.com/api/v1/links \
-H "Authorization: Bearer sk_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Pro Plan — Monthly",
"amount": 29,
"displayCurrency": "USD",
"linkType": "subscription",
"metadata": { "plan": "pro" }
}'Fields
| Field | Type | Default | Notes |
|---|---|---|---|
title | string | — | Required, up to 255 characters. |
description | string | — | Up to 2000 characters. |
amount | number | null | open amount | A number, not a string. null or no field — the customer enters the amount. |
displayCurrency | string | USD | USD or EUR. |
acceptedTokens | string[] | ["USDC", "USDT"] | USDC and USDT settle USD; EURC settles EUR. A token that does not settle displayCurrency is refused. |
acceptedChains | string[] | all supported | solana, polygon, base, ton, tron, ethereum. |
isReusable | boolean | true | true — the link accepts payments until you pause or archive it. false — one payment, then the link is paid. |
linkType | string | custom | See Link types. |
expiresAt | ISO 8601 | — | After this time the link no longer opens checkout. |
redirectUrl | URL | — | Where the customer goes after paying. |
webhookUrl | URL | — | HTTPS endpoint for this link’s payment events. |
metadata | object | — | String values, up to 500 characters each. |
payerId | UUID | — | Link addressed to a saved payer. No field — anyone can pay. |
isReusable defaults to true through the API. A link created without the field accepts more than one payment. The dashboard creates one-time requests by default; the API default does not change, so integrations that do not send the field keep their behaviour. Send "isReusable": false for a one-time request.
Unknown fields are ignored, not rejected — check the field names above if a setting seems to have no effect.
Link types
| Type | Use case |
|---|---|
invoice | One-time payment for a specific amount |
donation | Flexible amount (user chooses) |
subscription | Recurring billing (manual re-payment) |
custom | General purpose |
List payment links
GET /api/v1/links?limit=20&offset=0Get payment link
GET /api/v1/links/{id}Returns the same link object as one row of the list.
Link object
| Field | Type | Notes |
|---|---|---|
id | string (uuid) | |
shortCode | string | |
title | string | |
description | string | null | |
amount | number | null | null — the payer enters the amount. See the note below. |
displayCurrency | string | Currency of amount and of every amount in request. |
acceptedTokens | string[] | |
acceptedChains | string[] | |
isReusable | boolean | false with a non-null amount is a payment request. |
status | string | active, paused, archived, canceled. |
isActive | boolean | Derived from status. |
linkType | string | null | |
paymentUrl | string | |
payerId | string | null | Who the link is issued to. |
createdAt | string (ISO 8601) | |
totalReceived | number | Deprecated for payment requests — use request. |
paymentCount | number | Deprecated for payment requests — use request. |
request | object | null | Payment state of a payment request. null for reusable links and links without a fixed amount. |
totalReceived and paymentCount are deprecated for payment requests.
They count the request only once it closes and never show a partial
payment. Read request.received, request.remaining and request.state
instead — they sum every attempt on the request.
Known inconsistency: amount is a number. Every other amount in the API
is a decimal string (request.received, request.remaining, checkout
amounts). amount will become a string in the next API version; parse it
as a decimal, not as a float, until then.
request — payment request state
All amounts are decimal strings in displayCurrency, without trailing zeros.
| Field | Type | Notes |
|---|---|---|
state | string | awaiting · detected · partially_paid · paid · overpaid |
received | string | null | Sum over every attempt on the request. null — nothing arrived. |
remaining | string | null | Left to pay. On a request accepted as paid — the amount written off. |
surplus | string | null | Only when overpaid. |
acceptedAsPaid | boolean | Closed with Accept as paid rather than paid in full. |
acceptedAsPaidAt | string | null | ISO 8601. When it was accepted as paid. |
acceptedAsPaidBy | string | null | Team member who accepted it: name, or email if the member has no name. |
topUpOpenUntil | string | null | ISO 8601. Until when a top-up can still arrive on at least one attempt. null — no window left, or the request is closed. |
While topUpOpenUntil is in the future, a transfer may still be on its way.
Accepting the request as paid before then writes off money that may yet
arrive.
Accept a partially paid request as paid
POST /api/v1/links/{id}/accept-as-paidCloses a partially paid request with the amount actually received. The
difference is written off, recorded in the audit log, and you receive
checkout.completed with accepted_as_paid: true. Owner or admin only, from
the dashboard session; API keys are refused.
| Error | Status | Meaning |
|---|---|---|
NOT_FOUND | 404 | No such request for this merchant. |
NOT_A_REQUEST | 409 | Reusable link or no fixed amount. |
NOT_PARTIALLY_PAID | 409 | Nothing arrived yet, or it is already paid in full. |
ALREADY_CLOSED | 409 | Already closed as paid. |
Send a request by email
POST /api/v1/links/{id}/send-email{ "to": "client@example.com" }Emails the request to your customer: title, amount, what they pay one to one, and the payment link. Sending again sends the same request — no new link is created. The link and QR code work whether or not the email went out.
201 means our email provider accepted the email; it is not a delivery
receipt. Every attempt is kept: GET /api/v1/links/{id}/emails lists them
newest first. GET /api/v1/links/{id}/email-preview returns the subject and
text that will be sent.
Only a person on your team with a confirmed email can send; API keys cannot.
| Error | Status | Meaning |
|---|---|---|
NOT_FOUND | 404 | No such link for this merchant. |
LINK_NOT_OPEN | 409 | The link is paused, archived or canceled. |
REQUEST_EMAILS_NOT_AVAILABLE | 403 | The sender has no confirmed email, or it is an API key. |
TOO_MANY_EMAILS | 429 | 5 emails already went out for this request in the last hour; details.retryAfterSec. |
REQUEST_EMAIL_LIMIT | 429 | Too many request emails from this account. |
EMAIL_NOT_SENT | 502 | The email did not go out. The attempt is recorded as failed. |
Update link status
PATCH /api/v1/links/{id}/status{ "status": "paused" }Available statuses: active, paused, archived.
Payment links use the Checkout API under the hood. Each time someone pays via a payment link, a new checkout session is created. You receive the same checkout.completed webhook.