Payment Links
A payment link lets you create a shareable URL for a single payment request without building Card Handoff integration. The buyer opens this URL in their own browser, picks an installment count (if offered), and completes the payment themselves; your checkout does not collect the card. It is an alternative to the POST /v1/payments + handoff flow, useful when you want to avoid the card surface entirely (for example, sharing an order by phone or message).
POST /v1/payment-linksAuthorization: Bearer ptk_live_…Content-Type: application/jsonRequest body
Section titled “Request body”{ "amount": 125050, "terminalId": "trm_3Kd9x", "customerCommissionShareBps": 0, "description": "Order #8841", "redirectUrl": "https://yourstore.example/payment"}| Field | Required | Description |
|---|---|---|
amount |
Yes | The base amount you are requesting, integer in minor units (kuruş) (1,250.50 TRY → 125050). See Amounts and Currency. |
terminalId |
Yes | The terminal the payment is routed to. Must belong to you and be active; otherwise terminal_not_allowed is returned. |
customerCommissionShareBps |
No | The share of the commission passed on to the buyer, integer basis points (0-10000; 2.5% → 250). Defaults to 0 (you absorb the entire commission). |
description |
No | Link description. |
redirectUrl |
No | The base address the buyer is redirected to after the payment is settled; validated at creation time (see redirectUrl behavior). |
allowedInstallmentCounts |
No | The list of installment counts accepted for this link. If omitted (or null), there is no restriction and your terminal’s effective installment set (Installment Options) applies. If you supply it, the list cannot be empty and must be a subset of your terminal’s effective installment set; otherwise the request is rejected with 422 installment_not_allowed. This restriction cannot be changed once the link is created. |
Response
Section titled “Response”201 Created:
{ "id": "01J9K5QATN6M1PXG7VYSD3HZWB", "token": "plk_EXAMPLE0000000000…", "url": "https://pay.lydiagate.example/link/plk_EXAMPLE0000000000…", "partnerReference": 42, "status": "pending", "amount": 125050, "customerCommissionShareBps": 0, "description": "Order #8841", "redirectUrl": "https://yourstore.example/payment", "firstOpenedAt": null, "lastOpenedAt": null, "expiresAt": "2026-06-21T12:00:00Z", "createdAt": "2026-06-14T12:00:00Z", "updatedAt": "2026-06-14T12:00:00Z", "allowedInstallmentCounts": null}| Field | Description |
|---|---|
id |
The link’s permanent identifier; used in the single-item query, cancel calls, and the paymentLinkId field in the webhook body. |
token |
The secret component of url. You do not need to store it separately; url already contains it. |
url |
The full address you share with the buyer. |
partnerReference |
An increasing sequence number scoped to your account (for display/reference only). |
status |
The link’s current status. See Lifecycle. |
amount |
The base amount you requested (kuruş). |
firstOpenedAt / lastOpenedAt |
The instant the buyer first/last opened the link; null if not opened yet. |
expiresAt |
The link’s expiry instant. See Window (TTL). |
createdAt / updatedAt |
Timestamps (UTC). |
allowedInstallmentCounts |
The installment restriction you sent in the request, sorted ascending; null if there is no restriction. |
Lifecycle
Section titled “Lifecycle”| Status | Meaning |
|---|---|
pending |
The link was created; the buyer has not opened it yet. |
launched |
The buyer opened the link. |
initiated |
A payment attempt is in 3D Secure; in flight. No new attempt can be started while in this status. If the attempt fails without completing, the link becomes payable again. |
completed |
The payment was completed (terminal — no further transition). |
expired |
The window (TTL) elapsed; the link became invalid unpaid (terminal). |
failed |
A payment attempt failed; not terminal — the link can be paid again. |
cancelled |
You cancelled it (terminal). |
Window (TTL)
Section titled “Window (TTL)”A link’s default validity window is 7 days from creation. Once expiresAt has passed, the link moves to expired and can no longer be paid.
Listing links
Section titled “Listing links”GET /v1/payment-links?status=pending&status=launched&page=0&size=20Authorization: Bearer ptk_live_…| Parameter | Description |
|---|---|
status |
Filter by one or more statuses; repeat the parameter (status=pending&status=launched). |
minAmount / maxAmount |
Amount range (kuruş). |
createdFrom / createdTo |
Creation time range (UTC, ISO 8601). |
page / size |
Pagination; page starts at 0, size defaults to 20. |
Response (200 OK):
{ "items": [ { "id": "01J9K5QATN6M1PXG7VYSD3HZWB", "token": "plk_EXAMPLE0000000000…", "url": "https://pay.lydiagate.example/link/plk_EXAMPLE0000000000…", "partnerReference": 42, "status": "pending", "amount": 125050, "customerCommissionShareBps": 0, "description": "Order #8841", "redirectUrl": "https://yourstore.example/payment", "firstOpenedAt": null, "lastOpenedAt": null, "expiresAt": "2026-06-21T12:00:00Z", "createdAt": "2026-06-14T12:00:00Z", "updatedAt": "2026-06-14T12:00:00Z", "allowedInstallmentCounts": null } ], "page": 0, "size": 20, "hasMore": false}| Field | Description |
|---|---|
items |
The links on this page; each item carries the same fields as the creation response. |
hasMore |
true when the number of returned items equals size. Increment page for the next page. |
Query a single link
Section titled “Query a single link”GET /v1/payment-links/{id}Authorization: Bearer ptk_live_…{id} is the id field from the creation or listing response (not token).
Cancelling a link
Section titled “Cancelling a link”DELETE /v1/payment-links/{id}Authorization: Bearer ptk_live_…Only links in a non-terminal status (pending / launched / initiated / failed) can be cancelled; a successful call moves the link to cancelled and returns the updated link record. Trying to cancel a link that has already completed, expired, or was already cancelled fails (see below).
redirectUrl behavior
Section titled “redirectUrl behavior”If you supply a redirectUrl, Lydia Gate validates it at link creation time:
- The address must be an absolute URL with the
httporhttpsscheme; otherwise the request is rejected with400 validation_error. - If your account has an allowed host list configured, the
redirectUrlhost must appear on that list; a host that is not on the list is rejected the same way, with400 validation_error. If no such list is configured, only the scheme is checked. This is the same open-redirect protection as thereturnUrlvalidation onPOST /v1/payments.
Once redirectUrl passes validation, after the buyer sees the payment result, they are redirected to:
- On a completed payment →
{redirectUrl}/payment/success, - On a failed attempt →
{redirectUrl}/payment/failure.
If you do not send a redirectUrl, the buyer sees the result on a Lydia Gate-hosted page.
Possible errors
Section titled “Possible errors”| Code | HTTP | Reason |
|---|---|---|
payment_link_not_found |
404 |
The link was not found or does not belong to this partner. |
payment_link_already_paid |
409 |
The link is already completed. (Rarely, the same error is returned if your cancellation races with a payment completing at that exact moment.) |
payment_link_expired |
409 |
The link’s window has expired; it can no longer be cancelled. |
payment_link_cancelled |
409 |
The link was already cancelled. |
installment_not_allowed |
422 |
allowedInstallmentCounts was sent empty, or is not a subset of your terminal’s effective installment set. |
Full list: Error Codes.
Webhooks
Section titled “Webhooks”When a link completes or expires, Lydia Gate sends you a webhook (payment_link.completed / payment_link.expired); the body carries this page’s id field (named paymentLinkId) instead of paymentCode. Detail and a sample body: Webhooks.
Related
Section titled “Related”- Create Payment: the direct S2S flow with card handoff
- Webhooks
- Error Codes