Skip to content

API reference

The Zana REST API lets you create customers, raise invoices, take payments, run utility billing, and manage contacts programmatically. All requests are JSON over HTTPS.

Base URL

https://zana.norialabs.com/api/v1

Auth

Bearer nk_...

Format

JSON over HTTPS

Authentication

Authenticate every request with an API key in the Authorization header. Create keys in Settings → API keys; the full key (nk_<prefix>_<secret>) is shown once at creation - store it securely. Keys are workspace-scoped and grant full read/write access, so treat them like passwords. API access requires a paid plan.

curl
curl https://zana.norialabs.com/api/v1/invoicing/customers \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"

Pagination

List endpoints return newest-first and page with a keyset cursor. Pass limit (1–100, default 50) and the nextCursor from the previous response as cursor. When pagination.nextCursor is null, you have reached the last page.

json
{
  "data": [ /* ... */ ],
  "pagination": { "total": 128, "nextCursor": "eyJpZCI6..." }
}

Idempotency

Safely retry writes by sending an Idempotency-Key header (any unique string, e.g. a UUID) on POST/PUT/PATCH/DELETE. The first request is processed and its response stored; retries with the same key return that stored response instead of acting twice.

curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Idempotency-Key: 3f0c8a2e-1b4d-4e6f-9a01-2b3c4d5e6f70" \
  -H "Content-Type: application/json" \
  -d '{ /* ... */ }'

Errors

Errors use standard HTTP status codes and a consistent body:

json
{ "error": { "status": 400, "message": "issueDate is required" } }
400 Bad RequestThe request body or query failed validation. The message names the problem.
401 UnauthorizedMissing or invalid API key. Send `Authorization: Bearer nk_...`.
403 ForbiddenYour plan lacks API access, a module is disabled, or a quota (e.g. invoice cap) is exceeded.
404 Not FoundNo resource with that id in your workspace.
409 ConflictThe request conflicts with existing state (e.g. a duplicate, or insufficient reminder funds).
429 Too Many RequestsRate limit exceeded. Back off and retry.
500 Server ErrorSomething went wrong on our side. Safe to retry idempotent requests.

Invoicing

Customers

The people and companies you bill. Every invoice settles against a customer.

List customers

GET/invoicing/customers

curl
curl "https://zana.norialabs.com/api/v1/invoicing/customers?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "name": "Acme Logistics Ltd",
      "email": null,
      "phone": null,
      "taxPin": null,
      "billingAddress": null,
      "notes": null,
      "contactId": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create customer

POST/invoicing/customers

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/customers \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "email": "string",
    "phone": "+254720123456",
    "taxPin": "string",
    "billingAddress": "string",
    "notes": "Adjustment",
    "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Export customers

GET/invoicing/customers/export

curl
curl https://zana.norialabs.com/api/v1/invoicing/customers/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Retrieve customer

GET/invoicing/customers/{id}

curl
curl https://zana.norialabs.com/api/v1/invoicing/customers/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "email": "string",
    "phone": "+254720123456",
    "taxPin": "string",
    "billingAddress": "string",
    "notes": "Adjustment",
    "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Update customer

PUT/invoicing/customers/{id}

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/invoicing/customers/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "email": "string",
    "phone": "+254720123456",
    "taxPin": "string",
    "billingAddress": "string",
    "notes": "Adjustment",
    "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete customer

DELETE/invoicing/customers/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/invoicing/customers/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

List stats

GET/invoicing/customers/{id}/stats

curl
curl https://zana.norialabs.com/api/v1/invoicing/customers/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/stats \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "outstanding": 0,
    "totalPaid": 500000,
    "invoiceCount": 0,
    "openInvoiceCount": 0,
    "creditBalance": 500000,
    "lastInvoiceAt": "string"
  }
}

Import customers

POST/invoicing/customers/import

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/customers/import \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "csv": "string",
  "dataBase64": "string"
}'
Response · 200 OK
json
{
  "data": {
    "created": 0,
    "updated": 0,
    "skipped": [
      {
        "row": 0,
        "message": "string"
      }
    ]
  }
}

Invoices

Create, send, and collect on invoices. Amounts are in minor units (cents).

List invoices

GET/invoicing/invoices

curl
curl "https://zana.norialabs.com/api/v1/invoicing/invoices?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "invoice": {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "recurringInvoiceId": null,
        "sourceModule": "invoicing",
        "invoiceNumber": "string",
        "invoiceCode": null,
        "status": "draft",
        "currency": "KES",
        "subtotal": 500000,
        "taxTotal": 500000,
        "total": 500000,
        "amountPaid": 500000,
        "amountCredited": 500000,
        "balanceDue": 500000,
        "issueDate": "2026-07-06",
        "dueDate": null,
        "publicToken": "string",
        "allowedChannels": null,
        "allowedProviders": null,
        "notes": null,
        "pdfObjectKey": null,
        "sentAt": null,
        "writtenOffAt": null,
        "writtenOffReason": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z",
        "deletedAt": null
      },
      "customerName": null
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create invoice

POST/invoicing/invoices

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "issueDate": "2026-07-06",
  "lineItems": [
    {
      "description": "string",
      "quantity": 2,
      "unitPrice": 500000,
      "taxRate": 0
    }
  ]
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "recurringInvoiceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "invoicing",
    "invoiceNumber": "string",
    "invoiceCode": "string",
    "status": "draft",
    "currency": "KES",
    "subtotal": 500000,
    "taxTotal": 500000,
    "total": 500000,
    "amountPaid": 500000,
    "amountCredited": 500000,
    "balanceDue": 500000,
    "issueDate": "2026-07-06",
    "dueDate": "2026-07-06",
    "publicToken": "string",
    "allowedChannels": "string",
    "allowedProviders": "string",
    "notes": "Adjustment",
    "pdfObjectKey": "string",
    "sentAt": "2026-07-06T09:00:00.000Z",
    "writtenOffAt": "2026-07-06T09:00:00.000Z",
    "writtenOffReason": "Adjustment",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Open invoices

GET/invoicing/invoices/open

curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/open \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "invoiceNumber": "string",
      "customerName": null,
      "balanceDue": 500000,
      "currency": "KES"
    }
  ]
}

Export invoices

GET/invoicing/invoices/export

curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Import invoices

POST/invoicing/invoices/import

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/import \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "csv": "string",
  "dataBase64": "string"
}'
Response · 200 OK
json
{
  "data": {
    "created": 0,
    "updated": 0,
    "skipped": [
      {
        "row": 0,
        "message": "string"
      }
    ]
  }
}

Retrieve invoice

GET/invoicing/invoices/{id}

curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "invoice": {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "recurringInvoiceId": null,
      "sourceModule": "invoicing",
      "invoiceNumber": "string",
      "invoiceCode": null,
      "status": "draft",
      "currency": "KES",
      "subtotal": 500000,
      "taxTotal": 500000,
      "total": 500000,
      "amountPaid": 500000,
      "amountCredited": 500000,
      "balanceDue": 500000,
      "issueDate": "2026-07-06",
      "dueDate": null,
      "publicToken": "string",
      "allowedChannels": null,
      "allowedProviders": null,
      "notes": null,
      "pdfObjectKey": null,
      "sentAt": null,
      "writtenOffAt": null,
      "writtenOffReason": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null
    },
    "customer": {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "name": "Acme Logistics Ltd",
      "email": null,
      "phone": null,
      "taxPin": null,
      "billingAddress": null,
      "notes": null,
      "contactId": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null
    },
    "lineItems": [
      {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "invoiceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "description": "string",
        "quantity": "string",
        "unitPrice": 500000,
        "taxRate": "string",
        "taxAmount": 500000,
        "lineTotal": 500000,
        "sortOrder": 1,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z"
      }
    ]
  }
}

Update invoice

PUT/invoicing/invoices/{id}

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "issueDate": "2026-07-06",
  "lineItems": [
    {
      "description": "string",
      "quantity": 2,
      "unitPrice": 500000,
      "taxRate": 0
    }
  ]
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "recurringInvoiceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "invoicing",
    "invoiceNumber": "string",
    "invoiceCode": "string",
    "status": "draft",
    "currency": "KES",
    "subtotal": 500000,
    "taxTotal": 500000,
    "total": 500000,
    "amountPaid": 500000,
    "amountCredited": 500000,
    "balanceDue": 500000,
    "issueDate": "2026-07-06",
    "dueDate": "2026-07-06",
    "publicToken": "string",
    "allowedChannels": "string",
    "allowedProviders": "string",
    "notes": "Adjustment",
    "pdfObjectKey": "string",
    "sentAt": "2026-07-06T09:00:00.000Z",
    "writtenOffAt": "2026-07-06T09:00:00.000Z",
    "writtenOffReason": "Adjustment",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete invoice

DELETE/invoicing/invoices/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

List delivery status

GET/invoicing/invoices/{id}/delivery-status

curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/delivery-status \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "customer": {
      "hasEmail": true,
      "hasPhone": true
    },
    "channels": {
      "email": {
        "enabled": true,
        "lastSentAt": null
      },
      "sms": {
        "enabled": true,
        "lastSentAt": null
      },
      "whatsapp": {
        "enabled": true,
        "lastSentAt": null
      }
    }
  }
}

Send invoice

POST/invoicing/invoices/{id}/send

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/send \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "channels": [
    "email"
  ]
}'
Response · 200 OK
json
{
  "ok": true,
  "delivered": [
    "email"
  ],
  "skipped": [
    "string"
  ],
  "queued": true,
  "jobId": "string"
}

Remind invoice

POST/invoicing/invoices/{id}/remind

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/remind \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true,
  "sent": 0,
  "failed": 0,
  "skipped": [
    "string"
  ]
}

Bulk remind invoice

POST/invoicing/invoices/bulk-remind

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/bulk-remind \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "invoiceIds": [
    "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
  ]
}'
Response · 200 OK
json
{
  "ok": true,
  "reminded": 0,
  "skipped": 0,
  "failed": 0
}

Void invoice

POST/invoicing/invoices/{id}/void

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/void \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Create write off

POST/invoicing/invoices/{id}/write-off

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/write-off \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Adjustment"
}'
Response · 200 OK
json
{
  "ok": true
}

List credit notes

GET/invoicing/invoices/{id}/credit-notes

curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/credit-notes \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "number": "string",
      "amountMinor": 500000,
      "reason": null,
      "status": "active",
      "createdAt": "2026-07-06T09:00:00.000Z"
    }
  ]
}

Create credit note

POST/invoicing/invoices/{id}/credit-notes

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/credit-notes \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "amountMinor": 1
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "number": "string",
    "amountMinor": 500000
  }
}

PUT providers

PUT/invoicing/invoices/{id}/providers

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/providers \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "allowedProviders": [
    "sasapay"
  ]
}'
Response · 200 OK
json
{
  "ok": true
}

Create payment

POST/invoicing/invoices/{id}/payments

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/payments \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "amount": 2,
  "paidAt": "string"
}'
Response · 200 OK
json
{
  "data": {
    "paymentId": "string",
    "receiptNumber": "string"
  }
}

Payments

Money received across your invoices and payment links.

List payments

GET/invoicing/invoices/{id}/payments

curl
curl https://zana.norialabs.com/api/v1/invoicing/invoices/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/payments \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "invoiceId": null,
      "paymentLinkId": null,
      "utilityAccountId": null,
      "customerId": null,
      "sourceModule": "invoicing",
      "payerName": null,
      "payerPhone": null,
      "payerEmail": null,
      "amount": 500000,
      "feeAmount": 500000,
      "currency": "KES",
      "method": "mpesa_sasapay",
      "paymentInstructionId": null,
      "status": "pending",
      "channel": null,
      "paidAt": null,
      "receiptNumber": null,
      "receiptPdfObjectKey": null,
      "providerTxnCode": null,
      "failureReason": null,
      "note": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null
    }
  ],
  "meta": {
    "hiddenFailedCount": 0
  }
}

Resend receipt for payment

POST/invoicing/payments/{paymentId}/resend-receipt

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payments/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/resend-receipt \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

List payments

GET/invoicing/payments

curl
curl "https://zana.norialabs.com/api/v1/invoicing/payments?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "payment": {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "invoiceId": null,
        "paymentLinkId": null,
        "utilityAccountId": null,
        "customerId": null,
        "sourceModule": "invoicing",
        "payerName": null,
        "payerPhone": null,
        "payerEmail": null,
        "amount": 500000,
        "feeAmount": 500000,
        "currency": "KES",
        "method": "mpesa_sasapay",
        "paymentInstructionId": null,
        "status": "pending",
        "channel": null,
        "paidAt": null,
        "receiptNumber": null,
        "receiptPdfObjectKey": null,
        "providerTxnCode": null,
        "failureReason": null,
        "note": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z",
        "deletedAt": null
      },
      "invoiceNumber": null,
      "customerName": null,
      "linkTitle": null,
      "instructionLabel": null,
      "instructionKind": null
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Export payments

GET/invoicing/payments/export

curl
curl https://zana.norialabs.com/api/v1/invoicing/payments/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Retrieve payment

GET/invoicing/payments/{id}

curl
curl https://zana.norialabs.com/api/v1/invoicing/payments/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "invoiceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "paymentLinkId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "utilityAccountId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "invoicing",
    "payerName": "Acme Logistics Ltd",
    "payerPhone": "+254720123456",
    "payerEmail": "string",
    "amount": 500000,
    "feeAmount": 500000,
    "currency": "KES",
    "method": "mpesa_sasapay",
    "paymentInstructionId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "status": "pending",
    "channel": "mpesa",
    "paidAt": "2026-07-06T09:00:00.000Z",
    "receiptNumber": "string",
    "receiptPdfObjectKey": "string",
    "providerTxnCode": "string",
    "failureReason": "Adjustment",
    "note": "Adjustment",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

List refunds

GET/invoicing/payments/{id}/refunds

curl
curl https://zana.norialabs.com/api/v1/invoicing/payments/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/refunds \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "amountMinor": 500000,
      "mode": "record",
      "providerRef": null,
      "status": "pending",
      "idempotencyKey": null,
      "reason": null,
      "createdAt": "2026-07-06T09:00:00.000Z"
    }
  ]
}

Create refund

POST/invoicing/payments/{id}/refunds

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payments/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/refunds \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "amountMinor": 1,
  "idempotencyKey": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "amountMinor": 500000,
    "status": "pending"
  }
}

Void payment

POST/invoicing/payments/{id}/void

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payments/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/void \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Adjustment"
}'
Response · 200 OK
json
{
  "ok": true
}

List statement imports

GET/invoicing/statement-imports

curl
curl https://zana.norialabs.com/api/v1/invoicing/statement-imports \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "filename": "Acme Logistics Ltd",
      "status": "uploaded",
      "totalRows": 500000,
      "matchedRows": 0,
      "unmatchedRows": 0,
      "duplicateRows": 0,
      "createdRows": 0,
      "errors": [
        {
          "row": 0,
          "message": "string"
        }
      ],
      "creatorId": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "completedAt": null
    }
  ]
}

Create statement import

