API v2

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
PermissionAllows
read
Read
Account, wallets, transactions, receipts, payment links, subscription plans and subscribers, products, customers, invoices, payees, payouts and withdrawals.
payments
Create 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.
refunds
Refunds
Refund payments the account received. The money leaves the wallet.
payouts
Pay 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 have page and hasMore.
  • Times are UTC in ISO 8601. /account gives 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
readBusiness name, username, verification status, time zone and this key's permissions.
GET/wallets
readEach open wallet: currency, balance, available, default.

Products

Saved products and services, for invoice lines. kind is PRODUCT or SERVICE.

GET/products
readAll saved products and services.
POST/products
paymentsname, description, unitPrice, currency, taxRate, kind, priceIncludesTax.
PATCH/products/{id}
paymentsChange a product.
DELETE/products/{id}
paymentsRemove 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
readSaved customers.
POST/customers
paymentsname, email, phone, addressLine, addressCity, addressPostalCode, addressCountry, taxId.
PATCH/customers/{id}
paymentsChange a customer.
GET/invoices
readThe latest 200 invoices, newest first, with status and whether they are overdue.
GET/invoices/{id}
readOne invoice with lines, totals, payerUrl, reminders sent and repeat.
POST/invoices
paymentsSave a draft. Fields below.
PATCH/invoices/{id}
paymentsChange an invoice. Send the full set of fields.
POST/invoices/{id}/send
paymentsNumber it and open it for payment. Body {"email": false} skips the email to the customer.
POST/invoices/{id}/void
paymentsVoid an unpaid invoice.
GET/invoices/{id}/pdf
readThe 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
readAll plans, newest first, with their link, summary and how many subscribers are on each.
GET/subscription-plans/{id}
readOne plan.
POST/subscription-plans
paymentsMake a plan. Fields below. Price and terms can't change afterwards.
PATCH/subscription-plans/{id}
paymentsChange the name or description.
POST/subscription-plans/{id}/archive
paymentsStop new sign-ups. Existing subscribers keep paying.
POST/subscriptions/checkout
paymentsA 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
readYour subscribers, newest first. status is TRIALING, ACTIVE, PAST_DUE, PAUSED, CANCELLED or COMPLETED.
GET/subscriptions/{id}
readOne subscription with every payment. Paid payments carry the transactionId to refund.
POST/subscriptions/{id}/cancel
paymentsBody {"atPeriodEnd": true} ends it when the paid period runs out; false ends it now.
POST/subscriptions/{id}/pause
paymentsNo payments are taken while paused.
POST/subscriptions/{id}/resume
paymentsAfter 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
readNewest first. direction is IN or OUT. Each row says if it is refundable and what the refund fee would be.
GET/transactions/{id}
readOne transaction, with its refund if it was refunded.
GET/transactions/{id}/receipt
readThe PDF receipt, with times in the account's own time zone.
POST/transactions/{id}/refund
refundsRefund 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
readSaved payees. Add payees in the dashboard under Pay.
POST/payouts/quote
readFees and totals for a batch, without paying.
POST/payouts
payoutsPay one or more payees from one wallet. All rows are paid or none.
GET/payouts
readPayments made with Pay, with status and bank reference once paid.
GET/bank-accounts
readThe account's approved bank accounts.
POST/withdrawals
payoutsbankAccountId, walletId, amount, memo.
GET/withdrawals
readRecent withdrawals with status.

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.

walletIdThe wallet that receives the payment. Its currency is the invoice currency.
customerId or customerA saved customer, or a customer object for this invoice only.
linesdescription, quantity, unitPrice, taxRate (percent), details, priceIncludesTax.
discountType, discountValueNONE, PERCENT or AMOUNT.
issueDate, dueDateyyyy-mm-dd. Issue date defaults to today in the business's time zone.
memo, footerText on the invoice.
cardOn, walletOnWhich ways the customer may pay.
sendRemindersEmail 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, descriptionWhat subscribers see. Name 2 to 80 characters.
amount, currencyThe price of each payment. You need an active wallet in that currency; payments are paid into it.
intervalWEEK, MONTH, QUARTER (every 3 months) or YEAR.
trialDaysFree days before the first payment, 0 to 365. We email the subscriber 3 days before it ends.
setupFeeA one-off amount taken with the first payment.
totalPaymentsStop after this many payments (2 to 120). Leave out to charge until cancelled.
allowWallet, allowCardHow subscribers may pay. Plans that allow cards take them once card subscriptions are switched on for your account.

Sign-up link fields

planIdOne of your active plans.
customerName, customerEmailFilled in on the sign-up page. Optional.
referenceType, referenceIdYour 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 -.
returnUrlWhere 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_requestThe customer asked for a refund. The payer is emailed.
duplicateThe customer paid twice. The payer is emailed.
fraudulentA payment you believe was fraud. The payer is not emailed.
otherAnything 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.paid A payment link, product link or invoice was paid.
  • payment_request.expired Someone tried to pay an expired link.
  • payment_request.cancelled A link was cancelled.
  • payment.refunded A payment you received was refunded, by you or by Payclio.
  • subscription.created Someone subscribed (on a free trial or after the first payment).
  • subscription.payment_succeeded A subscription payment was taken. charge has the details.
  • subscription.payment_failed A payment failed and will be tried again (next_retry_at), or the subscriber's bank asked them to confirm it (requires_action).
  • subscription.past_due The last try failed. No more payments are taken until you resume it.
  • subscription.trial_ending The free trial ends in 3 days.
  • subscription.cancelled Cancelled, or set to end when the paid period runs out (cancel_at_period_end). cancelled_by is subscriber, merchant or period_end.
  • subscription.completed The 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

400The 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.
401Missing, unknown or revoked API key, or the account is suspended or deleted.
403The key doesn't have the permission this endpoint needs. error names it.
404Not found, or it belongs to another account.
409The action can't be done now, for example the card network refused a refund.