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
Amount Format
All amounts use minor currency units (e.g., cents for EUR):
- Request: String format (e.g.,
"2500"for €25.00) - Response: Long/integer format (e.g.,
2500for €25.00)
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 link details |
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) |
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) |
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 | 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) |
Get Payment Link​
Request​
curl -X GET https://api.paysera.com/checkout-payment-link/integration/v1/payment-links/c8d9e0f1-2a3b-4c5d-6e7f-8a9b0c1d2e3f \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
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",
"country_code": "LT"
},
"payer_information": {
"name": "John Doe",
"email": "john.doe@paysera.net"
},
"expired_at": 1736436870,
"created_at": 1736433270
}
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 |
No Failed Status
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?currency=EUR&country=LT" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response includes available methods with their keys:
{
"items": [
{
"key": "swedbank",
"name": "Swedbank",
"country_code": "LT",
"min_amount": 1,
"max_amount": 5000000
},
{
"key": "seb",
"name": "SEB",
"country_code": "LT",
"min_amount": 1,
"max_amount": 5000000
}
]
}
Error Responses​
Invalid Order​
{
"error": "not_found",
"message": "Order not found"
}
Order Already Paid​
{
"error": "conflict",
"message": "Order is already completed"
}
Invalid Payment Method​
{
"error": "validation_error",
"message": "Payment method not available",
"details": [
{
"field": "preferred_payment_method_key",
"message": "Payment method 'invalid-key' is not available for this currency"
}
]
}
Related Documentation​
- Payment Orders - Create orders before payment links
- Webhooks - Handle payment notifications
- Payment Statuses Reference - Complete status reference