TchokoPay
Guides

What changed

New endpoint names, direct charges, and why nothing you built has broken.

We renamed the API around two words — collect and disburse — and added direct charges plus a set of endpoints that tell you what we support.

You don't have to change anything. Every previous path still answers, behaves identically, and returns the same fields. Move when it suits you.

The names

The old names did not describe what they did — POST /v1/payments created a checkout page rather than taking a payment. The new ones say which direction money moves:

BeforeNow
POST /v1/paymentsPOST /v1/collect/checkout
GET /v1/payments/{reference}GET /v1/collect/{reference}
POST /v1/payoutsPOST /v1/disburse
GET /v1/payouts/{reference}GET /v1/disburse/{reference}
GET /v1/payout-limits/{currency}GET /v1/account/disburse-limits/{currency}
GET /v1/channelsGET /v1/account/providers
POST /v1/webhooksPUT /v1/webhook

Money in is collect, money out is disburse. Every endpoint, field and error uses those two words and no others.

What's new

Charge a number directly — POST /v1/collect/charge pushes a prompt straight to a phone, so your customer never leaves your checkout.

Endpoints that answer "what do you support?" — instead of hardcoding what we told you in an email:

Disburse limits answer one question

GET /v1/account/disburse-limits/{currency} now returns enabled — true only when a payout would actually be accepted.

It always answered 200 OK, including when payouts were switched off, and the only hint was configured, which described whether an admin had set you a ceiling and said nothing about whether the capability was on. An integration that checked the status code, or checked configured, could read a green light while payouts were off platform-wide.

- if (!limits.configured) throw new Error('Payouts not enabled');
+ if (!limits.enabled) throw new Error(limits.message);

configured still returns and still means what it meant, so nothing breaks. Alongside enabled you now get platformEnabled, blockedBy (PLATFORM, ACCOUNT_DISABLED, CURRENCY_CLOSED, or null) and a message you can show a person.

You don't need a payout limit provisioned. Your per-payout ceiling is the currency's own maximum — the same one that bounds a collection — unless support has agreed a different one with you. There is nothing to request before your first payout.

Errors have a shape now

Previously an error carried message, error and statusCode, and validation failures returned message as an array — two shapes for the same problem, neither with anything stable to branch on.

Now every error is:

{ "code": "INVALID_REQUEST", "message": "...", "param": "amount", "requestId": "..." }

Branch on code. See errors.

This is the one change worth a moment. If you were matching on error text, switch to code — wording will keep improving, and code won't move.

Statuses are untouched

PENDING, PROCESSING, SUCCESS, FAILED — same values, same spelling, same casing. Nothing to change.

Webhooks

Endpoints registered before this change keep receiving the old names — payment.succeeded, payment.failed, payout.sent, payout.paid, payout.failed. New ones get collect.succeeded, collect.failed, disburse.sent, disburse.succeeded and disburse.failed.

Your handler keeps working with no change. When you want the new names, deploy a handler that reads them and then re-register with "events": "v2" — see webhooks.

Rate limits can be raised

The default is 30/minute and 600/hour per key. If you're driving volume, we raise it per key — write to tech@tchokopay.com. Takes effect immediately, no key rotation.

If you're integrating today

Build against the new names. The old ones keep working and we will give you plenty of notice before anything changes, but the new names are what to write against.

On this page