POST/invoicing/statement-imports

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/statement-imports \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "filename": "Acme Logistics Ltd",
  "dataBase64": "string"
}'
Response · 200 OK
json
{
  "data": {
    "import": {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "filename": "Acme Logistics Ltd",
      "status": "uploaded",
      "totalRows": 500000,
      "matchedRows": 0,
      "unmatchedRows": 0,
      "duplicateRows": 0,
      "createdRows": 0,
      "errors": [
        {
          "row": 0,
          "message": "string"
        }
      ],
      "creatorId": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "completedAt": null
    },
    "summary": {
      "totalRows": 500000,
      "matched": 0,
      "unmatched": 0,
      "duplicates": 0,
      "skipped": 0,
      "matchedAmountMinor": 500000
    },
    "results": [
      {
        "row": 0,
        "receipt": "string",
        "completedAt": null,
        "paidInMinor": 500000,
        "accountRef": null,
        "payerName": null,
        "payerPhone": null,
        "details": null,
        "outcome": "matched",
        "matchedBy": "invoice_number",
        "invoiceId": "string",
        "invoiceNumber": null,
        "customerName": null,
        "message": null
      }
    ],
    "resultsTruncated": true,
    "skipped": [
      {
        "row": 0,
        "message": "string"
      }
    ]
  }
}

Retrieve statement import

GET/invoicing/statement-imports/{id}

curl
curl https://zana.norialabs.com/api/v1/invoicing/statement-imports/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "import": {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "filename": "Acme Logistics Ltd",
      "status": "uploaded",
      "totalRows": 500000,
      "matchedRows": 0,
      "unmatchedRows": 0,
      "duplicateRows": 0,
      "createdRows": 0,
      "errors": [
        {
          "row": 0,
          "message": "string"
        }
      ],
      "creatorId": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "completedAt": null
    },
    "summary": {
      "totalRows": 500000,
      "matched": 0,
      "unmatched": 0,
      "duplicates": 0,
      "skipped": 0,
      "matchedAmountMinor": 500000
    },
    "results": [
      {
        "row": 0,
        "receipt": "string",
        "completedAt": null,
        "paidInMinor": 500000,
        "accountRef": null,
        "payerName": null,
        "payerPhone": null,
        "details": null,
        "outcome": "matched",
        "matchedBy": "invoice_number",
        "invoiceId": "string",
        "invoiceNumber": null,
        "customerName": null,
        "message": null
      }
    ],
    "resultsTruncated": true,
    "skipped": [
      {
        "row": 0,
        "message": "string"
      }
    ]
  }
}

Commit statement import

POST/invoicing/statement-imports/{id}/commit

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/statement-imports/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/commit \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "sendReceipts": false
}'
Response · 200 OK
json
{
  "data": {
    "import": {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "filename": "Acme Logistics Ltd",
      "status": "uploaded",
      "totalRows": 500000,
      "matchedRows": 0,
      "unmatchedRows": 0,
      "duplicateRows": 0,
      "createdRows": 0,
      "errors": [
        {
          "row": 0,
          "message": "string"
        }
      ],
      "creatorId": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "completedAt": null
    },
    "created": 0,
    "skipped": [
      {
        "row": 0,
        "message": "string"
      }
    ]
  }
}

Get unresolved

GET/invoicing/statement-imports/{id}/unresolved

curl
curl https://zana.norialabs.com/api/v1/invoicing/statement-imports/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/unresolved \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Recurring invoices

Schedules that raise invoices automatically on a cadence.

List recurring

GET/invoicing/recurring

curl
curl "https://zana.norialabs.com/api/v1/invoicing/recurring?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "recurring": {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "title": null,
        "currency": "KES",
        "lineItems": null,
        "cadence": "weekly",
        "dueInDays": 1,
        "allowedChannels": null,
        "allowedProviders": null,
        "active": true,
        "autoSend": true,
        "nextRunAt": "2026-07-06T09:00:00.000Z",
        "lastGeneratedInvoiceId": null,
        "lastRunAt": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z",
        "deletedAt": null
      },
      "customerName": null
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create recurring

POST/invoicing/recurring

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/recurring \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "cadence": "weekly",
  "startDate": "2026-07-06",
  "lineItems": [
    {
      "description": "string",
      "quantity": 2,
      "unitPrice": 500000,
      "taxRate": 0
    }
  ]
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "title": "string",
    "currency": "KES",
    "lineItems": "string",
    "cadence": "weekly",
    "dueInDays": 1,
    "allowedChannels": "string",
    "allowedProviders": "string",
    "active": true,
    "autoSend": true,
    "nextRunAt": "2026-07-06T09:00:00.000Z",
    "lastGeneratedInvoiceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "lastRunAt": "2026-07-06T09:00:00.000Z",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Retrieve recurring

GET/invoicing/recurring/{id}

curl
curl https://zana.norialabs.com/api/v1/invoicing/recurring/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "recurring": {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "title": null,
      "currency": "KES",
      "lineItems": null,
      "cadence": "weekly",
      "dueInDays": 1,
      "allowedChannels": null,
      "allowedProviders": null,
      "active": true,
      "autoSend": true,
      "nextRunAt": "2026-07-06T09:00:00.000Z",
      "lastGeneratedInvoiceId": null,
      "lastRunAt": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null
    },
    "customerName": "Acme Logistics Ltd"
  }
}

Delete recurring

DELETE/invoicing/recurring/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/invoicing/recurring/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

List invoices

GET/invoicing/recurring/{id}/invoices

curl
curl https://zana.norialabs.com/api/v1/invoicing/recurring/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/invoices \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "recurringInvoiceId": null,
      "sourceModule": "invoicing",
      "invoiceNumber": "string",
      "invoiceCode": null,
      "status": "draft",
      "currency": "KES",
      "subtotal": 500000,
      "taxTotal": 500000,
      "total": 500000,
      "amountPaid": 500000,
      "amountCredited": 500000,
      "balanceDue": 500000,
      "issueDate": "2026-07-06",
      "dueDate": null,
      "publicToken": "string",
      "allowedChannels": null,
      "allowedProviders": null,
      "notes": null,
      "pdfObjectKey": null,
      "sentAt": null,
      "writtenOffAt": null,
      "writtenOffReason": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null
    }
  ]
}

Toggle recurring

POST/invoicing/recurring/{id}/toggle

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/recurring/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/toggle \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "active": true
}'
Response · 200 OK
json
{
  "ok": true
}

Run due recurring

POST/invoicing/recurring/run-due

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/recurring/run-due \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "generated": 0
  }
}

Payouts

Disburse funds to suppliers and recipients (M-Pesa / bank).

List payouts

GET/invoicing/payouts

curl
curl "https://zana.norialabs.com/api/v1/invoicing/payouts?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "type": "b2c",
      "destination": "mobile",
      "status": "pending_approval",
      "merchantTransactionReference": "string",
      "amount": 500000,
      "currency": "KES",
      "networkCode": null,
      "receiverNumber": null,
      "receiverMerchantCode": null,
      "receiverAccountType": null,
      "accountReference": null,
      "receiverName": null,
      "reason": "Adjustment",
      "checkoutRequestId": null,
      "transactionCode": null,
      "resultCode": null,
      "resultDescription": null,
      "initiatorId": null,
      "approverId": null,
      "rawRequest": null,
      "rawResponse": null,
      "rawCallback": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create payout

POST/invoicing/payouts

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "type": "b2c",
  "destination": "mobile",
  "amount": 2,
  "reason": "Adjustment"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "status": "active",
    "needsApproval": true
  }
}

Export payouts

GET/invoicing/payouts/export

curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Overview

GET/invoicing/payouts/overview

curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/overview \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "pending": [
      {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "type": "b2c",
        "destination": "mobile",
        "status": "pending_approval",
        "merchantTransactionReference": "string",
        "amount": 500000,
        "currency": "KES",
        "networkCode": null,
        "receiverNumber": null,
        "receiverMerchantCode": null,
        "receiverAccountType": null,
        "accountReference": null,
        "receiverName": null,
        "reason": "Adjustment",
        "checkoutRequestId": null,
        "transactionCode": null,
        "resultCode": null,
        "resultDescription": null,
        "initiatorId": null,
        "approverId": null,
        "rawRequest": null,
        "rawResponse": null,
        "rawCallback": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z"
      }
    ],
    "stats": {
      "paidOutMinor": 500000,
      "pendingApproval": 0,
      "needsReview": 0
    }
  }
}

Payout wallet balance

GET/invoicing/payouts/wallet

curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/wallet \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "currency": "KES",
    "orgBalanceMinor": 500000,
    "accounts": [
      {
        "label": "string",
        "balanceMinor": 500000
      }
    ]
  }
}

List recipients

GET/invoicing/payouts/recipients

curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/recipients \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "destination": "mobile",
      "name": "Acme Logistics Ltd",
      "receiverNumber": null,
      "channelCode": null,
      "receiverMerchantCode": null,
      "accountReference": null,
      "favorite": true,
      "lastPaidAt": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null
    }
  ]
}

Create recipient

POST/invoicing/payouts/recipients

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/recipients \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "destination": "mobile",
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "destination": "mobile",
    "name": "Acme Logistics Ltd",
    "receiverNumber": "string",
    "channelCode": "string",
    "receiverMerchantCode": "string",
    "accountReference": "string",
    "favorite": true,
    "lastPaidAt": "2026-07-06T09:00:00.000Z",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Import recipients

POST/invoicing/payouts/recipients/import

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/recipients/import \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "csv": "string",
  "dataBase64": "string"
}'
Response · 200 OK
json
{
  "data": {
    "created": 0,
    "updated": 0,
    "skipped": [
      {
        "row": 0,
        "message": "string"
      }
    ]
  }
}

Update recipient

PATCH/invoicing/payouts/recipients/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/invoicing/payouts/recipients/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "favorite": true
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "destination": "mobile",
    "name": "Acme Logistics Ltd",
    "receiverNumber": "string",
    "channelCode": "string",
    "receiverMerchantCode": "string",
    "accountReference": "string",
    "favorite": true,
    "lastPaidAt": "2026-07-06T09:00:00.000Z",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete recipient

DELETE/invoicing/payouts/recipients/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/invoicing/payouts/recipients/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "ok": true
  }
}

Approve payout

POST/invoicing/payouts/{id}/approve

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/approve \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "ok": true,
    "status": "active",
    "changed": true
  }
}

Reject payout

POST/invoicing/payouts/{id}/reject

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/reject \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "ok": true,
    "status": "active",
    "changed": true
  }
}

Cancel payout

POST/invoicing/payouts/{id}/cancel

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/cancel \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "ok": true,
    "status": "active",
    "changed": true
  }
}

Recheck payout

POST/invoicing/payouts/{id}/recheck

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/recheck \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "ok": true,
    "status": "active",
    "changed": true
  }
}

Mark failed: payout

POST/invoicing/payouts/{id}/mark-failed

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/mark-failed \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "ok": true,
    "status": "active",
    "changed": true
  }
}

Retry payout

POST/invoicing/payouts/{id}/retry

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/retry \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "ok": true,
    "status": "active",
    "changed": true
  }
}

Move funds into payout

POST/invoicing/payouts/move-funds

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/payouts/move-funds \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "amount": 2
}'
Response · 200 OK
json
{
  "ok": true
}

Reports

Financial reports - payment methods, tax, and AR aging.

Payment method breakdown

GET/invoicing/reports/payment-methods

curl
curl https://zana.norialabs.com/api/v1/invoicing/reports/payment-methods \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "method": "string",
      "count": 0,
      "totalMinor": 500000
    }
  ]
}

Tax report

GET/invoicing/reports/tax

curl
curl https://zana.norialabs.com/api/v1/invoicing/reports/tax \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "taxRate": "string",
      "netMinor": 500000,
      "taxMinor": 500000,
      "grossMinor": 500000,
      "invoiceCount": 0
    }
  ]
}

Export tax

GET/invoicing/reports/tax/export

curl
curl https://zana.norialabs.com/api/v1/invoicing/reports/tax/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Aging report

GET/invoicing/reports/aging

curl
curl https://zana.norialabs.com/api/v1/invoicing/reports/aging \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "customerId": "string",
      "customerName": "Acme Logistics Ltd",
      "current": 0,
      "d30": 0,
      "d60": 0,
      "d90": 0,
      "older": 0,
      "totalMinor": 500000,
      "invoiceCount": 0
    }
  ]
}

Export aging

GET/invoicing/reports/aging/export

curl
curl https://zana.norialabs.com/api/v1/invoicing/reports/aging/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Dashboard

Aggregate metrics and revenue trends.

List dashboard

GET/invoicing/dashboard

curl
curl https://zana.norialabs.com/api/v1/invoicing/dashboard \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "outstanding": 0,
    "overdue": 0,
    "paidThisMonth": 0,
    "customerCount": 0,
    "openInvoiceCount": 0,
    "recent": [
      {
        "id": "string",
        "invoiceNumber": "string",
        "customerName": "Acme Logistics Ltd",
        "status": "active",
        "total": 500000,
        "balanceDue": 500000,
        "currency": "KES",
        "issueDate": "2026-07-06",
        "publicToken": "string",
        "sentAt": null
      }
    ]
  }
}

Invoice stats

GET/invoicing/dashboard/invoice-stats

curl
curl https://zana.norialabs.com/api/v1/invoicing/dashboard/invoice-stats \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "outstanding": 0,
    "overdue": 0,
    "paidThisMonth": 0,
    "customerCount": 0,
    "openInvoiceCount": 0
  }
}

Revenue trend

GET/invoicing/dashboard/trend

curl
curl https://zana.norialabs.com/api/v1/invoicing/dashboard/trend \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "months": [
      {
        "month": "string",
        "invoiced": 0,
        "collected": 0
      }
    ],
    "statusBreakdown": [
      {
        "status": "active",
        "count": 0,
        "amount": 500000
      }
    ]
  }
}

Invoicing settings

Invoicing and disbursement configuration.

Payout channels

GET/invoicing/settings/channels

curl
curl "https://zana.norialabs.com/api/v1/invoicing/settings/channels?category=mobile_money" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "code": "string",
      "name": "Acme Logistics Ltd"
    }
  ]
}

List disbursements

GET/invoicing/settings/disbursements

curl
curl https://zana.norialabs.com/api/v1/invoicing/settings/disbursements \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "enabled": true,
    "makerCheckerRequired": true,
    "approvalThresholdMinor": 500000,
    "dailyLimitMinor": 500000
  }
}

Update disbursement

PUT/invoicing/settings/disbursements

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/invoicing/settings/disbursements \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "makerCheckerRequired": false,
  "approvalThreshold": 0,
  "dailyLimit": 0
}'
Response · 200 OK
json
{
  "ok": true
}

Toggle disbursement

POST/invoicing/settings/disbursements/toggle

idempotent
curl
curl https://zana.norialabs.com/api/v1/invoicing/settings/disbursements/toggle \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true
}'
Response · 200 OK
json
{
  "ok": true
}

Utility Billing

Accounts

Metered service accounts linked to billing customers.

List accounts

GET/utility/accounts

curl
curl "https://zana.norialabs.com/api/v1/utility/accounts?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "account": {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "accountNumber": "string",
        "serviceAddress": null,
        "zoneId": null,
        "routeId": null,
        "category": "domestic",
        "status": "active",
        "openingBalanceMinor": 500000,
        "openingInvoiceId": null,
        "currency": "KES",
        "tariffId": null,
        "serviceStartDate": null,
        "closedAt": null,
        "closerId": null,
        "notes": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z",
        "deletedAt": null,
        "zoneName": null,
        "routeName": null
      },
      "customerName": "Acme Logistics Ltd",
      "meterCount": 0
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create account

POST/utility/accounts

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/accounts \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "accountNumber": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "accountNumber": "string",
    "serviceAddress": "string",
    "zoneId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "routeId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "category": "domestic",
    "status": "active",
    "openingBalanceMinor": 500000,
    "openingInvoiceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "currency": "KES",
    "tariffId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "serviceStartDate": "2026-07-06",
    "closedAt": "2026-07-06T09:00:00.000Z",
    "closerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "notes": "Adjustment",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z",
    "zoneName": "Acme Logistics Ltd",
    "routeName": "Acme Logistics Ltd"
  }
}

Accounts needing attention

GET/utility/accounts/attention

curl
curl https://zana.norialabs.com/api/v1/utility/accounts/attention \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "total": 500000,
    "byReason": {
      "no_contact": 0,
      "no_meter": 0,
      "no_tariff": 0
    },
    "accounts": [
      {
        "id": "string",
        "accountNumber": "string",
        "customerName": "Acme Logistics Ltd",
        "reasons": []
      }
    ]
  }
}

Export accounts

GET/utility/accounts/export

curl
curl https://zana.norialabs.com/api/v1/utility/accounts/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Import accounts

POST/utility/accounts/import

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/accounts/import \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "csv": "string",
  "dataBase64": "string"
}'
Response · 200 OK
json
{
  "data": {
    "created": 0,
    "updated": 0,
    "skipped": [
      {
        "row": 0,
        "message": "string"
      }
    ]
  }
}

Retrieve account

GET/utility/accounts/{id}

curl
curl https://zana.norialabs.com/api/v1/utility/accounts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "account": {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "accountNumber": "string",
      "serviceAddress": null,
      "zoneId": null,
      "routeId": null,
      "category": "domestic",
      "status": "active",
      "openingBalanceMinor": 500000,
      "openingInvoiceId": null,
      "currency": "KES",
      "tariffId": null,
      "serviceStartDate": null,
      "closedAt": null,
      "closerId": null,
      "notes": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null,
      "zoneName": null,
      "routeName": null
    },
    "customerName": "Acme Logistics Ltd",
    "meters": [
      {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "accountId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "meterNumber": "string",
        "status": "active",
        "installedAt": null,
        "location": null,
        "initialReading": null,
        "replacedByMeterId": null,
        "replacedAt": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z",
        "deletedAt": null
      }
    ]
  }
}

Update account

PATCH/utility/accounts/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/utility/accounts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "accountNumber": "string",
  "serviceAddress": "string",
  "zoneId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "accountNumber": "string",
    "serviceAddress": "string",
    "zoneId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "routeId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "category": "domestic",
    "status": "active",
    "openingBalanceMinor": 500000,
    "openingInvoiceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "currency": "KES",
    "tariffId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "serviceStartDate": "2026-07-06",
    "closedAt": "2026-07-06T09:00:00.000Z",
    "closerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "notes": "Adjustment",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z",
    "zoneName": "Acme Logistics Ltd",
    "routeName": "Acme Logistics Ltd"
  }
}

Delete account

DELETE/utility/accounts/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/utility/accounts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Create meter

POST/utility/meters

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/meters \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "accountId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "meterNumber": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "accountId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "meterNumber": "string",
    "status": "active",
    "installedAt": "2026-07-06T09:00:00.000Z",
    "location": "string",
    "initialReading": "string",
    "replacedByMeterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "replacedAt": "2026-07-06T09:00:00.000Z",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Import meters

POST/utility/meters/import

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/meters/import \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "csv": "string",
  "dataBase64": "string"
}'
Response · 200 OK
json
{
  "data": {
    "created": 0,
    "updated": 0,
    "skipped": [
      {
        "row": 0,
        "message": "string"
      }
    ]
  }
}

Update meter

PATCH/utility/meters/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/utility/meters/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "meterNumber": "string",
  "status": "active",
  "installedAt": "string",
  "location": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "accountId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "meterNumber": "string",
    "status": "active",
    "installedAt": "2026-07-06T09:00:00.000Z",
    "location": "string",
    "initialReading": "string",
    "replacedByMeterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "replacedAt": "2026-07-06T09:00:00.000Z",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete meter

DELETE/utility/meters/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/utility/meters/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

List deposits

GET/utility/accounts/{id}/deposits

curl
curl https://zana.norialabs.com/api/v1/utility/accounts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/deposits \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "ownerContactId": null,
      "sourceModule": "string",
      "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "entryType": "charge",
      "amountMinor": 500000,
      "currency": "KES",
      "invoiceId": null,
      "reason": "Adjustment",
      "creatorId": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ]
}

Create deposit

POST/utility/accounts/{id}/deposits

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/accounts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/deposits \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "entryType": "charge",
  "amount": 2,
  "reason": "Adjustment"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "ownerContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "entryType": "charge",
    "amountMinor": 500000,
    "currency": "KES",
    "invoiceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "reason": "Adjustment",
    "creatorId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Close account

POST/utility/accounts/{id}/close

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/accounts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/close \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Adjustment"
}'
Response · 200 OK
json
{
  "data": {
    "account": {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "accountNumber": "string",
      "serviceAddress": null,
      "zoneId": null,
      "routeId": null,
      "category": "domestic",
      "status": "active",
      "openingBalanceMinor": 500000,
      "openingInvoiceId": null,
      "currency": "KES",
      "tariffId": null,
      "serviceStartDate": null,
      "closedAt": null,
      "closerId": null,
      "notes": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null,
      "zoneName": null,
      "routeName": null
    },
    "finalBillMinor": 500000,
    "depositOffsetMinor": 500000,
    "depositRefundDueMinor": 500000
  }
}

Replace meter

POST/utility/meters/{id}/replace

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/meters/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/replace \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "newMeterNumber": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "accountId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "meterNumber": "string",
    "status": "active",
    "installedAt": "2026-07-06T09:00:00.000Z",
    "location": "string",
    "initialReading": "string",
    "replacedByMeterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "replacedAt": "2026-07-06T09:00:00.000Z",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Meter readings

Capture and review meter readings ahead of a billing run.

List readings

GET/utility/readings

curl
curl "https://zana.norialabs.com/api/v1/utility/readings?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "reading": {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "meterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "period": "2026-07",
        "previousReading": null,
        "currentReading": "string",
        "consumption": "string",
        "readingType": "actual",
        "status": "pending",
        "rollover": true,
        "anomaly": null,
        "readAt": null,
        "approverId": null,
        "approvedAt": null,
        "readerId": null,
        "notes": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z"
      },
      "meterNumber": "string",
      "accountId": "string",
      "accountNumber": "string"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create reading

POST/utility/readings

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/readings \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "meterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "period": "2026-07",
  "currentReading": 0
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "meterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "period": "2026-07",
    "previousReading": "string",
    "currentReading": "string",
    "consumption": "string",
    "readingType": "actual",
    "status": "pending",
    "rollover": true,
    "anomaly": "lower_than_previous",
    "readAt": "2026-07-06T09:00:00.000Z",
    "approverId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "approvedAt": "2026-07-06T09:00:00.000Z",
    "readerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "notes": "Adjustment",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Readings capture

GET/utility/readings/capture

curl
curl "https://zana.norialabs.com/api/v1/utility/readings/capture?period=2026-07" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "meterId": "string",
      "meterNumber": "string",
      "accountId": "string",
      "accountNumber": "string",
      "customerName": "Acme Logistics Ltd",
      "zone": null,
      "route": null,
      "previousReading": null,
      "existingReading": null
    }
  ]
}

Create bulk

POST/utility/readings/bulk

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/readings/bulk \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "period": "2026-07",
  "entries": [
    {
      "meterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "currentReading": 0
    }
  ]
}'
Response · 200 OK
json
{
  "data": {
    "created": 0,
    "skipped": [
      {
        "meterId": "string",
        "message": "string"
      }
    ]
  }
}

Capture sheet

GET/utility/readings/capture-sheet

curl
curl https://zana.norialabs.com/api/v1/utility/readings/capture-sheet \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Export readings

GET/utility/readings/export

curl
curl https://zana.norialabs.com/api/v1/utility/readings/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Import readings

POST/utility/readings/import

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/readings/import \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "period": "2026-07"
}'
Response · 200 OK
json
{
  "data": {
    "created": 0,
    "updated": 0,
    "skipped": [
      {
        "row": 0,
        "message": "string"
      }
    ]
  }
}

Review reading

POST/utility/readings/{id}/review

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/readings/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/review \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "decision": "approved"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "meterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "period": "2026-07",
    "previousReading": "string",
    "currentReading": "string",
    "consumption": "string",
    "readingType": "actual",
    "status": "pending",
    "rollover": true,
    "anomaly": "lower_than_previous",
    "readAt": "2026-07-06T09:00:00.000Z",
    "approverId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "approvedAt": "2026-07-06T09:00:00.000Z",
    "readerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "notes": "Adjustment",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Create photo

POST/utility/readings/{id}/photo

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/readings/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/photo \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "contentType": "image/jpeg",
  "dataBase64": "string"
}'
Response · 200 OK
json
{
  "data": {
    "documentId": "string",
    "objectKey": "string"
  }
}

Create recognize

POST/utility/readings/recognize

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/readings/recognize \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "contentType": "image/jpeg",
  "dataBase64": "string"
}'
Response · 200 OK
json
{
  "data": {
    "reading": 0,
    "confidence": 0,
    "meterNumberVisible": "string",
    "meterNumberMatch": true,
    "anomalyHint": "string",
    "model": "string"
  }
}

Tariffs

Tariff structures used to price consumption.

List tariffs

GET/utility/tariffs

curl
curl https://zana.norialabs.com/api/v1/utility/tariffs \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "workspaceId": "string",
      "name": "Acme Logistics Ltd",
      "category": "string",
      "basis": "string",
      "currency": "KES",
      "standingChargeMinor": 500000,
      "minimumChargeMinor": 500000,
      "prorateStandingCharge": true,
      "isDefault": true,
      "bands": [
        {
          "upTo": 0,
          "ratePerUnitMinor": 500000
        }
      ],
      "levies": [
        {
          "name": "Acme Logistics Ltd",
          "mode": "percent",
          "value": 0
        }
      ],
      "effectiveFrom": "string",
      "effectiveTo": null,
      "status": "active",
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ]
}

Create tariff

POST/utility/tariffs

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/tariffs \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "category": "domestic",
  "effectiveFrom": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "workspaceId": "string",
    "name": "Acme Logistics Ltd",
    "category": "string",
    "basis": "string",
    "currency": "KES",
    "standingChargeMinor": 500000,
    "minimumChargeMinor": 500000,
    "prorateStandingCharge": true,
    "isDefault": true,
    "bands": [
      {
        "upTo": 0,
        "ratePerUnitMinor": 500000
      }
    ],
    "levies": [
      {
        "name": "Acme Logistics Ltd",
        "mode": "percent",
        "value": 0
      }
    ],
    "effectiveFrom": "string",
    "effectiveTo": "string",
    "status": "active",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Update tariff

PATCH/utility/tariffs/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/utility/tariffs/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "active"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "workspaceId": "string",
    "name": "Acme Logistics Ltd",
    "category": "string",
    "basis": "string",
    "currency": "KES",
    "standingChargeMinor": 500000,
    "minimumChargeMinor": 500000,
    "prorateStandingCharge": true,
    "isDefault": true,
    "bands": [
      {
        "upTo": 0,
        "ratePerUnitMinor": 500000
      }
    ],
    "levies": [
      {
        "name": "Acme Logistics Ltd",
        "mode": "percent",
        "value": 0
      }
    ],
    "effectiveFrom": "string",
    "effectiveTo": "string",
    "status": "active",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Replace tariff

POST/utility/tariffs/{id}/replace

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/tariffs/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/replace \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "category": "domestic",
  "effectiveFrom": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "workspaceId": "string",
    "name": "Acme Logistics Ltd",
    "category": "string",
    "basis": "string",
    "currency": "KES",
    "standingChargeMinor": 500000,
    "minimumChargeMinor": 500000,
    "prorateStandingCharge": true,
    "isDefault": true,
    "bands": [
      {
        "upTo": 0,
        "ratePerUnitMinor": 500000
      }
    ],
    "levies": [
      {
        "name": "Acme Logistics Ltd",
        "mode": "percent",
        "value": 0
      }
    ],
    "effectiveFrom": "string",
    "effectiveTo": "string",
    "status": "active",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Preview tariff

POST/utility/tariffs/{id}/preview

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/tariffs/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/preview \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "consumption": 0
}'
Response · 200 OK
json
{
  "data": {
    "lines": [
      {
        "description": "string",
        "quantity": 0,
        "unitPriceMinor": 500000,
        "amountMinor": 500000
      }
    ],
    "totalMinor": 500000
  }
}

Billing runs

Generate and post a period's bills across accounts.

List runs

GET/utility/runs

curl
curl https://zana.norialabs.com/api/v1/utility/runs \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "sourceModule": "string",
      "period": "2026-07",
      "scopeType": "string",
      "scopeValue": null,
      "status": "draft",
      "accountCount": 1,
      "calculatedCount": 1,
      "exceptionCount": 1,
      "postedCount": 1,
      "totalAmountMinor": 500000,
      "notes": null,
      "posterId": null,
      "postedAt": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "scopeLabel": null
    }
  ]
}

Create run

POST/utility/runs

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/runs \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "period": "2026-07"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "period": "2026-07",
    "scopeType": "string",
    "scopeValue": "string",
    "status": "draft",
    "accountCount": 1,
    "calculatedCount": 1,
    "exceptionCount": 1,
    "postedCount": 1,
    "totalAmountMinor": 500000,
    "notes": "Adjustment",
    "posterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "postedAt": "2026-07-06T09:00:00.000Z",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "scopeLabel": "string"
  }
}

Retrieve run

GET/utility/runs/{id}

curl
curl https://zana.norialabs.com/api/v1/utility/runs/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "run": {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "sourceModule": "string",
      "period": "2026-07",
      "scopeType": "string",
      "scopeValue": null,
      "status": "draft",
      "accountCount": 1,
      "calculatedCount": 1,
      "exceptionCount": 1,
      "postedCount": 1,
      "totalAmountMinor": 500000,
      "notes": null,
      "posterId": null,
      "postedAt": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "scopeLabel": null
    },
    "items": [
      {
        "id": "string",
        "runId": "string",
        "accountId": "string",
        "tariffId": null,
        "consumption": "string",
        "amountMinor": 500000,
        "breakdown": {
          "readings": [],
          "tariffId": null,
          "tariffName": "Acme Logistics Ltd",
          "consumption": 0,
          "currency": "KES",
          "lines": []
        },
        "status": "active",
        "exceptionCode": null,
        "exceptionMessage": null,
        "invoiceId": null,
        "accountNumber": "string",
        "customerName": "Acme Logistics Ltd"
      }
    ]
  }
}

Export items

GET/utility/runs/{id}/items/export

curl
curl https://zana.norialabs.com/api/v1/utility/runs/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/items/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Calculate run

