ElliboHelp Centre

API and webhooks

The Ellibo Books API for developers - API keys, the base address, every resource, list filters, creating customers, items, invoices and payments, errors and limits - plus where to find each app's own API.

The Ellibo Books API reads and writes your Accounting and Inventory data: customers, vendors, items and stock, invoices, bills, credit notes, estimates, orders and payments. It's a plain REST API that answers JSON. It works on every plan.

Other Ellibo apps - CRM, Subscriptions, Projects, Helpdesk, Bookings, Field Service, Sign, Expense, Manufacturing, HR, Timesheets and Ecommerce - have their own APIs. They're all listed under Every app's own API at the bottom of the API & webhooks tab:

Every app's own API
Each app's own API, with its address and a button to its keys and webhooks.

API keys

  1. Open Settings › Integrations › API & webhooks.
  2. Under Ellibo Books API, type a name (2) for the key, such as the app that will use it.
  3. Choose Read only or Read & write (3).
  4. Click Make a key (4). Copy the key now - it is shown only once.
API keys
1 Base address, 2 key name, 3 access, 4 Make a key.
Key starts withCan do
ellb_ro_Read (GET)
ellb_rw_Read and create (GET and POST)
  • A business can have 20 active keys. Revoke a key to stop it at once.
  • The list shows when each key was last used.
  • Keep keys secret: use them only on a server, never in a web page or a mobile app.

Making a call

  • Base address (1): https://www.ellibo.com/integrations/api/v1.php
  • Authentication: Authorization: Bearer <your key> (or X-Api-Key: <your key>)
  • Limit: 60 calls a minute per key. Above that you get 429.
  • Dates are YYYY-MM-DD. Times are UTC, like 2026-11-09T10:15:00Z.
curl https://www.ellibo.com/integrations/api/v1.php/invoices?status=unpaid \
  -H "Authorization: Bearer ellb_ro_xxxxxxxx"

Reading (GET)

ResourceWhat it lists
/customers, /vendorsParties with contact details, tax ID and address
/itemsItems and services, with price, tax rate and stock
/stockOnly stock-tracked items: SKU and quantity on hand
/invoices, /credit_notes, /estimates, /sales_ordersSales documents
/bills, /purchase_ordersPurchase documents
/paymentsPayments in and out

Add /{id} for one record, for example /invoices/1042. One invoice includes its lines and its pay_link (the customer's Pay now page).

List filters:

ParameterUse
page, per_pagePaging; per_page up to 100 (default 50). The answer says has_more
updated_sinceOnly records changed since a date or time - good for syncing
qSearch by name, email, phone (parties) or name, SKU, barcode (items)
statusDocuments: unpaid, paid, partial or cancelled
customer_id, vendor_idDocuments of one party
from, toDocuments by date
directionPayments: in or out

A list answer looks like:

{"data": [ {...}, {...} ], "page": 1, "per_page": 50, "has_more": false}

Creating (POST, read & write key)

Send JSON with Content-Type: application/json. A new record answers 201 with the record.

POST /customers (or /vendors) - name is required:

{"name": "Green Leaf Restaurant", "email": "accounts@greenleaf.example", "mobile": "+1 555 0100",
 "tax_id": "", "billing_address": "12 Main St", "city": "Denver", "state": "Colorado",
 "postal_code": "80202", "country": "United States", "external_ref": "crm-1882"}

POST /items - name is required; sku must be unique:

{"name": "Coffee beans 1 kg", "type": "goods", "sku": "CB-1KG", "sale_price": 18.50,
 "purchase_price": 11.00, "tax_rate": 5, "unit": "PCS", "track_stock": true}

POST /invoices - a sales invoice for one of your customers:

{"customer_id": 311, "date": "2026-11-09", "due_date": "2026-11-23", "reference": "PO-5521",
 "notes": "Thank you!", "external_ref": "shop-order-1001",
 "lines": [
   {"item_id": 57, "qty": 2},
   {"name": "Delivery", "qty": 1, "rate": 5.00, "tax_rate": 0},
   {"name": "Gift box", "qty": 1, "rate": 11.80, "tax_rate": 18, "rate_includes_tax": true, "discount": 1.00}
 ]}
  • 1 to 200 lines. A line with item_id uses the item's name, price and tax unless you send them.
  • rate_includes_tax: true means the rate already includes tax.
  • is_igst: true for IGST, false for CGST + SGST. Leave it out and Ellibo decides from the customer's state.
  • The answer includes the invoice's number, totals and pay_link.

POST /payments - money received against an invoice:

{"invoice_id": 1042, "amount": 41.80, "date": "2026-11-10", "mode": "Bank transfer",
 "reference": "TRX-88231", "account_id": 12}

account_id is the bank or cash account it went into (your first bank account if left out).

Errors

Errors answer with a status code and:

{"error": {"code": "invalid", "message": "customer_id must be one of your customers.", "field": "customer_id"}}
StatusCodeMeaning
400bad_requestA filter is malformed, e.g. updated_since
401unauthorizedNo key, a wrong key, or a revoked key
403forbidden / read_only / plan_limitRead-only key, the business is read-only (plan ended), or your plan's invoice limit is reached
404not_foundNo such record or resource
409duplicateAn item with that SKU already exists
422invalidA field is missing or wrong - see field
429rate_limitedMore than 60 calls a minute

Webhooks

To hear about changes instead of asking repeatedly, add a webhook. See Webhooks.

Every app's own API

Each app's address and keys are on its own settings page (the Keys & webhooks button). For example:

  • CRM: leads, contacts, companies, deals, activities and quotes - see CRM API.
  • Subscriptions: customers, plans, subscriptions and invoices - see Subscriptions API.
  • Projects: projects, tasks, issues and time logs - see Projects API.
Still need help?Write to us and we'll walk you through it.
Contact support