coal
coal

Payment Links API

Payment links are shareable URLs that open a hosted Coal checkout page. This page covers the console-managed link lifecycle.

Public merchant API actions still use x-api-key on checkout/session routes. Payment-link CRUD under /api/console/* is part of the authenticated console surface and uses a Privy Bearer token.

Base URL: https://api.usecoal.xyz


Create a Payment Link

POST /api/console/links

Creates a new payment link for your merchant account.

Authentication

HeaderRequiredDescription
AuthorizationYesBearer <privy_access_token> from an authenticated console session

Request Body

FieldTypeRequiredDescription
slugstringNoOptional URL-safe path segment used at usecoal.xyz/pay/:slug.
productIdstringNoExisting product to attach to this link.
titlestringNoTitle shown when no product is attached.
descriptionstringNoOptional description shown on the hosted checkout page.
payerInfoobjectNoConfigure which payer details Coal should collect before checkout.

Response

201 Created

FieldTypeDescription
idstringPayment link ID.
merchantIdstringOwning merchant ID.
productIdstring | nullAttached product, if present.
slugstringPublic checkout slug.
titlestring | nullTitle for flexible links.
descriptionstring | nullDescription shown on checkout.
payerInfoConfigobject | nullPayer info collection rules attached to the link.
activebooleanWhether the link is active.
createdAtstringISO 8601 creation timestamp.

cURL Example

bash
1curl -X POST https://api.usecoal.xyz/api/console/links \
2 -H "Content-Type: application/json" \
3 -H "Authorization: Bearer <privy_access_token>" \
4 -d '{
5 "slug": "premium-membership",
6 "title": "Premium Membership",
7 "description": "Full access to all premium features for one year.",
8 "payerInfo": {
9 "required": true,
10 "fields": ["fullName", "email", "company"]
11 }
12 }'

Response Example

json
1{
2 "id": "lnk_cm9x4k2j00003lb08n5qz7v1r",
3 "merchantId": "usr_cm9x1merch",
4 "productId": null,
5 "slug": "premium-membership",
6 "title": "Premium Membership",
7 "description": "Full access to all premium features for one year.",
8 "payerInfoConfig": {
9 "required": true,
10 "fields": ["fullName", "email", "company"]
11 },
12 "active": true,
13 "createdAt": "2026-03-22T10:00:00.000Z"
14}

List Payment Links

GET /api/console/links

Returns all payment links for the authenticated merchant, sorted by creation date descending.

Authentication

HeaderRequiredDescription
AuthorizationYesBearer <privy_access_token> from an authenticated console session

Response

200 OK

json
1{
2 "links": [
3 {
4 "id": "lnk_cm9x4k2j00003lb08n5qz7v1r",
5 "slug": "premium-membership",
6 "url": "https://usecoal.xyz/pay/premium-membership",
7 "productName": "Premium Membership",
8 "productImage": null,
9 "price": "49.00",
10 "payerInfoConfig": {
11 "required": true,
12 "fields": ["fullName", "email", "company"]
13 },
14 "active": true,
15 "createdAt": "2026-03-22T10:00:00.000Z"
16 }
17 ]
18}

cURL Example

bash
1curl https://api.usecoal.xyz/api/console/links \
2 -H "Authorization: Bearer <privy_access_token>"

Delete a Payment Link

DELETE /api/console/links/:id

Soft-deletes a payment link by marking it inactive.

Authentication

HeaderRequiredDescription
AuthorizationYesBearer <privy_access_token> from an authenticated console session

Path Parameters

ParameterTypeDescription
idstringThe payment link ID (lnk_…).

Response

200 OK

json
1{
2 "id": "lnk_cm9x4k2j00003lb08n5qz7v1r",
3 "slug": "premium-membership",
4 "title": "Premium Membership",
5 "description": "Full access to all premium features for one year.",
6 "active": false
7}

Error Responses

StatusCodeDescription
401UNAUTHORIZEDMissing or invalid Bearer token.
404NOT_FOUNDNo link found for this merchant.

cURL Example

bash
1curl -X DELETE https://api.usecoal.xyz/api/console/links/lnk_cm9x4k2j00003lb08n5qz7v1r \
2 -H "Authorization: Bearer <privy_access_token>"

Node.js Examples

typescript
1const COAL_API = 'https://api.usecoal.xyz';
2const consoleToken = '<privy_access_token>';
3
4async function createPaymentLink(opts: {
5 slug: string;
6 amount?: number;
7 productName: string;
8 redirectUrl?: string;
9 callbackUrl?: string;
10 flexible?: boolean;
11 payerInfo?: {
12 required: boolean;
13 fields: Array<'fullName' | 'email' | 'phone' | 'company' | 'country'>;
14 };
15}) {
16 const res = await fetch(`${COAL_API}/api/console/links`, {
17 method: 'POST',
18 headers: {
19 'Content-Type': 'application/json',
20 Authorization: `Bearer ${consoleToken}`,
21 },
22 body: JSON.stringify(opts),
23 });
24
25 if (!res.ok) {
26 const err = await res.json();
27 throw new Error(`Failed to create link: ${err.error}`);
28 }
29
30 return res.json();
31}
32
33async function deletePaymentLink(id: string) {
34 const res = await fetch(`${COAL_API}/api/console/links/${id}`, {
35 method: 'DELETE',
36 headers: { Authorization: `Bearer ${consoleToken}` },
37 });
38
39 if (res.status === 404) {
40 throw new Error('Link not found');
41 }
42
43 return res.json();
44}