POST/utility/runs/{id}/calculate

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/runs/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/calculate \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "period": "2026-07",
    "scopeType": "string",
    "scopeValue": "string",
    "status": "draft",
    "accountCount": 1,
    "calculatedCount": 1,
    "exceptionCount": 1,
    "postedCount": 1,
    "totalAmountMinor": 500000,
    "notes": "Adjustment",
    "posterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "postedAt": "2026-07-06T09:00:00.000Z",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "scopeLabel": "string"
  }
}

Post run

POST/utility/runs/{id}/post

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/runs/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/post \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "period": "2026-07",
    "scopeType": "string",
    "scopeValue": "string",
    "status": "draft",
    "accountCount": 1,
    "calculatedCount": 1,
    "exceptionCount": 1,
    "postedCount": 1,
    "totalAmountMinor": 500000,
    "notes": "Adjustment",
    "posterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "postedAt": "2026-07-06T09:00:00.000Z",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "scopeLabel": "string"
  }
}

Send bills for run

POST/utility/runs/{id}/send-bills

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/runs/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/send-bills \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "accounts": 0,
    "emailsSent": 0,
    "emailsSkipped": 0,
    "smsSent": 0,
    "whatsappSent": 0,
    "errors": [
      "string"
    ]
  }
}

Void run

POST/utility/runs/{id}/void

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/runs/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/void \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "period": "2026-07",
    "scopeType": "string",
    "scopeValue": "string",
    "status": "draft",
    "accountCount": 1,
    "calculatedCount": 1,
    "exceptionCount": 1,
    "postedCount": 1,
    "totalAmountMinor": 500000,
    "notes": "Adjustment",
    "posterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "postedAt": "2026-07-06T09:00:00.000Z",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "scopeLabel": "string"
  }
}

Collections

Chase overdue balances over SMS and WhatsApp.

Get statement

GET/utility/accounts/{id}/statement

curl
curl https://zana.norialabs.com/api/v1/utility/accounts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/statement \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "account": {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "accountNumber": "string",
      "serviceAddress": null,
      "zoneId": null,
      "routeId": null,
      "category": "domestic",
      "status": "active",
      "openingBalanceMinor": 500000,
      "openingInvoiceId": null,
      "currency": "KES",
      "tariffId": null,
      "serviceStartDate": null,
      "closedAt": null,
      "closerId": null,
      "notes": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null,
      "zoneName": null,
      "routeName": null
    },
    "customerName": "Acme Logistics Ltd",
    "balanceDueMinor": 500000,
    "creditMinor": 500000,
    "depositMinor": 500000,
    "entries": [
      {
        "invoice": {
          "id": "string",
          "invoiceNumber": "string",
          "status": "active",
          "total": 500000,
          "amountPaid": 500000,
          "balanceDue": 500000,
          "issueDate": "2026-07-06",
          "publicToken": null
        },
        "period": null,
        "isOpeningBalance": true,
        "payments": []
      }
    ]
  }
}

Summary

GET/utility/collections/summary

curl
curl https://zana.norialabs.com/api/v1/utility/collections/summary \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "totalOutstandingMinor": 500000,
    "accountsInArrears": 0,
    "current": 0,
    "d30": 0,
    "d60": 0,
    "d90": 0,
    "older": 0,
    "collected30Minor": 500000,
    "billed30Minor": 500000,
    "collectionRate": 0
  }
}

Debtors

GET/utility/collections/debtors

curl
curl "https://zana.norialabs.com/api/v1/utility/collections/debtors?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "accountId": "string",
      "accountNumber": "string",
      "customerName": "Acme Logistics Ltd",
      "zone": null,
      "route": null,
      "status": "active",
      "outstandingMinor": 500000,
      "overdueMinor": 500000,
      "oldestIssueDate": null,
      "daysOverdue": 0
    }
  ],
  "total": 500000
}

Export debtors

GET/utility/collections/debtors/export

curl
curl https://zana.norialabs.com/api/v1/utility/collections/debtors/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Aging report

GET/utility/collections/aging

curl
curl https://zana.norialabs.com/api/v1/utility/collections/aging \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "group": "string",
      "current": 0,
      "d30": 0,
      "d60": 0,
      "d90": 0,
      "older": 0,
      "totalMinor": 500000,
      "accounts": 0
    }
  ]
}

Export aging

GET/utility/collections/aging/export

curl
curl https://zana.norialabs.com/api/v1/utility/collections/aging/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Disconnection list

GET/utility/collections/disconnection-list

curl
curl https://zana.norialabs.com/api/v1/utility/collections/disconnection-list \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "accountId": "string",
      "accountNumber": "string",
      "customerName": "Acme Logistics Ltd",
      "zone": null,
      "route": null,
      "status": "active",
      "overdueMinor": 500000,
      "oldestIssueDate": null
    }
  ]
}

Export disconnection list

GET/utility/collections/disconnection-list/export

curl
curl https://zana.norialabs.com/api/v1/utility/collections/disconnection-list/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Outstanding balances

GET/utility/collections/outstanding

curl
curl "https://zana.norialabs.com/api/v1/utility/collections/outstanding?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "invoiceId": "string",
      "accountId": "string",
      "accountNumber": "string",
      "customerName": "Acme Logistics Ltd",
      "hasPhone": true,
      "hasEmail": true,
      "balanceMinor": 500000,
      "currency": "KES",
      "dueDate": null,
      "status": "pending"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string"
  }
}

Preview reminder

POST/utility/collections/reminders/preview

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/collections/reminders/preview \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "channels": [
    "sms"
  ],
  "templateKey": "utility_overdue"
}'
Response · 200 OK
json
{
  "data": {
    "invoiceCount": 0,
    "recipientsWithPhone": 0,
    "channels": [
      {
        "channel": "sms",
        "fundingMode": "platform",
        "enabled": true,
        "messages": 0,
        "units": 0,
        "costMinor": 500000,
        "balanceMinor": 500000,
        "balanceUnits": 500000,
        "sufficient": true,
        "shortfallMinor": 500000,
        "shortfallUnits": 0,
        "sampleBody": null,
        "sampleUnits": 0
      }
    ],
    "canSend": true,
    "truncated": true
  }
}

Send reminder

POST/utility/collections/reminders/send

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/collections/reminders/send \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "channels": [
    "sms"
  ],
  "templateKey": "utility_overdue"
}'
Response · 200 OK
json
{
  "data": {
    "sent": 0,
    "failed": 0,
    "skipped": [
      "string"
    ]
  }
}

Create payment

POST/utility/accounts/{id}/payments

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/accounts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/payments \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "amount": 2
}'
Response · 200 OK
json
{
  "data": {
    "paymentId": "string",
    "receiptNumber": "string",
    "allocatedMinor": 500000,
    "creditMinor": 500000
  }
}

Operations

Penalties, adjustments, and service orders.

List penalty rules

GET/utility/penalty-rules

curl
curl https://zana.norialabs.com/api/v1/utility/penalty-rules \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "name": "Acme Logistics Ltd",
      "graceDays": 1,
      "mode": "fixed",
      "value": "string",
      "capMinor": 500000,
      "minimumBalanceMinor": 500000,
      "status": "active",
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ]
}

Create penalty rule

POST/utility/penalty-rules

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/penalty-rules \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "mode": "fixed",
  "value": 0
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "graceDays": 1,
    "mode": "fixed",
    "value": "string",
    "capMinor": 500000,
    "minimumBalanceMinor": 500000,
    "status": "active",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Update penalty rule

PATCH/utility/penalty-rules/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/utility/penalty-rules/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "graceDays": 30,
  "mode": "fixed",
  "value": 0
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "graceDays": 1,
    "mode": "fixed",
    "value": "string",
    "capMinor": 500000,
    "minimumBalanceMinor": 500000,
    "status": "active",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Apply penalty

POST/utility/penalties/apply

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/penalties/apply \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "period": "2026-07"
}'
Response · 200 OK
json
{
  "data": {
    "created": 0,
    "skipped": 0,
    "totalMinor": 500000
  }
}

List adjustments

GET/utility/adjustments

curl
curl https://zana.norialabs.com/api/v1/utility/adjustments \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "adjustment": {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "ownerContactId": null,
        "sourceModule": "string",
        "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "type": "debit",
        "status": "draft",
        "amountMinor": 500000,
        "currency": "KES",
        "period": null,
        "reason": "Adjustment",
        "invoiceId": null,
        "penaltyRuleId": null,
        "creatorId": null,
        "posterId": null,
        "postedAt": null,
        "voiderId": null,
        "voidedAt": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z"
      },
      "accountNumber": "string",
      "customerName": "Acme Logistics Ltd"
    }
  ]
}

Create adjustment

POST/utility/adjustments

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/adjustments \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "accountId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "type": "debit",
  "amount": 2,
  "reason": "Adjustment"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "ownerContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "type": "debit",
    "status": "draft",
    "amountMinor": 500000,
    "currency": "KES",
    "period": "2026-07",
    "reason": "Adjustment",
    "invoiceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "penaltyRuleId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "creatorId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "posterId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "postedAt": "2026-07-06T09:00:00.000Z",
    "voiderId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "voidedAt": "2026-07-06T09:00:00.000Z",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

List service orders

GET/utility/service-orders

curl
curl https://zana.norialabs.com/api/v1/utility/service-orders \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "order": {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "ownerContactId": null,
        "sourceModule": "string",
        "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "type": "string",
        "status": "active",
        "priority": "string",
        "reason": "Adjustment",
        "assigneeId": null,
        "vendorContactId": null,
        "scheduledFor": null,
        "completedAt": null,
        "completerId": null,
        "cancellationReason": null,
        "creatorId": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z"
      },
      "accountNumber": "string",
      "customerName": "Acme Logistics Ltd"
    }
  ]
}

Create service order

POST/utility/service-orders

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/service-orders \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "accountId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "type": "disconnect",
  "reason": "Adjustment"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "ownerContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "type": "string",
    "status": "active",
    "priority": "string",
    "reason": "Adjustment",
    "assigneeId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "vendorContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "scheduledFor": "2026-07-06T09:00:00.000Z",
    "completedAt": "2026-07-06T09:00:00.000Z",
    "completerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "cancellationReason": "Adjustment",
    "creatorId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Update service order

PATCH/utility/service-orders/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/utility/service-orders/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "open"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "ownerContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "type": "string",
    "status": "active",
    "priority": "string",
    "reason": "Adjustment",
    "assigneeId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "vendorContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "scheduledFor": "2026-07-06T09:00:00.000Z",
    "completedAt": "2026-07-06T09:00:00.000Z",
    "completerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "cancellationReason": "Adjustment",
    "creatorId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Bulk disconnect service order

POST/utility/service-orders/bulk-disconnect

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/service-orders/bulk-disconnect \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "minDays": 1,
  "minBalance": 500000,
  "assigneeId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
}'
Response · 200 OK
json
{
  "data": {
    "created": 0,
    "skipped": 0
  }
}

Zones & routes

Zones and routes that organize accounts geographically.

List zones

GET/utility/zones

curl
curl https://zana.norialabs.com/api/v1/utility/zones \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "name": "Acme Logistics Ltd",
      "accountCount": 0,
      "routes": [
        {
          "id": "string",
          "name": "Acme Logistics Ltd",
          "accountCount": 0
        }
      ]
    }
  ]
}

Create zone

POST/utility/zones

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/zones \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Summary

GET/utility/zones/summary

curl
curl https://zana.norialabs.com/api/v1/utility/zones/summary \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "totalAccounts": 500000,
    "unzonedAccounts": 0,
    "unroutedAccounts": 0
  }
}

Update zone

PATCH/utility/zones/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/utility/zones/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete zone

DELETE/utility/zones/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/utility/zones/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Create route

POST/utility/zones/{zoneId}/routes

idempotent
curl
curl https://zana.norialabs.com/api/v1/utility/zones/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/routes \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "zoneId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Update route

PATCH/utility/routes/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/utility/routes/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "zoneId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete route

DELETE/utility/routes/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/utility/routes/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Analytics

Utility stats, trends, and reports.

Invoice stats

GET/utility/dashboard/invoice-stats

curl
curl https://zana.norialabs.com/api/v1/utility/dashboard/invoice-stats \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "outstanding": 0,
    "overdue": 0,
    "paidThisMonth": 0,
    "customerCount": 0,
    "openInvoiceCount": 0
  }
}

Revenue trend

GET/utility/dashboard/trend

curl
curl https://zana.norialabs.com/api/v1/utility/dashboard/trend \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "months": [
      {
        "month": "string",
        "invoiced": 0,
        "collected": 0
      }
    ],
    "statusBreakdown": [
      {
        "status": "active",
        "count": 0,
        "amount": 500000
      }
    ]
  }
}

Payment method breakdown

GET/utility/reports/payment-methods

curl
curl https://zana.norialabs.com/api/v1/utility/reports/payment-methods \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "method": "string",
      "count": 0,
      "totalMinor": 500000
    }
  ]
}

Tax report

GET/utility/reports/tax

curl
curl https://zana.norialabs.com/api/v1/utility/reports/tax \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "taxRate": "string",
      "netMinor": 500000,
      "taxMinor": 500000,
      "grossMinor": 500000,
      "invoiceCount": 0
    }
  ]
}

Export tax

GET/utility/reports/tax/export

curl
curl https://zana.norialabs.com/api/v1/utility/reports/tax/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Utility settings

Utility billing configuration.

List settings

GET/utility/settings

curl
curl https://zana.norialabs.com/api/v1/utility/settings \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "autoCreateRuns": true,
    "billingDay": 0,
    "autoApplyPenalties": true,
    "penaltyApplyDay": 0,
    "autoSendBills": true,
    "autoApplyCredit": true,
    "connectionFeeMinor": 500000,
    "reconnectionFeeMinor": 500000,
    "defaultDepositMinor": 500000,
    "disconnectAfterDays": 0,
    "disconnectMinBalanceMinor": 500000
  }
}

Update setting

PUT/utility/settings

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/utility/settings \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "autoCreateRuns": true,
  "billingDay": 1,
  "autoApplyPenalties": true,
  "penaltyApplyDay": 1
}'
Response · 200 OK
json
{
  "data": {
    "autoCreateRuns": true,
    "billingDay": 0,
    "autoApplyPenalties": true,
    "penaltyApplyDay": 0,
    "autoSendBills": true,
    "autoApplyCredit": true,
    "connectionFeeMinor": 500000,
    "reconnectionFeeMinor": 500000,
    "defaultDepositMinor": 500000,
    "disconnectAfterDays": 0,
    "disconnectMinBalanceMinor": 500000
  }
}

Utility invoices

Invoices posted by utility billing runs.

List invoices

GET/utility/invoices

curl
curl "https://zana.norialabs.com/api/v1/utility/invoices?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "invoice": {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "recurringInvoiceId": null,
        "sourceModule": "invoicing",
        "invoiceNumber": "string",
        "invoiceCode": null,
        "status": "draft",
        "currency": "KES",
        "subtotal": 500000,
        "taxTotal": 500000,
        "total": 500000,
        "amountPaid": 500000,
        "amountCredited": 500000,
        "balanceDue": 500000,
        "issueDate": "2026-07-06",
        "dueDate": null,
        "publicToken": "string",
        "allowedChannels": null,
        "allowedProviders": null,
        "notes": null,
        "pdfObjectKey": null,
        "sentAt": null,
        "writtenOffAt": null,
        "writtenOffReason": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z",
        "deletedAt": null
      },
      "customerName": null
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Export invoices

