CentraPoint

Resources

Changelog

Changes to the CentraPoint public API and this documentation.

On this page

25 September 2026: EFT reminders and proof source#

  • New: EFT order proofs[] items include source: api, dashboard or payer.
  • New: EFT payment reminders: one email about 48 hours before expiry for unpaid orders at least a day old, with the bank details and payer page link, sent to the payer's checkout email or otherwise the customer's.
  • New: Settings → Webhooks can change an endpoint's events without re-creating it, so the signing secret is kept.

25 September 2026: EFT payer page and EFT at checkout#

  • New: EFT orders return payUrl, a signed public payer page with the bank details, the reference and a proof upload. No login needed; share it instead of building your own upload.
  • New: POST /api/v1/eft-orders accepts notifyPayer to email the customer the bank details and payUrl (400 without a customer email).
  • New: hosted payment-link and invoice pages offer Bank transfer (EFT) for once-off payments. Approval pays the link or invoice, and payment.complete carries the link's externalReference and metadata. See EFT at hosted checkout.
  • Changed: once-off payment links and invoice pay links can be created when Manual EFT is the only gateway.

25 September 2026: subscription pause and resume#

  • New: POST /api/v1/subscriptions/{id}/pause and /resume on gateways that support it (e.g. PayFast). See the rules.
  • New webhooks: subscription.paused and subscription.resumed, also sent for dashboard actions; data is the subscription.
  • Changed: pause, resume and cancel share the same rules: repeating an action that already took effect returns 200 unchanged, invalid transitions return the new error 409 invalid_state, and gateway refusals return 502 gateway_error. Cancel is allowed from active or paused.
  • Changed: pausing or resuming a Netcash Pay Now subscription (which supports cancel only) now returns 409 unsupported instead of 502 gateway_error; the dashboard no longer offers Pause for it.

25 September 2026: eft.cancelled and fixes#

  • New webhook: eft.cancelled, sent when an EFT order is cancelled through the API or the dashboard; data is the EFT order.
  • Changed: POST /api/v1/invoices accepts customerId as an alternative to customer; send exactly one.
  • Fixed: payers returning from a Netcash Pay Now service-level Accept or Decline URL now land on their payment (the reference is read from Reference/p2 when there is no ref).
  • Clarified: staff may approve an EFT order without proof, including an expired one, and subscription.payment_failed has no billing period because none was paid.

25 September 2026: EFT orders, reconciliation API, subscription webhooks#

  • New: EFT orders API and the Accepting EFT with proof of payment guide: unique deposit references on your own bank account, multipart proof upload (PDF, PNG or JPEG, up to 10 MB), staff approval with statement matching. New Manual EFT gateway and transaction type eft.
  • New: Reconciliation results API: GET /api/v1/reconciliation/runs and /runs/{id} with totals, item statuses and not_received for Netcash statements.
  • New webhooks: eft.proof_received, eft.rejected, eft.expired, reconciliation.completed, and subscription.activated, subscription.charged, subscription.payment_failed, subscription.cancelled.
  • Changed: payment.* webhooks add eftOrderId; externalReference and metadata fall back to the EFT order's.
  • Changed: GET /api/v1/transactions/{reference}: metadata is always an object (was null without a payment link); externalReference and metadata fall back to the EFT order's; adds eftOrderId; invoice is now { id, number, invoiceNumber, status, externalReference }, matching webhooks (invoiceNumber kept for compatibility).
  • Changed: GET /api/v1/payment-links/{id} now includes subscription, like the list.
  • Changed: invoices reject currency codes that are not ISO 4217 (400).
  • Fixed: Idempotency-Key is scoped to the HTTP method and exact path, so the same key on two different invoices (e.g. /invoices/A/send and /invoices/B/send) no longer replays the first response.
  • New guide: Migrating an existing Netcash Pay Now integration (legacy passthrough).

