Payment Links
Generate shareable payment links for flexible payment collection scenarios.
Payment links provide a URL where customers can complete their payment. This guide covers creating and managing payment links.
Overview​
A payment link:
- Associates with a payment order
- Generates a checkout URL for customers
- Has configurable lifetime (expiration)
- Supports language and payment method customization
All amounts use minor currency units (e.g., cents for EUR), as integers:
- Request: integer (e.g.,
2500for €25.00) - Response: integer (e.g.,
2500for €25.00)
If the underlying order was created with splits, the payment link must not expire. Set lifetime: 0 — otherwise the request is rejected with validation_split_expiration_not_allowed. The link amount must also equal the order's full amount; a mismatch is rejected with validation_split_amount_mismatch (partial-amount links are only allowed for non-split orders).
Endpoints​
| Method | Endpoint | Description |
|---|---|---|
| POST | /checkout-payment-link/integration/v1/payment-links | Create a payment link |
| GET | /checkout-payment-link/integration/v1/payment-links/{id} | Get a payment link |
| GET | /checkout-payment-link/integration/v1/payment-links | List payment links |
| PUT | /checkout-payment-link/integration/v1/payment-links/{id} | Update a payment link |
| PUT | /checkout-payment-link/integration/v1/payment-links/{id}/cancel | Cancel a payment link |
You can read a link with GET /payment-links/{id} and list links with GET /payment-links. Links can also be updated (PUT /payment-links/{id}) and canceled (PUT /payment-links/{id}/cancel). Webhooks remain available for state changes (see Webhooks).
Create Payment Link​
Request​
curl -X POST https://api.paysera.com/checkout-payment-link/integration/v1/payment-links \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"order_id": "a6f2b8e3-5e5f-47d9-b13f-87ed2db2938a",
"name": "Order #12345",
"lifetime": 3600,
"experience": {
"language": "en",
"payment_flow": "paysera_checkout"
},
"purchase": {
"amount": 2500
},
"payment_details": {
"key": "swedbank",
"purpose": "Order #12345 - Leather Wallet",
"country_code": "LT"
},
"payer_information": {
"name": "John Doe",
"email": "john.doe@paysera.net"
},
"metadata": {
"referrer": "https://paysera.net"
}
}'
Request Parameters​
| Parameter | Type | Required | Description |
|---|---|---|---|
order_id | UUID | Yes | The payment order ID |
name | string | Yes | Display name for the payment link (max 255 chars) |
lifetime | integer | No | Link validity in seconds (default: 259200 = 3 days, 0 = never expire, max: 86313600). Must be 0 if the order has splits. |
experience | object | Yes | Payment experience configuration |
experience.language | string | Yes | UI language code (ISO 639-1, e.g., "en", "lt") |
experience.payment_flow | string | No | Payment flow: "paysera_checkout" (default) or "direct_payment" |
purchase | object | Yes | Purchase information |
purchase.amount | integer | Yes | Amount in minor units (e.g., 2500 for €25.00) |
payment_details | object | No | Pre-selected payment method configuration |
payment_details.key | string | No | Payment method key (e.g., "swedbank") |
payment_details.purpose | string | No | Payment purpose description (max 255 chars). Used verbatim as the payer-facing payment purpose, truncated to 140 chars — see Payment purpose |
payment_details.country_code | string | No | ISO 3166-1 alpha-2 country code |
payer_information | object | No | Customer information |
payer_information.name | string | No | Customer name (max 150 chars) |
payer_information.email | string | No | Customer email |
metadata | object | No | Additional key-value metadata |
Response​
{
"link_id": "c8d9e0f1-2a3b-4c5d-6e7f-8a9b0c1d2e3f",
"order_id": "a6f2b8e3-5e5f-47d9-b13f-87ed2db2938a",
"payment_URL": "https://api.paysera.com/checkout-payment-link/payment-collection/v1/payment-links/abc123def456GhiJkl_mNOpQrStUvWxYz0123456",
"experience": {
"language": "en",
"payment_flow": "paysera_checkout"
},
"purchase": {
"amount": 2500
},
"payment_details": {
"key": "swedbank",
"purpose": "Order #12345 - Leather Wallet",
"country_code": "LT"
},
"payer_information": {
"name": "John Doe",
"email": "john.doe@paysera.net"
},
"expired_at": 1736436870,
"created_at": 1736433270
}
Response Fields​
| Field | Type | Description |
|---|---|---|
link_id | UUID | Unique payment link identifier |
order_id | UUID | Associated order identifier |
payment_URL | string | Payment URL for customer redirect |
experience | object | Payment experience configuration |
experience.language | string | UI language code |
experience.payment_flow | string | Payment flow type |
purchase | object | Purchase information |
purchase.amount | Long | Amount in minor units |
payment_details | object | Payment details (if provided) |
payment_details.key | string | Payment method key |
payment_details.purpose | string | The purpose you sent, echoed back — null if you omitted it. See Payment purpose |
payment_details.country_code | string | Country code |
payer_information | object | Payer information (if provided) |
payer_information.name | string | Payer name |
payer_information.email | string | Payer email |
expired_at | Long | Expiration Unix timestamp (seconds), null if never expires |
created_at | Long | Creation Unix timestamp (seconds) |
Payment purpose​
The payment purpose is the narrative the payer sees on the payment page and on their bank
statement. The resolved narrative — yours or the generated default — is returned as purpose on
the payment object and in payment webhooks. The payment link object echoes back only what you sent
in payment_details.purpose, so that field stays null when you omit it, even though the payer
still sees the generated default.
The purpose is set at creation only. The management endpoints use a different, flat representation of the link and do not carry it at all: neither Get a Payment Link nor List Payment Links returns it, and Update a Payment Link cannot change it. To change the purpose, cancel the link and create a new one.
If you send payment_details.purpose, it is used verbatim as the payer-facing purpose,
truncated to 140 characters (banks do not accept longer narratives, even though the field itself
accepts up to 255). Write it in the language your payer should read — it is never translated.
If you omit it, Paysera generates a default narrative from the order and project:
Payment for order #<purchase.reference> at <business name> (<project website>)
The generated text is translated into experience.language; languages without a translation fall
back to English. The (<project website>) suffix is omitted when the project has no website
configured.
The text on your own settlement statement is always the generated English narrative with your legal
or registered name, regardless of payment_details.purpose and experience.language, so your
reconciliation text stays stable.
Payment Link Statuses​
| Status | Code | Description |
|---|---|---|
| Active | active | Link is valid and can be used for payment |
| Completed | completed | Payment completed successfully via this link |
| Expired | expired | Link has expired (can still complete if payment in-flight) |
| Canceled | canceled | Link was invalidated |
Payment links do not have a failed status. If a payment attempt fails, the link remains active (unless expired or canceled), allowing the customer to retry.
See Payment Statuses Reference for complete status documentation.
Code Examples​
- PHP
- JavaScript
- Python
- Kotlin
- Go
- C#
<?php
function createPaymentLink(string $accessToken, string $orderId, array $linkData): array
{
$ch = curl_init('https://api.paysera.com/checkout-payment-link/integration/v1/payment-links');
$payload = [
'order_id' => $orderId,
'name' => $linkData['name'],
'lifetime' => $linkData['lifetime'] ?? 3600,
'experience' => [
'language' => $linkData['language'] ?? 'en',
'payment_flow' => 'paysera_checkout',
],
'purchase' => [
'amount' => $linkData['amount'], // In minor units (cents)
],
];
// Add optional payer information
if (!empty($linkData['payer_email'])) {
$payload['payer_information'] = [
'name' => $linkData['payer_name'] ?? null,
'email' => $linkData['payer_email'],
];
}
// Add pre-selected payment method
if (!empty($linkData['payment_method'])) {
$payload['payment_details'] = [
'key' => $linkData['payment_method'],
'country_code' => $linkData['country_code'] ?? null,
];
}
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $accessToken,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 201) {
throw new Exception('Failed to create payment link: ' . $response);
}
return json_decode($response, true);
}
// Usage - amount is in minor units (cents)
$link = createPaymentLink($accessToken, $orderId, [
'name' => 'Order #12345',
'amount' => 2500, // €25.00 in cents
'language' => 'en',
'lifetime' => 3600,
'payer_email' => 'customer@paysera.net',
]);
echo "Payment URL: " . $link['payment_URL'];
async function createPaymentLink(accessToken, orderId, linkData) {
const payload = {
order_id: orderId,
name: linkData.name,
lifetime: linkData.lifetime || 3600,
experience: {
language: linkData.language || 'en',
payment_flow: 'paysera_checkout',
},
purchase: {
amount: linkData.amount, // In minor units (cents)
},
};
if (linkData.payerEmail) {
payload.payer_information = {
name: linkData.payerName,
email: linkData.payerEmail,
};
}
if (linkData.paymentMethod) {
payload.payment_details = {
key: linkData.paymentMethod,
country_code: linkData.countryCode,
};
}
const response = await fetch(
'https://api.paysera.com/checkout-payment-link/integration/v1/payment-links',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
}
);
if (!response.ok) {
throw new Error(`Failed to create payment link: ${await response.text()}`);
}
return response.json();
}
// Usage - amount is in minor units (cents)
const link = await createPaymentLink(accessToken, orderId, {
name: 'Order #12345',
amount: 2500, // €25.00 in cents
language: 'en',
lifetime: 3600,
payerEmail: 'customer@paysera.net',
});
console.log('Payment URL:', link.payment_URL);
import requests
def create_payment_link(access_token: str, order_id: str, link_data: dict) -> dict:
payload = {
'order_id': order_id,
'name': link_data['name'],
'lifetime': link_data.get('lifetime', 3600),
'experience': {
'language': link_data.get('language', 'en'),
'payment_flow': 'paysera_checkout',
},
'purchase': {
'amount': link_data['amount'], # In minor units (cents)
},
}
if link_data.get('payer_email'):
payload['payer_information'] = {
'name': link_data.get('payer_name'),
'email': link_data['payer_email'],
}
if link_data.get('payment_method'):
payload['payment_details'] = {
'key': link_data['payment_method'],
'country_code': link_data.get('country_code'),
}
response = requests.post(
'https://api.paysera.com/checkout-payment-link/integration/v1/payment-links',
headers={
'Authorization': f'Bearer {access_token}',
'Content-Type': 'application/json',
},
json=payload,
)
response.raise_for_status()
return response.json()
# Usage - amount is in minor units (cents)
link = create_payment_link(access_token, order_id, {
'name': 'Order #12345',
'amount': 2500, # €25.00 in cents
'language': 'en',
'lifetime': 3600,
'payer_email': 'customer@paysera.net',
})
print(f"Payment URL: {link['payment_URL']}")
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import kotlinx.serialization.json.*
data class PaymentLinkData(
val name: String,
val amount: Long,
val language: String = "en",
val lifetime: Int = 3600,
val payerEmail: String? = null,
val payerName: String? = null,
val paymentMethod: String? = null,
val countryCode: String? = null
)
suspend fun createPaymentLink(accessToken: String, orderId: String, linkData: PaymentLinkData): JsonObject {
val client = HttpClient.newHttpClient()
val requestBody = buildJsonObject {
put("order_id", orderId)
put("name", linkData.name)
put("lifetime", linkData.lifetime)
putJsonObject("experience") {
put("language", linkData.language)
put("payment_flow", "paysera_checkout")
}
putJsonObject("purchase") {
put("amount", linkData.amount)
}
linkData.payerEmail?.let {
putJsonObject("payer_information") {
linkData.payerName?.let { name -> put("name", name) }
put("email", it)
}
}
linkData.paymentMethod?.let {
putJsonObject("payment_details") {
put("key", it)
linkData.countryCode?.let { code -> put("country_code", code) }
}
}
}
val request = HttpRequest.newBuilder()
.uri(URI.create("https://api.paysera.com/checkout-payment-link/integration/v1/payment-links"))
.header("Authorization", "Bearer $accessToken")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody.toString()))
.build()
val response = client.send(request, HttpResponse.BodyHandlers.ofString())
if (response.statusCode() != 201) {
throw Exception("Failed to create payment link: ${response.body()}")
}
return Json.parseToJsonElement(response.body()).jsonObject
}
// Usage - amount is in minor units (cents)
val link = createPaymentLink(accessToken, orderId, PaymentLinkData(
name = "Order #12345",
amount = 2500, // €25.00 in cents
language = "en",
lifetime = 3600,
payerEmail = "customer@paysera.net"
))
println("Payment URL: ${link["payment_URL"]}")
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
type PaymentLinkRequest struct {
OrderID string `json:"order_id"`
Name string `json:"name"`
Lifetime int `json:"lifetime"`
Experience Experience `json:"experience"`
Purchase Purchase `json:"purchase"`
PayerInfo *PayerInfo `json:"payer_information,omitempty"`
PaymentDetails *PaymentDetails `json:"payment_details,omitempty"`
}
type Experience struct {
Language string `json:"language"`
PaymentFlow string `json:"payment_flow"`
}
type Purchase struct {
Amount int64 `json:"amount"`
}
type PayerInfo struct {
Name string `json:"name,omitempty"`
Email string `json:"email"`
}
type PaymentDetails struct {
Key string `json:"key"`
CountryCode string `json:"country_code,omitempty"`
}
func createPaymentLink(accessToken, orderId string, linkData PaymentLinkRequest) (map[string]interface{}, error) {
linkData.OrderID = orderId
jsonData, _ := json.Marshal(linkData)
req, _ := http.NewRequest("POST",
"https://api.paysera.com/checkout-payment-link/integration/v1/payment-links",
bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode != 201 {
return nil, fmt.Errorf("failed to create payment link: %s", string(body))
}
var result map[string]interface{}
json.Unmarshal(body, &result)
return result, nil
}
// Usage - amount is in minor units (cents)
func main() {
link, _ := createPaymentLink(accessToken, orderId, PaymentLinkRequest{
Name: "Order #12345",
Lifetime: 3600,
Experience: Experience{
Language: "en",
PaymentFlow: "paysera_checkout",
},
Purchase: Purchase{
Amount: 2500, // €25.00 in cents
},
PayerInfo: &PayerInfo{
Email: "customer@paysera.net",
},
})
fmt.Printf("Payment URL: %s\n", link["payment_URL"])
}
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
public class PayseraPaymentLinkClient
{
private readonly HttpClient _httpClient;
public PayseraPaymentLinkClient(string accessToken)
{
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
}
public async Task<JsonDocument> CreatePaymentLinkAsync(string orderId, PaymentLinkData linkData)
{
var request = new Dictionary<string, object>
{
["order_id"] = orderId,
["name"] = linkData.Name,
["lifetime"] = linkData.Lifetime,
["experience"] = new Dictionary<string, string>
{
["language"] = linkData.Language,
["payment_flow"] = "paysera_checkout"
},
["purchase"] = new Dictionary<string, long>
{
["amount"] = linkData.Amount
}
};
if (!string.IsNullOrEmpty(linkData.PayerEmail))
{
request["payer_information"] = new Dictionary<string, string>
{
["name"] = linkData.PayerName,
["email"] = linkData.PayerEmail
};
}
if (!string.IsNullOrEmpty(linkData.PaymentMethod))
{
var paymentDetails = new Dictionary<string, string>
{
["key"] = linkData.PaymentMethod
};
if (!string.IsNullOrEmpty(linkData.CountryCode))
{
paymentDetails["country_code"] = linkData.CountryCode;
}
request["payment_details"] = paymentDetails;
}
var json = JsonSerializer.Serialize(request);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(
"https://api.paysera.com/checkout-payment-link/integration/v1/payment-links",
content);
var responseBody = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Failed to create payment link: {responseBody}");
}
return JsonDocument.Parse(responseBody);
}
}
public record PaymentLinkData(
string Name,
long Amount,
string Language = "en",
int Lifetime = 3600,
string? PayerEmail = null,
string? PayerName = null,
string? PaymentMethod = null,
string? CountryCode = null
);
// Usage - amount is in minor units (cents)
var client = new PayseraPaymentLinkClient(accessToken);
var link = await client.CreatePaymentLinkAsync(orderId, new PaymentLinkData(
Name: "Order #12345",
Amount: 2500, // €25.00 in cents
Language: "en",
Lifetime: 3600,
PayerEmail: "customer@paysera.net"
));
var linkUrl = link.RootElement.GetProperty("payment_URL").GetString();
Console.WriteLine($"Payment URL: {linkUrl}");
Pre-selecting Payment Method​
To skip the payment method selection screen, use direct_payment flow with the preferred payment method:
curl -X POST https://api.paysera.com/checkout-payment-link/integration/v1/payment-links \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"order_id": "order-uuid",
"name": "Direct bank payment",
"lifetime": 3600,
"experience": {
"language": "en",
"payment_flow": "direct_payment"
},
"purchase": {
"amount": 2500
},
"payment_details": {
"key": "swedbank",
"country_code": "LT"
}
}'
Getting Available Payment Methods​
To get available payment methods for pre-selection:
curl -X GET "https://api.paysera.com/checkout-project/integration/v1/methods?amount=2500¤cy=EUR" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Filtering by amount and currency is optional and only applied when both are provided. There is no country query parameter — supported countries are returned per method in available_countries.
Response includes available methods with their keys:
{
"items": [
{
"key": "swedbank",
"title": "Swedbank",
"description": "Pay via Swedbank online banking.",
"type": "banklink",
"flow": "redirect",
"available_countries": ["LT", "EE"],
"available_currencies": {
"EUR": { "main": true }
}
},
{
"key": "seb",
"title": "SEB",
"type": "banklink",
"flow": "redirect",
"available_countries": ["LT"],
"available_currencies": {
"EUR": { "main": true }
}
}
]
}
See Payment Methods Reference for the full field list.
Error Responses​
Invalid Order​
{
"error": "not_found",
"error_description": "Order not found"
}
Validation Error​
{
"error": "invalid_properties",
"error_description": "Validation failed",
"error_properties": {
"purchase.amount": ["Amount should be greater than 0"],
"experience.language": ["Language is required"]
}
}
Duplicate Link Name​
Creating a link whose name is already used by another link on the same order returns 409 Conflict:
{
"error": "validation_duplicate_name",
"error_description": "A payment link with this name already exists"
}
Authentication Failure​
{
"error": "unauthorized",
"error_description": "Authentication is required to access this resource"
}
Get a Payment Link​
GET /checkout-payment-link/integration/v1/payment-links/{id}
Retrieves a single payment link. Expired links are recognised on read and reflected
in status.
curl https://api.paysera.com/checkout-payment-link/integration/v1/payment-links/{id} \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response​
{
"id": "c8d9e0f1-2a3b-4c5d-6e7f-8a9b0c1d2e3f",
"order_id": "a6f2b8e3-5e5f-47d9-b13f-87ed2db2938a",
"project_id": "your-project-id",
"name": "Order #12345",
"amount": 2500,
"currency": "EUR",
"language": "en",
"country_code": "LT",
"link": { "url": "https://api.paysera.com/…/payment-links/abc123", "hash": "abc123" },
"preferred_payment_method_key": "swedbank",
"status": "active",
"is_personalized": true,
"expired_at": 1736436870,
"created_at": 1736433270,
"updated_at": 1736433270
}
List Payment Links​
GET /checkout-payment-link/integration/v1/payment-links
Returns a cursor-paginated list of payment links for your project.
curl "https://api.paysera.com/checkout-payment-link/integration/v1/payment-links?status=active&size=50" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Filter Parameters​
| Parameter | Type | Description |
|---|---|---|
order_id | UUID | Filter by associated order |
status | string | Comma-separated statuses, e.g. active,expired |
Pagination Parameters​
The order, payment link, payment and refund list endpoints share the same cursor-based
pagination. Cursors are opaque strings — read them from _metadata.cursors and send
them back unchanged; never build or parse them yourself.
| Parameter | Type | Default | Description |
|---|---|---|---|
size | integer | 10 | Items per page (1–1000). Out-of-range values return 400 invalid_properties. |
after | string | — | Cursor for the next page. Take it from _metadata.cursors.after. |
before | string | — | Cursor for the previous page. Take it from _metadata.cursors.before. Mutually exclusive with after. |
order_direction | string | desc | Sort direction: asc or desc. |
order_by | string | creation time | Field to sort by. Allowed values differ per endpoint — see the endpoint's parameter table. |
include_total_count | boolean | false | Set to true to populate _metadata.total. Off by default because counting is more expensive. |
Every list response has the same envelope:
{
"items": [],
"_metadata": {
"has_next": true,
"has_previous": false,
"cursors": {
"after": "MDE5ZmRiMmUtOWE5NC03ZDVmLThmY2ItNGRhMTQ1MzFkZGQ0",
"before": "MDE5ZmRjMjgtNWQ5YS03NjQ5LWExOWItZDhjNDAzODQ2NTRi"
},
"total": null
}
}
total is null unless you pass include_total_count=true.
To walk the whole collection, keep sending after until has_next is false:
# first page
curl "https://api.paysera.com/merchant-order/integration/v1/orders?size=50" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
# next page — reuse _metadata.cursors.after from the previous response
curl "https://api.paysera.com/merchant-order/integration/v1/orders?size=50&after=MDE5ZmRiMmUtOWE5NC03ZDVmLThmY2ItNGRhMTQ1MzFkZGQ0" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
The API does not reject parameters it doesn't know. Sending limit or cursor (names
used by some other APIs) does not return an error — the values are silently dropped
and you keep receiving the first page with the default size of 10. If pagination seems
stuck, check the parameter names first.
order_by accepts created_at (default), updated_at, status, amount,
currency and name.
Response​
{
"items": [
{
"id": "c8d9e0f1-2a3b-4c5d-6e7f-8a9b0c1d2e3f",
"link": { "url": "https://api.paysera.com/…/payment-links/abc123", "hash": "abc123" },
"project_id": "your-project-id",
"order_id": "a6f2b8e3-5e5f-47d9-b13f-87ed2db2938a",
"name": "Order #12345",
"amount": 2500,
"currency": "EUR",
"language": "en",
"country_code": "LT",
"receiver": { "name": null, "email": null },
"payer": { "name": "Jonas Jonaitis", "email": "jonas@example.com" },
"expired_at": 1736436870,
"preferred_payment_method_key": "swedbank",
"status": "active",
"is_personalized": true,
"created_at": 1736433270,
"updated_at": 1736433270,
"is_test": false
}
],
"_metadata": {
"has_next": true,
"has_previous": false,
"cursors": {
"after": "MDE5ZmRiMmUtYTY2Ny03MjFiLTkyZjMtNTUxODk4ZDg5OWM2",
"before": "MDE5ZmRjMjgtNjYwMy03NzJhLWI3NjQtNzM3NGViM2Q4MTUx"
},
"total": null
}
}
Update a Payment Link​
PUT /checkout-payment-link/integration/v1/payment-links/{id}
Updates a payment link. This is a full replacement — send all required fields; changes take effect immediately. The full updated payment-link object is returned.
The update request uses a flat structure and names the lifetime field link_lifetime — unlike the create request, which nests purchase.amount / experience.language and names the field lifetime. This difference is intentional; use the field names shown below when updating. As with create, set link_lifetime: 0 if the order has splits.
Request Parameters​
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name (max 255 chars) |
amount | integer | Yes | Amount in minor units (≥ 1) |
currency | string | Yes | ISO 4217 currency |
language | string | Yes | UI language (ISO 639-1) |
payer | object | Yes | { name, email } |
receiver | object | No | { name, email } |
link_lifetime | integer | No | Seconds; default 259200 (3 days), 0 = never expires (max 86313600). Must be 0 if the order has splits. |
preferred_payment_method_key | string | No | Pre-selected payment method |
Cancel a Payment Link​
PUT /checkout-payment-link/integration/v1/payment-links/{id}/cancel
Cancels a payment link. The request body is empty; a 200 OK is returned.
Re-cancelling an already-canceled link succeeds. A 409 is returned only if the link
has an active payment session in progress.
Related Documentation​
- Payment Orders - Create orders before payment links
- Webhooks - Handle payment notifications
- Payment Statuses Reference - Complete status reference