Request Conventions
URL Structure
Section titled “URL Structure”Public-API URLs are flat — no tenant or workspace IDs in the path:
https://api.getzutax.com/api/public/v1/{resource}Examples:
POST /api/public/v1/partiesPOST /api/public/v1/invoices/transmitGET /api/public/v1/invoices/by-external-id/{external_id}The workspace and tenant scope are derived from the API key — you never need to look them up or pass them in.
Required Headers
Section titled “Required Headers”| Header | Required for | Notes |
|---|---|---|
| Authorization: Bearer <api_key> | every call | See Authentication |
| Content-Type: application/json | POST / PATCH | Required for JSON bodies |
| Idempotency-Key: <uuid-or-stable-string> | every write (POST, PATCH) | See “Idempotency” below |
External IDs
Section titled “External IDs”Every write supports a client-supplied external_id per resource. Use it to:
- De-duplicate retries — a re-POST with the same
external_idreturns the existing record without creating a duplicate - Look up the resource later without storing the ZUTAX UUID:
GET /api/public/v1/{resource}/by-external-id/{external_id}
external_id is unique per workspace per resource type; it must not be reused.
Idempotency
Section titled “Idempotency”Every write endpoint requires an Idempotency-Key header. Recommended value: a stable derivation of your source-system ID, e.g.:
sha256(your_workspace_id || resource_type || your_record_id || your_record_version)Behavior within a 24-hour window:
- Same key + same body → server returns the original cached response
- Same key + different body → server returns
409 Conflict - New key → server processes the request and caches the response
Keys persist for 24 hours and are workspace-scoped.
Pagination
Section titled “Pagination”Where supported, list endpoints accept:
page(default1)page_size(default20, max100)
Typical paginated response:
{ "items": [], "total": 0, "page": 1, "page_size": 20, "pages": 0}Sorting and Filtering
Section titled “Sorting and Filtering”Where supported:
sort_bysort_order(ascordesc)- resource-specific filters (
status,search,external_id, etc.)
Refer to the Endpoint Reference for the exact query parameters each endpoint accepts.
Currency
Section titled “Currency”All monetary values in public-API request and response bodies are in naira (Decimal). The backend stores billing amounts in kobo internally, but no kobo value ever crosses the API boundary.
Field names ending in _naira (e.g., unit_price_naira, total_naira) are explicit reminders. Locale is always en-NG.
Async Mode
Section titled “Async Mode”Most write endpoints accept ?async=true, which returns:
{ "job_id": "j_...", "status": "queued", "result_url": "/api/public/v1/jobs/j_..." }with HTTP 202. Poll GET /api/public/v1/jobs/{job_id} or wait for the configured webhook callback.