Docs / API reference

API overview

The Invoa REST API for developers: base URL, JSON conventions, money in integer sen, dates, request IDs, a first request and every resource.

The Invoa REST API lets your own systems create contacts, draft and issue invoices, record payments, run billing schedules and submit e-invoices to LHDN. Use it to connect a booking system, an online shop or your ERP to Invoa.

The REST API and webhooks are part of the Core and Pro plans. On Free, requests return 403 plan_limit.

Each API key belongs to one company in Invoa. Every request reads and writes that company's data only.

Base URL

http
https://app.invoa.io/api/v1

All requests use HTTPS. Send and receive JSON (content-type: application/json), except the PDF download, which returns application/pdf.

Conventions

TopicRule
Field namescamelCase in requests and responses, for example contactId, unitPrice, issueDate. The exceptions are has_more in the pagination object and required_scope / required_scopes in insufficient_scope error details.
MoneyIntegers in sen. 125000 is RM 1,250.00. Never send decimals or strings for amounts.
CurrencyMYR unless you set currency on a document.
DatesBusiness dates are YYYY-MM-DD, for example "2026-10-15". If you leave a date out, Invoa uses today in the company's timezone (default Asia/Kuala_Lumpur).
TimestampsISO 8601 in UTC, for example "2026-10-15T02:14:09.000Z".
Decimal quantities and ratesFields stored as decimals come back as strings: quantity ("1.5000"), taxRate ("8.00"), discountValue, exchangeRate. Send quantity as a number.
IDsUUIDs.
ResponsesA single object is wrapped in data. Lists return data plus pagination. Errors return error.

Request IDs

Every authenticated response carries an x-request-id header. Send your own x-request-id on a request and Invoa echoes it back; otherwise it generates one. Include it when you contact support about a specific call.

Your first request

Create an API key in Settings → API keys (see Authentication and scopes), then list your contacts:

bash
curl https://app.invoa.io/api/v1/contacts?limit=2 \
  -H "Authorization: Bearer $INVOA_API_KEY"
json
{
  "data": [
    {
      "id": "c0a10000-0000-4000-8000-000000000007",
      "kind": "customer",
      "name": "Aina Rahman",
      "companyName": "Teratai Biru Ventures Sdn. Bhd.",
      "tin": "C12345678900",
      "email": "aina@teratai-biru.example",
      "outstanding": 135000,
      "documentCount": 4
    }
  ],
  "pagination": { "total": 1, "limit": 2, "offset": 0, "has_more": false }
}

(Contact objects have more fields than shown; see Contacts.)

A typical flow

  1. Find or create the customer: GET /contacts?search=…, then POST /contacts.
  2. Create a draft invoice with an idempotencyKey: POST /documents.
  3. Issue it to allocate the number and create the PDF: POST /documents/{id}/issue.
  4. Email it to the customer: POST /documents/{id}/send.
  5. When the money arrives, record the payment, which issues a receipt: POST /payments.
  6. Optionally submit the invoice to LHDN: POST /einvoice/{documentId}/submit.
  7. Listen for webhooks instead of polling.

Note: API keys are trusted system integrations. Unlike Claude, an API key with the right scope issues, voids and submits immediately, without a human approval step.

Resources

ResourceEndpoints
ContactsList, retrieve with balances, create, update customers and suppliers.
ItemsList and create catalogue items.
DocumentsList, retrieve, create drafts, issue, send, download the PDF, void.
PaymentsList payments, record a payment and issue a receipt.
Billing schedulesList, retrieve, create, trigger a milestone.
e-InvoiceSubmit to LHDN MyInvois, check status.
WebhooksManage endpoints, events, payloads and signature verification.

There is no endpoint to delete contacts, documents or payments. Issued documents are voided, never deleted.

Something unclear or out of date? Tell us at hello@invoa.io and we'll fix the page.