GET/utility/invoices/export

curl
curl https://zana.norialabs.com/api/v1/utility/invoices/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Utility payments

Payments received against utility accounts.

List payments

GET/utility/payments

curl
curl "https://zana.norialabs.com/api/v1/utility/payments?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "payment": {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "invoiceId": null,
        "paymentLinkId": null,
        "utilityAccountId": null,
        "customerId": null,
        "sourceModule": "invoicing",
        "payerName": null,
        "payerPhone": null,
        "payerEmail": null,
        "amount": 500000,
        "feeAmount": 500000,
        "currency": "KES",
        "method": "mpesa_sasapay",
        "paymentInstructionId": null,
        "status": "pending",
        "channel": null,
        "paidAt": null,
        "receiptNumber": null,
        "receiptPdfObjectKey": null,
        "providerTxnCode": null,
        "failureReason": null,
        "note": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z",
        "deletedAt": null
      },
      "invoiceNumber": null,
      "customerName": null,
      "linkTitle": null,
      "instructionLabel": null,
      "instructionKind": null
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Export payments

GET/utility/payments/export

curl
curl https://zana.norialabs.com/api/v1/utility/payments/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

CRM

Contacts

Your shared party directory of people and organizations.

List contacts

GET/contacts

curl
curl "https://zana.norialabs.com/api/v1/contacts?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "name": "Acme Logistics Ltd",
      "phone": "+254720123456",
      "email": null,
      "whatsappPhone": null,
      "externalRef": null,
      "source": "string",
      "kind": "string",
      "ownerUserId": null,
      "linkedCustomer": {
        "id": "string",
        "name": "Acme Logistics Ltd"
      },
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create contact

POST/contacts

idempotent
curl
curl https://zana.norialabs.com/api/v1/contacts \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "phone": "+254720123456"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "phone": "+254720123456",
    "email": "string",
    "whatsappPhone": "+254720123456",
    "externalRef": "string",
    "source": "string",
    "kind": "string",
    "ownerUserId": "string",
    "linkedCustomer": {
      "id": "string",
      "name": "Acme Logistics Ltd"
    },
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Export contacts

GET/contacts/export

curl
curl https://zana.norialabs.com/api/v1/contacts/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Retrieve contact

GET/contacts/{id}

curl
curl https://zana.norialabs.com/api/v1/contacts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "phone": "+254720123456",
    "email": "string",
    "whatsappPhone": "+254720123456",
    "externalRef": "string",
    "source": "string",
    "kind": "string",
    "ownerUserId": "string",
    "linkedCustomer": {
      "id": "string",
      "name": "Acme Logistics Ltd"
    },
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Update contact

PUT/contacts/{id}

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/contacts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "phone": "+254720123456"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "phone": "+254720123456",
    "email": "string",
    "whatsappPhone": "+254720123456",
    "externalRef": "string",
    "source": "string",
    "kind": "string",
    "ownerUserId": "string",
    "linkedCustomer": {
      "id": "string",
      "name": "Acme Logistics Ltd"
    },
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete contact

DELETE/contacts/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/contacts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Overview

GET/contacts/{id}/overview

curl
curl https://zana.norialabs.com/api/v1/contacts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/overview \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "contact": {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "name": "Acme Logistics Ltd",
      "phone": "+254720123456",
      "email": null,
      "whatsappPhone": null,
      "externalRef": null,
      "source": "string",
      "kind": "string",
      "ownerUserId": null,
      "linkedCustomer": {
        "id": "string",
        "name": "Acme Logistics Ltd"
      },
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    },
    "owner": {
      "id": "string",
      "name": "Acme Logistics Ltd"
    },
    "linkedCustomers": [
      {
        "id": "string",
        "name": "Acme Logistics Ltd"
      }
    ],
    "ledger": {
      "invoiceCount": 0,
      "totalBilled": 500000,
      "totalPaid": 500000,
      "totalOutstanding": 500000,
      "currency": null
    },
    "pipeline": [
      {
        "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "applicantContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
        "sourceModule": null,
        "sourceId": null,
        "status": "new",
        "pipeline": null,
        "expectedValueMinor": 500000,
        "convertedModule": null,
        "convertedId": null,
        "notes": null,
        "metadata": null,
        "createdAt": "2026-07-06T09:00:00.000Z",
        "updatedAt": "2026-07-06T09:00:00.000Z",
        "deletedAt": null
      }
    ],
    "consent": {
      "optOuts": [
        {
          "channel": "string",
          "recipient": "string"
        }
      ]
    },
    "links": [
      {
        "linkedModuleKey": "string",
        "linkedRecordId": "string"
      }
    ],
    "customFields": [
      {
        "key": "string",
        "label": "string",
        "fieldType": "string",
        "value": "string"
      }
    ],
    "counts": {
      "openTasks": 0,
      "activities": 0,
      "relationships": 0,
      "links": 0
    }
  }
}

Import from customers: contact

POST/contacts/import-from-customers

idempotent
curl
curl https://zana.norialabs.com/api/v1/contacts/import-from-customers \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "targetGroupId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "newGroupName": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "created": [
      {
        "contactId": "string",
        "customerId": "string"
      }
    ],
    "skipped": [
      "string"
    ],
    "groupId": "string"
  }
}

Convert to customer: contact

POST/contacts/{id}/convert-to-customer

idempotent
curl
curl https://zana.norialabs.com/api/v1/contacts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/convert-to-customer \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "customerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
}'
Response · 200 OK
json
{
  "data": {
    "status": "already_linked",
    "customerId": "string",
    "candidates": [
      {
        "id": "string",
        "name": "Acme Logistics Ltd",
        "phone": null
      }
    ],
    "reason": "Adjustment"
  }
}

Bulk convert to customers: contact

POST/contacts/convert-to-customers

idempotent
curl
curl https://zana.norialabs.com/api/v1/contacts/convert-to-customers \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "groupId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
}'
Response · 200 OK
json
{
  "data": {
    "created": 0,
    "linked": 0,
    "alreadyLinked": 0,
    "skipped": [
      {
        "contactId": "string",
        "reason": "Adjustment"
      }
    ]
  }
}

Segments

Saved audiences of contacts, static or rule-based.

List segments

GET/segments

curl
curl "https://zana.norialabs.com/api/v1/segments?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "name": "Acme Logistics Ltd",
      "description": null,
      "criteria": {
        "match": "all",
        "conditions": []
      },
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create segment

POST/segments

idempotent
curl
curl https://zana.norialabs.com/api/v1/segments \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "description": "string",
    "criteria": {
      "match": "all",
      "conditions": [
        {
          "field": "name",
          "op": "eq",
          "value": "string"
        }
      ]
    },
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Retrieve segment

GET/segments/{id}

curl
curl https://zana.norialabs.com/api/v1/segments/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "description": "string",
    "criteria": {
      "match": "all",
      "conditions": [
        {
          "field": "name",
          "op": "eq",
          "value": "string"
        }
      ]
    },
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  },
  "members": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "name": "Acme Logistics Ltd",
      "phone": "+254720123456",
      "email": null,
      "whatsappPhone": null,
      "externalRef": null,
      "source": "string",
      "kind": "string",
      "ownerUserId": null,
      "linkedCustomer": {
        "id": "string",
        "name": "Acme Logistics Ltd"
      },
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ]
}

Update segment

PUT/segments/{id}

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/segments/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "description": "string",
    "criteria": {
      "match": "all",
      "conditions": [
        {
          "field": "name",
          "op": "eq",
          "value": "string"
        }
      ]
    },
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete segment

DELETE/segments/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/segments/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Create member

POST/segments/{id}/members

idempotent
curl
curl https://zana.norialabs.com/api/v1/segments/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/members \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "contactIds": [
    "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
  ]
}'
Response · 200 OK
json
{
  "data": [
    "string"
  ]
}

Import members

POST/segments/{id}/members/import

idempotent
curl
curl https://zana.norialabs.com/api/v1/segments/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/members/import \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "csv": "string",
  "dataBase64": "string"
}'
Response · 200 OK
json
{
  "data": {
    "created": 0,
    "updated": 0,
    "skipped": [
      {
        "row": 0,
        "message": "string"
      }
    ]
  }
}

Delete member

DELETE/segments/{id}/members/{contactId}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/segments/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/members/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Opt-outs

Contacts who have opted out of messaging.

List opt outs

GET/opt-outs

curl
curl "https://zana.norialabs.com/api/v1/opt-outs?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "channel": "sms",
      "recipient": "string",
      "topic": "all",
      "reason": null,
      "source": "manual",
      "createdAt": "2026-07-06T09:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create opt out

POST/opt-outs

idempotent
curl
curl https://zana.norialabs.com/api/v1/opt-outs \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "channel": "sms",
  "recipient": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "channel": "sms",
    "recipient": "string",
    "topic": "all",
    "reason": "Adjustment",
    "source": "manual",
    "createdAt": "2026-07-06T09:00:00.000Z"
  }
}

Export opt outs

GET/opt-outs/export

curl
curl https://zana.norialabs.com/api/v1/opt-outs/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Delete opt out

DELETE/opt-outs/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/opt-outs/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Activities

Logged interactions and tasks against contacts.

List activities

GET/activities

curl
curl "https://zana.norialabs.com/api/v1/activities?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "type": "note",
      "subject": null,
      "body": null,
      "status": null,
      "dueAt": null,
      "completedAt": null,
      "sourceModule": null,
      "sourceId": null,
      "actorUserId": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create activity

POST/activities

idempotent
curl
curl https://zana.norialabs.com/api/v1/activities \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "type": "note"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "type": "note",
    "subject": "string",
    "body": "string",
    "status": "open",
    "dueAt": "2026-07-06T09:00:00.000Z",
    "completedAt": "2026-07-06T09:00:00.000Z",
    "sourceModule": "string",
    "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "actorUserId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Update activity

PATCH/activities/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/activities/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "subject": "string",
  "body": "string",
  "status": "open",
  "dueAt": "2026-07-06T09:00:00.000Z"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "type": "note",
    "subject": "string",
    "body": "string",
    "status": "open",
    "dueAt": "2026-07-06T09:00:00.000Z",
    "completedAt": "2026-07-06T09:00:00.000Z",
    "sourceModule": "string",
    "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "actorUserId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete activity

DELETE/activities/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/activities/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Relationships

Links between contacts (e.g. employer, spouse).

List relationships

GET/contacts/{id}/relationships

curl
curl https://zana.norialabs.com/api/v1/contacts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/relationships \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "relatedContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "relationship": "employee_of",
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null,
      "contact": {
        "id": "string",
        "name": "Acme Logistics Ltd"
      },
      "relatedContact": {
        "id": "string",
        "name": "Acme Logistics Ltd"
      }
    }
  ]
}

Create relationship

POST/contacts/{id}/relationships

idempotent
curl
curl https://zana.norialabs.com/api/v1/contacts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/relationships \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "relatedContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "relationship": "employee_of"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "relatedContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "relationship": "employee_of",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete relationship

DELETE/contacts/{id}/relationships/{relId}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/contacts/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/relationships/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Prospects

Your sales / application pipeline.

List prospects

GET/prospects

curl
curl "https://zana.norialabs.com/api/v1/prospects?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "applicantContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "sourceModule": null,
      "sourceId": null,
      "status": "new",
      "pipeline": null,
      "expectedValueMinor": 500000,
      "convertedModule": null,
      "convertedId": null,
      "notes": null,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z",
      "deletedAt": null
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create prospect

POST/prospects

idempotent
curl
curl https://zana.norialabs.com/api/v1/prospects \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "applicantContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "applicantContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "status": "new",
    "pipeline": "string",
    "expectedValueMinor": 500000,
    "convertedModule": "string",
    "convertedId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "notes": "Adjustment",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Update prospect

PATCH/prospects/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/prospects/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "new",
  "pipeline": "string",
  "expectedValueMinor": 500000,
  "notes": "Adjustment"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "applicantContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "status": "new",
    "pipeline": "string",
    "expectedValueMinor": 500000,
    "convertedModule": "string",
    "convertedId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "notes": "Adjustment",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Convert prospect

POST/prospects/{id}/convert

idempotent
curl
curl https://zana.norialabs.com/api/v1/prospects/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/convert \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "resolveCustomerId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "applicantContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "status": "new",
    "pipeline": "string",
    "expectedValueMinor": 500000,
    "convertedModule": "string",
    "convertedId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "notes": "Adjustment",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  },
  "convertedModule": "string",
  "convertedId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "accountId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
}

Drop prospect

POST/prospects/{id}/drop

idempotent
curl
curl https://zana.norialabs.com/api/v1/prospects/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/drop \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "rejected"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "applicantContactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "sourceModule": "string",
    "sourceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "status": "new",
    "pipeline": "string",
    "expectedValueMinor": 500000,
    "convertedModule": "string",
    "convertedId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "notes": "Adjustment",
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z",
    "deletedAt": "2026-07-06T09:00:00.000Z"
  }
}

Custom fields

Custom field definitions for contacts.

List custom fields

GET/custom-fields

curl
curl https://zana.norialabs.com/api/v1/custom-fields \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "entity": "string",
      "key": "string",
      "label": "string",
      "fieldType": "string",
      "options": null,
      "required": true,
      "sortOrder": 1,
      "active": true,
      "metadata": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ]
}

Create custom field

POST/custom-fields

idempotent
curl
curl https://zana.norialabs.com/api/v1/custom-fields \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "entity": "contact",
  "key": "string",
  "label": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "entity": "string",
    "key": "string",
    "label": "string",
    "fieldType": "string",
    "options": "string",
    "required": true,
    "sortOrder": 1,
    "active": true,
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Update custom field

PATCH/custom-fields/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/custom-fields/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "label": "string",
  "fieldType": "text",
  "required": true,
  "sortOrder": 1
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "workspaceId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "entity": "string",
    "key": "string",
    "label": "string",
    "fieldType": "string",
    "options": "string",
    "required": true,
    "sortOrder": 1,
    "active": true,
    "metadata": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete custom field

DELETE/custom-fields/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/custom-fields/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Inbox · Conversations

Shared inbox conversations.

List conversations

GET/inbox/conversations

curl
curl "https://zana.norialabs.com/api/v1/inbox/conversations?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "contactName": "Acme Logistics Ltd",
      "contactPhone": "+254720123456",
      "channel": "whatsapp",
      "status": "open",
      "assignedUserId": null,
      "unreadCount": 0,
      "lastMessagePreview": null,
      "lastMessageAt": null,
      "lastInboundAt": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Unread count

GET/inbox/unread-count

curl
curl https://zana.norialabs.com/api/v1/inbox/unread-count \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "unread": 0
  }
}

Retrieve conversation

GET/inbox/conversations/{id}

curl
curl https://zana.norialabs.com/api/v1/inbox/conversations/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "contactName": "Acme Logistics Ltd",
    "contactPhone": "+254720123456",
    "channel": "whatsapp",
    "status": "open",
    "assignedUserId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "unreadCount": 0,
    "lastMessagePreview": "string",
    "lastMessageAt": "string",
    "lastInboundAt": "string",
    "createdAt": "string",
    "updatedAt": "string"
  }
}

Update conversation

