API
API reference
Endpoint reference generated from the CentraPoint OpenAPI 3.1 specification, with code samples.
On this page
- List payment links
- Create a payment link
- Get a payment link
- List customers
- Create or upsert a customer
- Get a customer
- Update a customer
- List invoices
- Create an invoice
- Get an invoice
- Send an invoice
- Cancel an invoice
- Record an offline payment
- List subscriptions
- Get a subscription
- Pause a subscription
- Resume a subscription
- Cancel a subscription
- List EFT orders
- Create an EFT order
- Get an EFT order
- Upload proof of payment
- Cancel an EFT order
- Get a transaction by reference
- List reconciliation runs
- Get a reconciliation run
- List accounting referral links
- Webhook events
CentraPoint API v1.8.1 · OpenAPI 3.1.0 · Base URL https://app.centrapoint.co.za
The CentraPoint REST API lets your systems manage customers and invoices, create hosted payment links, subscriptions and EFT orders, check the status of payments and read reconciliation results. Every API key may make 120 requests per minute; responses report usage in X-RateLimit-* headers. All requests are authenticated with a tenant-scoped API key sent as a Bearer token. API access requires a plan that includes the REST API (Growth or higher).
Outbound webhooks that CentraPoint sends to your endpoints are described in the webhooks section. Gateway notification URLs (/api/webhooks/{type}) are called by payment gateways, not by API clients, and are therefore not part of this specification.
Download the machine-readable specification: openapi.json. Import it into Postman, Insomnia or a code generator.
/api/v1/payment-linksPOSTCreate a payment link/api/v1/payment-linksGETGet a payment link/api/v1/payment-links/{id}GETList customers/api/v1/customersPOSTCreate or upsert a customer/api/v1/customersGETGet a customer/api/v1/customers/{id}PATCHUpdate a customer/api/v1/customers/{id}GETList invoices/api/v1/invoicesPOSTCreate an invoice/api/v1/invoicesGETGet an invoice/api/v1/invoices/{id}POSTSend an invoice/api/v1/invoices/{id}/sendPOSTCancel an invoice/api/v1/invoices/{id}/cancelPOSTRecord an offline payment/api/v1/invoices/{id}/paymentsGETList subscriptions/api/v1/subscriptionsGETGet a subscription/api/v1/subscriptions/{id}POSTPause a subscription/api/v1/subscriptions/{id}/pausePOSTResume a subscription/api/v1/subscriptions/{id}/resumePOSTCancel a subscription/api/v1/subscriptions/{id}/cancelGETList EFT orders/api/v1/eft-ordersPOSTCreate an EFT order/api/v1/eft-ordersGETGet an EFT order/api/v1/eft-orders/{id}POSTUpload proof of payment/api/v1/eft-orders/{id}/proofPOSTCancel an EFT order/api/v1/eft-orders/{id}/cancelGETGet a transaction by reference/api/v1/transactions/{reference}GETList reconciliation runs/api/v1/reconciliation/runsGETGet a reconciliation run/api/v1/reconciliation/runs/{id}GETList accounting referral links/api/v1/accounting/referral-linksList payment links#
/api/v1/payment-linksReturns your organisation's payment links, newest first, each with the payments made through it (up to 50 per link). Filter by externalReference to find the link for one of your orders and discover its payment references.
Query parameters#
| Field | Type | Description |
|---|---|---|
externalReference | string | Only links with exactly this external reference (leading/trailing whitespace ignored). |
limit | integer | Maximum number of links to return, 1–100. Invalid or missing values fall back to 20; values out of range are clamped. ≥ 1 · ≤ 100 · default 20 |
Responses#
200Matching links.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
datarequired | PaymentLinkWithPayments[] | Show fields
|
{
"data": [
{
"id": "cmg1k2x3y0001abcd1234efgh",
"url": "https://app.centrapoint.co.za/pay/Xb7kP2qR9sLm4TvWz8Yc",
"title": "Website hosting - October",
"description": "Monthly hosting for example.co.za",
"amount": 499,
"currency": "ZAR",
"externalReference": "ORDER-1001",
"singleUse": true,
"active": false,
"expiresAt": "2026-10-31T21:59:59.000Z",
"paidCount": 1,
"createdAt": "2026-09-25T08:10:02.114Z",
"payments": [
{
"reference": "CP-20260925-9F3A1C7B",
"status": "complete",
"amount": 499,
"currency": "ZAR",
"paidAt": "2026-09-25T08:14:03.512Z",
"createdAt": "2026-09-25T08:12:47.020Z"
},
{
"reference": "CP-20260925-41D07E2A",
"status": "cancelled",
"amount": 499,
"currency": "ZAR",
"paidAt": null,
"createdAt": "2026-09-25T08:11:15.873Z"
}
],
"returnUrl": null,
"metadata": {},
"recurring": null,
"subscription": null
}
]
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403API access is not included in your plan.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "API access is not included in your plan"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/payment-links?externalReference=ORDER-1001" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Create a payment link#
/api/v1/payment-linksCreates a hosted payment link at /pay/{token}. When customerEmail is supplied, the link is attached to the existing customer with that email address in your organisation, or a new customer is created (subject to your plan's customer limit).
Requires the API and Payment links features on your plan, and an account that is not read-only (suspended, cancelled or expired trial).
Pass externalReference (your order ID) so you can later find the link and the payment references made through it with GET /api/v1/payment-links?externalReference=.
Unknown body fields are ignored. This endpoint is not idempotent: retrying a request creates another link.
Request headers#
| Field | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional, up to 200 characters. Keys are scoped to your organisation, the HTTP method and the exact request path (e.g. max 200 chars |
Request body#
application/json · required
| Field | Type | Description | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
titlerequired | string | Shown to the payer. Leading and trailing whitespace is trimmed before the length check. 1–100 chars | |||||||||
description | string | Optional longer text shown under the title on the payment page. max 255 chars | |||||||||
amountrequired | number | Amount in major units (e.g. 499.00 rand). Rounded to 2 decimal places. Gateways may enforce their own minimums or whole-unit amounts. > 0 · ≤ 10 000 000 | |||||||||
currency | string | ISO 4217 currency code, upper-cased by the server. Must be a valid ISO 4217 code and accepted by at least one of your enabled checkout gateways (or, for once-off links, by your Manual EFT gateway); otherwise the request fails with 400 invalid_request. default "ZAR" | |||||||||
externalReference | string | Your own identifier for this link, e.g. your order or invoice number. Trimmed before validation. Not required to be unique. Use it with 1–100 chars | |||||||||
returnUrl | string (uri) | Where to send the payer after a final outcome. Must be https and on an origin allow-listed under Settings → API keys → Allowed return URLs. CentraPoint appends max 1000 chars | |||||||||
metadata | MetadataInput | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | |||||||||
customerId | string | Attach an existing customer (takes precedence over customerEmail). | |||||||||
recurring | object | Start a gateway-managed subscription when the link is paid. Requires a plan with recurring billing and an enabled gateway that supports it (PayFast, Netcash Pay Now); only such gateways are offered to the payer. Show fields
| |||||||||
productId | string | ID of a product in your organisation. Recurring products start a gateway-managed subscription at checkout (plan and gateway permitting). | |||||||||
invoiceId | string | ID of an invoice in your organisation. Successful payments are applied to the invoice. | |||||||||
customerEmail | string (email) | Attach the link to a customer. Matched case-insensitively against existing customers; a new customer is created if none exists. | |||||||||
customerFirstName | string | Used only when a new customer is created. Defaults to the part of the email before @. max 100 chars | |||||||||
customerLastName | string | Used only when a new customer is created. max 100 chars | |||||||||
singleUse | boolean | When true, the link is deactivated after its first successful payment. default true | |||||||||
expiresAt | string (date-time) | ISO 8601 timestamp with |
Responses#
201Payment link created.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Idempotent-Replayed– `true` when this response is a replay of an earlier request with the same Idempotency-Key.
| Field | Type | Description | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | Payment link ID. | |||||||||
urlrequired | string (uri) | Hosted payment page to send to the payer: https://app.centrapoint.co.za/pay/{token}. | |||||||||
titlerequired | string | ||||||||||
descriptionrequired | string | null | ||||||||||
amountrequired | number | Amount after rounding to 2 decimal places. | |||||||||
currencyrequired | string | Upper-case ISO 4217 code. | |||||||||
externalReferencerequired | string | null | Your identifier, as supplied when the link was created. | |||||||||
returnUrlrequired | string (uri) | null | ||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | |||||||||
recurringrequired | null | object | Show fields
| |||||||||
singleUserequired | boolean | Whether the link deactivates after its first successful payment. | |||||||||
activerequired | boolean | False once deactivated (in the dashboard, or after a single-use link is paid). | |||||||||
expiresAtrequired | string (date-time) | null | ||||||||||
paidCountrequired | integer | Number of successful payments made through the link. | |||||||||
createdAtrequired | string (date-time) |
{
"id": "cmg1k2x3y0001abcd1234efgh",
"url": "https://app.centrapoint.co.za/pay/Xb7kP2qR9sLm4TvWz8Yc",
"title": "Website hosting - October",
"description": "Monthly hosting for example.co.za",
"amount": 499,
"currency": "ZAR",
"externalReference": "ORDER-1001",
"singleUse": true,
"active": true,
"expiresAt": "2026-10-31T21:59:59.000Z",
"paidCount": 0,
"createdAt": "2026-09-25T08:10:02.114Z",
"returnUrl": "https://shop.example.co.za/checkout/done",
"metadata": {
"crmId": "0061x00000AbCdE"
},
"recurring": null
}400The body failed validation (`issues` lists each problem), or a business rule failed: unknown product/invoice, invalid or unsupported currency, or `expiresAt` not in the future / more than 1 year ahead.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "Invalid body",
"issues": [
{
"origin": "number",
"code": "too_small",
"minimum": 0,
"inclusive": false,
"path": [
"amount"
],
"message": "Too small: expected number to be >0"
}
]
}{
"error": "invalid_request",
"message": "Product not found"
}{
"error": "invalid_request",
"message": "None of your enabled payment gateways accept USD. Enable a gateway that supports USD first."
}{
"error": "invalid_request",
"message": "expiresAt must be in the future"
}{
"error": "invalid_request",
"message": "returnUrl origin https://shop.example.co.za is not allowed - add it under Settings > API keys > Allowed return URLs"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Your plan does not include the API or payment links (`plan_restricted`), a plan quota such as the customer limit was reached (`plan_limit`), or the account is read-only (`account_restricted`).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}{
"error": "plan_limit",
"message": "Customers limit reached (2000/2000) on the Growth plan. Upgrade under Settings > Billing."
}{
"error": "account_restricted",
"message": "Your free trial has ended. Choose a plan to continue."
}409The Idempotency-Key was already used with a different request body.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "idempotency_conflict",
"message": "This Idempotency-Key was already used with a different request body"
}413Request body larger than 100 000 characters.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "Request body too large"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/payment-links" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: 3f6c2a4e-8d1b-4f7a-9c2e-5b1d0a7e6f31" \
-H "Content-Type: application/json" \
-d '{
"title": "Pro plan",
"amount": 499,
"externalReference": "SUB-ACME-PRO",
"customerId": "cmg2c0s7t0003cust0001abcd",
"recurring": {
"frequency": "monthly"
},
"singleUse": true
}'Get a payment link#
/api/v1/payment-links/{id}Returns one payment link in your organisation with the payments made through it (newest first, up to 100).
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string | Payment link ID returned when the link was created. |
Responses#
200The payment link.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | Payment link ID. | |||||||||||||||||||||
urlrequired | string (uri) | Hosted payment page to send to the payer: https://app.centrapoint.co.za/pay/{token}. | |||||||||||||||||||||
titlerequired | string | ||||||||||||||||||||||
descriptionrequired | string | null | ||||||||||||||||||||||
amountrequired | number | Amount after rounding to 2 decimal places. | |||||||||||||||||||||
currencyrequired | string | Upper-case ISO 4217 code. | |||||||||||||||||||||
externalReferencerequired | string | null | Your identifier, as supplied when the link was created. | |||||||||||||||||||||
returnUrlrequired | string (uri) | null | ||||||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | |||||||||||||||||||||
recurringrequired | null | object | Show fields
| |||||||||||||||||||||
singleUserequired | boolean | Whether the link deactivates after its first successful payment. | |||||||||||||||||||||
activerequired | boolean | False once deactivated (in the dashboard, or after a single-use link is paid). | |||||||||||||||||||||
expiresAtrequired | string (date-time) | null | ||||||||||||||||||||||
paidCountrequired | integer | Number of successful payments made through the link. | |||||||||||||||||||||
createdAtrequired | string (date-time) | ||||||||||||||||||||||
paymentsrequired | LinkPayment[] | Checkout attempts made through the link, newest first. Each attempt is a transaction with its own reference. Show fields
| |||||||||||||||||||||
subscription | null | object | The latest subscription started by this link, or null. Show fields
|
{
"id": "cmg1k2x3y0001abcd1234efgh",
"url": "https://app.centrapoint.co.za/pay/Xb7kP2qR9sLm4TvWz8Yc",
"title": "Website hosting - October",
"description": "Monthly hosting for example.co.za",
"amount": 499,
"currency": "ZAR",
"externalReference": "ORDER-1001",
"singleUse": true,
"active": false,
"expiresAt": "2026-10-31T21:59:59.000Z",
"paidCount": 1,
"createdAt": "2026-09-25T08:10:02.114Z",
"payments": [
{
"reference": "CP-20260925-9F3A1C7B",
"status": "complete",
"amount": 499,
"currency": "ZAR",
"paidAt": "2026-09-25T08:14:03.512Z",
"createdAt": "2026-09-25T08:12:47.020Z"
},
{
"reference": "CP-20260925-41D07E2A",
"status": "cancelled",
"amount": 499,
"currency": "ZAR",
"paidAt": null,
"createdAt": "2026-09-25T08:11:15.873Z"
}
],
"returnUrl": null,
"metadata": {},
"recurring": null,
"subscription": null
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403API access is not included in your plan.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "API access is not included in your plan"
}404No payment link with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Payment link not found"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/payment-links/cmg1k2x3y0001abcd1234efgh" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"List customers#
/api/v1/customersNewest first.
Query parameters#
| Field | Type | Description |
|---|---|---|
externalReference | string | Exact match on your customer ID. |
email | string | Exact match (case-insensitive). |
limit | integer | 1–100, default 20. Out-of-range values are clamped; invalid values fall back to 20. ≥ 1 · ≤ 100 · default 20 |
Responses#
200Customers.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
datarequired | Customer[] | Show fields
|
{
"data": [
{
"id": "cmg2c0s7t0003cust0001abcd",
"accountCode": "CUS-00042",
"externalReference": "CRM-1001",
"email": "[email protected]",
"firstName": "Thandi",
"lastName": "Nkosi",
"company": "Nkosi Trading (Pty) Ltd",
"vatNumber": "4123456789",
"phone": "+27821234567",
"address": "12 Long Street, Cape Town, 8001",
"active": true,
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:00:00.000Z",
"updatedAt": "2026-09-25T08:00:00.000Z"
}
]
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403API access (or the feature) is not included in your plan.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/customers" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Create or upsert a customer#
/api/v1/customersWithout externalReference: creates a customer (201). With externalReference: upsert keyed on it — updates the customer with that reference (200), otherwise adopts an existing customer with the same email and no reference (200), otherwise creates one (201). Available on any plan with API access; creating counts towards your customer limit.
Request headers#
| Field | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional, up to 200 characters. Keys are scoped to your organisation, the HTTP method and the exact request path (e.g. max 200 chars |
Request body#
application/json · required
| Field | Type | Description |
|---|---|---|
externalReference | string | Your ID. When set, the request is an upsert keyed on it. 1–190 chars |
emailrequired | string (email) | Stored lower-cased. max 200 chars |
firstNamerequired | string | 1–100 chars |
lastName | string | null | max 100 chars |
company | string | null | max 200 chars |
vatNumber | string | null | max 30 chars |
phone | string | null | max 30 chars |
address | string | null | max 1000 chars |
metadata | MetadataInput | null |
Responses#
200Existing customer updated (upsert).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Idempotent-Replayed– `true` when this response is a replay of an earlier request with the same Idempotency-Key.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
accountCoderequired | string | Customer account code assigned by CentraPoint. |
externalReferencerequired | string | null | Your ID for the customer. |
emailrequired | string | |
firstNamerequired | string | |
lastNamerequired | string | null | |
companyrequired | string | null | |
vatNumberrequired | string | null | |
phonerequired | string | null | |
addressrequired | string | null | |
activerequired | boolean | |
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
{
"id": "cmg2c0s7t0003cust0001abcd",
"accountCode": "CUS-00042",
"externalReference": "CRM-1001",
"email": "[email protected]",
"firstName": "Thandi",
"lastName": "Nkosi",
"company": "Nkosi Trading (Pty) Ltd",
"vatNumber": "4123456789",
"phone": "+27821234567",
"address": "12 Long Street, Cape Town, 8001",
"active": true,
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:00:00.000Z",
"updatedAt": "2026-09-25T08:00:00.000Z"
}201Customer created.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Idempotent-Replayed– `true` when this response is a replay of an earlier request with the same Idempotency-Key.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
accountCoderequired | string | Customer account code assigned by CentraPoint. |
externalReferencerequired | string | null | Your ID for the customer. |
emailrequired | string | |
firstNamerequired | string | |
lastNamerequired | string | null | |
companyrequired | string | null | |
vatNumberrequired | string | null | |
phonerequired | string | null | |
addressrequired | string | null | |
activerequired | boolean | |
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
{
"id": "cmg2c0s7t0003cust0001abcd",
"accountCode": "CUS-00042",
"externalReference": "CRM-1001",
"email": "[email protected]",
"firstName": "Thandi",
"lastName": "Nkosi",
"company": "Nkosi Trading (Pty) Ltd",
"vatNumber": "4123456789",
"phone": "+27821234567",
"address": "12 Long Street, Cape Town, 8001",
"active": true,
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:00:00.000Z",
"updatedAt": "2026-09-25T08:00:00.000Z"
}400Validation failed or invalid metadata.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "Invalid body",
"issues": [
{
"code": "invalid_format",
"format": "email",
"path": [
"email"
],
"message": "Invalid email address"
}
]
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API, customer limit reached (`plan_limit`), or account read-only.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_limit",
"message": "Customers limit reached (2000/2000) on the Growth plan. Upgrade under Settings > Billing."
}409The Idempotency-Key was already used with a different request body.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "idempotency_conflict",
"message": "This Idempotency-Key was already used with a different request body"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/customers" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: 3f6c2a4e-8d1b-4f7a-9c2e-5b1d0a7e6f31" \
-H "Content-Type: application/json" \
-d '{
"externalReference": "CRM-1001",
"email": "[email protected]",
"firstName": "Thandi",
"lastName": "Nkosi",
"company": "Nkosi Trading (Pty) Ltd",
"vatNumber": "4123456789",
"phone": "+27821234567",
"metadata": {
"crmId": "0061x00000AbCdE"
}
}'Get a customer#
/api/v1/customers/{id}Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Responses#
200The customer.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
accountCoderequired | string | Customer account code assigned by CentraPoint. |
externalReferencerequired | string | null | Your ID for the customer. |
emailrequired | string | |
firstNamerequired | string | |
lastNamerequired | string | null | |
companyrequired | string | null | |
vatNumberrequired | string | null | |
phonerequired | string | null | |
addressrequired | string | null | |
activerequired | boolean | |
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
{
"id": "cmg2c0s7t0003cust0001abcd",
"accountCode": "CUS-00042",
"externalReference": "CRM-1001",
"email": "[email protected]",
"firstName": "Thandi",
"lastName": "Nkosi",
"company": "Nkosi Trading (Pty) Ltd",
"vatNumber": "4123456789",
"phone": "+27821234567",
"address": "12 Long Street, Cape Town, 8001",
"active": true,
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:00:00.000Z",
"updatedAt": "2026-09-25T08:00:00.000Z"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403API access (or the feature) is not included in your plan.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}404No customer with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Customer not found"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/customers/cmg2c0s7t0003cust0001abcd" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Update a customer#
/api/v1/customers/{id}Partial update. Omitted fields are unchanged; null clears optional fields; metadata replaces the whole map. Unknown fields are rejected. Idempotency-Key is not used (PATCH is naturally repeatable).
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Request body#
application/json · required
| Field | Type | Description |
|---|---|---|
externalReference | string | null | Must not be used by another customer. 1–190 chars |
email | string (email) | Stored lower-cased. max 200 chars |
firstName | string | 1–100 chars |
lastName | string | null | max 100 chars |
company | string | null | max 200 chars |
vatNumber | string | null | max 30 chars |
phone | string | null | max 30 chars |
address | string | null | max 1000 chars |
metadata | MetadataInput | null | |
active | boolean |
Responses#
200Updated customer.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
accountCoderequired | string | Customer account code assigned by CentraPoint. |
externalReferencerequired | string | null | Your ID for the customer. |
emailrequired | string | |
firstNamerequired | string | |
lastNamerequired | string | null | |
companyrequired | string | null | |
vatNumberrequired | string | null | |
phonerequired | string | null | |
addressrequired | string | null | |
activerequired | boolean | |
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
{
"id": "cmg2c0s7t0003cust0001abcd",
"accountCode": "CUS-00042",
"externalReference": "CRM-1001",
"email": "[email protected]",
"firstName": "Thandi",
"lastName": "Nkosi",
"company": "Nkosi Trading (Pty) Ltd",
"vatNumber": "4123456789",
"phone": "+27821234567",
"address": "12 Long Street, Cape Town, 8001",
"active": true,
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:00:00.000Z",
"updatedAt": "2026-09-25T08:00:00.000Z"
}400Validation failed, unknown field, or externalReference used by another customer.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "Another customer already has that externalReference"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Account is read-only (suspended, cancelled or trial ended), or a plan feature/quota is missing.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "account_restricted",
"message": "Your free trial has ended. Choose a plan to continue."
}404No customer with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Customer not found"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X PATCH "https://app.centrapoint.co.za/api/v1/customers/cmg2c0s7t0003cust0001abcd" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "+27829876543",
"company": null,
"active": true
}'List invoices#
/api/v1/invoicesNewest first. status=draft|sent|overdue returns only invoices with nothing paid; use partially_paid for those with part payments.
Query parameters#
| Field | Type | Description |
|---|---|---|
customerId | string | |
externalReference | string | |
status | string | One of: |
limit | integer | 1–100, default 20. Out-of-range values are clamped; invalid values fall back to 20. ≥ 1 · ≤ 100 · default 20 |
Responses#
200Invoices.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
datarequired | Invoice[] | Show fields
|
{
"data": [
{
"id": "cmg2i9n0v0005inv0001abcd",
"number": "INV-000042",
"status": "sent",
"externalReference": "ORDER-1001",
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001",
"email": "[email protected]"
},
"currency": "ZAR",
"issueDate": "2026-09-24T22:00:00.000Z",
"dueDate": "2026-10-08T21:59:59.000Z",
"lines": [
{
"description": "Website hosting - October",
"quantity": 1,
"unitPrice": 434.78,
"taxRate": 15,
"amount": 434.78
},
{
"description": "Domain renewal (zero-rated)",
"quantity": 1,
"unitPrice": 120,
"taxRate": 0,
"amount": 120
}
],
"subtotal": 554.78,
"taxAmount": 65.22,
"total": 620,
"amountPaid": 0,
"amountDue": 620,
"paidAt": null,
"payUrl": "https://app.centrapoint.co.za/pay/Xb7kP2qR9sLm4TvWz8Yc",
"notes": "Payment due within 14 days.",
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:05:00.000Z",
"updatedAt": "2026-09-25T08:05:00.000Z"
}
]
}400Unknown status.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "status must be one of draft, sent, overdue, paid, cancelled, partially_paid"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or invoicing, or account read-only.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/invoices" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Create an invoice#
/api/v1/invoicesCreates an invoice with per-line VAT (201). If externalReference matches an existing invoice, that invoice is returned unchanged with 200 (the body is not applied and it is not re-sent). A pay link for the balance is created when your plan includes payment links and a gateway accepts the currency. With send: true the invoice is created as sent and emailed. Requires the Invoicing feature.
Request headers#
| Field | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional, up to 200 characters. Keys are scoped to your organisation, the HTTP method and the exact request path (e.g. max 200 chars |
Request body#
application/json · required
| Field | Type | Description | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
customerId | string | The customer's CentraPoint ID. Send exactly one of | |||||||||||||||
customer | object | object | The customer, by CentraPoint ID or by your externalReference. Send exactly one of Show fields
| |||||||||||||||
externalReference | string | Your ID for the invoice. If an invoice with this reference exists, it is returned unchanged with 200. 1–190 chars | |||||||||||||||
currency | string | ISO 4217 code (validated). No gateway is required: invoices can be paid offline, but default "ZAR" | |||||||||||||||
issueDate | string (date) | YYYY-MM-DD (South African time). Default today. | |||||||||||||||
dueDate | string (date) | YYYY-MM-DD (South African time, end of day). Default: today plus your invoice due days setting. | |||||||||||||||
linesrequired | object[] | Show fields
| |||||||||||||||
notes | string | Defaults to your invoice terms. max 4000 chars | |||||||||||||||
metadata | MetadataInput | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | |||||||||||||||
send | boolean | Create as default false |
Responses#
200An invoice with this externalReference already existed; returned unchanged.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | |||||||||||||||||||
numberrequired | string | |||||||||||||||||||
statusrequired | string |
One of: | ||||||||||||||||||
externalReferencerequired | string | null | |||||||||||||||||||
customerrequired | object | Show fields
| ||||||||||||||||||
currencyrequired | string | |||||||||||||||||||
issueDaterequired | string (date-time) | |||||||||||||||||||
dueDaterequired | string (date-time) | null | |||||||||||||||||||
linesrequired | InvoiceLine[] | Show fields
| ||||||||||||||||||
subtotalrequired | number | |||||||||||||||||||
taxAmountrequired | number | |||||||||||||||||||
totalrequired | number | |||||||||||||||||||
amountPaidrequired | number | |||||||||||||||||||
amountDuerequired | number | total − amountPaid. | ||||||||||||||||||
paidAtrequired | string (date-time) | null | |||||||||||||||||||
payUrlrequired | string (uri) | null | Hosted payment page for the outstanding balance, or null (paid/cancelled, no pay link yet, or neither a checkout gateway nor Manual EFT accepts the currency). | ||||||||||||||||||
notesrequired | string | null | |||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | ||||||||||||||||||
createdAtrequired | string (date-time) | |||||||||||||||||||
updatedAtrequired | string (date-time) |
{
"id": "cmg2i9n0v0005inv0001abcd",
"number": "INV-000042",
"status": "sent",
"externalReference": "ORDER-1001",
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001",
"email": "[email protected]"
},
"currency": "ZAR",
"issueDate": "2026-09-24T22:00:00.000Z",
"dueDate": "2026-10-08T21:59:59.000Z",
"lines": [
{
"description": "Website hosting - October",
"quantity": 1,
"unitPrice": 434.78,
"taxRate": 15,
"amount": 434.78
},
{
"description": "Domain renewal (zero-rated)",
"quantity": 1,
"unitPrice": 120,
"taxRate": 0,
"amount": 120
}
],
"subtotal": 554.78,
"taxAmount": 65.22,
"total": 620,
"amountPaid": 0,
"amountDue": 620,
"paidAt": null,
"payUrl": "https://app.centrapoint.co.za/pay/Xb7kP2qR9sLm4TvWz8Yc",
"notes": "Payment due within 14 days.",
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:05:00.000Z",
"updatedAt": "2026-09-25T08:05:00.000Z"
}201Invoice created.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Idempotent-Replayed– `true` when this response is a replay of an earlier request with the same Idempotency-Key.
| Field | Type | Description | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | |||||||||||||||||||
numberrequired | string | |||||||||||||||||||
statusrequired | string |
One of: | ||||||||||||||||||
externalReferencerequired | string | null | |||||||||||||||||||
customerrequired | object | Show fields
| ||||||||||||||||||
currencyrequired | string | |||||||||||||||||||
issueDaterequired | string (date-time) | |||||||||||||||||||
dueDaterequired | string (date-time) | null | |||||||||||||||||||
linesrequired | InvoiceLine[] | Show fields
| ||||||||||||||||||
subtotalrequired | number | |||||||||||||||||||
taxAmountrequired | number | |||||||||||||||||||
totalrequired | number | |||||||||||||||||||
amountPaidrequired | number | |||||||||||||||||||
amountDuerequired | number | total − amountPaid. | ||||||||||||||||||
paidAtrequired | string (date-time) | null | |||||||||||||||||||
payUrlrequired | string (uri) | null | Hosted payment page for the outstanding balance, or null (paid/cancelled, no pay link yet, or neither a checkout gateway nor Manual EFT accepts the currency). | ||||||||||||||||||
notesrequired | string | null | |||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | ||||||||||||||||||
createdAtrequired | string (date-time) | |||||||||||||||||||
updatedAtrequired | string (date-time) |
{
"id": "cmg2i9n0v0005inv0001abcd",
"number": "INV-000042",
"status": "sent",
"externalReference": "ORDER-1001",
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001",
"email": "[email protected]"
},
"currency": "ZAR",
"issueDate": "2026-09-24T22:00:00.000Z",
"dueDate": "2026-10-08T21:59:59.000Z",
"lines": [
{
"description": "Website hosting - October",
"quantity": 1,
"unitPrice": 434.78,
"taxRate": 15,
"amount": 434.78
},
{
"description": "Domain renewal (zero-rated)",
"quantity": 1,
"unitPrice": 120,
"taxRate": 0,
"amount": 120
}
],
"subtotal": 554.78,
"taxAmount": 65.22,
"total": 620,
"amountPaid": 0,
"amountDue": 620,
"paidAt": null,
"payUrl": "https://app.centrapoint.co.za/pay/Xb7kP2qR9sLm4TvWz8Yc",
"notes": "Payment due within 14 days.",
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:05:00.000Z",
"updatedAt": "2026-09-25T08:05:00.000Z"
}400Validation failed, invalid ISO 4217 currency, customer not found, or totals invalid.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "Customer not found"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or invoicing, or account read-only.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}409The Idempotency-Key was already used with a different request body.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "idempotency_conflict",
"message": "This Idempotency-Key was already used with a different request body"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/invoices" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: 3f6c2a4e-8d1b-4f7a-9c2e-5b1d0a7e6f31" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"externalReference": "CRM-1001"
},
"externalReference": "ORDER-1001",
"dueDate": "2026-10-08",
"lines": [
{
"description": "Website hosting - October",
"quantity": 1,
"unitPrice": 434.78
},
{
"description": "Domain renewal (zero-rated)",
"quantity": 1,
"unitPrice": 120,
"taxRate": 0
}
],
"metadata": {
"crmId": "0061x00000AbCdE"
},
"send": true
}'Get an invoice#
/api/v1/invoices/{id}Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Responses#
200The invoice.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | |||||||||||||||||||
numberrequired | string | |||||||||||||||||||
statusrequired | string |
One of: | ||||||||||||||||||
externalReferencerequired | string | null | |||||||||||||||||||
customerrequired | object | Show fields
| ||||||||||||||||||
currencyrequired | string | |||||||||||||||||||
issueDaterequired | string (date-time) | |||||||||||||||||||
dueDaterequired | string (date-time) | null | |||||||||||||||||||
linesrequired | InvoiceLine[] | Show fields
| ||||||||||||||||||
subtotalrequired | number | |||||||||||||||||||
taxAmountrequired | number | |||||||||||||||||||
totalrequired | number | |||||||||||||||||||
amountPaidrequired | number | |||||||||||||||||||
amountDuerequired | number | total − amountPaid. | ||||||||||||||||||
paidAtrequired | string (date-time) | null | |||||||||||||||||||
payUrlrequired | string (uri) | null | Hosted payment page for the outstanding balance, or null (paid/cancelled, no pay link yet, or neither a checkout gateway nor Manual EFT accepts the currency). | ||||||||||||||||||
notesrequired | string | null | |||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | ||||||||||||||||||
createdAtrequired | string (date-time) | |||||||||||||||||||
updatedAtrequired | string (date-time) |
{
"id": "cmg2i9n0v0005inv0001abcd",
"number": "INV-000042",
"status": "sent",
"externalReference": "ORDER-1001",
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001",
"email": "[email protected]"
},
"currency": "ZAR",
"issueDate": "2026-09-24T22:00:00.000Z",
"dueDate": "2026-10-08T21:59:59.000Z",
"lines": [
{
"description": "Website hosting - October",
"quantity": 1,
"unitPrice": 434.78,
"taxRate": 15,
"amount": 434.78
},
{
"description": "Domain renewal (zero-rated)",
"quantity": 1,
"unitPrice": 120,
"taxRate": 0,
"amount": 120
}
],
"subtotal": 554.78,
"taxAmount": 65.22,
"total": 620,
"amountPaid": 0,
"amountDue": 620,
"paidAt": null,
"payUrl": "https://app.centrapoint.co.za/pay/Xb7kP2qR9sLm4TvWz8Yc",
"notes": "Payment due within 14 days.",
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:05:00.000Z",
"updatedAt": "2026-09-25T08:05:00.000Z"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or invoicing, or account read-only.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}404No invoice with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Invoice not found"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/invoices/cmg2i9n0v0005inv0001abcd" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Send an invoice#
/api/v1/invoices/{id}/sendEmails the invoice to the customer, with a pay link for the balance when possible. A draft becomes sent. Paid or cancelled invoices cannot be sent. No body is required.
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Request headers#
| Field | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional, up to 200 characters. Keys are scoped to your organisation, the HTTP method and the exact request path (e.g. max 200 chars |
Request body#
application/json
object
Responses#
200The invoice after sending.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Idempotent-Replayed– `true` when this response is a replay of an earlier request with the same Idempotency-Key.
| Field | Type | Description | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | |||||||||||||||||||
numberrequired | string | |||||||||||||||||||
statusrequired | string |
One of: | ||||||||||||||||||
externalReferencerequired | string | null | |||||||||||||||||||
customerrequired | object | Show fields
| ||||||||||||||||||
currencyrequired | string | |||||||||||||||||||
issueDaterequired | string (date-time) | |||||||||||||||||||
dueDaterequired | string (date-time) | null | |||||||||||||||||||
linesrequired | InvoiceLine[] | Show fields
| ||||||||||||||||||
subtotalrequired | number | |||||||||||||||||||
taxAmountrequired | number | |||||||||||||||||||
totalrequired | number | |||||||||||||||||||
amountPaidrequired | number | |||||||||||||||||||
amountDuerequired | number | total − amountPaid. | ||||||||||||||||||
paidAtrequired | string (date-time) | null | |||||||||||||||||||
payUrlrequired | string (uri) | null | Hosted payment page for the outstanding balance, or null (paid/cancelled, no pay link yet, or neither a checkout gateway nor Manual EFT accepts the currency). | ||||||||||||||||||
notesrequired | string | null | |||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | ||||||||||||||||||
createdAtrequired | string (date-time) | |||||||||||||||||||
updatedAtrequired | string (date-time) |
{
"id": "cmg2i9n0v0005inv0001abcd",
"number": "INV-000042",
"status": "sent",
"externalReference": "ORDER-1001",
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001",
"email": "[email protected]"
},
"currency": "ZAR",
"issueDate": "2026-09-24T22:00:00.000Z",
"dueDate": "2026-10-08T21:59:59.000Z",
"lines": [
{
"description": "Website hosting - October",
"quantity": 1,
"unitPrice": 434.78,
"taxRate": 15,
"amount": 434.78
},
{
"description": "Domain renewal (zero-rated)",
"quantity": 1,
"unitPrice": 120,
"taxRate": 0,
"amount": 120
}
],
"subtotal": 554.78,
"taxAmount": 65.22,
"total": 620,
"amountPaid": 0,
"amountDue": 620,
"paidAt": null,
"payUrl": "https://app.centrapoint.co.za/pay/Xb7kP2qR9sLm4TvWz8Yc",
"notes": "Payment due within 14 days.",
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:05:00.000Z",
"updatedAt": "2026-09-25T08:05:00.000Z"
}400The invoice is in a state that does not allow this, or validation failed.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "Invoice is paid"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or invoicing, or account read-only.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}404No invoice with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Invoice not found"
}409The Idempotency-Key was already used with a different request body.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "idempotency_conflict",
"message": "This Idempotency-Key was already used with a different request body"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/invoices/cmg2i9n0v0005inv0001abcd/send" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: 3f6c2a4e-8d1b-4f7a-9c2e-5b1d0a7e6f31"Cancel an invoice#
/api/v1/invoices/{id}/cancelVoids an unpaid (or partially paid) invoice and deactivates its pay links. Cancelling an already cancelled invoice returns it unchanged. Paid invoices cannot be cancelled.
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Request headers#
| Field | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional, up to 200 characters. Keys are scoped to your organisation, the HTTP method and the exact request path (e.g. max 200 chars |
Request body#
application/json
| Field | Type | Description |
|---|---|---|
reason | string | Appended to the invoice notes. max 500 chars |
Responses#
200The cancelled invoice.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Idempotent-Replayed– `true` when this response is a replay of an earlier request with the same Idempotency-Key.
| Field | Type | Description | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | |||||||||||||||||||
numberrequired | string | |||||||||||||||||||
statusrequired | string |
One of: | ||||||||||||||||||
externalReferencerequired | string | null | |||||||||||||||||||
customerrequired | object | Show fields
| ||||||||||||||||||
currencyrequired | string | |||||||||||||||||||
issueDaterequired | string (date-time) | |||||||||||||||||||
dueDaterequired | string (date-time) | null | |||||||||||||||||||
linesrequired | InvoiceLine[] | Show fields
| ||||||||||||||||||
subtotalrequired | number | |||||||||||||||||||
taxAmountrequired | number | |||||||||||||||||||
totalrequired | number | |||||||||||||||||||
amountPaidrequired | number | |||||||||||||||||||
amountDuerequired | number | total − amountPaid. | ||||||||||||||||||
paidAtrequired | string (date-time) | null | |||||||||||||||||||
payUrlrequired | string (uri) | null | Hosted payment page for the outstanding balance, or null (paid/cancelled, no pay link yet, or neither a checkout gateway nor Manual EFT accepts the currency). | ||||||||||||||||||
notesrequired | string | null | |||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | ||||||||||||||||||
createdAtrequired | string (date-time) | |||||||||||||||||||
updatedAtrequired | string (date-time) |
{
"id": "cmg2i9n0v0005inv0001abcd",
"number": "INV-000042",
"status": "cancelled",
"externalReference": "ORDER-1001",
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001",
"email": "[email protected]"
},
"currency": "ZAR",
"issueDate": "2026-09-24T22:00:00.000Z",
"dueDate": "2026-10-08T21:59:59.000Z",
"lines": [
{
"description": "Website hosting - October",
"quantity": 1,
"unitPrice": 434.78,
"taxRate": 15,
"amount": 434.78
},
{
"description": "Domain renewal (zero-rated)",
"quantity": 1,
"unitPrice": 120,
"taxRate": 0,
"amount": 120
}
],
"subtotal": 554.78,
"taxAmount": 65.22,
"total": 620,
"amountPaid": 0,
"amountDue": 620,
"paidAt": null,
"payUrl": null,
"notes": "Payment due within 14 days.",
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:05:00.000Z",
"updatedAt": "2026-09-25T08:05:00.000Z"
}400The invoice is in a state that does not allow this, or validation failed.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "Paid invoices cannot be cancelled - record a refund or credit instead"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or invoicing, or account read-only.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}404No invoice with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Invoice not found"
}409The Idempotency-Key was already used with a different request body.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "idempotency_conflict",
"message": "This Idempotency-Key was already used with a different request body"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/invoices/cmg2i9n0v0005inv0001abcd/cancel" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: 3f6c2a4e-8d1b-4f7a-9c2e-5b1d0a7e6f31" \
-H "Content-Type: application/json" \
-d '{
"reason": "Order cancelled by customer"
}'Record an offline payment#
/api/v1/invoices/{id}/paymentsRecords money received outside CentraPoint's gateways (EFT, cash, card machine, wallet credit…). The invoice becomes paid when fully paid (pay links are deactivated) or partially_paid otherwise. Always send an Idempotency-Key so a retry does not record the payment twice.
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Request headers#
| Field | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional, up to 200 characters. Keys are scoped to your organisation, the HTTP method and the exact request path (e.g. max 200 chars |
Request body#
application/json
| Field | Type | Description |
|---|---|---|
amountrequired | number | Must not exceed the outstanding balance. > 0 · ≤ 100 000 000 |
methodrequired | string | One of: |
reference | string | Your reference, e.g. a bank statement reference. max 190 chars |
paidAt | string (date-time) | ISO 8601 with Z or an offset. Default now. Cannot be in the future. |
Responses#
201Payment recorded; the updated invoice.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Idempotent-Replayed– `true` when this response is a replay of an earlier request with the same Idempotency-Key.
| Field | Type | Description | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | |||||||||||||||||||
numberrequired | string | |||||||||||||||||||
statusrequired | string |
One of: | ||||||||||||||||||
externalReferencerequired | string | null | |||||||||||||||||||
customerrequired | object | Show fields
| ||||||||||||||||||
currencyrequired | string | |||||||||||||||||||
issueDaterequired | string (date-time) | |||||||||||||||||||
dueDaterequired | string (date-time) | null | |||||||||||||||||||
linesrequired | InvoiceLine[] | Show fields
| ||||||||||||||||||
subtotalrequired | number | |||||||||||||||||||
taxAmountrequired | number | |||||||||||||||||||
totalrequired | number | |||||||||||||||||||
amountPaidrequired | number | |||||||||||||||||||
amountDuerequired | number | total − amountPaid. | ||||||||||||||||||
paidAtrequired | string (date-time) | null | |||||||||||||||||||
payUrlrequired | string (uri) | null | Hosted payment page for the outstanding balance, or null (paid/cancelled, no pay link yet, or neither a checkout gateway nor Manual EFT accepts the currency). | ||||||||||||||||||
notesrequired | string | null | |||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | ||||||||||||||||||
createdAtrequired | string (date-time) | |||||||||||||||||||
updatedAtrequired | string (date-time) |
{
"id": "cmg2i9n0v0005inv0001abcd",
"number": "INV-000042",
"status": "paid",
"externalReference": "ORDER-1001",
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001",
"email": "[email protected]"
},
"currency": "ZAR",
"issueDate": "2026-09-24T22:00:00.000Z",
"dueDate": "2026-10-08T21:59:59.000Z",
"lines": [
{
"description": "Website hosting - October",
"quantity": 1,
"unitPrice": 434.78,
"taxRate": 15,
"amount": 434.78
},
{
"description": "Domain renewal (zero-rated)",
"quantity": 1,
"unitPrice": 120,
"taxRate": 0,
"amount": 120
}
],
"subtotal": 554.78,
"taxAmount": 65.22,
"total": 620,
"amountPaid": 620,
"amountDue": 0,
"paidAt": "2026-10-02T08:15:00.000Z",
"payUrl": null,
"notes": "Payment due within 14 days.",
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:05:00.000Z",
"updatedAt": "2026-09-25T08:05:00.000Z"
}400The invoice is in a state that does not allow this, or validation failed.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "Amount exceeds the outstanding balance of 620.00"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or invoicing, or account read-only.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}404No invoice with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Invoice not found"
}409The Idempotency-Key was already used with a different request body.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "idempotency_conflict",
"message": "This Idempotency-Key was already used with a different request body"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/invoices/cmg2i9n0v0005inv0001abcd/payments" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: 3f6c2a4e-8d1b-4f7a-9c2e-5b1d0a7e6f31" \
-H "Content-Type: application/json" \
-d '{
"amount": 620,
"method": "eft",
"reference": "FNB 2026-10-02 NKOSI",
"paidAt": "2026-10-02T10:15:00+02:00"
}'List subscriptions#
/api/v1/subscriptionsGateway-managed subscriptions started by recurring payment links, newest first.
Query parameters#
| Field | Type | Description |
|---|---|---|
externalReference | string | The payment link's externalReference. |
limit | integer | 1–100, default 20. Out-of-range values are clamped; invalid values fall back to 20. ≥ 1 · ≤ 100 · default 20 |
Responses#
200Subscriptions.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
datarequired | Subscription[] | Show fields
|
{
"data": [
{
"id": "cmg2s5b8k0007sub0001abcd",
"status": "active",
"frequency": "monthly",
"amount": 499,
"currency": "ZAR",
"gateway": "payfast",
"paymentLinkId": "cmg1k2x3y0001abcd1234efgh",
"externalReference": "SUB-ACME-PRO",
"metadata": {
"plan": "pro"
},
"createdAt": "2026-09-25T08:14:04.000Z",
"updatedAt": "2026-09-25T08:14:04.000Z"
}
]
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403API access (or the feature) is not included in your plan.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/subscriptions" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Get a subscription#
/api/v1/subscriptions/{id}Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Responses#
200The subscription.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
statusrequired | string | One of: |
frequencyrequired | string | null | One of: |
amountrequired | number | null | Amount of each collection. |
currencyrequired | string | |
gatewayrequired | string | Gateway that bills the subscription, e.g. |
paymentLinkIdrequired | string | null | The recurring payment link that started it. |
externalReferencerequired | string | null | That link's externalReference. |
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
{
"id": "cmg2s5b8k0007sub0001abcd",
"status": "active",
"frequency": "monthly",
"amount": 499,
"currency": "ZAR",
"gateway": "payfast",
"paymentLinkId": "cmg1k2x3y0001abcd1234efgh",
"externalReference": "SUB-ACME-PRO",
"metadata": {
"plan": "pro"
},
"createdAt": "2026-09-25T08:14:04.000Z",
"updatedAt": "2026-09-25T08:14:04.000Z"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403API access (or the feature) is not included in your plan.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}404No subscription with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Subscription not found"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/subscriptions/cmg2s5b8k0007sub0001abcd" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Pause a subscription#
/api/v1/subscriptions/{id}/pausePauses future collections at the gateway and sends subscription.paused. Allowed from active. Supported on gateways that can pause subscriptions, e.g. PayFast. Repeating a call that already took effect returns 200 with the subscription unchanged (the Idempotency-Key header is not used). An invalid transition returns 409 invalid_state and nothing changes. No body is required.
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Responses#
200The subscription (status `paused`).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
statusrequired | string | One of: |
frequencyrequired | string | null | One of: |
amountrequired | number | null | Amount of each collection. |
currencyrequired | string | |
gatewayrequired | string | Gateway that bills the subscription, e.g. |
paymentLinkIdrequired | string | null | The recurring payment link that started it. |
externalReferencerequired | string | null | That link's externalReference. |
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
{
"id": "cmg2s5b8k0007sub0001abcd",
"status": "paused",
"frequency": "monthly",
"amount": 499,
"currency": "ZAR",
"gateway": "payfast",
"paymentLinkId": "cmg1k2x3y0001abcd1234efgh",
"externalReference": "SUB-ACME-PRO",
"metadata": {
"plan": "pro"
},
"createdAt": "2026-09-25T08:14:04.000Z",
"updatedAt": "2026-09-25T08:14:04.000Z"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Account is read-only (suspended, cancelled or trial ended), or a plan feature/quota is missing.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "account_restricted",
"message": "Your free trial has ended. Choose a plan to continue."
}404No subscription with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Subscription not found"
}409`invalid_state`: not allowed from the current status. `unsupported`: the subscription's gateway can't do this, e.g. Netcash Pay Now subscriptions can only be cancelled.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_state",
"message": "Subscription is cancelled"
}{
"error": "unsupported",
"message": "Netcash Pay Now does not support pausing subscriptions"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}502The gateway rejected or failed the request. Nothing changed; retry later.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "gateway_error",
"message": "The payment gateway did not accept the request (pausing). Please try again."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/subscriptions/cmg2s5b8k0007sub0001abcd/pause" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Resume a subscription#
/api/v1/subscriptions/{id}/resumeResumes a paused subscription at the gateway and sends subscription.resumed. Allowed from paused. Supported on gateways that can pause subscriptions, e.g. PayFast. Repeating a call that already took effect returns 200 with the subscription unchanged (the Idempotency-Key header is not used). An invalid transition returns 409 invalid_state and nothing changes. No body is required.
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Responses#
200The subscription (status `active`).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
statusrequired | string | One of: |
frequencyrequired | string | null | One of: |
amountrequired | number | null | Amount of each collection. |
currencyrequired | string | |
gatewayrequired | string | Gateway that bills the subscription, e.g. |
paymentLinkIdrequired | string | null | The recurring payment link that started it. |
externalReferencerequired | string | null | That link's externalReference. |
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
{
"id": "cmg2s5b8k0007sub0001abcd",
"status": "active",
"frequency": "monthly",
"amount": 499,
"currency": "ZAR",
"gateway": "payfast",
"paymentLinkId": "cmg1k2x3y0001abcd1234efgh",
"externalReference": "SUB-ACME-PRO",
"metadata": {
"plan": "pro"
},
"createdAt": "2026-09-25T08:14:04.000Z",
"updatedAt": "2026-09-25T08:14:04.000Z"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Account is read-only (suspended, cancelled or trial ended), or a plan feature/quota is missing.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "account_restricted",
"message": "Your free trial has ended. Choose a plan to continue."
}404No subscription with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Subscription not found"
}409`invalid_state`: not allowed from the current status. `unsupported`: the subscription's gateway can't do this, e.g. Netcash Pay Now subscriptions can only be cancelled.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_state",
"message": "Subscription is cancelled"
}{
"error": "unsupported",
"message": "Netcash Pay Now does not support resuming subscriptions"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}502The gateway rejected or failed the request. Nothing changed; retry later.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "gateway_error",
"message": "The payment gateway did not accept the request (resuming). Please try again."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/subscriptions/cmg2s5b8k0007sub0001abcd/resume" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Cancel a subscription#
/api/v1/subscriptions/{id}/cancelStops future collections at the gateway and sends subscription.cancelled. Allowed from active or paused. Repeating a call that already took effect returns 200 with the subscription unchanged (the Idempotency-Key header is not used). An invalid transition returns 409 invalid_state and nothing changes. No body is required.
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Responses#
200The cancelled subscription.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description |
|---|---|---|
idrequired | string | |
statusrequired | string | One of: |
frequencyrequired | string | null | One of: |
amountrequired | number | null | Amount of each collection. |
currencyrequired | string | |
gatewayrequired | string | Gateway that bills the subscription, e.g. |
paymentLinkIdrequired | string | null | The recurring payment link that started it. |
externalReferencerequired | string | null | That link's externalReference. |
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
{
"id": "cmg2s5b8k0007sub0001abcd",
"status": "cancelled",
"frequency": "monthly",
"amount": 499,
"currency": "ZAR",
"gateway": "payfast",
"paymentLinkId": "cmg1k2x3y0001abcd1234efgh",
"externalReference": "SUB-ACME-PRO",
"metadata": {
"plan": "pro"
},
"createdAt": "2026-09-25T08:14:04.000Z",
"updatedAt": "2026-09-25T08:14:04.000Z"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Account is read-only (suspended, cancelled or trial ended), or a plan feature/quota is missing.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "account_restricted",
"message": "Your free trial has ended. Choose a plan to continue."
}404No subscription with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Subscription not found"
}409`invalid_state`: not allowed from the current status. `unsupported`: the gateway can't cancel through CentraPoint.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_state",
"message": "Subscription is cancelled"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}502The gateway rejected or failed the request. Nothing changed; retry later.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "gateway_error",
"message": "The payment gateway did not accept the cancellation. Please try again."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/subscriptions/cmg2s5b8k0007sub0001abcd/cancel" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"List EFT orders#
/api/v1/eft-ordersNewest first.
Query parameters#
| Field | Type | Description |
|---|---|---|
externalReference | string | |
customerId | string | |
status | string | One of: |
limit | integer | 1–100, default 20. Out-of-range values are clamped; invalid values fall back to 20. ≥ 1 · ≤ 100 · default 20 |
Responses#
200EFT orders.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
datarequired | EftOrder[] | Show fields
|
{
"data": [
{
"id": "cmg3e1f2t0009eft0001abcd",
"reference": "EFT-7K3Q9P2M",
"status": "awaiting_review",
"amount": 1250,
"currency": "ZAR",
"description": "Order #1001",
"externalReference": "ORDER-1001",
"metadata": {
"cartId": "c_8841"
},
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001"
},
"bankDetails": {
"bankName": "FNB",
"accountName": "Example Traders (Pty) Ltd",
"accountNumber": "62000000000",
"branchCode": "250655",
"accountType": "current"
},
"paymentReference": "EFT-7K3Q9P2M",
"payUrl": "https://app.centrapoint.co.za/eft/cmg3e1f2t0009eft0001abcd.Qm9ndXMtc2lnbmF0dXJlLWV4YW1wbGU",
"proofs": [
{
"id": "cmg3p0r0f0011prf0001abcd",
"fileName": "proof.pdf",
"contentType": "application/pdf",
"size": 184213,
"source": "payer",
"createdAt": "2026-09-25T09:12:00.000Z"
}
],
"rejectionReason": null,
"expiresAt": "2026-10-02T08:00:00.000Z",
"reviewedAt": null,
"paidAt": null,
"createdAt": "2026-09-25T08:00:00.000Z"
}
]
}400Unknown status.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "status must be one of awaiting_payment, awaiting_review, paid, rejected, expired, cancelled"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or payment links, or the account is read-only (writes).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/eft-orders" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Create an EFT order#
/api/v1/eft-ordersIssues a unique deposit reference and returns your bank details for the payer (201). Requires an enabled Manual EFT gateway, the Payment links feature and API access. Idempotent on externalReference for open orders (200).
Request headers#
| Field | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional, up to 200 characters. Keys are scoped to your organisation, the HTTP method and the exact request path (e.g. max 200 chars |
Request body#
application/json · required
| Field | Type | Description | ||||||
|---|---|---|---|---|---|---|---|---|
amountrequired | number | > 0 · ≤ 100 000 000 | ||||||
currency | string | One of ZAR, NAD, BWP, LSL, SZL. default "ZAR" | ||||||
customerId | string | |||||||
customer | object | object | Show fields
| ||||||
description | string | max 1000 chars | ||||||
externalReference | string | Your ID. If an open order (awaiting_payment, awaiting_review or rejected) with this reference exists, it is returned with 200 instead of creating another; a different amount or currency is a 400. 1–190 chars | ||||||
metadata | MetadataInput | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | ||||||
expiresAt | string (date-time) | At least 5 minutes and at most 90 days ahead. Default: the gateway's expiry days (7 by default). | ||||||
notifyPayer | boolean | Email the customer the bank details and default false |
Responses#
200An open order with this externalReference already existed; returned unchanged.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | ||||||||||||||||||||||
referencerequired | string | Unique deposit reference, e.g. | |||||||||||||||||||||
statusrequired | string | One of: | |||||||||||||||||||||
amountrequired | number | ||||||||||||||||||||||
currencyrequired | string | ||||||||||||||||||||||
descriptionrequired | string | null | ||||||||||||||||||||||
externalReferencerequired | string | null | ||||||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | |||||||||||||||||||||
customerrequired | null | object | Show fields
| |||||||||||||||||||||
bankDetailsrequired | object | Your bank account from the Manual EFT gateway. Show these to the payer. Show fields
| |||||||||||||||||||||
paymentReferencerequired | string | The reference the payer must use on the transfer (same as | |||||||||||||||||||||
payUrlrequired | string (uri) | Signed public payer page with the bank details, the reference and a proof-of-payment upload. No login needed; share it instead of building your own upload. A tampered link returns 404. | |||||||||||||||||||||
proofsrequired | object[] | Show fields
| |||||||||||||||||||||
rejectionReasonrequired | string | null | ||||||||||||||||||||||
expiresAtrequired | string (date-time) | null | ||||||||||||||||||||||
reviewedAtrequired | string (date-time) | null | ||||||||||||||||||||||
paidAtrequired | string (date-time) | null | ||||||||||||||||||||||
createdAtrequired | string (date-time) |
{
"id": "cmg3e1f2t0009eft0001abcd",
"reference": "EFT-7K3Q9P2M",
"status": "awaiting_payment",
"amount": 1250,
"currency": "ZAR",
"description": "Order #1001",
"externalReference": "ORDER-1001",
"metadata": {
"cartId": "c_8841"
},
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001"
},
"bankDetails": {
"bankName": "FNB",
"accountName": "Example Traders (Pty) Ltd",
"accountNumber": "62000000000",
"branchCode": "250655",
"accountType": "current"
},
"paymentReference": "EFT-7K3Q9P2M",
"payUrl": "https://app.centrapoint.co.za/eft/cmg3e1f2t0009eft0001abcd.Qm9ndXMtc2lnbmF0dXJlLWV4YW1wbGU",
"proofs": [],
"rejectionReason": null,
"expiresAt": "2026-10-02T08:00:00.000Z",
"reviewedAt": null,
"paidAt": null,
"createdAt": "2026-09-25T08:00:00.000Z"
}201Order created.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Idempotent-Replayed– `true` when this response is a replay of an earlier request with the same Idempotency-Key.
| Field | Type | Description | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | ||||||||||||||||||||||
referencerequired | string | Unique deposit reference, e.g. | |||||||||||||||||||||
statusrequired | string | One of: | |||||||||||||||||||||
amountrequired | number | ||||||||||||||||||||||
currencyrequired | string | ||||||||||||||||||||||
descriptionrequired | string | null | ||||||||||||||||||||||
externalReferencerequired | string | null | ||||||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | |||||||||||||||||||||
customerrequired | null | object | Show fields
| |||||||||||||||||||||
bankDetailsrequired | object | Your bank account from the Manual EFT gateway. Show these to the payer. Show fields
| |||||||||||||||||||||
paymentReferencerequired | string | The reference the payer must use on the transfer (same as | |||||||||||||||||||||
payUrlrequired | string (uri) | Signed public payer page with the bank details, the reference and a proof-of-payment upload. No login needed; share it instead of building your own upload. A tampered link returns 404. | |||||||||||||||||||||
proofsrequired | object[] | Show fields
| |||||||||||||||||||||
rejectionReasonrequired | string | null | ||||||||||||||||||||||
expiresAtrequired | string (date-time) | null | ||||||||||||||||||||||
reviewedAtrequired | string (date-time) | null | ||||||||||||||||||||||
paidAtrequired | string (date-time) | null | ||||||||||||||||||||||
createdAtrequired | string (date-time) |
{
"id": "cmg3e1f2t0009eft0001abcd",
"reference": "EFT-7K3Q9P2M",
"status": "awaiting_payment",
"amount": 1250,
"currency": "ZAR",
"description": "Order #1001",
"externalReference": "ORDER-1001",
"metadata": {
"cartId": "c_8841"
},
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001"
},
"bankDetails": {
"bankName": "FNB",
"accountName": "Example Traders (Pty) Ltd",
"accountNumber": "62000000000",
"branchCode": "250655",
"accountType": "current"
},
"paymentReference": "EFT-7K3Q9P2M",
"payUrl": "https://app.centrapoint.co.za/eft/cmg3e1f2t0009eft0001abcd.Qm9ndXMtc2lnbmF0dXJlLWV4YW1wbGU",
"proofs": [],
"rejectionReason": null,
"expiresAt": "2026-10-02T08:00:00.000Z",
"reviewedAt": null,
"paidAt": null,
"createdAt": "2026-09-25T08:00:00.000Z"
}400Validation failed, Manual EFT not set up or not available, unsupported currency, customer not found, expiresAt out of range, or an open order for this externalReference has a different amount. `notifyPayer` without a customer email address.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "Manual EFT is not set up. Add a 'Manual EFT (bank transfer)' gateway with your bank details under Settings > Payment providers."
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan lacks the API or payment links, monthly transaction limit reached (`plan_limit`), or account read-only.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}409The Idempotency-Key was already used with a different request body.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "idempotency_conflict",
"message": "This Idempotency-Key was already used with a different request body"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/eft-orders" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: 3f6c2a4e-8d1b-4f7a-9c2e-5b1d0a7e6f31" \
-H "Content-Type: application/json" \
-d '{
"amount": 1250,
"customer": {
"externalReference": "CRM-1001"
},
"description": "Order #1001",
"externalReference": "ORDER-1001",
"metadata": {
"cartId": "c_8841"
},
"notifyPayer": true
}'Get an EFT order#
/api/v1/eft-orders/{id}Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Responses#
200The order.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | ||||||||||||||||||||||
referencerequired | string | Unique deposit reference, e.g. | |||||||||||||||||||||
statusrequired | string | One of: | |||||||||||||||||||||
amountrequired | number | ||||||||||||||||||||||
currencyrequired | string | ||||||||||||||||||||||
descriptionrequired | string | null | ||||||||||||||||||||||
externalReferencerequired | string | null | ||||||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | |||||||||||||||||||||
customerrequired | null | object | Show fields
| |||||||||||||||||||||
bankDetailsrequired | object | Your bank account from the Manual EFT gateway. Show these to the payer. Show fields
| |||||||||||||||||||||
paymentReferencerequired | string | The reference the payer must use on the transfer (same as | |||||||||||||||||||||
payUrlrequired | string (uri) | Signed public payer page with the bank details, the reference and a proof-of-payment upload. No login needed; share it instead of building your own upload. A tampered link returns 404. | |||||||||||||||||||||
proofsrequired | object[] | Show fields
| |||||||||||||||||||||
rejectionReasonrequired | string | null | ||||||||||||||||||||||
expiresAtrequired | string (date-time) | null | ||||||||||||||||||||||
reviewedAtrequired | string (date-time) | null | ||||||||||||||||||||||
paidAtrequired | string (date-time) | null | ||||||||||||||||||||||
createdAtrequired | string (date-time) |
{
"id": "cmg3e1f2t0009eft0001abcd",
"reference": "EFT-7K3Q9P2M",
"status": "awaiting_review",
"amount": 1250,
"currency": "ZAR",
"description": "Order #1001",
"externalReference": "ORDER-1001",
"metadata": {
"cartId": "c_8841"
},
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001"
},
"bankDetails": {
"bankName": "FNB",
"accountName": "Example Traders (Pty) Ltd",
"accountNumber": "62000000000",
"branchCode": "250655",
"accountType": "current"
},
"paymentReference": "EFT-7K3Q9P2M",
"payUrl": "https://app.centrapoint.co.za/eft/cmg3e1f2t0009eft0001abcd.Qm9ndXMtc2lnbmF0dXJlLWV4YW1wbGU",
"proofs": [
{
"id": "cmg3p0r0f0011prf0001abcd",
"fileName": "proof.pdf",
"contentType": "application/pdf",
"size": 184213,
"source": "payer",
"createdAt": "2026-09-25T09:12:00.000Z"
}
],
"rejectionReason": null,
"expiresAt": "2026-10-02T08:00:00.000Z",
"reviewedAt": null,
"paidAt": null,
"createdAt": "2026-09-25T08:00:00.000Z"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or payment links, or the account is read-only (writes).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}404No EFT order with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "EFT order not found"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/eft-orders/cmg3e1f2t0009eft0001abcd" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Upload proof of payment#
/api/v1/eft-orders/{id}/proofmultipart/form-data with one file field. The type is detected from the file's bytes: PDF, PNG or JPEG only; at most 10 MB; at most 10 files per order. Allowed while the order is awaiting_payment, awaiting_review or rejected (and not past its expiry, unless already in review). Moves the order to awaiting_review, notifies your staff and sends eft.proof_received. Uploading an identical file again is harmless (deduplicated by content hash). The Idempotency-Key header is not used on this endpoint.
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Request body#
multipart/form-data · required
| Field | Type | Description |
|---|---|---|
filerequired | string (binary) | PDF, PNG or JPEG, max 10 MB. |
Responses#
200The order after the upload.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | ||||||||||||||||||||||
referencerequired | string | Unique deposit reference, e.g. | |||||||||||||||||||||
statusrequired | string | One of: | |||||||||||||||||||||
amountrequired | number | ||||||||||||||||||||||
currencyrequired | string | ||||||||||||||||||||||
descriptionrequired | string | null | ||||||||||||||||||||||
externalReferencerequired | string | null | ||||||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | |||||||||||||||||||||
customerrequired | null | object | Show fields
| |||||||||||||||||||||
bankDetailsrequired | object | Your bank account from the Manual EFT gateway. Show these to the payer. Show fields
| |||||||||||||||||||||
paymentReferencerequired | string | The reference the payer must use on the transfer (same as | |||||||||||||||||||||
payUrlrequired | string (uri) | Signed public payer page with the bank details, the reference and a proof-of-payment upload. No login needed; share it instead of building your own upload. A tampered link returns 404. | |||||||||||||||||||||
proofsrequired | object[] | Show fields
| |||||||||||||||||||||
rejectionReasonrequired | string | null | ||||||||||||||||||||||
expiresAtrequired | string (date-time) | null | ||||||||||||||||||||||
reviewedAtrequired | string (date-time) | null | ||||||||||||||||||||||
paidAtrequired | string (date-time) | null | ||||||||||||||||||||||
createdAtrequired | string (date-time) |
{
"id": "cmg3e1f2t0009eft0001abcd",
"reference": "EFT-7K3Q9P2M",
"status": "awaiting_review",
"amount": 1250,
"currency": "ZAR",
"description": "Order #1001",
"externalReference": "ORDER-1001",
"metadata": {
"cartId": "c_8841"
},
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001"
},
"bankDetails": {
"bankName": "FNB",
"accountName": "Example Traders (Pty) Ltd",
"accountNumber": "62000000000",
"branchCode": "250655",
"accountType": "current"
},
"paymentReference": "EFT-7K3Q9P2M",
"payUrl": "https://app.centrapoint.co.za/eft/cmg3e1f2t0009eft0001abcd.Qm9ndXMtc2lnbmF0dXJlLWV4YW1wbGU",
"proofs": [
{
"id": "cmg3p0r0f0011prf0001abcd",
"fileName": "proof.pdf",
"contentType": "application/pdf",
"size": 184213,
"source": "payer",
"createdAt": "2026-09-25T09:12:00.000Z"
}
],
"rejectionReason": null,
"expiresAt": "2026-10-02T08:00:00.000Z",
"reviewedAt": null,
"paidAt": null,
"createdAt": "2026-09-25T08:00:00.000Z"
}400Missing file, empty or unsupported file type, order not open or expired, or too many proofs.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "Proof must be a PDF, PNG or JPEG file"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or payment links, or the account is read-only (writes).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}404No EFT order with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "EFT order not found"
}413File larger than 10 MB.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "File is larger than 10 MB"
}415Body is not multipart/form-data.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "Send multipart/form-data with a 'file' field"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/eft-orders/cmg3e1f2t0009eft0001abcd/proof" -H "Authorization: Bearer $CENTRAPOINT_API_KEY" -F "[email protected];type=application/pdf"Cancel an EFT order#
/api/v1/eft-orders/{id}/cancelCancels an unpaid order (awaiting_payment, awaiting_review or rejected) and its pending transaction, and sends eft.cancelled and payment.cancelled. Cancelling a cancelled order returns it unchanged. No body is required.
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Request headers#
| Field | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional, up to 200 characters. Keys are scoped to your organisation, the HTTP method and the exact request path (e.g. max 200 chars |
Request body#
application/json
object
Responses#
200The cancelled order.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Idempotent-Replayed– `true` when this response is a replay of an earlier request with the same Idempotency-Key.
| Field | Type | Description | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | ||||||||||||||||||||||
referencerequired | string | Unique deposit reference, e.g. | |||||||||||||||||||||
statusrequired | string | One of: | |||||||||||||||||||||
amountrequired | number | ||||||||||||||||||||||
currencyrequired | string | ||||||||||||||||||||||
descriptionrequired | string | null | ||||||||||||||||||||||
externalReferencerequired | string | null | ||||||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | |||||||||||||||||||||
customerrequired | null | object | Show fields
| |||||||||||||||||||||
bankDetailsrequired | object | Your bank account from the Manual EFT gateway. Show these to the payer. Show fields
| |||||||||||||||||||||
paymentReferencerequired | string | The reference the payer must use on the transfer (same as | |||||||||||||||||||||
payUrlrequired | string (uri) | Signed public payer page with the bank details, the reference and a proof-of-payment upload. No login needed; share it instead of building your own upload. A tampered link returns 404. | |||||||||||||||||||||
proofsrequired | object[] | Show fields
| |||||||||||||||||||||
rejectionReasonrequired | string | null | ||||||||||||||||||||||
expiresAtrequired | string (date-time) | null | ||||||||||||||||||||||
reviewedAtrequired | string (date-time) | null | ||||||||||||||||||||||
paidAtrequired | string (date-time) | null | ||||||||||||||||||||||
createdAtrequired | string (date-time) |
{
"id": "cmg3e1f2t0009eft0001abcd",
"reference": "EFT-7K3Q9P2M",
"status": "cancelled",
"amount": 1250,
"currency": "ZAR",
"description": "Order #1001",
"externalReference": "ORDER-1001",
"metadata": {
"cartId": "c_8841"
},
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001"
},
"bankDetails": {
"bankName": "FNB",
"accountName": "Example Traders (Pty) Ltd",
"accountNumber": "62000000000",
"branchCode": "250655",
"accountType": "current"
},
"paymentReference": "EFT-7K3Q9P2M",
"payUrl": "https://app.centrapoint.co.za/eft/cmg3e1f2t0009eft0001abcd.Qm9ndXMtc2lnbmF0dXJlLWV4YW1wbGU",
"proofs": [],
"rejectionReason": null,
"expiresAt": "2026-10-02T08:00:00.000Z",
"reviewedAt": null,
"paidAt": null,
"createdAt": "2026-09-25T08:00:00.000Z"
}400The order is paid or expired.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "EFT order is paid"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or payment links, or the account is read-only (writes).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}404No EFT order with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "EFT order not found"
}409The Idempotency-Key was already used with a different request body.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "idempotency_conflict",
"message": "This Idempotency-Key was already used with a different request body"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X POST "https://app.centrapoint.co.za/api/v1/eft-orders/cmg3e1f2t0009eft0001abcd/cancel" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY" \
-H "Idempotency-Key: 3f6c2a4e-8d1b-4f7a-9c2e-5b1d0a7e6f31"Get a transaction by reference#
/api/v1/transactions/{reference}Returns the current state of a payment in your organisation, looked up by its CentraPoint payment reference. Transactions in other organisations are reported as not found.
Path parameters#
| Field | Type | Description |
|---|---|---|
referencerequired | string | CentraPoint payment reference, e.g. |
Responses#
200The transaction.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
referencerequired | string | CentraPoint payment reference. | |||||||||||||||||||||
statusrequired | string |
One of: | |||||||||||||||||||||
amountrequired | number | Gross amount in major units. | |||||||||||||||||||||
feerequired | number | null | Gateway fee, when the gateway reports it. | |||||||||||||||||||||
netrequired | number | null | Amount after the gateway fee, when reported. | |||||||||||||||||||||
currencyrequired | string | ||||||||||||||||||||||
typerequired | string |
One of: | |||||||||||||||||||||
gatewayrequired | string | Gateway type that processed the payment, e.g. | |||||||||||||||||||||
descriptionrequired | string | null | Usually the payment link title. | |||||||||||||||||||||
providerRefrequired | string | null | The gateway's own ID for the payment (e.g. PayFast pf_payment_id). | |||||||||||||||||||||
payerEmailrequired | string | null | ||||||||||||||||||||||
paymentLinkIdrequired | string | null | ID of the payment link the payment was made through, if any. | |||||||||||||||||||||
externalReferencerequired | string | null | The payment link's externalReference, or the EFT order's. | |||||||||||||||||||||
eftOrderIdrequired | string | null | EFT order the payment belongs to (Manual EFT). | |||||||||||||||||||||
metadatarequired | Metadata | Your own key/value data. Flat map of strings (numbers and booleans are converted to strings; null values are dropped). Up to 50 keys; keys 1–40 characters of letters, digits, | |||||||||||||||||||||
renewalrequired | boolean | True for later collections of a subscription. | |||||||||||||||||||||
parentReferencerequired | string | null | For renewals: reference of the first payment. | |||||||||||||||||||||
subscriptionIdrequired | string | null | Subscription started by the payment link, if any. | |||||||||||||||||||||
refundedAmountrequired | number | Total of non-failed refunds, 0 if none. | |||||||||||||||||||||
refundsrequired | Refund[] | Refunds recorded for this payment, oldest first. Failed refunds are excluded. Show fields
| |||||||||||||||||||||
invoicerequired | null | object | Show fields
| |||||||||||||||||||||
paidAtrequired | string (date-time) | null | Set when the transaction becomes complete. | |||||||||||||||||||||
createdAtrequired | string (date-time) |
{
"reference": "CP-20260925-9F3A1C7B",
"status": "partially_refunded",
"amount": 499,
"fee": 14.47,
"net": 484.53,
"currency": "ZAR",
"type": "once",
"gateway": "payfast",
"description": "Website hosting - October",
"providerRef": "2458761",
"payerEmail": "[email protected]",
"paymentLinkId": "cmg1k2x3y0001abcd1234efgh",
"externalReference": "ORDER-1001",
"eftOrderId": null,
"metadata": {
"crmId": "0061x00000AbCdE"
},
"renewal": false,
"parentReference": null,
"subscriptionId": null,
"refundedAmount": 100,
"refunds": [
{
"refundNumber": "REF-7C21A9F0",
"amount": 100,
"currency": "ZAR",
"status": "processed",
"processedAt": "2026-09-26T09:30:00.000Z",
"createdAt": "2026-09-26T09:29:41.000Z"
}
],
"invoice": null,
"paidAt": "2026-09-25T08:14:03.512Z",
"createdAt": "2026-09-25T08:12:47.020Z"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403API access is not included in your plan.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "API access is not included in your plan"
}404No transaction with this reference exists in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Transaction not found"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/transactions/CP-20260925-9F3A1C7B" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"List reconciliation runs#
/api/v1/reconciliation/runsStatement imports (Netcash statements and CSV uploads) with their results, newest first by start time. Requires the Reconciliation feature (Business plan and above).
Query parameters#
| Field | Type | Description |
|---|---|---|
from | string (date) | YYYY-MM-DD (South African time): runs started on or after this day. |
to | string (date) | YYYY-MM-DD (South African time): runs started on or before this day. |
limit | integer | 1–100, default 20. Out-of-range values are clamped; invalid values fall back to 20. ≥ 1 · ≤ 100 · default 20 |
Responses#
200Runs.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
datarequired | ReconciliationRun[] | Show fields
|
{
"data": [
{
"id": "cmg3r7c0n0013run0001abcd",
"source": "netcash_statement",
"statementDate": "2026-09-24T22:00:00.000Z",
"periodStart": "2026-09-23T22:00:00.000Z",
"periodEnd": "2026-09-24T22:00:00.000Z",
"status": "exceptions",
"lineCount": 42,
"matched": 38,
"exceptions": 2,
"totals": {
"receipts": 48250.5,
"fees": 612.4,
"refunds": 499,
"payouts": 45000,
"unpaids": 350
},
"openingBalance": 1203.55,
"closingBalance": 3342.71,
"error": null,
"createdAt": "2026-09-25T02:00:03.000Z",
"completedAt": "2026-09-25T02:04:11.000Z"
}
]
}400Bad date.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "invalid_request",
"message": "from and to must be YYYY-MM-DD"
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or reconciliation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/reconciliation/runs" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Get a reconciliation run#
/api/v1/reconciliation/runs/{id}The run summary plus its items: every statement line except ignored ones (fees, payouts and balances are only in totals), and for completed Netcash statement runs, not_received items.
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string |
Responses#
200The run with items.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | ||||||||||||||||||||||||||||
sourcerequired | string | One of: | |||||||||||||||||||||||||||
statementDaterequired | string (date-time) | null | End of the statement period (or its start when no end is known). | |||||||||||||||||||||||||||
periodStartrequired | string (date-time) | null | ||||||||||||||||||||||||||||
periodEndrequired | string (date-time) | null | ||||||||||||||||||||||||||||
statusrequired | string |
One of: | |||||||||||||||||||||||||||
lineCountrequired | integer | Statement lines imported. | |||||||||||||||||||||||||||
matchedrequired | integer | ||||||||||||||||||||||||||||
exceptionsrequired | integer | Items needing attention (mismatches, unmatched lines and not_received payments). | |||||||||||||||||||||||||||
totalsrequired | ReconciliationTotals | Absolute sums of the statement lines in each category. Show fields
| |||||||||||||||||||||||||||
openingBalancerequired | number | null | From the statement's opening balance line, if present. | |||||||||||||||||||||||||||
closingBalancerequired | number | null | ||||||||||||||||||||||||||||
errorrequired | string | null | ||||||||||||||||||||||||||||
createdAtrequired | string (date-time) | ||||||||||||||||||||||||||||
completedAtrequired | string (date-time) | null | ||||||||||||||||||||||||||||
itemsrequired | ReconciliationItem[] | Show fields
|
{
"id": "cmg3r7c0n0013run0001abcd",
"source": "netcash_statement",
"statementDate": "2026-09-24T22:00:00.000Z",
"periodStart": "2026-09-23T22:00:00.000Z",
"periodEnd": "2026-09-24T22:00:00.000Z",
"status": "exceptions",
"lineCount": 42,
"matched": 38,
"exceptions": 2,
"totals": {
"receipts": 48250.5,
"fees": 612.4,
"refunds": 499,
"payouts": 45000,
"unpaids": 350
},
"openingBalance": 1203.55,
"closingBalance": 3342.71,
"error": null,
"createdAt": "2026-09-25T02:00:03.000Z",
"completedAt": "2026-09-25T02:04:11.000Z",
"items": [
{
"status": "matched",
"reference": "CP-20260924-9F3A1C7B",
"externalReference": "ORDER-1001",
"expectedAmount": 499,
"statementAmount": 499,
"date": "2026-09-24T00:00:00.000Z",
"description": "PAYNOW CP-20260924-9F3A1C7B",
"note": null
},
{
"status": "amount_mismatch",
"reference": "CP-20260924-41D07E2A",
"externalReference": "ORDER-1002",
"expectedAmount": 1200,
"statementAmount": 1100,
"date": "2026-09-24T00:00:00.000Z",
"description": "PAYNOW CP-20260924-41D07E2A",
"note": "Amount differs: statement 1100.00 vs transaction 1200.00"
},
{
"status": "not_received",
"reference": "CP-20260920-7C21A9F0",
"externalReference": "ORDER-0990",
"expectedAmount": 250,
"statementAmount": null,
"date": null,
"description": "Website hosting",
"note": "Completed in CentraPoint but not on the statement after 3 days"
}
]
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403Plan does not include the API or reconciliation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "This feature is not included in your plan"
}404No run with this ID in your organisation.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "not_found",
"message": "Reconciliation run not found"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/reconciliation/runs/cmg3r7c0n0013run0001abcd" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"List accounting referral links#
/api/v1/accounting/referral-linksReturns tracked sign-up links for the accounting systems CentraPoint partners with, so you can show a "Don't have Xero? Sign up" link in your own app. Only active partner programmes are returned; the list can be empty. Each url is specific to your organisation. Available on any plan with API access: signing up for an accounting system does not require CentraPoint's accounting sync feature.
Responses#
200Active referral links.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
| Field | Type | Description | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
datarequired | ReferralLink[] | Show fields
|
{
"data": [
{
"connector": "xero",
"name": "Xero",
"program": "Xero App Partner",
"url": "https://app.centrapoint.co.za/r/accounting/xero?s=cpQ2VudHJhUG9pbnQx.bG9uZy1zaWduYXR1cmUx"
},
{
"connector": "zoho_books",
"name": "Zoho Books",
"program": "Zoho Affiliate",
"url": "https://app.centrapoint.co.za/r/accounting/zoho_books?s=cpQ2VudHJhUG9pbnQx.c2Vjb25kLXNpZ25hdHVyZQ"
}
]
}401The API key is missing, malformed, unknown or revoked. No rate-limit headers are sent, because the key is not known.
{
"error": "unauthorized",
"message": "Missing or malformed API key"
}{
"error": "unauthorized",
"message": "Invalid API key"
}403API access is not included in your plan.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "plan_restricted",
"message": "API access is not included in your plan"
}429More than 120 requests in the current 60-second window for this API key, or more than 600 from one client IP before authentication (message `Too many requests from this network`; headers then describe the IP window).
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.Retry-After– Seconds to wait before retrying.
{
"error": "rate_limited",
"message": "Rate limit of 120 requests per minute exceeded for this API key"
}500Unexpected server error. The details are logged by CentraPoint; the message is generic.
Headers
X-RateLimit-Limit– Requests allowed per 60-second window for this API key.X-RateLimit-Remaining– Requests left in the current window.X-RateLimit-Reset– Unix time (seconds) when the current window ends.
{
"error": "internal_error",
"message": "An unexpected error occurred. Please try again or contact support."
}Code samples#
curl -X GET "https://app.centrapoint.co.za/api/v1/accounting/referral-links" \
-H "Authorization: Bearer $CENTRAPOINT_API_KEY"Webhook events#
Sent by CentraPoint to each HTTPS endpoint configured under Settings → Webhooks and subscribed to this event. Respond 2xx within 10 seconds. Failed deliveries are retried after 1m, 5m, 30m, 2h, 6h, 12h and 24h (8 attempts). Redirects are not followed. Deliveries may repeat and may arrive out of order.
payment.complete: Payment completedpayment.failed: Payment failedpayment.cancelled: Payment cancelledpayment.refunded: Payment fully refundedpayment.partially_refunded: Payment partially refundedinvoice.paid: Invoice fully paidinvoice.partially_paid: Invoice partially paidinvoice.cancelled: Invoice cancelledeft.proof_received: EFT proof of payment receivedeft.rejected: EFT proof rejectedeft.expired: EFT order expiredeft.cancelled: EFT order cancelledreconciliation.completed: Reconciliation run completedsubscription.activated: Subscription activated (first payment completed)subscription.charged: Subscription renewal chargedsubscription.payment_failed: Subscription renewal failedsubscription.cancelled: Subscription cancelledsubscription.paused: Subscription pausedsubscription.resumed: Subscription resumed
Headers#
| Field | Type | Description |
|---|---|---|
CentraPoint-Eventrequired | string | Event type. |
CentraPoint-Deliveryrequired | string | Delivery ID (constant across retries of this delivery). |
CentraPoint-Signaturerequired | string |
|
Payload: payment.complete, payment.failed, payment.cancelled, payment.refunded, payment.partially_refunded#
| Field | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | Unique event ID ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
typerequired | string | One of: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createdrequired | string (date-time) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
datarequired | WebhookPaymentData | Show fields
|
{
"id": "evt_3f9a1c7b2e4d6f8091a2b3c4",
"type": "payment.complete",
"created": "2026-09-25T08:14:04.201Z",
"data": {
"reference": "CP-20260925-9F3A1C7B",
"status": "complete",
"amount": 499,
"currency": "ZAR",
"type": "once",
"gateway": "payfast",
"providerRef": "2458761",
"paymentLinkId": "cmg1k2x3y0001abcd1234efgh",
"externalReference": "ORDER-1001",
"eftOrderId": null,
"invoice": null,
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001"
},
"metadata": {
"crmId": "0061x00000AbCdE"
},
"renewal": false,
"parentReference": null,
"subscriptionId": null,
"refundedAmount": 0,
"paidAt": "2026-09-25T08:14:03.512Z"
}
}Payload: invoice.paid, invoice.partially_paid, invoice.cancelled#
| Field | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | Unique event ID ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
typerequired | string | One of: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createdrequired | string (date-time) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
datarequired | Invoice | Show fields
|
{
"id": "evt_8b2d4f6a0c1e3a5b7d9f1c2e",
"type": "invoice.paid",
"created": "2026-10-02T08:15:01.000Z",
"data": {
"id": "cmg2i9n0v0005inv0001abcd",
"number": "INV-000042",
"status": "paid",
"externalReference": "ORDER-1001",
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001",
"email": "[email protected]"
},
"currency": "ZAR",
"issueDate": "2026-09-24T22:00:00.000Z",
"dueDate": "2026-10-08T21:59:59.000Z",
"lines": [
{
"description": "Website hosting - October",
"quantity": 1,
"unitPrice": 434.78,
"taxRate": 15,
"amount": 434.78
},
{
"description": "Domain renewal (zero-rated)",
"quantity": 1,
"unitPrice": 120,
"taxRate": 0,
"amount": 120
}
],
"subtotal": 554.78,
"taxAmount": 65.22,
"total": 620,
"amountPaid": 620,
"amountDue": 0,
"paidAt": "2026-10-02T08:15:00.000Z",
"payUrl": null,
"notes": "Payment due within 14 days.",
"metadata": {
"crmId": "0061x00000AbCdE"
},
"createdAt": "2026-09-25T08:05:00.000Z",
"updatedAt": "2026-09-25T08:05:00.000Z"
}
}Payload: eft.proof_received, eft.rejected, eft.expired, eft.cancelled#
| Field | Type | Description | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
typerequired | string | One of: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createdrequired | string (date-time) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
datarequired | EftOrder | Show fields
|
{
"id": "evt_5c7e9a1b3d5f7a9c1e3b5d7f",
"type": "eft.proof_received",
"created": "2026-09-25T09:12:01.000Z",
"data": {
"id": "cmg3e1f2t0009eft0001abcd",
"reference": "EFT-7K3Q9P2M",
"status": "awaiting_review",
"amount": 1250,
"currency": "ZAR",
"description": "Order #1001",
"externalReference": "ORDER-1001",
"metadata": {
"cartId": "c_8841"
},
"customer": {
"id": "cmg2c0s7t0003cust0001abcd",
"externalReference": "CRM-1001"
},
"bankDetails": {
"bankName": "FNB",
"accountName": "Example Traders (Pty) Ltd",
"accountNumber": "62000000000",
"branchCode": "250655",
"accountType": "current"
},
"paymentReference": "EFT-7K3Q9P2M",
"payUrl": "https://app.centrapoint.co.za/eft/cmg3e1f2t0009eft0001abcd.Qm9ndXMtc2lnbmF0dXJlLWV4YW1wbGU",
"proofs": [
{
"id": "cmg3p0r0f0011prf0001abcd",
"fileName": "proof.pdf",
"contentType": "application/pdf",
"size": 184213,
"source": "payer",
"createdAt": "2026-09-25T09:12:00.000Z"
}
],
"rejectionReason": null,
"expiresAt": "2026-10-02T08:00:00.000Z",
"reviewedAt": null,
"paidAt": null,
"createdAt": "2026-09-25T08:00:00.000Z"
}
}Payload: reconciliation.completed#
| Field | Type | Description | |||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | ||||||||||||||||||||||||||||||||||||||||
typerequired | string | One of: | |||||||||||||||||||||||||||||||||||||||
createdrequired | string (date-time) | ||||||||||||||||||||||||||||||||||||||||
datarequired | object | Show fields
|
{
"id": "evt_5c7e9a1b3d5f7a9c1e3b5d7f",
"type": "reconciliation.completed",
"created": "2026-09-25T09:12:01.000Z",
"data": {
"runId": "cmg3r7c0n0013run0001abcd",
"status": "exceptions",
"exceptions": 2,
"lineCount": 42,
"statementDate": "2026-09-24T22:00:00.000Z",
"totals": {
"receipts": 48250.5,
"fees": 612.4,
"refunds": 499,
"payouts": 45000,
"unpaids": 350
}
}
}Payload: subscription.activated, subscription.charged, subscription.payment_failed, subscription.cancelled, subscription.paused, subscription.resumed#
| Field | Type | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
idrequired | string | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
typerequired | string | One of: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createdrequired | string (date-time) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
datarequired | SubscriptionWebhookData | Show fields
|
{
"id": "evt_2a4c6e8f0b1d3f5a7c9e1b3d",
"type": "subscription.activated",
"created": "2026-10-25T08:14:05.000Z",
"data": {
"id": "cmg2s5b8k0007sub0001abcd",
"status": "active",
"frequency": "monthly",
"amount": 499,
"currency": "ZAR",
"gateway": "payfast",
"paymentLinkId": "cmg1k2x3y0001abcd1234efgh",
"externalReference": "SUB-ACME-PRO",
"metadata": {
"plan": "pro"
},
"createdAt": "2026-09-25T08:14:04.000Z",
"updatedAt": "2026-09-25T08:14:04.000Z",
"subscriptionId": "cmg2s5b8k0007sub0001abcd",
"payment": {
"reference": "CP-20260925-9F3A1C7B",
"amount": 499,
"currency": "ZAR",
"status": "complete",
"paidAt": "2026-09-25T08:14:03.512Z"
},
"periodStart": "2026-09-25T08:14:03.512Z",
"periodEnd": "2026-10-25T08:14:03.512Z"
}
}See the Webhooks guide for setup and signature verification code.