25 September 2026: customers, invoices and subscriptions#

  • New: Customers API: create or upsert by externalReference, list, get and update.
  • New: Invoices API: create with per-line VAT (idempotent on externalReference), list (including partially_paid), get, send, cancel and record offline payments. Invoices include payUrl and amountDue.
  • New: Subscriptions API and recurring payment links (recurring: { frequency, amount? }) on PayFast and Netcash Pay Now. See Recurring billing.
  • New: payment links accept returnUrl (allow-listed origins), metadata and customerId; responses add returnUrl, metadata, recurring and (list)subscription.
  • New: Idempotency-Key on POST endpoints (24 hours, Idempotent-Replayed: true, 409 idempotency_conflict) and metadata on links, customers and invoices.
  • New webhooks: invoice.paid, invoice.partially_paid, invoice.cancelled. payment.* data adds metadata, customer, renewal, parentReference, subscriptionId; invoice is now { id, number, status, externalReference }.
  • New: transactions return metadata, renewal, parentReference and subscriptionId.
  • New error codes: 409 idempotency_conflict, 409 unsupported, 502 gateway_error. Invalid JSON now returns Body must be JSON; bodies over 100 000 characters return 413.

25 September 2026: accounting integrations#

  • New: accounting integrations (Business plan and above) for Sage Business Cloud Accounting (South Africa and international), Xero, QuickBooks Online and Zoho Books, plus a Sage Pastel / Sage 50 CSV export. Customers, invoices, completed payments and refunds sync automatically.
  • New endpoint: GET /api/v1/accounting/referral-links returns tracked sign-up links for partner accounting systems.

25 September 2026: webhooks and refunds#

  • New: outbound webhooks. Configure up to 5 HTTPS endpoints under Settings → Webhooks to receive payment.complete, payment.failed, payment.cancelled, payment.refunded and payment.partially_refunded events, signed with CentraPoint-Signature (HMAC-SHA256) and retried for about 2 days. Polling remains available as a fallback.
  • Changed: POST /api/v1/payment-links validates currency as ISO 4217 and requires one of your enabled gateways to accept it (400 otherwise).
  • Changed: expiresAt accepts any ISO 8601 UTC offset (e.g. +02:00), and must be in the future and at most 1 year ahead.
  • New: GET /api/v1/transactions/{reference} returns refundedAmount and refunds[].
  • The page previously titled "Webhook notification URLs & security" is now Gateway notification URLs.

25 September 2026: rate limits and references#

  • Changed: rate limits are now per API key (120 requests per minute, fixed window, shared across all servers) instead of per IP. A coarse guard of 600 requests per minute per IP applies before authentication; the client IP comes from our proxy's X-Forwarded-For entry and cannot be spoofed.
  • New: X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix seconds) on every authenticated response; 429 responses include an exact Retry-After.
  • Changed: new payment references use the CP-YYYYMMDD-XXXXXXXX format. Existing GSS- references stay valid and are still matched by reconciliation. Treat references as opaque strings.

25 September 2026: payment references#

  • New: optional externalReference (1–100 characters, your order ID) on POST /api/v1/payment-links.
  • Changed: POST /api/v1/payment-links now returns the full payment link object: id, url, title, description, amount, currency, externalReference, singleUse, active, expiresAt, paidCount, createdAt. Additive; existing fields are unchanged.
  • New: GET /api/v1/payment-links (filter by externalReference, limit 1–100) and GET /api/v1/payment-links/{id}, both including the payments (references and statuses) made through each link. This removes the earlier limitation that payment references could not be discovered via the API.
  • New: GET /api/v1/transactions/{reference} returns gateway, paymentLinkId and externalReference.
  • New error code: 500 internal_error with a generic message for unexpected errors. 400 invalid_request now only carries validation messages (e.g. Product not found).
  • Security: the payer cancel URL is now HMAC-signed (&sig=). An unsigned /payment/cancel?ref=… no longer cancels a payment.

25 September 2026: launch#

Documentation launched at docs.centrapoint.co.za, covering API v1 as it stands today.

  • API keys use the cp_<8 hex>_<secret> format and are scoped to one organisation. API access requires a plan that includes the REST API.
  • Error responses use { "error": "<code>", "message": "<text>" } with the codes invalid_request, unauthorized, plan_restricted, plan_limit, account_restricted, not_found and rate_limited. 429 responses include Retry-After.
  • POST /api/v1/payment-links accepts an optional currency (default ZAR), accepts any positive amount up to 10 000 000, and returns singleUse.
  • GET /api/v1/transactions/{reference} is scoped to your organisation and can return type: "debit_order".
  • Gateway notification URLs use one format for every gateway: /api/webhooks/{type}?provider={providerId} (GET and POST).

Versioning policy#

  • Additive changes (new endpoints, new optional request fields, new response fields, new error codes or enum values) can ship in v1 without notice. Write clients that ignore unknown fields and handle unknown enum values.
  • Breaking changes will ship under a new version path and be announced here first.