PATCH/inbox/conversations/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/inbox/conversations/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "assignedUserId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
  "status": "open",
  "markRead": true
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "contactId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "contactName": "Acme Logistics Ltd",
    "contactPhone": "+254720123456",
    "channel": "whatsapp",
    "status": "open",
    "assignedUserId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "unreadCount": 0,
    "lastMessagePreview": "string",
    "lastMessageAt": "string",
    "lastInboundAt": "string",
    "createdAt": "string",
    "updatedAt": "string"
  }
}

Inbox · Messages

Messages within inbox conversations.

List messages

GET/inbox/conversations/{id}/messages

curl
curl "https://zana.norialabs.com/api/v1/inbox/conversations/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/messages?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "conversationId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "channel": "whatsapp",
      "direction": "inbound",
      "senderUserId": null,
      "contentType": "text",
      "body": null,
      "mediaKey": null,
      "mediaMime": null,
      "mediaFilename": null,
      "templateName": null,
      "replyToMessageId": null,
      "interactiveReplyId": null,
      "providerMessageId": null,
      "status": "pending",
      "errorDetail": null,
      "replyToBody": null,
      "reactions": [
        {
          "emoji": "string",
          "actorType": "customer"
        }
      ],
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create message

POST/inbox/conversations/{id}/messages

idempotent
curl
curl https://zana.norialabs.com/api/v1/inbox/conversations/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/messages \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "body": "string",
  "templateName": "Acme Logistics Ltd",
  "templateLanguage": "string",
  "replyToMessageId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
}'
Response · 201 Created
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "conversationId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "channel": "whatsapp",
    "direction": "inbound",
    "senderUserId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "contentType": "text",
    "body": "string",
    "mediaKey": "string",
    "mediaMime": "string",
    "mediaFilename": "Acme Logistics Ltd",
    "templateName": "Acme Logistics Ltd",
    "replyToMessageId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "interactiveReplyId": "string",
    "providerMessageId": "string",
    "status": "pending",
    "errorDetail": "string",
    "replyToBody": "string",
    "reactions": [
      {
        "emoji": "string",
        "actorType": "customer"
      }
    ],
    "createdAt": "string",
    "updatedAt": "string"
  }
}

React to message

POST/inbox/conversations/{id}/messages/{messageId}/reactions

idempotent
curl
curl https://zana.norialabs.com/api/v1/inbox/conversations/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/messages/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/reactions \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "emoji": "string"
}'
Response · 204 No Content
No response body.

Create attachment

POST/inbox/conversations/{id}/attachments

idempotent
curl
curl https://zana.norialabs.com/api/v1/inbox/conversations/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/attachments \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 201 Created
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "conversationId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "channel": "whatsapp",
    "direction": "inbound",
    "senderUserId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "contentType": "text",
    "body": "string",
    "mediaKey": "string",
    "mediaMime": "string",
    "mediaFilename": "Acme Logistics Ltd",
    "templateName": "Acme Logistics Ltd",
    "replyToMessageId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "interactiveReplyId": "string",
    "providerMessageId": "string",
    "status": "pending",
    "errorDetail": "string",
    "replyToBody": "string",
    "reactions": [
      {
        "emoji": "string",
        "actorType": "customer"
      }
    ],
    "createdAt": "string",
    "updatedAt": "string"
  }
}

Campaigns

Bulk SMS and WhatsApp campaigns.

Estimate cost for campaign

POST/engage/campaigns/estimate-cost

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/campaigns/estimate-cost \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "channel": "sms",
  "audienceType": "group"
}'
Response · 200 OK
json
{
  "data": {
    "recipientCount": 0,
    "optedOutCount": 0,
    "invalidCount": 0,
    "skippedCount": 0,
    "smsSegments": 0,
    "unitPrice": 500000,
    "estimatedCost": 0,
    "smsUnitsNeeded": 0,
    "smsUnitsBalance": 500000,
    "recipientsRemaining": 0,
    "quotaOk": true,
    "quotaError": "string",
    "testRequired": true
  }
}

List campaigns

GET/engage/campaigns

curl
curl "https://zana.norialabs.com/api/v1/engage/campaigns?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "name": "Acme Logistics Ltd",
      "channel": "sms",
      "status": "draft",
      "audienceType": "string",
      "audienceConfig": {
        "groupIds": [],
        "manualRecipients": [],
        "variableDefaults": {}
      },
      "templateId": null,
      "body": null,
      "recipientCount": 0,
      "optedOutCount": 0,
      "sentCount": 0,
      "deliveredCount": 0,
      "failedCount": 0,
      "estimatedCost": null,
      "scheduledAt": null,
      "startedAt": null,
      "testSentAt": null,
      "completedAt": null,
      "creatorId": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create campaign

POST/engage/campaigns

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/campaigns \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "channel": "sms",
  "audienceType": "group"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "channel": "sms",
    "status": "draft",
    "audienceType": "string",
    "audienceConfig": {
      "groupIds": [
        "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
      ],
      "manualRecipients": [
        "string"
      ],
      "variableDefaults": {}
    },
    "templateId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "body": "string",
    "recipientCount": 0,
    "optedOutCount": 0,
    "sentCount": 0,
    "deliveredCount": 0,
    "failedCount": 0,
    "estimatedCost": "string",
    "scheduledAt": "2026-07-06T09:00:00.000Z",
    "startedAt": "2026-07-06T09:00:00.000Z",
    "testSentAt": "2026-07-06T09:00:00.000Z",
    "completedAt": "2026-07-06T09:00:00.000Z",
    "creatorId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Retrieve campaign

GET/engage/campaigns/{id}

curl
curl https://zana.norialabs.com/api/v1/engage/campaigns/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "channel": "sms",
    "status": "draft",
    "audienceType": "string",
    "audienceConfig": {
      "groupIds": [
        "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
      ],
      "manualRecipients": [
        "string"
      ],
      "variableDefaults": {}
    },
    "templateId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "body": "string",
    "recipientCount": 0,
    "optedOutCount": 0,
    "sentCount": 0,
    "deliveredCount": 0,
    "failedCount": 0,
    "estimatedCost": "string",
    "scheduledAt": "2026-07-06T09:00:00.000Z",
    "startedAt": "2026-07-06T09:00:00.000Z",
    "testSentAt": "2026-07-06T09:00:00.000Z",
    "completedAt": "2026-07-06T09:00:00.000Z",
    "creatorId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Update campaign

PUT/engage/campaigns/{id}

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/engage/campaigns/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "channel": "sms",
  "audienceType": "group"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "channel": "sms",
    "status": "draft",
    "audienceType": "string",
    "audienceConfig": {
      "groupIds": [
        "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
      ],
      "manualRecipients": [
        "string"
      ],
      "variableDefaults": {}
    },
    "templateId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "body": "string",
    "recipientCount": 0,
    "optedOutCount": 0,
    "sentCount": 0,
    "deliveredCount": 0,
    "failedCount": 0,
    "estimatedCost": "string",
    "scheduledAt": "2026-07-06T09:00:00.000Z",
    "startedAt": "2026-07-06T09:00:00.000Z",
    "testSentAt": "2026-07-06T09:00:00.000Z",
    "completedAt": "2026-07-06T09:00:00.000Z",
    "creatorId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Send test for campaign

POST/engage/campaigns/{id}/test

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/campaigns/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/test \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "string"
}'
Response · 200 OK
json
{
  "ok": true
}

Schedule campaign

POST/engage/campaigns/{id}/schedule

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/campaigns/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/schedule \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "scheduledAt": "string"
}'
Response · 200 OK
json
{
  "ok": true,
  "jobId": "string"
}

Retry failed recipients: campaign

POST/engage/campaigns/{id}/retry-failed

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/campaigns/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/retry-failed \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true,
  "jobId": "string",
  "count": 0
}

Reschedule campaign

POST/engage/campaigns/{id}/reschedule

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/campaigns/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/reschedule \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "scheduledAt": "string"
}'
Response · 200 OK
json
{
  "ok": true,
  "jobId": "string"
}

Send campaign

POST/engage/campaigns/{id}/send-now

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/campaigns/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/send-now \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true,
  "jobId": "string"
}

Cancel campaign

POST/engage/campaigns/{id}/cancel

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/campaigns/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/cancel \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

List recipients

GET/engage/campaigns/{id}/recipients

curl
curl "https://zana.norialabs.com/api/v1/engage/campaigns/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/recipients?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "campaignId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "contactId": null,
      "recipient": "string",
      "variables": {},
      "renderedBody": null,
      "status": "queued",
      "provider": null,
      "providerMessageId": null,
      "errorCode": null,
      "errorMessage": null,
      "queuedAt": null,
      "sentAt": null,
      "deliveredAt": null,
      "readAt": null,
      "failedAt": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Export recipients

GET/engage/campaigns/{id}/recipients/export

curl
curl https://zana.norialabs.com/api/v1/engage/campaigns/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/recipients/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Templates

Reusable message templates.

List templates

GET/engage/templates

curl
curl "https://zana.norialabs.com/api/v1/engage/templates?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "channel": "sms",
      "name": "Acme Logistics Ltd",
      "body": null,
      "whatsappTemplateName": null,
      "whatsappTemplateLanguage": null,
      "whatsappVariables": {
        "order": [],
        "urlVariable": "string"
      },
      "status": "draft",
      "whatsappMetaStatus": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Create template

POST/engage/templates

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/templates \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "channel": "sms",
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "channel": "sms",
    "name": "Acme Logistics Ltd",
    "body": "string",
    "whatsappTemplateName": "Acme Logistics Ltd",
    "whatsappTemplateLanguage": "string",
    "whatsappVariables": {
      "order": [
        "string"
      ],
      "urlVariable": "string"
    },
    "status": "draft",
    "whatsappMetaStatus": "active",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Retrieve template

GET/engage/templates/{id}

curl
curl https://zana.norialabs.com/api/v1/engage/templates/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "channel": "sms",
    "name": "Acme Logistics Ltd",
    "body": "string",
    "whatsappTemplateName": "Acme Logistics Ltd",
    "whatsappTemplateLanguage": "string",
    "whatsappVariables": {
      "order": [
        "string"
      ],
      "urlVariable": "string"
    },
    "status": "draft",
    "whatsappMetaStatus": "active",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Update template

PUT/engage/templates/{id}

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/engage/templates/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "channel": "sms",
    "name": "Acme Logistics Ltd",
    "body": "string",
    "whatsappTemplateName": "Acme Logistics Ltd",
    "whatsappTemplateLanguage": "string",
    "whatsappVariables": {
      "order": [
        "string"
      ],
      "urlVariable": "string"
    },
    "status": "draft",
    "whatsappMetaStatus": "active",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Delete template

DELETE/engage/templates/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/engage/templates/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Send test for template

POST/engage/templates/{id}/test

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/templates/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/test \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "string"
}'
Response · 200 OK
json
{
  "ok": true
}

Imports

Bulk contact imports.

Create import

POST/engage/imports

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/imports \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "filename": "Acme Logistics Ltd",
  "dataBase64": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "filename": "Acme Logistics Ltd",
    "status": "uploaded",
    "totalRows": 500000,
    "validRows": 0,
    "invalidRows": 0,
    "duplicateRows": 0,
    "mapping": {},
    "errors": [
      {
        "row": 0,
        "message": "string"
      }
    ],
    "targetGroupId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "creatorId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "completedAt": "2026-07-06T09:00:00.000Z"
  }
}

Retrieve import

GET/engage/imports/{id}

curl
curl https://zana.norialabs.com/api/v1/engage/imports/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "filename": "Acme Logistics Ltd",
    "status": "uploaded",
    "totalRows": 500000,
    "validRows": 0,
    "invalidRows": 0,
    "duplicateRows": 0,
    "mapping": {},
    "errors": [
      {
        "row": 0,
        "message": "string"
      }
    ],
    "targetGroupId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "creatorId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "completedAt": "2026-07-06T09:00:00.000Z"
  }
}

Preview import

POST/engage/imports/{id}/preview

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/imports/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/preview \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "mapping": {
    "name": "Acme Logistics Ltd",
    "phone": "+254720123456",
    "email": "string"
  }
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "filename": "Acme Logistics Ltd",
    "status": "uploaded",
    "totalRows": 500000,
    "validRows": 0,
    "invalidRows": 0,
    "duplicateRows": 0,
    "mapping": {},
    "errors": [
      {
        "row": 0,
        "message": "string"
      }
    ],
    "targetGroupId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "creatorId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "completedAt": "2026-07-06T09:00:00.000Z"
  },
  "preview": {
    "totalRows": 500000,
    "validRows": [
      {
        "row": 0,
        "name": "Acme Logistics Ltd",
        "phone": "+254720123456",
        "email": "string"
      }
    ],
    "invalidRows": [
      {
        "row": 0,
        "message": "string"
      }
    ],
    "duplicateRows": [
      {
        "row": 0,
        "phone": "+254720123456"
      }
    ]
  }
}

Commit import

POST/engage/imports/{id}/commit

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/imports/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/commit \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "targetGroupId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "filename": "Acme Logistics Ltd",
    "status": "uploaded",
    "totalRows": 500000,
    "validRows": 0,
    "invalidRows": 0,
    "duplicateRows": 0,
    "mapping": {},
    "errors": [
      {
        "row": 0,
        "message": "string"
      }
    ],
    "targetGroupId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "creatorId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "completedAt": "2026-07-06T09:00:00.000Z"
  }
}

Inbound

Inbound messages and replies.

List messages

GET/engage/inbound/messages

curl
curl "https://zana.norialabs.com/api/v1/engage/inbound/messages?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "channel": "whatsapp",
      "provider": "ses",
      "direction": "inbound",
      "fromPhone": "+254720123456",
      "toPhone": "+254720123456",
      "body": "string",
      "providerMessageId": null,
      "sentBy": null,
      "receivedAt": "2026-07-06T09:00:00.000Z",
      "createdAt": "2026-07-06T09:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

List conversations

GET/engage/inbound/conversations

curl
curl "https://zana.norialabs.com/api/v1/engage/inbound/conversations?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "channel": "whatsapp",
      "contactPhone": "+254720123456",
      "status": "open",
      "assigneeId": null,
      "lastMessageAt": null,
      "lastMessagePreview": null,
      "createdAt": "2026-07-06T09:00:00.000Z",
      "updatedAt": "2026-07-06T09:00:00.000Z"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Retrieve conversation

GET/engage/inbound/conversations/{channel}/{phone}

curl
curl https://zana.norialabs.com/api/v1/engage/inbound/conversations/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
      "channel": "whatsapp",
      "provider": "ses",
      "direction": "inbound",
      "fromPhone": "+254720123456",
      "toPhone": "+254720123456",
      "body": "string",
      "providerMessageId": null,
      "sentBy": null,
      "receivedAt": "2026-07-06T09:00:00.000Z",
      "createdAt": "2026-07-06T09:00:00.000Z"
    }
  ]
}

Update conversation

PATCH/engage/inbound/conversations/{channel}/{phone}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/engage/inbound/conversations/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "open",
  "assigneeId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
}'
Response · 200 OK
json
{
  "data": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "channel": "whatsapp",
    "contactPhone": "+254720123456",
    "status": "open",
    "assigneeId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "lastMessageAt": "2026-07-06T09:00:00.000Z",
    "lastMessagePreview": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  }
}

Create reply

POST/engage/inbound/conversations/{channel}/{phone}/reply

