Skip to content

First API Integration

By the end of this guide you’ll have:

  1. Created a workspace API key in the dashboard
  2. Verified the key with _introspect
  3. Created a customer and an invoice via the composite “issue and transmit” endpoint

Throughout, replace zk_live_... with your own key, and use https://api.getzutax.com for production or your staging URL during development.

API keys are created in the ZUTAX dashboard under Workspace Settings → API Keys. Each key is shown once at creation; store it in your secret manager.

Recommended scopes for a typical ERP integration:

  • parties:read, parties:write
  • products:read, products:write
  • invoices:read, invoices:write, invoices:transmit
Terminal window
curl -sS https://api.getzutax.com/api/public/v1/_introspect \
-H "Authorization: Bearer zk_live_<prefix>_<secret>"

Expected response:

{
"workspace_id": "8a1c7f6c-61a1-4d89-8d96-3f7e7747f0c0",
"tenant_id": "...",
"api_key_id": "...",
"scopes": ["invoices:read", "invoices:write", "invoices:transmit", "parties:read", "parties:write"]
}

If you get 401, double-check the header (Authorization: Bearer ..., not X-API-Key). If scopes is missing what you need, regenerate the key with the right scopes.

This single call upserts the customer party (using the external_id from your ERP), creates the invoice, signs the IRN, and submits it to the Access Point Provider.

Terminal window
curl -sS -X POST https://api.getzutax.com/api/public/v1/invoices/transmit \
-H "Authorization: Bearer zk_live_<prefix>_<secret>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"external_id": "ERP-INV-2026-00451",
"currency": "NGN",
"issue_date": "2026-05-02",
"due_date": "2026-06-01",
"customer": {
"external_id": "ERP-CUST-9",
"legal_name": "Acme Ltd",
"tin": "12345678-1234"
},
"lines": [
{
"name": "Widget",
"quantity": 10,
"unit_price_naira": 1500,
"vat_rate": 0.075
}
],
"options": {
"submit_to_pasca": true,
"fail_fast": true
}
}'

Successful response (abridged):

{
"invoice": {
"id": "inv_...",
"external_id": "ERP-INV-2026-00451",
"status": "transmitted",
"irn": "INV-2026-05-02-...",
"pasca_dispatch_id": "dsp_..."
},
"customer": { "id": "party_...", "external_id": "ERP-CUST-9", "created": true },
"steps_completed": ["party_upsert", "invoice_create", "validate", "irn_sign", "pasca_submit"],
"elapsed_ms": 2340
}

Re-issuing the same call with the same Idempotency-Key and the same body returns the cached response — no duplicate invoice, no duplicate party. Use this pattern in your integration’s retry loop.

If your transport fails between sending the request and receiving the response, retry with the same key. The server either processes it (first attempt) or returns the cached response (subsequent attempts).