Developers
Connect your own systems to Citizen Pay — authentication, base URL, errors and pagination for the Business API.
The Citizen Pay Business API lets a system of yours — an HR tool, a school register, a membership platform — work with your business's data without anyone opening the dashboard. Today it covers members and badges: keep the list of badge holders in sync, register cards, and block a card the moment it is reported lost.
It is a plain JSON-over-HTTPS API. Every request is made on behalf of one business, the one the API key belongs to, so there is no business id in any path.
Authentication
Every request carries an API key in the Authorization header, as a bearer token:
Authorization: Bearer cpk_…A key starts with cpk_, followed by 43 more characters. You create keys in the dashboard, under
Badges → API keys — see API keys. Only owners and admins
of the business can do that.
- The full key is shown once, when it is created. Store it in your secret manager or server configuration straight away; Citizen Pay keeps only a hash of it and cannot show it again.
- Revoking a key in the dashboard takes effect immediately: the very next request with it is refused.
- A missing, unknown or revoked key is answered with
401and{"error":"invalid api key"}. - The dashboard shows when each key was last used, which helps you spot a key nobody needs any more.
Keep keys on your server
A key gives full read and write access to your business's members and badges. Call the API from your back end only — never from a browser, a mobile app or anything else you hand out to other people — and give each system its own key, so you can revoke one without breaking the others.
Base URL
All endpoints live under:
https://api2.citizenpay.xyzPaths in this section are relative to it, so GET /v2/business/members means
https://api2.citizenpay.xyz/v2/business/members.
A request with a body sends it as JSON, with Content-Type: application/json. Responses are JSON
too, with camelCase field names, and timestamps are RFC 3339 strings such as
2026-09-25T09:30:00Z.
Errors
A request that fails answers with an HTTP status code and a JSON body holding one human-readable message:
{ "error": "invalid api key" }The status code is what your code should branch on; the message is for logs and people, and its wording may change.
| Status | Meaning |
|---|---|
400 | The request is not valid: a missing or malformed field, a serial that is not hexadecimal, both memberId and memberExternalId given, too many items in a bulk request. |
401 | The API key is missing, unknown or revoked. |
404 | The member or badge does not exist — or belongs to another business, which looks exactly the same from your side. |
409 | A conflict with what is already there: another member has this email or external id, or this serial is already registered. |
422 | {"error":"badges treasury not configured"}: no badge token is configured for your business, so a badge can't be registered, bulk-registered, deleted or have its status changed. Your organization has to issue its token first — see Your token — and Badges must be enabled with it. |
A successful call answers 200, 201 when it created something, or 204 with no body after a
delete.
Pagination
List endpoints return one page at a time. Two query parameters choose the page:
limit— how many items, from 1 to 100. The default is 50.offset— how many items to skip first. The default is 0.
Every list comes back in the same envelope, with the total number of matching items so you know when to stop:
{
"items": [
// up to `limit` objects
],
"total": 132,
"limit": 50,
"offset": 100
}To read everything, start at offset=0 and add limit to the offset until it reaches total.
curl "https://api2.citizenpay.xyz/v2/business/members?limit=100&offset=0" \
-H "Authorization: Bearer $CITIZENPAY_API_KEY"Related pages
- Issued by Citizen Pay
- docs.citizenpay.eu
- Title
- Developers
- Lang
- EN
- Sheet
- 034 / 035