idempotent
curl
curl https://zana.norialabs.com/api/v1/engage/inbound/conversations/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/reply \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "body": "string"
}'
Response · 200 OK
json
{
  "ok": true,
  "conversation": {
    "id": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "channel": "whatsapp",
    "contactPhone": "+254720123456",
    "status": "open",
    "assigneeId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "lastMessageAt": "2026-07-06T09:00:00.000Z",
    "lastMessagePreview": "string",
    "createdAt": "2026-07-06T09:00:00.000Z",
    "updatedAt": "2026-07-06T09:00:00.000Z"
  },
  "messageId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
}

Messaging analytics

Messaging campaign analytics.

Analytics

GET/engage/analytics

curl
curl https://zana.norialabs.com/api/v1/engage/analytics \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {}
}

Analytics

GET/engage/campaigns/{id}/analytics

curl
curl https://zana.norialabs.com/api/v1/engage/campaigns/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/analytics \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "campaignId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "name": "Acme Logistics Ltd",
    "status": "active",
    "channel": "string",
    "recipientCount": 0,
    "optedOutCount": 0,
    "estimatedCost": "string",
    "funnel": {
      "queued": 0,
      "sent": 0,
      "delivered": 0,
      "read": 0,
      "failed": 0,
      "skipped": 0,
      "optedOut": 0
    },
    "rates": {
      "deliveryRate": 0,
      "readRate": 0,
      "failureRate": 0
    },
    "failureBreakdown": [
      {
        "errorCode": null,
        "errorMessage": null,
        "count": 0
      }
    ]
  }
}

Messaging settings

Messaging configuration.

List settings

GET/engage/settings

curl
curl https://zana.norialabs.com/api/v1/engage/settings \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "unitPrices": {
      "sms": 0,
      "whatsapp": 0
    },
    "sendRateLimits": {
      "sms": {
        "limit": 0,
        "windowSec": 0
      },
      "whatsapp": {
        "limit": 0,
        "windowSec": 0
      }
    }
  }
}

Account & Settings

Session

The signed-in principal and active workspace.

List me

GET/me

curl
curl https://zana.norialabs.com/api/v1/me \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
No response body.

Update preference

PATCH/me/preferences

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/me/preferences \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "showApiDocs": true
}'
Response · 200 OK
json
{
  "data": {
    "showApiDocs": true
  }
}

Workspace settings

Workspace profile, branding, currency, timezone, and module configuration.

List settings

GET/settings

curl
curl https://zana.norialabs.com/api/v1/settings \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "companyName": "Acme Logistics Ltd",
    "companyEmail": "string",
    "companyPhone": "+254720123456",
    "companyAddress": "string",
    "companyTaxPin": "string",
    "currency": "KES",
    "taxRate": 0,
    "timezone": "string",
    "logoObjectKey": "string",
    "logoContentType": "string",
    "defaultChannel": "string",
    "passCardFees": true,
    "accent": "cyan",
    "aiEnabled": true,
    "emailNotificationsEnabled": true,
    "autoDunningEnabled": true,
    "paymentMethods": [
      {
        "id": "string",
        "provider": "string",
        "label": "string",
        "enabled": true,
        "configured": true,
        "callbackSlug": null
      }
    ],
    "manualEnabled": true,
    "paymentInstructions": [
      {
        "id": "string",
        "kind": "mpesa_paybill",
        "label": "string",
        "accountName": null,
        "shortCode": null,
        "accountNumber": null,
        "useInvoiceReference": true,
        "phone": null,
        "bankName": null,
        "bankBranch": null,
        "swiftCode": null,
        "instructions": null,
        "enabled": true
      }
    ]
  }
}

List onboarding

GET/settings/onboarding

curl
curl https://zana.norialabs.com/api/v1/settings/onboarding \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "company": true,
    "payments": true,
    "customer": true,
    "invoice": true,
    "dismissed": true
  }
}

Update onboarding dismissed

PUT/settings/onboarding-dismissed

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/onboarding-dismissed \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "dismissed": true
}'
Response · 200 OK
json
{
  "ok": true
}

Update company

PUT/settings/company

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/company \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "companyName": "Acme Logistics Ltd",
  "companyEmail": "string",
  "companyPhone": "+254720123456",
  "companyAddress": "string"
}'
Response · 200 OK
json
{
  "ok": true
}

Update accent

PUT/settings/accent

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/accent \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "accent": "cyan"
}'
Response · 200 OK
json
{
  "ok": true
}

Update ai

PUT/settings/ai

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/ai \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true
}'
Response · 200 OK
json
{
  "ok": true
}

Update email notification

PUT/settings/email-notifications

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/email-notifications \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true
}'
Response · 200 OK
json
{
  "ok": true
}

Update auto dunning

PUT/settings/auto-dunning

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/auto-dunning \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true
}'
Response · 200 OK
json
{
  "ok": true
}

List providers

GET/settings/providers

curl
curl https://zana.norialabs.com/api/v1/settings/providers \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    "string"
  ]
}

Update sasapay

PUT/settings/gateways/sasapay

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/gateways/sasapay \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "clientId": "string",
  "clientSecret": "string",
  "merchantCode": "string"
}'
Response · 200 OK
json
{
  "ok": true
}

Update daraja

PUT/settings/gateways/daraja

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/gateways/daraja \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "consumerKey": "string",
  "consumerSecret": "string",
  "shortcode": "string",
  "passkey": "string"
}'
Response · 200 OK
json
{
  "ok": true
}

Update paystack

PUT/settings/gateways/paystack

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/gateways/paystack \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "secretKey": "string"
}'
Response · 200 OK
json
{
  "ok": true
}

Update default channel

PUT/settings/default-channel

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/default-channel \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "channel": "mpesa"
}'
Response · 200 OK
json
{
  "ok": true
}

Update card fee

PUT/settings/card-fees

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/card-fees \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true
}'
Response · 200 OK
json
{
  "ok": true
}

List payment instructions

GET/settings/payment-instructions

curl
curl https://zana.norialabs.com/api/v1/settings/payment-instructions \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "kind": "mpesa_paybill",
      "label": "string",
      "accountName": null,
      "shortCode": null,
      "accountNumber": null,
      "useInvoiceReference": true,
      "phone": null,
      "bankName": null,
      "bankBranch": null,
      "swiftCode": null,
      "instructions": null,
      "enabled": true
    }
  ]
}

Create payment instruction

POST/settings/payment-instructions

idempotent
curl
curl https://zana.norialabs.com/api/v1/settings/payment-instructions \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "kind": "mpesa_paybill",
  "label": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "kind": "mpesa_paybill",
    "label": "string",
    "accountName": "Acme Logistics Ltd",
    "shortCode": "string",
    "accountNumber": "string",
    "useInvoiceReference": true,
    "phone": "+254720123456",
    "bankName": "Acme Logistics Ltd",
    "bankBranch": "string",
    "swiftCode": "string",
    "instructions": "string",
    "enabled": true
  }
}

Update payment instruction

PUT/settings/payment-instructions/{id}

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/payment-instructions/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "kind": "mpesa_paybill",
  "label": "string",
  "accountName": "Acme Logistics Ltd",
  "shortCode": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "kind": "mpesa_paybill",
    "label": "string",
    "accountName": "Acme Logistics Ltd",
    "shortCode": "string",
    "accountNumber": "string",
    "useInvoiceReference": true,
    "phone": "+254720123456",
    "bankName": "Acme Logistics Ltd",
    "bankBranch": "string",
    "swiftCode": "string",
    "instructions": "string",
    "enabled": true
  }
}

Delete payment instruction

DELETE/settings/payment-instructions/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/settings/payment-instructions/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Update order

PUT/settings/payment-instructions/order

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/settings/payment-instructions/order \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "ids": [
    "0f9a1c2e-3b4d-4e8f-9012-3456789abcde"
  ]
}'
Response · 200 OK
json
{
  "ok": true
}

Toggle gateway

POST/settings/gateways/{provider}/toggle

idempotent
curl
curl https://zana.norialabs.com/api/v1/settings/gateways/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/toggle \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true
}'
Response · 200 OK
json
{
  "ok": true
}

Delete workspace

DELETE/settings/workspace

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/settings/workspace \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
No response body.

Export settings

GET/settings/export

curl
curl https://zana.norialabs.com/api/v1/settings/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 202 Accepted
json
{
  "data": {
    "exportId": "0f9a1c2e-3b4d-4e8f-9012-3456789abcde",
    "jobId": "string"
  }
}

Retrieve export

GET/settings/exports/{id}

curl
curl https://zana.norialabs.com/api/v1/settings/exports/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
"string"

Export audit

GET/settings/audit/export

curl
curl https://zana.norialabs.com/api/v1/settings/audit/export \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "csv": "string"
  }
}

Subscription & plan

Current plan, entitlements, and quota usage.

List subscription

GET/subscription

curl
curl https://zana.norialabs.com/api/v1/subscription \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "plan": "free",
    "status": "active",
    "pendingPlan": "free",
    "currentPeriodEnd": "2026-07-06T09:00:00.000Z",
    "entitlements": {
      "invoicesPerMonth": 0,
      "members": 0,
      "recurring": true,
      "api": true,
      "crm": true,
      "campaignRecipientsPerMonth": 0,
      "utility": true,
      "billableAccounts": 0,
      "bundledNotifications": true,
      "ai": true,
      "aiCreditsPerMonth": 0
    },
    "extraSeats": 0,
    "internal": true,
    "monthlyInvoiceCount": 0,
    "monthlyRecipientUsage": 0,
    "mpesaEnabled": true,
    "billableAccountsUsed": 0,
    "aboveTier": true,
    "recommendedPlan": "free"
  }
}

Create paystack

POST/subscription/upgrade/paystack

idempotent
curl
curl https://zana.norialabs.com/api/v1/subscription/upgrade/paystack \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "plan": "starter"
}'
Response · 200 OK
json
{
  "data": {
    "authorizationUrl": "string"
  }
}

Create mpesa

POST/subscription/upgrade/mpesa

idempotent
curl
curl https://zana.norialabs.com/api/v1/subscription/upgrade/mpesa \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "plan": "starter",
  "phone": "+254720123456"
}'
Response · 200 OK
json
{
  "data": {
    "chargeId": "string",
    "customerMessage": "string"
  }
}

Retrieve charge

GET/subscription/charge/{id}

curl
curl https://zana.norialabs.com/api/v1/subscription/charge/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "status": "pending"
  }
}

Create change

POST/subscription/change

idempotent
curl
curl https://zana.norialabs.com/api/v1/subscription/change \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "plan": "free"
}'
Response · 200 OK
json
{
  "data": {
    "ok": true
  }
}

Create resume

POST/subscription/resume

idempotent
curl
curl https://zana.norialabs.com/api/v1/subscription/resume \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "ok": true
  }
}

List seats

GET/seats

curl
curl https://zana.norialabs.com/api/v1/seats \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "seats": 0,
    "monthlyMinor": 500000,
    "proratedMinor": 500000,
    "currency": "KES",
    "periodEnd": "2026-07-06T09:00:00.000Z",
    "includedMembers": 0,
    "extraSeats": 0,
    "eligible": true,
    "reason": "Adjustment"
  }
}

Create seat

POST/seats

idempotent
curl
curl https://zana.norialabs.com/api/v1/seats \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "seats": 1,
  "phone": "+254720123456"
}'
Response · 200 OK
json
{
  "data": {
    "chargeId": "string",
    "customerMessage": "string"
  }
}

Delete seat

DELETE/seats

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/seats \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "seats": 1
}'
Response · 200 OK
json
{
  "data": {
    "extraSeats": 0
  }
}

List modules

GET/modules

curl
curl https://zana.norialabs.com/api/v1/modules \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "key": "string",
      "name": "Acme Logistics Ltd",
      "description": "string",
      "icon": "string",
      "status": "active",
      "isCore": true,
      "enabled": true,
      "locked": true,
      "source": "plan",
      "canSelfEnable": true,
      "needsUpgrade": true,
      "needsPurchase": true,
      "blockedReasons": [
        "Adjustment"
      ]
    }
  ]
}

Create enable

POST/modules/{slug}/enable

idempotent
curl
curl https://zana.norialabs.com/api/v1/modules/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/enable \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "ok": true
  }
}

Create disable

POST/modules/{slug}/disable

idempotent
curl
curl https://zana.norialabs.com/api/v1/modules/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/disable \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "ok": true
  }
}

Roles & permissions

Custom roles and their permission grants.

List roles

GET/roles

curl
curl https://zana.norialabs.com/api/v1/roles \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "slug": "string",
      "name": "Acme Logistics Ltd",
      "description": null,
      "permissions": {},
      "system": true,
      "memberCount": 0
    }
  ],
  "catalog": [
    {
      "resource": "invoicing:invoices",
      "action": "read",
      "label": "string",
      "description": null,
      "module": "string"
    }
  ]
}

Create role

POST/roles

idempotent
curl
curl https://zana.norialabs.com/api/v1/roles \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "permissions": {}
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "slug": "string",
    "name": "Acme Logistics Ltd",
    "description": "string",
    "permissions": {},
    "system": true,
    "memberCount": 0
  }
}

List members

GET/members

curl
curl https://zana.norialabs.com/api/v1/members \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "userId": "string",
      "name": "Acme Logistics Ltd",
      "email": "string",
      "role": "string"
    }
  ]
}

Retrieve role

GET/roles/{id}

curl
curl https://zana.norialabs.com/api/v1/roles/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "slug": "string",
    "name": "Acme Logistics Ltd",
    "description": "string",
    "permissions": {},
    "system": true,
    "memberCount": 0
  }
}

Update role

PATCH/roles/{id}

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/roles/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "description": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "slug": "string",
    "name": "Acme Logistics Ltd",
    "description": "string",
    "permissions": {},
    "system": true,
    "memberCount": 0
  }
}

Delete role

DELETE/roles/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/roles/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

PATCH role

PATCH/members/{memberId}/role

idempotent
curl
curl -X PATCH https://zana.norialabs.com/api/v1/members/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/role \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "role": "string"
}'
Response · 200 OK
json
{
  "ok": true
}

API keys

Manage API keys. Note: creating a key requires a real user session, so it can't be done with an API key alone.

List api keys

GET/api-keys

curl
curl https://zana.norialabs.com/api/v1/api-keys \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "name": "Acme Logistics Ltd",
      "prefix": "string",
      "lastUsedAt": null,
      "revokedAt": null,
      "createdAt": "2026-07-06T09:00:00.000Z"
    }
  ]
}

Create api key

POST/api-keys

idempotent
curl
curl https://zana.norialabs.com/api/v1/api-keys \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "fullKey": "string",
    "prefix": "string"
  }
}

Delete api key

DELETE/api-keys/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/api-keys/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

Notifications

Notification channel configuration and templates.

Payout channels

GET/channels

curl
curl https://zana.norialabs.com/api/v1/channels \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "channel": "string",
      "provider": "string",
      "label": "string",
      "enabled": true,
      "configured": true,
      "deliveryMode": "string",
      "byokEnabled": true,
      "callbackSlug": null,
      "callbackUrl": null
    }
  ]
}

List managed

GET/channels/managed

curl
curl https://zana.norialabs.com/api/v1/channels/managed \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "configured": true,
    "webhookUrl": "string"
  }
}

Update sm

