An invoice and accounting API, ledger included.
Guliel is accounting and finance-operations software that runs invoicing, expenses, purchasing, payroll, reporting and a double-entry general ledger on one engine. The REST API is how your code reaches that engine. Issuing an invoice, recording a payment, approving an expense, posting a journal entry and pulling a trial balance are each one documented route, and each runs under the same rules as a person working in the app.
The dashboard, the AI companion, the MCP server and the automations engine call the same routes. If the app can do it, the API can.
Status. Live: the REST API, API keys and OAuth 2.1 grants issued from the dashboard, the per-route reference at /docs, an OpenAPI 3.1 spec, and the same routes published as MCP tools. Planned: an
Idempotency-Keyheader, signed webhook subscriptions, a versioning policy, and structured e-invoice output such as Peppol BIS Billing. The API belongs to Automate & Plan, the second of Guliel's four phases: your code, your agents and your automations work on the same records.
What the engine enforces
Every caller gets the same checks, whether it is a person, a script or an AI client:
- Document numbers are allocated in sequence at issue. A draft has no number.
- Each issued document is checked against its organisation's country rules before it is saved.
- Totals and ledger postings are derived from the document's line items.
- A journal entry needs at least two legs and equal debits and credits, or the call returns a 400.
- Nothing posts to the books on or before the lock date, and only a manager can move the lock date.
- An expense captured from a scan or an inbox waits for approval before it reaches the ledger.
Auth
Two options, one authorization layer.
API keys. For scripts, internal tools and your own servers. Create a key on the Developer page while signed in; a key cannot create another key. It is a bearer token (gli_…) in the Authorization header. Each key carries feature scopes (invoices:write, expenses:read, accounting:read and so on), is limited to the organisations you pick or to all of yours, can expire, and can be revoked. The secret is shown once and stored as a hash.
OAuth 2.1. For apps and AI clients acting for a user. Authorization-code flow with PKCE (S256 only), refresh-token rotation, revocation and introspection endpoints, and dynamic client registration for MCP clients. Discovery is at /.well-known/oauth-authorization-server. The consent screen names the scopes and the organisations.
Scopes come as read and write for 21 feature areas, from invoices and expenses to accounting, payroll, imports and automations; reports is read-only. The user's role caps every scope. A key holding invoices:write still cannot issue an invoice if the person who made it is a viewer, and moving the books lock date takes a manager. An accountant who works for several client organisations can hold one key scoped to exactly those organisations.
Issue an invoice, then book it
The hello-world is one POST. customerId is a customer record from /api/customers.
curl -X POST https://app.guliel.com/api/documents \
-H "Authorization: Bearer $GULIEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"organizationId": "YOUR_ORG_ID",
"customerId": "YOUR_CUSTOMER_ID",
"documentType": "INVOICE",
"status": "UNSENT",
"currency": "SGD",
"dueDate": "2026-11-02",
"items": [
{ "id": "line-1", "description": "Consulting, October 2026", "quantity": 12, "unitPrice": 250, "amount": 3000 }
],
"subtotal": 3000,
"taxRate": 9,
"taxAmount": 270,
"total": 3270
}'
The response is the created document: id, invoiceNumber (the next number in the organisation's sequence), status, totals and createdAt. Leave status out and you get a draft with no number.
Then:
POST /api/documents/{id}/sendemails the PDF to the customer's addresses and moves the invoice to SENT. From that point it is in the general ledger: accounts receivable against revenue and tax payable.POST /api/documents/{id}/paymentsrecords a payment with an amount, a date and a method. Cash moves against receivables, and a receipt is issued by default.
The PDF follows the issuing organisation's country: a Singapore GST tax invoice for a Singapore organisation, a Hebrew tax invoice (חשבונית מס) for an Israeli one, an EU VAT invoice for a German one, across 39 countries in 10 format families. There is no per-call format flag. For Israeli organisations, an allocation number (מספר הקצאה) issued by the tax authority can be recorded with POST /api/documents/{id}/manual-allocation; requesting it from SHAAM directly is built and not yet switched on.
Documents are PDF today. Guliel's own Peppol access point is built and awaiting OpenPeppol certification, and it is not yet connected to the app; Peppol BIS Billing output is planned. Country coverage is listed on /invoicing.
The ledger over the API
Issued documents, approved expenses, payments and payroll post to the double-entry general ledger without a separate call. The accounting routes cover the rest. A manual journal entry:
curl -X POST https://app.guliel.com/api/journal-entries \
-H "Authorization: Bearer $GULIEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"organizationId": "YOUR_ORG_ID",
"date": "2026-10-01",
"memo": "Owner capital contribution",
"legs": [
{ "account": "CASH", "debit": 10000, "credit": 0 },
{ "account": "EQUITY", "debit": 0, "credit": 10000 }
]
}'
GET /api/reports/trial-balance?organizationId=…&startDate=2026-01-01&endDate=2026-09-30returns debits, credits and the net per account.general-ledger,income-statementandcash-flowtake the same dates;balance-sheettakesasOfDate.GET /api/ledger/exportreturns the general ledger as CSV, one row per posting, for your accountant or another system.GET /api/ledger/postingsandGET /api/ledger/summaryread postings and totals;PATCH /api/ledger/locksets the books lock date.
The chart of accounts is fixed today: cash, receivables, payables, revenue, expense, tax, equity, payroll and a few bridge accounts such as deferred revenue. Custom accounts are planned.
Endpoints
The full reference, with request and response schemas, is at /docs. A sample:
| Area | Endpoints |
|---|---|
| Documents (invoices, receipts, credit and debit memos) | POST /api/documents, GET /api/documents, GET /api/documents/{id}, POST /api/documents/{id}/send, POST /api/documents/{id}/payments, POST /api/documents/{id}/cancel |
| Expenses | POST /api/expenses, POST /api/expenses/scan, GET /api/expenses, PATCH /api/expenses/{id}/status |
| Ledger | POST /api/journal-entries, GET /api/journal-entries, GET /api/ledger/postings, GET /api/ledger/summary, GET /api/ledger/export, PATCH /api/ledger/lock |
| Reports | GET /api/reports, GET /api/reports/{reportType} |
| Customers | POST /api/customers, GET /api/customers, PATCH /api/customers/{id} |
| Suppliers and purchase orders | POST /api/suppliers, POST /api/orders, POST /api/orders/{id}/invoice |
| Items and stock | POST /api/items, GET /api/items, POST /api/items/{id}/stock |
| Payroll | POST /api/payroll/generate, POST /api/payroll/approve, POST /api/payroll/pay |
| Imports | POST /api/imports/upload, GET /api/imports/{id}/records, POST /api/imports/{id}/commit |
| Automations | POST /api/automations, GET /api/automations, POST /api/automations/{id}/runs/{runId}/replay |
| Organizations | GET /api/organizations, POST /api/organizations |
Every resource below an organisation is scoped to one: organizationId is required on create and list calls, except the organizations endpoints themselves, which list the organisations you belong to and create a new one. POST /api/orders/{id}/invoice is the supplier's side of a purchase order: a supplier that accepted your invitation with its own Guliel organisation invoices your approved order through it, and the order moves to invoiced.
Webhooks
Outbound webhooks run through the automations engine. Pick one of 14 triggers (invoice.paid, invoice.overdue, expense.approved, supplier.order.invoiced, logistics.item.stock_below_threshold, daily, weekly or monthly schedules, and more) and a webhook.post action with your URL, method, headers and body. A non-2xx response or a 10-second timeout fails the run. Every delivery is a logged run you can inspect and replay. URLs that resolve to private or internal addresses are refused.
Payloads are not signed yet. To authenticate deliveries today, put a shared secret in a custom header. A standalone webhook-subscription endpoint with signed payloads is planned.
Idempotency
An Idempotency-Key header on create calls is planned. Today a retried create can make a duplicate, so check before you retry: list endpoints filter by customer, status and search. Two paths already deduplicate. An expense scan is rejected as a duplicate when its vendor and document number match an existing document, and imports record each source record's id, so a re-run shows those rows as already imported.
Rate limits
Per credential, per minute, with separate buckets for reads and writes. Responses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; a 429 includes Retry-After. Today each bucket allows 6,000 requests a minute. Some routes have their own lower cap: sending a document by email allows 30 a minute per credential. Every authenticated request is recorded with its route, status and duration. If a limit gets in the way of a real workflow, write to support@guliel.com.
Pricing
The API is not metered per call. The published plans are per organisation, not per seat: Free at $0 (200 invoices, 100 expense scans, 10 reports and 5 automations a month), Standard at $20 and Premium at $99 a month, with MCP access listed from Standard. Billing is not live and paid plans are not on sale yet. See /pricing.
FAQ
Does the API include the general ledger?
Yes. Guliel keeps a double-entry general ledger. Issued documents, approved expenses, payments and payroll post to it automatically, /api/journal-entries posts manual entries that must balance, the reports routes return the trial balance, balance sheet, general ledger, income statement and cash flow, and /api/ledger/export returns the ledger as CSV. The chart of accounts is fixed today; custom accounts are planned.
Is there an SDK?
Not an official one. The OpenAPI 3.1 spec is published at /api/openapi.json, and every route in the reference at /docs has samples in cURL, JavaScript, Python, Go, Rust and PHP, so you can generate a client in your language. For MCP clients there is the @guliel/mcp-server package on npm.
How is this different from the MCP server?
REST is for code. MCP is for AI clients such as Claude, ChatGPT or Copilot. The MCP tools are the same routes underneath, with the same scopes and role checks. A backend integration uses REST; an AI assistant connected through OAuth uses MCP. Both can work on the same organisation.
Can I generate country-specific invoices through the API?
Yes. The format follows the issuing organisation's country. Set it once, and every document created for that organisation renders in that country's format, as PDF, across 39 countries. Structured e-invoice files such as Peppol BIS Billing, XRechnung or ZUGFeRD are not produced today; Peppol output is planned.
How does pagination work?
List endpoints are page-based. Pass ?page=2&limit=50; limit is capped at 100. The response includes a pagination object with page, limit, total and totalPages.
Can I import from QuickBooks or Xero through the API?
Not yet. There is no QuickBooks, Xero, Zoho, Wave, FreshBooks, Invoice Ninja, Stripe or Shopify importer; connectors for all eight are planned. The /api/imports routes take a customer spreadsheet on Guliel's template, Morning client and document exports, and the Israeli uniform file (מבנה אחיד), each through a column check and a staged review before anything is committed. From other tools, export customers to the template and create new documents through the API.
Is there an SLA?
There is no contractual SLA and no public status page today. Premium lists priority support in the published price list; paid plans are not on sale yet.
Is the API versioned?
Routes are unversioned today. A versioning policy is planned, designed to add new versions beside the current routes rather than change them in place. Changes are announced in the changelog.
Create an API key on the Developer page of your dashboard. Prices are at /pricing.
Last updated: