Documentation Index
Fetch the complete documentation index at: https://docs.centryos.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Create a payment link for collecting payments from customers. The link can be one-time (default) or recurring. For POST /v1/ext/collections/payment-link, itemDeliveryAddress and cartItems are required, and each cart item must include at least name and description.
Endpoint: POST /v1/ext/collections/payment-link
Auth: Bearer token with scope external.apis (authorizer: walletos-account-service-{stage}-authorizer).
Default vs recurring
| Mode | How to request | Result |
|---|
| One-time (default) | Omit checkoutType and recurringCharge, or send checkoutType: "generic". | Single-use or multi-use payment link; customer pays once (or multiple times if isOpenLink is true). |
| Recurring | Send checkoutType: "recurring" and a valid recurringCharge object. | Payment link that creates a subscription (fixed, consumption, or seating) after the customer completes checkout. |
Recurring compatibility: Existing callers that do not send checkoutType or recurringCharge still get one-time payment links.
Request
URL
POST {{LIQUIDITY_URL}}/v1/ext/collections/payment-link
| Header | Required | Description |
|---|
Authorization | Yes | Bearer <token> with scope external.apis. |
Content-Type | Yes | application/json. |
Body (JSON) – common fields
| Field | Type | Required | Description |
|---|
currency | string | Yes | Currency code. Supported: USD, NGN, CAD, GBP, EUR. |
name | string | No | Display name for the link (default: "page"). |
amount | number | Yes* | Amount per payment. *For one-time: min 0.5. For recurring subscription: required (min 0.5). For consumption/seating: optional (min 0). |
customUrlPath | string | No | Slug for the URL (default: "page"). |
redirectTo | string | No | URI to redirect after payment (default: "https://www.centryos.xyz"). |
expiredAt | string | No | ISO date when the link expires (default: one year from now). |
checkoutType | string | No | "generic" (default), "ecommerce", or "recurring". Use "recurring" for recurring payment links. |
recurringCharge | object | No** | Required when checkoutType === "recurring". Forbidden otherwise. See Recurring body. |
isOpenLink | boolean | No | If true, link can be used multiple times (default: true). |
customerPays | boolean | No | If true, customer pays fees (default: true). |
orderId | string | No | Your order/reference id. |
dataCollections | array | No | Extra data to collect (e.g. ["Phone number"]). Base set always includes Email, First name, Last name, Phone number. |
customFields | array | No | Custom field names. |
acceptedPaymentOptions | array | No | e.g. ["card"] (default). |
notifyPayee | boolean | No | Notify payee (default: false). |
agent | object | No | Agent details (type, email, name, etc.) for notifications. |
brandingConfig | object | No | Logo, colors, etc. |
advancedConfig | object | No | websiteUrl, webhookPath, webhookSecret for external webhook registration when using /ext path. |
customData | object | No | Key-value metadata (string values only). |
itemDeliveryAddress | string | Yes | Merchant-supplied delivery address saved with the payment link and copied into transaction metadata when the customer pays. |
cartItems | array | Yes | Cart items for the payment link. Send at least one item, and each item must include name and description. |
externalId | string | No | Your external reference. |
Cart items
Each cartItems[] entry must include:
| Field | Type | Required | Description |
|---|
name | string | Yes | Item name shown for the order. |
description | string | Yes | Item description shown for the order. |
qty | number | No | Quantity of the item. |
price | number | No | Item price. |
currency | string | No | Item currency code. |
productId | string | No | Your product identifier. |
imageUrl | string | No | Public image URL for the item. |
Recurring body
When checkoutType is "recurring", you must send recurringCharge with this shape:
| Field | Type | Required | Description |
|---|
type | string | Yes | "subscription", "consumption", or "seating". |
startDate | string | Yes | ISO date when billing starts (trial end). Must be before expiredAt. |
interval | object | Yes | Billing interval. |
interval.type | string | Yes | "day", "week", "month", or "year". |
interval.count | number | Yes | e.g. 1 for monthly. |
productId | string | No | Product ID for recurring billing (optional). |
consumptionDetails | object | Yes if type is consumption | See below. |
seatDetails | object | Yes if type is seating | See below. |
When type === "consumption":
| Field | Type | Required | Description |
|---|
unit | string | Yes | e.g. "API call", "GB". |
costPerUnit | number | Yes | Price per unit. |
minimumUnits | number | No | Included units before charges apply. |
baseFee | number | Conditional | Required if minimumUnits is set. |
When type === "seating":
| Field | Type | Required | Description |
|---|
baseFee | number | Yes | Fixed fee per period. |
costPerSeat | number | Yes | Price per seat. |
newSeatBillingType | string | Yes | "prorate", "next_cycle", or "immediate". |
Examples
All POST /v1/ext/collections/payment-link examples below include the required itemDeliveryAddress and cartItems fields.
One-time payment link (default)
curl -X POST "{{LIQUIDITY_URL}}/v1/ext/collections/payment-link" \
-H "Authorization: Bearer {{accessToken}}" \
-H "Content-Type: application/json" \
-d '{
"currency": "USD",
"name": "One-time donation",
"amount": 25.00,
"customUrlPath": "donate",
"redirectTo": "https://example.com/thanks",
"itemDeliveryAddress": "123 Main St, Austin, TX, 78701, US",
"cartItems": [
{
"name": "Hourly service",
"description": "One hour of service",
"price": 25.00,
"currency": "USD"
}
]
}'
Omit checkoutType and recurringCharge to get the existing one-time behavior.
Recurring – fixed subscription
{
"currency": "USD",
"name": "Monthly plan",
"amount": 29.99,
"customUrlPath": "monthly-plan",
"redirectTo": "https://example.com/thanks",
"itemDeliveryAddress": "123 Main St, Austin, TX, 78701, US",
"cartItems": [
{
"name": "Monthly plan seat",
"description": "Monthly subscription access",
"price": 29.99,
"currency": "USD"
}
],
"checkoutType": "recurring",
"recurringCharge": {
"type": "subscription",
"startDate": "2026-02-01",
"interval": { "type": "month", "count": 1 }
}
}
Recurring – consumption (usage-based)
{
"currency": "USD",
"name": "API usage",
"amount": 0,
"customUrlPath": "api-usage",
"redirectTo": "https://example.com/thanks",
"itemDeliveryAddress": "123 Main St, Austin, TX, 78701, US",
"cartItems": [
{
"name": "API usage plan",
"description": "Usage-based billing plan",
"price": 0,
"currency": "USD"
}
],
"checkoutType": "recurring",
"recurringCharge": {
"type": "consumption",
"startDate": "2026-02-01",
"interval": { "type": "month", "count": 1 },
"consumptionDetails": {
"unit": "API call",
"costPerUnit": 0.10,
"minimumUnits": 1000,
"baseFee": 20
}
}
}
Recurring – seating (per-seat)
{
"currency": "USD",
"name": "Team plan",
"amount": 0,
"customUrlPath": "team-plan",
"redirectTo": "https://example.com/thanks",
"itemDeliveryAddress": "123 Main St, Austin, TX, 78701, US",
"cartItems": [
{
"name": "Team plan base seat",
"description": "Seat-based team subscription",
"price": 0,
"currency": "USD"
}
],
"checkoutType": "recurring",
"recurringCharge": {
"type": "seating",
"startDate": "2026-02-01",
"interval": { "type": "month", "count": 1 },
"seatDetails": {
"baseFee": 20,
"costPerSeat": 5,
"newSeatBillingType": "prorate"
}
}
}
Response
Success (200)
{
"success": true,
"data": {
"url": "<checkout-widget-url>",
"application": {
"id": "<payment-link-uuid>",
"token": "<token>",
"tokenType": "<type>",
"expiredAt": "<ISO-date>",
"valid": true
}
}
}
data.url is the payment link URL to share with customers.
- For recurring links, after the customer completes checkout (payment method saved), a subscription is created and billing follows the configured interval and type.
Error (4xx / 5xx)
{
"success": false,
"message": "<error detail or validation errors>",
"fatal": true
}
| Situation | HTTP | Notes |
|---|
| Unauthorized | 401 | Invalid or expired token, or missing external.apis scope. |
| Validation error | 400 | Missing/invalid fields (e.g. amount, currency, itemDeliveryAddress, cartItems, or recurringCharge when checkoutType is recurring). |
| recurringCharge when not recurring | 400 | recurringCharge is only allowed when checkoutType is "recurring". |
| Missing recurringCharge | 400 | When checkoutType is "recurring", recurringCharge is required with valid type, startDate, interval, and type-specific details. |
| Collection account not found | 400 | No collection account for the business/currency. |
| Server error | 500 | e.g. database or downstream failure. |
Validation summary
- currency – Required, one of supported types.
- amount – Required for one-time and for recurring
subscription (min 0.5). Optional for consumption/seating (min 0).
- itemDeliveryAddress – Required on
POST /v1/ext/collections/payment-link.
- cartItems – Required on
POST /v1/ext/collections/payment-link; send at least one item, and each item must include name and description.
- checkoutType – Optional. Default:
"generic". Use "recurring" for recurring payment links.
- recurringCharge – Allowed only when
checkoutType === "recurring". Required then, with type, startDate, interval; plus consumptionDetails or seatDetails depending on type.
- startDate – Must be before
expiredAt.
Recurring billing behavior
For recurring links, the customer is first asked to save a payment method (no charge at link use). When the setup succeeds, a subscription is created and charges follow the configured model (subscription, consumption, or seating). Billing cycles, seat changes, and usage reporting follow the platform’s recurring payments behavior.
Changelog
- External API request fields:
itemDeliveryAddress and cartItems are required on POST /v1/ext/collections/payment-link. Each cart item must include at least name and description.
- Recurring via External API: Create payment link supports
checkoutType: "recurring" and recurringCharge on POST /v1/ext/collections/payment-link. Default remains one-time when these fields are omitted (no breaking changes).