Run your Payclio business from your own system.
Payment links and product links, subscriptions, products, customers and invoices, transactions with PDF receipts, refunds, Pay and withdrawals. The same things your dashboard does, over one REST API, with keys that only do what you allow.
API v1 keeps working as it is. To take a single payment from a checkout, the v1 payment requests API is still the simplest path.
Base URL https://payclio.com/api/v2
curl https://payclio.com/api/v2/account \
-H "Authorization: Bearer $PAYCLIO_KEY"
{ "id": 133, "businessName": "Darth Consulting cc",
"status": "ACTIVE", "verification": "APPROVED",
"timeZone": "Africa/Windhoek",
"permissions": ["read", "payments"] }Authentication and permissions
Send your API key as a bearer token. Make keys in the dashboard under API keys and tick what each key may do. A key without Refunds or Pay out can't move money out of your account, so give a key only what it needs and keep it on your server.
Keys made before API v2 have Read and Create payments.
Authorization: Bearer pclk_live_... Content-Type: application/json
| Permission | Allows |
|---|---|
readRead | Account, wallets, transactions, receipts, payment links, subscription plans and subscribers, products, customers, invoices, payees, payouts and withdrawals. |
paymentsCreate payments | Create and change payment links, product links, subscription plans, products, customers and invoices. Send and void invoices. Make subscription sign-up links, and cancel, pause or resume subscriptions. |
refundsRefunds | Refund payments the account received. The money leaves the wallet. |
payoutsPay out | Pay saved payees with Pay, and withdraw to the account's own approved bank account. The money leaves the wallet. |
How it works
- JSON in and out. Field names are camelCase. Amounts are numbers in the wallet's currency, for example
240.00. - Lists come back as
{"data": [...]}. Paged lists also havepageandhasMore. - Times are UTC in ISO 8601.
/accountgives the business's time zone if you want to show local times, the way receipts and the dashboard do. - Errors are
{"error": "...", "code": "..."}with the HTTP status below.
Endpoints
Paths are relative to https://payclio.com/api/v2.
Account and wallets
Who the key belongs to, what it may do, and the balances. available is the balance less funds on hold.
GET /account | read | Business name, username, verification status, time zone and this key's permissions. |
GET /wallets | read | Each open wallet: currency, balance, available, default. |
Payment links and product links
A payment link is an amount and a note. A product link is a small checkout page: title, description, a fixed or customer-chosen amount, quantity, and fields such as phone, address or a note.
GET /payment-links?page=0&size=20 | read | Both kinds, newest first, with payments taken and the total collected. |
POST /payment-links | payments | Make a payment link: walletId, amount, memo, expiresIn (days). |
POST /payment-links/{id}/cancel | payments | Cancel a pending payment link. |
POST /product-links | payments | Make a product link. Fields below. |
GET /product-links/{id} | read | One product link. |
PATCH /product-links/{id} | payments | Change a product link. Send the full set of fields. |
GET /product-links/{id}/payments | read | Every payment on a product link, with what the payer filled in. |
Products
Saved products and services, for invoice lines. kind is PRODUCT or SERVICE.
GET /products | read | All saved products and services. |
POST /products | payments | name, description, unitPrice, currency, taxRate, kind, priceIncludesTax. |
PATCH /products/{id} | payments | Change a product. |
DELETE /products/{id} | payments | Remove a product. Invoices that used it keep their lines. |
Customers and invoices
An invoice starts as a draft. Sending it gives it its number and a pay page that takes card and wallet. Reminders and repeats follow the business's invoice settings, in its own time zone.
GET /customers | read | Saved customers. |
POST /customers | payments | name, email, phone, addressLine, addressCity, addressPostalCode, addressCountry, taxId. |
PATCH /customers/{id} | payments | Change a customer. |
GET /invoices | read | The latest 200 invoices, newest first, with status and whether they are overdue. |
GET /invoices/{id} | read | One invoice with lines, totals, payerUrl, reminders sent and repeat. |
POST /invoices | payments | Save a draft. Fields below. |
PATCH /invoices/{id} | payments | Change an invoice. Send the full set of fields. |
POST /invoices/{id}/send | payments | Number it and open it for payment. Body {"email": false} skips the email to the customer. |
POST /invoices/{id}/void | payments | Void an unpaid invoice. |
GET /invoices/{id}/pdf | read | The invoice as a PDF. |
Subscriptions
A plan is a price and how often it is charged. Customers subscribe on the plan's link, or on a sign-up link you make for one customer. Payclio takes each payment, retries a failed one after 1, 3 and 5 days, then marks the subscription PAST_DUE.
GET /subscription-plans | read | All plans, newest first, with their link, summary and how many subscribers are on each. |
GET /subscription-plans/{id} | read | One plan. |
POST /subscription-plans | payments | Make a plan. Fields below. Price and terms can't change afterwards. |
PATCH /subscription-plans/{id} | payments | Change the name or description. |
POST /subscription-plans/{id}/archive | payments | Stop new sign-ups. Existing subscribers keep paying. |
POST /subscriptions/checkout | payments | A sign-up link for one customer, valid 24 hours, with your reference and return URL. Used once. |
GET /subscriptions?status=&planId=&page=0&size=25 | read | Your subscribers, newest first. status is TRIALING, ACTIVE, PAST_DUE, PAUSED, CANCELLED or COMPLETED. |
GET /subscriptions/{id} | read | One subscription with every payment. Paid payments carry the transactionId to refund. |
POST /subscriptions/{id}/cancel | payments | Body {"atPeriodEnd": true} ends it when the paid period runs out; false ends it now. |
POST /subscriptions/{id}/pause | payments | No payments are taken while paused. |
POST /subscriptions/{id}/resume | payments | After a pause or PAST_DUE. A missed payment is taken now; if it fails, 400 says why. |
Transactions, receipts and refunds
Every movement on the account's wallets. Payments received through a payment link, product link or subscription can be refunded. Invoice payments can't be refunded yet.
GET /transactions?type=&direction=&walletId=&page=0&size=25 | read | Newest first. direction is IN or OUT. Each row says if it is refundable and what the refund fee would be. |
GET /transactions/{id} | read | One transaction, with its refund if it was refunded. |
GET /transactions/{id}/receipt | read | The PDF receipt, with times in the account's own time zone. |
POST /transactions/{id}/refund | refunds | Refund a payment. reason and an optional message. |
Pay and withdrawals
Pay sends money to saved payees: bank payments go into Payclio's payment queue, payments to Payclio accounts arrive straight away. Withdrawals go to the account's own approved bank account. Both need a verified business account.
GET /payees | read | Saved payees. Add payees in the dashboard under Pay. |
POST /payouts/quote | read | Fees and totals for a batch, without paying. |
POST /payouts | payouts | Pay one or more payees from one wallet. All rows are paid or none. |
GET /payouts | read | Payments made with Pay, with status and bank reference once paid. |
GET /bank-accounts | read | The account's approved bank accounts. |
POST /withdrawals | payouts | bankAccountId, walletId, amount, memo. |
GET /withdrawals | read | Recent withdrawals with status. |
Make a product link
Share url with customers. Each payment shows under /product-links/{id}/payments and as a transaction.
walletId | The wallet that receives the money. Its currency is the link's currency. |
title, description | What the customer sees. Title is required. |
amountType | FIXED (set amount) or OPEN (the customer types it, with an optional minAmount). |
amount, minAmount | amount for FIXED, minAmount for OPEN. |
allowQuantity, maxQuantity | Let the customer buy more than one, up to maxQuantity (2 to 999). Fixed amounts only. |
collectPhone, noteMode | OFF, OPTIONAL or REQUIRED. noteLabel names the note field. |
collectAddress | Ask for a delivery address. |
reusable | true: many customers can pay it. false: it closes after one payment. |
expiresOn | yyyy-mm-dd. The link closes at the end of that day in the business's time zone. Leave out for no end. |
thankYou, returnUrl, sendReceipt | Message after payment, an https link to send the customer back to, and whether Payclio emails a receipt. |
curl -X POST https://payclio.com/api/v2/product-links \
-H "Authorization: Bearer $PAYCLIO_KEY" \
-H "Content-Type: application/json" \
-d '{
"walletId": 12,
"title": "Coffee beans, 1 kg",
"description": "Single origin, roasted this week.",
"amountType": "FIXED",
"amount": 240.00,
"allowQuantity": true,
"maxQuantity": 10,
"collectPhone": "REQUIRED",
"collectAddress": true,
"noteMode": "OPTIONAL",
"reusable": true,
"expiresOn": "2026-12-31",
"returnUrl": "https://example.com/thanks"
}'
# 200
{ "id": 88, "token": "a1b2c3", "url": "https://app.payclio.com/req/a1b2c3",
"status": "PENDING", "currency": "NAD", "title": "Coffee beans, 1 kg",
"paymentCount": 0, "collected": 0.00, ... }Send an invoice
The customer pays on payerUrl by card or wallet. When it is paid the invoice status becomes PAID and the payment shows as a transaction.
walletId | The wallet that receives the payment. Its currency is the invoice currency. |
customerId or customer | A saved customer, or a customer object for this invoice only. |
lines | description, quantity, unitPrice, taxRate (percent), details, priceIncludesTax. |
discountType, discountValue | NONE, PERCENT or AMOUNT. |
issueDate, dueDate | yyyy-mm-dd. Issue date defaults to today in the business's time zone. |
memo, footer | Text on the invoice. |
cardOn, walletOn | Which ways the customer may pay. |
sendReminders | Email reminders before and after the due date, on the schedule in invoice settings. |
# 1. Save a draft
curl -X POST https://payclio.com/api/v2/invoices \
-H "Authorization: Bearer $PAYCLIO_KEY" \
-H "Content-Type: application/json" \
-d '{
"walletId": 12,
"customerId": 31,
"lines": [
{ "description": "Website hosting, November", "quantity": 1, "unitPrice": 350.00, "taxRate": 15 },
{ "description": "Domain renewal", "quantity": 1, "unitPrice": 180.00 }
],
"issueDate": "2026-11-04",
"dueDate": "2026-11-18",
"memo": "Thank you for your business.",
"sendReminders": true
}'
# 2. Number it, open it for payment and email it
curl -X POST https://payclio.com/api/v2/invoices/204/send \
-H "Authorization: Bearer $PAYCLIO_KEY" -H "Content-Type: application/json" -d '{}'
# 200
{ "id": 204, "number": "INV-0042", "status": "OPEN", "total": 582.50,
"payerUrl": "https://app.payclio.com/i/kq81...", ... }Sell a subscription
Share the plan's url anywhere, or make a sign-up link for one customer with /subscriptions/checkout and send them to hostedUrl. Either way the customer agrees to the payments on a Payclio page and gets a link by email to manage or cancel. Watch the subscription.* webhooks to give or take away access.
name, description | What subscribers see. Name 2 to 80 characters. |
amount, currency | The price of each payment. You need an active wallet in that currency; payments are paid into it. |
interval | WEEK, MONTH, QUARTER (every 3 months) or YEAR. |
trialDays | Free days before the first payment, 0 to 365. We email the subscriber 3 days before it ends. |
setupFee | A one-off amount taken with the first payment. |
totalPayments | Stop after this many payments (2 to 120). Leave out to charge until cancelled. |
allowWallet, allowCard | How subscribers may pay. Plans that allow cards take them once card subscriptions are switched on for your account. |
Sign-up link fields
planId | One of your active plans. |
customerName, customerEmail | Filled in on the sign-up page. Optional. |
referenceType, referenceId | Your own ids, for example member and M-42. They come back on the subscription and in every webhook. referenceType uses a to z, 0 to 9, _ and -. |
returnUrl | Where the subscriber goes a few seconds after signing up. A full http or https address. |
# 1. A plan: NAD 199 a month, 7 days free
curl -X POST https://payclio.com/api/v2/subscription-plans \
-H "Authorization: Bearer $PAYCLIO_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Gym membership", "amount": 199.00, "currency": "NAD",
"interval": "MONTH", "trialDays": 7 }'
# 200
{ "id": 14, "url": "https://app.payclio.com/sub/k2m9...", "status": "ACTIVE",
"summary": "Free for 7 days, then NAD 199.00 every month until you cancel", ... }
# 2. A sign-up link for one of your members
curl -X POST https://payclio.com/api/v2/subscriptions/checkout \
-H "Authorization: Bearer $PAYCLIO_KEY" \
-H "Content-Type: application/json" \
-d '{ "planId": 14, "customerName": "Sam Example", "customerEmail": "sam@example.com",
"referenceType": "member", "referenceId": "M-42",
"returnUrl": "https://example.com/welcome" }'
# 200
{ "token": "x7p...", "hostedUrl": "https://app.payclio.com/sub/c/x7p...",
"expiresAt": "2026-11-05T18:00:00Z", "status": "OPEN", "subscriptionId": null, ... }Refund a payment
Payments received through a payment link, product link or subscription can be refunded once, in full. Refunding a subscription payment doesn't cancel the subscription. Invoice payments can't be refunded yet. The whole amount goes back to the card or Payclio wallet the customer paid with. Your wallet is charged the amount plus the refund fee (see Pricing), and the payment fee is not returned. If the wallet doesn't have enough, its balance goes below zero and new payments cover it first.
customer_request | The customer asked for a refund. The payer is emailed. |
duplicate | The customer paid twice. The payer is emailed. |
fraudulent | A payment you believe was fraud. The payer is not emailed. |
other | Anything else. Add a message. |
curl -X POST https://payclio.com/api/v2/transactions/4821/refund \
-H "Authorization: Bearer $PAYCLIO_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "customer_request", "message": "Order cancelled before dispatch." }'
# 200
{ "reason": "CUSTOMER_REQUEST", "reasonLabel": "The customer asked for a refund",
"by": "You", "method": "Card", "amount": 49.99, "fee": 0.50,
"debited": 50.49, "at": "2026-11-04T13:10:00Z" }Pay suppliers and staff
Pay up to many saved payees in one call. The wallet must cover the whole batch, and if one row fails none are paid. reference is what the payee sees, myReference stays with you. Use /payouts/quote first to show the fees.
Money can't leave an account while Payclio is reviewing a payment on it. Pay and withdrawals then return 400 with the reason.
curl -X POST https://payclio.com/api/v2/payouts \
-H "Authorization: Bearer $PAYCLIO_KEY" \
-H "Content-Type: application/json" \
-d '{
"walletId": 12,
"rows": [
{ "payeeId": 7, "amount": 1500.00, "reference": "Invoice 118", "myReference": "Supplier Oct" },
{ "payeeId": 9, "amount": 250.00, "reference": "Commission" }
]
}'
# 200
{ "batchId": 15, "currency": "NAD", "total": 1760.00, "feeTotal": 10.00,
"rows": [ { "payeeId": 7, "method": "BANK", "amount": 1500.00, "fee": 10.00, "status": "PENDING", ... },
{ "payeeId": 9, "method": "PAYCLIO", "amount": 250.00, "fee": 0, "status": "COMPLETED", ... } ] }Webhooks
Add an endpoint in the dashboard under Webhooks and pick the events. Every delivery is signed the same way as v1, with X-Payclio-Signature; see verifying signatures.
payment_request.paidA payment link, product link or invoice was paid.payment_request.expiredSomeone tried to pay an expired link.payment_request.cancelledA link was cancelled.payment.refundedA payment you received was refunded, by you or by Payclio.subscription.createdSomeone subscribed (on a free trial or after the first payment).subscription.payment_succeededA subscription payment was taken.chargehas the details.subscription.payment_failedA payment failed and will be tried again (next_retry_at), or the subscriber's bank asked them to confirm it (requires_action).subscription.past_dueThe last try failed. No more payments are taken until you resume it.subscription.trial_endingThe free trial ends in 3 days.subscription.cancelledCancelled, or set to end when the paid period runs out (cancel_at_period_end).cancelled_byis subscriber, merchant or period_end.subscription.completedThe last of a fixed number of payments was taken.
{
"id": "evt_9f2c...",
"event": "payment.refunded",
"created_at": "2026-11-04T13:10:02Z",
"data": {
"transaction_id": 4821,
"transaction_uuid": "0d6e...",
"amount": 49.99,
"currency": "USD",
"refund_fee": 0.50,
"debited": 50.49,
"method": "card",
"reason": "customer_request",
"refunded_by": "business",
"payment_request_token": "a1b2c3",
"reference_type": "woocommerce_order",
"reference_id": "1234",
"link_payment_id": null,
"refunded_at": "2026-11-04T13:10:00Z"
}
}{
"id": "evt_41ac...",
"event": "subscription.payment_succeeded",
"created_at": "2026-12-05T08:15:03Z",
"data": {
"subscription_id": 310,
"plan_id": 14,
"plan_name": "Gym membership",
"status": "ACTIVE",
"amount": 199.00,
"currency": "NAD",
"interval": "MONTH",
"payments_made": 1,
"current_period_start": "2026-12-05T08:15:00Z",
"current_period_end": "2027-01-05T08:15:00Z",
"next_charge_at": "2027-01-05T08:15:00Z",
"customer_name": "Sam Example",
"customer_email": "sam@example.com",
"payment_method": "wallet",
"reference_type": "member",
"reference_id": "M-42",
"source": "api",
"charge": { "id": 902, "payment_number": 1, "attempt": 1, "kind": "setup_and_first",
"amount": 199.00, "fee": 0.00, "net_amount": 199.00, "currency": "NAD",
"status": "succeeded", "failure_reason": null, "transaction_id": 5120, ... }
}
}Errors
| 400 | The body is wrong or the action isn't allowed, for example too little money in the wallet, or the account is under review. error says why. |
| 401 | Missing, unknown or revoked API key, or the account is suspended or deleted. |
| 403 | The key doesn't have the permission this endpoint needs. error names it. |
| 404 | Not found, or it belongs to another account. |
| 409 | The action can't be done now, for example the card network refused a refund. |