PUT/channels/sms

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/channels/sms \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "apiKey": "string",
  "clientId": "string",
  "senderId": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "channel": "string",
    "provider": "string",
    "label": "string",
    "enabled": true,
    "configured": true,
    "deliveryMode": "string",
    "byokEnabled": true,
    "callbackSlug": "string",
    "callbackUrl": "string"
  }
}

Update whatsapp

PUT/channels/whatsapp

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/channels/whatsapp \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "accessToken": "string",
  "phoneNumberId": "+254720123456",
  "businessAccountId": "string",
  "appSecret": "string",
  "verifyToken": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "channel": "string",
    "provider": "string",
    "label": "string",
    "enabled": true,
    "configured": true,
    "deliveryMode": "string",
    "byokEnabled": true,
    "callbackSlug": "string",
    "callbackUrl": "string"
  }
}

List templates

GET/channels/whatsapp/templates

curl
curl https://zana.norialabs.com/api/v1/channels/whatsapp/templates \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "name": "Acme Logistics Ltd",
      "language": "string",
      "category": "string",
      "status": "active",
      "remoteId": null,
      "components": [
        {
          "type": "string",
          "format": "string",
          "text": "string",
          "example": {},
          "buttons": []
        }
      ],
      "rejectedReason": null,
      "lastSyncedAt": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ]
}

Create template

POST/channels/whatsapp/templates

idempotent
curl
curl https://zana.norialabs.com/api/v1/channels/whatsapp/templates \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Logistics Ltd",
  "language": "string",
  "category": "AUTHENTICATION",
  "components": [
    {
      "type": "string",
      "format": "string",
      "text": "string",
      "example": {},
      "buttons": [
        {}
      ]
    }
  ]
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "name": "Acme Logistics Ltd",
    "language": "string",
    "category": "string",
    "status": "active",
    "remoteId": "string",
    "components": [
      {
        "type": "string",
        "format": "string",
        "text": "string",
        "example": {},
        "buttons": []
      }
    ],
    "rejectedReason": "Adjustment",
    "lastSyncedAt": "string",
    "createdAt": "string",
    "updatedAt": "string"
  }
}

Create sync

POST/channels/whatsapp/templates/sync

idempotent
curl
curl https://zana.norialabs.com/api/v1/channels/whatsapp/templates/sync \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "name": "Acme Logistics Ltd",
      "language": "string",
      "category": "string",
      "status": "active",
      "remoteId": null,
      "components": [
        {
          "type": "string",
          "format": "string",
          "text": "string",
          "example": {},
          "buttons": []
        }
      ],
      "rejectedReason": null,
      "lastSyncedAt": null,
      "createdAt": "string",
      "updatedAt": "string"
    }
  ],
  "synced": 0
}

Update template

PUT/channels/whatsapp/templates/{id}

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/channels/whatsapp/templates/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "category": "AUTHENTICATION",
  "components": [
    {
      "type": "string",
      "format": "string",
      "text": "string",
      "example": {},
      "buttons": [
        {}
      ]
    }
  ]
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "name": "Acme Logistics Ltd",
    "language": "string",
    "category": "string",
    "status": "active",
    "remoteId": "string",
    "components": [
      {
        "type": "string",
        "format": "string",
        "text": "string",
        "example": {},
        "buttons": []
      }
    ],
    "rejectedReason": "Adjustment",
    "lastSyncedAt": "string",
    "createdAt": "string",
    "updatedAt": "string"
  }
}

Delete template

DELETE/channels/whatsapp/templates/{id}

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/channels/whatsapp/templates/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "ok": true
}

List balance

GET/channels/sms/balance

curl
curl https://zana.norialabs.com/api/v1/channels/sms/balance \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "balanceUnits": 500000,
    "cachedAt": "string",
    "live": true
  }
}

Send test for channel

POST/channels/{id}/test

idempotent
curl
curl https://zana.norialabs.com/api/v1/channels/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/test \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "string"
}'
Response · 200 OK
json
{
  "ok": true
}

Toggle channel

POST/channels/{channel}/{provider}/toggle

idempotent
curl
curl https://zana.norialabs.com/api/v1/channels/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/toggle \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true
}'
Response · 200 OK
json
{
  "ok": true
}

List notification templates

GET/notification-templates

curl
curl https://zana.norialabs.com/api/v1/notification-templates \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "key": "string",
      "channel": "string",
      "locale": "string",
      "subject": null,
      "body": "string",
      "whatsappTemplateName": null,
      "whatsappTemplateLanguage": null,
      "whatsappVariables": {
        "order": [],
        "urlVariable": "string"
      },
      "enabled": true,
      "customized": true
    }
  ]
}

Update notification template

PUT/notification-templates/{id}

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/notification-templates/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "key": "string",
    "channel": "string",
    "locale": "string",
    "subject": "string",
    "body": "string",
    "whatsappTemplateName": "Acme Logistics Ltd",
    "whatsappTemplateLanguage": "string",
    "whatsappVariables": {
      "order": [
        "string"
      ],
      "urlVariable": "string"
    },
    "enabled": true,
    "customized": true
  }
}

PUT content

PUT/notification-templates/{id}/content

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/notification-templates/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/content \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "body": "string"
}'
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "key": "string",
    "channel": "string",
    "locale": "string",
    "subject": "string",
    "body": "string",
    "whatsappTemplateName": "Acme Logistics Ltd",
    "whatsappTemplateLanguage": "string",
    "whatsappVariables": {
      "order": [
        "string"
      ],
      "urlVariable": "string"
    },
    "enabled": true,
    "customized": true
  }
}

DELETE content

DELETE/notification-templates/{id}/content

idempotent
curl
curl -X DELETE https://zana.norialabs.com/api/v1/notification-templates/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/content \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "id": "string",
    "key": "string",
    "channel": "string",
    "locale": "string",
    "subject": "string",
    "body": "string",
    "whatsappTemplateName": "Acme Logistics Ltd",
    "whatsappTemplateLanguage": "string",
    "whatsappVariables": {
      "order": [
        "string"
      ],
      "urlVariable": "string"
    },
    "enabled": true,
    "customized": true
  }
}

List notifications

GET/notifications

curl
curl "https://zana.norialabs.com/api/v1/notifications?limit=50" \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": [
    {
      "id": "string",
      "channel": "string",
      "provider": "string",
      "templateKey": "string",
      "recipient": "string",
      "subject": null,
      "status": "active",
      "providerMessageId": null,
      "providerStatus": null,
      "errorMessage": null,
      "relatedInvoiceId": null,
      "relatedPaymentId": null,
      "queuedAt": "string",
      "sentAt": null,
      "deliveredAt": null,
      "readAt": null,
      "failedAt": null,
      "createdAt": "string"
    }
  ],
  "pagination": {
    "total": 500000,
    "nextCursor": "string",
    "hiddenFailedCount": 0
  }
}

Notification wallet

Prepaid SMS/WhatsApp wallet balance and top-ups.

List notification wallet

GET/notification-wallet

curl
curl https://zana.norialabs.com/api/v1/notification-wallet \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "balanceMinor": 500000,
    "rates": {
      "sms": 0,
      "whatsapp": 0
    },
    "byokSetupFeeMinor": 500000,
    "mpesaEnabled": true,
    "lowBalanceThresholdMinor": 500000,
    "channels": [
      {
        "channel": "sms",
        "enabled": true,
        "deliveryMode": "platform",
        "byokEnabled": true,
        "configured": true
      }
    ],
    "transactions": [
      {
        "id": "string",
        "amountMinor": 500000,
        "type": "topup",
        "channel": null,
        "reference": null,
        "balanceAfter": 500000,
        "createdAt": "string"
      }
    ],
    "smsUnits": {
      "balance": 500000,
      "smsRateMinor": 500000,
      "transactions": [
        {
          "id": "string",
          "units": 0,
          "type": "purchase",
          "reference": null,
          "balanceAfter": 500000,
          "createdAt": "string"
        }
      ]
    }
  }
}

Create mpesa

POST/notification-wallet/topup/mpesa

idempotent
curl
curl https://zana.norialabs.com/api/v1/notification-wallet/topup/mpesa \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "amountMinor": 50000,
  "phone": "+254720123456"
}'
Response · 200 OK
json
{
  "data": {
    "chargeId": "string",
    "customerMessage": "string"
  }
}

Create mpesa

POST/notification-wallet/sms-units/topup/mpesa

idempotent
curl
curl https://zana.norialabs.com/api/v1/notification-wallet/sms-units/topup/mpesa \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "amountMinor": 10000,
  "phone": "+254720123456"
}'
Response · 200 OK
json
{
  "data": {
    "chargeId": "string",
    "customerMessage": "string"
  }
}

Create mpesa

POST/notification-wallet/byok/setup-fee/mpesa

idempotent
curl
curl https://zana.norialabs.com/api/v1/notification-wallet/byok/setup-fee/mpesa \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "channel": "sms",
  "phone": "+254720123456"
}'
Response · 200 OK
json
{
  "data": {
    "chargeId": "string",
    "customerMessage": "string"
  }
}

Retrieve charge

GET/notification-wallet/charge/{id}

curl
curl https://zana.norialabs.com/api/v1/notification-wallet/charge/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX"
Response · 200 OK
json
{
  "data": {
    "status": "pending"
  }
}

Update channel

PUT/notification-wallet/channels/{channel}

idempotent
curl
curl -X PUT https://zana.norialabs.com/api/v1/notification-wallet/channels/0f9a1c2e-3b4d-4e8f-9012-3456789abcde \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true
}'
Response · 200 OK
json
{
  "data": {
    "ok": true
  }
}

Imports

Generic data-import preview and commit.

Preview import

POST/imports/preview

idempotent
curl
curl https://zana.norialabs.com/api/v1/imports/preview \
  -H "Authorization: Bearer nk_1a2b3c4d_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
  "csv": "string",
  "dataBase64": "string"
}'
Response · 200 OK
json
{
  "data": {
    "headers": [
      "string"
    ],
    "rows": [
      [
        "string"
      ]
    ],
    "total": 500000,
    "truncated": true
  }
}

Checkout (public)

Checkout

PUBLIC, token-authenticated - NO API key. Build your own checkout UI: read the invoice or payment link by its public token (from the invoice's pay link), start an M-Pesa STK push or card payment, then poll status. The token is the credential, so these can be called straight from a browser or mobile app.

Get an invoice to pay

GET/pay/{token}

curl
curl https://zana.norialabs.com/api/v1/pay/0f9a1c2e-3b4d-4e8f-9012-3456789abcde
Response · 200 OK
json
{
  "data": {
    "reference": "string",
    "invoice": {
      "invoiceNumber": "string",
      "status": "draft",
      "currency": "KES",
      "subtotal": 500000,
      "taxTotal": 500000,
      "total": 500000,
      "amountPaid": 500000,
      "balanceDue": 500000,
      "issueDate": "2026-07-06",
      "dueDate": null
    },
    "customer": {
      "name": "Acme Logistics Ltd",
      "email": null
    },
    "lineItems": [
      {
        "id": "string",
        "description": "string",
        "quantity": "string",
        "lineTotal": 500000
      }
    ],
    "channels": [
      "mpesa"
    ],
    "feeRates": {
      "card": 0,
      "mpesa": 0
    },
    "paymentInstructions": [
      {
        "id": "string",
        "kind": "mpesa_paybill",
        "label": "string",
        "accountName": null,
        "shortCode": null,
        "accountNumber": null,
        "useInvoiceReference": true,
        "phone": null,
        "bankName": null,
        "bankBranch": null,
        "swiftCode": null,
        "instructions": null,
        "enabled": true
      }
    ],
    "receipts": [
      {
        "id": "string",
        "receiptNumber": null,
        "paidAt": null
      }
    ],
    "settings": {
      "companyName": "Acme Logistics Ltd",
      "companyEmail": "string",
      "companyPhone": "+254720123456",
      "defaultChannel": null,
      "hasLogo": true,
      "accent": "cyan"
    }
  }
}

Start an invoice payment

POST/pay/{token}/initiate

idempotent
curl
curl https://zana.norialabs.com/api/v1/pay/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/initiate \
  -H "Content-Type: application/json" \
  -d '{
  "channel": "mpesa"
}'
Response · 200 OK
json
{
  "data": {
    "ok": true,
    "kind": "mpesa",
    "paymentId": "string",
    "customerMessage": "string"
  }
}

Check invoice payment status

GET/pay/{token}/status/{paymentId}

curl
curl https://zana.norialabs.com/api/v1/pay/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/status/0f9a1c2e-3b4d-4e8f-9012-3456789abcde
Response · 200 OK
json
{
  "data": {
    "status": "pending"
  }
}

Verify an invoice card payment

GET/pay/{token}/verify/{reference}

curl
curl https://zana.norialabs.com/api/v1/pay/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/verify/0f9a1c2e-3b4d-4e8f-9012-3456789abcde
Response · 200 OK
json
{
  "data": {
    "status": "pending"
  }
}

Get a payment link to pay

GET/l/{token}

curl
curl https://zana.norialabs.com/api/v1/l/0f9a1c2e-3b4d-4e8f-9012-3456789abcde
Response · 200 OK
json
{
  "data": {
    "link": {
      "title": "string",
      "description": null,
      "currency": "KES",
      "amountMinor": 500000,
      "presetAmounts": [
        500000
      ],
      "allowCustom": true,
      "minAmountMinor": 500000,
      "maxAmountMinor": 500000,
      "active": true
    },
    "workspaceId": "string",
    "channels": [
      "mpesa"
    ],
    "feeRates": {
      "card": 0,
      "mpesa": 0
    },
    "paymentInstructions": [
      {
        "id": "string",
        "kind": "mpesa_paybill",
        "label": "string",
        "accountName": null,
        "shortCode": null,
        "accountNumber": null,
        "useInvoiceReference": true,
        "phone": null,
        "bankName": null,
        "bankBranch": null,
        "swiftCode": null,
        "instructions": null,
        "enabled": true
      }
    ],
    "settings": {
      "companyName": "Acme Logistics Ltd",
      "companyEmail": "string",
      "companyPhone": "+254720123456",
      "defaultChannel": null,
      "hasLogo": true,
      "accent": "cyan"
    }
  }
}

Start a payment-link payment

POST/l/{token}/initiate

idempotent
curl
curl https://zana.norialabs.com/api/v1/l/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/initiate \
  -H "Content-Type: application/json" \
  -d '{
  "channel": "mpesa",
  "amount": 2
}'
Response · 200 OK
json
{
  "data": {
    "ok": true,
    "kind": "mpesa",
    "paymentId": "string",
    "customerMessage": "string"
  }
}

Check payment-link payment status

GET/l/{token}/status/{paymentId}

curl
curl https://zana.norialabs.com/api/v1/l/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/status/0f9a1c2e-3b4d-4e8f-9012-3456789abcde
Response · 200 OK
json
{
  "data": {
    "status": "pending"
  }
}

Verify a payment-link card payment

GET/l/{token}/verify/{reference}

curl
curl https://zana.norialabs.com/api/v1/l/0f9a1c2e-3b4d-4e8f-9012-3456789abcde/verify/0f9a1c2e-3b4d-4e8f-9012-3456789abcde
Response · 200 OK
json
{
  "data": {
    "status": "pending"
  }
}

Get your API key

Keys are created per workspace from your settings, and every endpoint here works with the same key. Tell us what you're building if you want a hand wiring it up.