Navorina
Get a key

Navorina API

Read invoices and transactions, create draft invoices and get signed webhooks when money moves. Part of the Plus plan.

Start

Create a key in Settings → API. It is shown once; keep it on your server. Send it as a bearer token.

https://navorina.ai/api/v1
curl https://navorina.ai/api/v1/invoices \
  -H "Authorization: Bearer $NAVORINA_API_KEY"

Answers are JSON. Amounts are whole minor units (cents): 120000 is 1,200.00. Dates are YYYY-MM-DD, times are UTC.

Access

Each key can do only what you chose when you created it.

AccessScopeAllows
Read invoicesinvoices:readGET /invoices, GET /invoices/{id}
Create draft invoicesinvoices:writePOST /invoices
Read transactionstransactions:readGET /transactions

List invoices

GET /invoicesinvoices:read

Newest first. Filters: status (draft, sent, partially_paid, paid, overdue, void), limit (1 to 100, default 25), starting_after.

curl "https://navorina.ai/api/v1/invoices?status=paid&limit=10" \
  -H "Authorization: Bearer $NAVORINA_API_KEY"

Get an invoice

GET /invoices/{id}invoices:read

The invoice with its line items.

curl https://navorina.ai/api/v1/invoices/7c1e0b52-… \
  -H "Authorization: Bearer $NAVORINA_API_KEY"

Create a draft invoice

POST /invoicesinvoices:write

Saved as a draft for you to review and send in Navorina. Send total_minor, or line_items with name, quantity and unit_price_minor. An Idempotency-Key makes a retry safe.

curl https://navorina.ai/api/v1/invoices \
  -H "Authorization: Bearer $NAVORINA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042" \
  -d '{"number":"INV-1042","customer_name":"Acme GmbH","customer_email":"[email protected]",
       "issue_date":"2026-10-21","due_date":"2026-11-04","currency_code":"EUR","total_minor":120000}'

List transactions

GET /transactionstransactions:read

Newest first. Filters: from and to (YYYY-MM-DD), limit, starting_after. amount_minor is negative for money out.

curl "https://navorina.ai/api/v1/transactions?from=2026-10-01&to=2026-10-31" \
  -H "Authorization: Bearer $NAVORINA_API_KEY"

Pages

Lists answer {"object":"list","data":[…],"has_more":true,"next_cursor":"…"}. Pass next_cursor as starting_after to get the next page.

Errors

Every error has one shape: {"error":{"code","message","status"},"request_id"}. Quote request_id when you write to support.

StatusCodeMeans
400INVALID_PARAMETERA query parameter is wrong, for example limit=500.
400INVALID_PAYLOADThe JSON body is missing a field or has a bad value.
401API_KEY_REQUIREDNo Authorization header.
401INVALID_API_KEYThe key is wrong or was revoked.
403SCOPE_REQUIREDThe key cannot do this. Create one with the right access.
403FEATURE_NOT_INCLUDEDThe workspace is not on Plus.
404NOT_FOUNDNo such object in this workspace, or no such endpoint.
409INVOICE_NUMBER_EXISTSAn invoice with this number already exists.
429RATE_LIMITEDToo many requests. Wait for Retry-After seconds.
500INTERNAL_ERRORSomething failed on our side. Retry with the same Idempotency-Key.

Limits

60 requests a minute for each key, and 12 new invoices a minute for each workspace. Over the limit the API answers 429 with Retry-After. Up to 10 keys and 5 webhook endpoints per workspace.

Webhooks

Add an https endpoint in Settings → API and choose its events. Navorina sends a POST for each event and expects a 2xx answer within 5 seconds. Redirects are not followed; private and local addresses are refused.

EventWhen
invoice.createdInvoice created
invoice.paidInvoice paid
invoice.payment_reportedClient says they paid
transaction.createdTransaction added
{
  "id": "evt_3f9a1c0b7d2e4a6f8b1c5d9e",
  "type": "invoice.paid",
  "created": "2026-10-21T09:14:03.120Z",
  "livemode": true,
  "data": {
    "object": {
      "id": "7c1e0b52-…",
      "object": "invoice",
      "number": "INV-1042",
      "status": "paid",
      "currency": "EUR",
      "total_minor": 120000,
      "amount_due_minor": 0
    }
  }
}

The object is read when the event is first sent; a retry sends the same body with the same id, so you can skip ids you already handled.

Check the signature

Each delivery has Navorina-Signature: t=<unix seconds>,v1=<hex>: an HMAC-SHA256 of t.body with the endpoint's signing secret (shown once when you add it). Also sent: Navorina-Event and Navorina-Delivery.

import crypto from "node:crypto";

// header: the Navorina-Signature header, body: the raw request body as text
function verify(header, body, secret) {
  const parts = Object.fromEntries(header.split(",").map((part) => part.split("=")));
  const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${body}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  return fresh && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1 || ""));
}

Retries

A failed delivery is tried again after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 24 hours, then marked failed. Settings → API shows the last 50 deliveries of each endpoint, with Resend and Send test.