API reference
A read-only REST API for your organisation’s invoices, clients, companies and exchange rates. JSON over HTTPS, authenticated with your personal API keys.
Overview
| Base URL | https://ledger.aapicos.com/api/v1 |
|---|---|
| Format | JSON, UTF-8. Dates are YYYY-MM-DD; timestamps are ISO 8601 in UTC. |
| Methods | GET only. v1 is read-only. |
| Rate limit | 120 requests per minute per key. |
| Spec | OpenAPI 3.1 (JSON): import it into Postman, Insomnia or a code generator. |
Authentication
Create a key in Invoice Hub under account menu → API tokens (see API tokens). Keys start with ydk_ and are shown once. Send it as a Bearer token:
Authorization: Bearer ydk_your_key_here
Important: Treat keys like passwords. Use them from servers and scripts, never in a web page or mobile app. Revoke a leaked key immediately.
Scopes and data access
Each key carries scopes chosen when it was created, such as invoices.view. On every request the key’s scopes are checked against its owner’s current role, so a key never does more than its owner may do today. Every response is limited to the key’s own organisation.
| Scope | Allows |
|---|---|
invoices.view | List and read invoices with line items. |
payments.view | Adds the payment object (dates, amounts received) to invoice details. |
clients.view | List and read clients. |
companies.view | List and read companies. |
rates.view | List exchange rates and look up the rate for a date. |
Pagination
List endpoints take page (from 1) and per_page (1–100, default 25), and return a meta object with total, totalPages and ready-made next / prev URLs.
Errors
Errors return a JSON body {"error": {"code": "…", "message": "…"}} with one of these statuses:
| Status | Code | When |
|---|---|---|
| 401 | unauthenticated | No key, or the key is invalid, expired or revoked, or its owner lost access. |
| 403 | insufficient_scope | The key (or its owner's current role) lacks the scope the endpoint needs. |
| 403 | organisation_suspended | The organisation is suspended. |
| 404 | not_found | No such record in your organisation, or no such endpoint. |
| 405 | method_not_allowed | Anything other than GET. v1 is read-only. |
| 422 | invalid_parameter | A parameter is malformed, e.g. a date that is not YYYY-MM-DD. |
| 429 | rate_limited | More than 120 requests a minute with one key. Wait for `Retry-After` seconds. |
Endpoints
Check your key
Check your keyThe organisation, owner and effective scopes of the key you are using. A good first call.
No parameters.
curl https://ledger.aapicos.com/api/v1/me \ -H "Authorization: Bearer $INVOICEHUB_KEY"
const res = await fetch('https://ledger.aapicos.com/api/v1/me', {
headers: { Authorization: `Bearer ${process.env.INVOICEHUB_KEY}` },
});
const { data } = await res.json();
import os, requests
r = requests.get(
"https://ledger.aapicos.com/api/v1/me",
headers={"Authorization": f"Bearer {os.environ['INVOICEHUB_KEY']}"},
)
data = r.json()["data"]
{
"data": {
"organisation": {
"name": "Rao Exports Pvt Ltd"
},
"token": {
"label": "Tally sync",
"prefix": "ydk_4f1a9c2e",
"scopes": [
"clients.view",
"invoices.view"
],
"expiresAt": "2027-10-30T00:00:00Z"
},
"owner": {
"name": "Asha Rao"
}
}
}
List invoices
List invoicesinvoices.viewInvoices in your organisation, newest invoice date first.
statusquery · string | Draft, Sent, Paid or Cancelled. |
currencyquery · string | Invoice currency, e.g. USD. |
companyquery · string | Only invoices from this company id. |
clientquery · string | Only invoices to this client id. |
fromquery · date | Invoice date on or after (YYYY-MM-DD). |
toquery · date | Invoice date on or before (YYYY-MM-DD). |
pagequery · integer | Page number, from 1. Default 1. |
per_pagequery · integer | Results per page, 1–100. Default 25. |
curl https://ledger.aapicos.com/api/v1/invoices?status=Sent¤cy=USD \ -H "Authorization: Bearer $INVOICEHUB_KEY"
const res = await fetch('https://ledger.aapicos.com/api/v1/invoices?status=Sent¤cy=USD', {
headers: { Authorization: `Bearer ${process.env.INVOICEHUB_KEY}` },
});
const { data, meta } = await res.json();
import os, requests
r = requests.get(
"https://ledger.aapicos.com/api/v1/invoices?status=Sent¤cy=USD",
headers={"Authorization": f"Bearer {os.environ['INVOICEHUB_KEY']}"},
)
data = r.json()["data"]
{
"data": [
{
"id": "3f9a1c7e2b4d6a",
"invoiceNumber": "INV/26-27/0142",
"invoiceDate": "2026-10-14",
"dueDate": "2026-10-29",
"status": "Sent",
"currency": "USD",
"exchangeRate": 83.48,
"subtotal": 12480,
"taxTotal": 0,
"totalAmount": 12480,
"totalAmountInr": 1041830.4,
"lutArn": "AD270326000123X",
"paidAt": null,
"cancelledAt": null,
"createdAt": "2026-10-14T06:12:09Z",
"updatedAt": "2026-10-14T06:20:41Z",
"company": {
"id": "9c2e7b1a0d3f55",
"name": "Rao Exports"
},
"client": {
"id": "1b8d4e6f2a9c07",
"name": "Nordlicht Handels GmbH"
},
"url": "https://ledger.aapicos.com/api/v1/invoices/3f9a1c7e2b4d6a"
}
],
"meta": {
"page": 1,
"perPage": 25,
"total": 1,
"totalPages": 1,
"next": null,
"prev": null
}
}
Get an invoice
Get an invoiceinvoices.viewOne invoice with its line items. Includes `payment` (when and what was received) only if the key also holds `payments.view`.
idrequiredpath · string | The invoice's id (from a list response). |
curl https://ledger.aapicos.com/api/v1/invoices/3f9a1c7e2b4d6a \ -H "Authorization: Bearer $INVOICEHUB_KEY"
const res = await fetch('https://ledger.aapicos.com/api/v1/invoices/3f9a1c7e2b4d6a', {
headers: { Authorization: `Bearer ${process.env.INVOICEHUB_KEY}` },
});
const { data } = await res.json();
import os, requests
r = requests.get(
"https://ledger.aapicos.com/api/v1/invoices/3f9a1c7e2b4d6a",
headers={"Authorization": f"Bearer {os.environ['INVOICEHUB_KEY']}"},
)
data = r.json()["data"]
{
"data": {
"id": "3f9a1c7e2b4d6a",
"invoiceNumber": "INV/26-27/0142",
"invoiceDate": "2026-10-14",
"dueDate": "2026-10-29",
"status": "Sent",
"currency": "USD",
"exchangeRate": 83.48,
"subtotal": 12480,
"taxTotal": 0,
"totalAmount": 12480,
"totalAmountInr": 1041830.4,
"lutArn": "AD270326000123X",
"paidAt": null,
"cancelledAt": null,
"createdAt": "2026-10-14T06:12:09Z",
"updatedAt": "2026-10-14T06:20:41Z",
"company": {
"id": "9c2e7b1a0d3f55",
"name": "Rao Exports"
},
"client": {
"id": "1b8d4e6f2a9c07",
"name": "Nordlicht Handels GmbH"
},
"url": "https://ledger.aapicos.com/api/v1/invoices/3f9a1c7e2b4d6a",
"rateSourceUsed": "Customs (CBIC)",
"supplyType": "Export under LUT",
"reverseCharge": "No",
"lutFinancialYear": "2026-27",
"placeOfSupply": "Outside India (96)",
"countryOfConsumption": "Germany",
"modeOfPayment": "SWIFT wire",
"items": [
{
"lineNumber": 1,
"description": "Cotton yarn, 30s combed",
"quantity": 4800,
"rate": 2.35,
"amount": 11280,
"igstRate": 0,
"igstAmount": 0
},
{
"lineNumber": 2,
"description": "Freight to Hamburg (CIF)",
"quantity": 1,
"rate": 1200,
"amount": 1200,
"igstRate": 0,
"igstAmount": 0
}
],
"payment": {
"id": "7e1c9a3b5d2f80",
"paidOn": "2026-10-27",
"receivedOn": "2026-10-29",
"amountForeign": 12455,
"amountInr": 1038904.15,
"reference": "SWIFT 0FX2610290042"
}
}
}
List clients
List clientsclients.viewYour buyers, alphabetically.
qquery · string | Name contains. |
activequery · boolean | true for active only, false for inactive only. |
pagequery · integer | Page number, from 1. Default 1. |
per_pagequery · integer | Results per page, 1–100. Default 25. |
curl https://ledger.aapicos.com/api/v1/clients \ -H "Authorization: Bearer $INVOICEHUB_KEY"
const res = await fetch('https://ledger.aapicos.com/api/v1/clients', {
headers: { Authorization: `Bearer ${process.env.INVOICEHUB_KEY}` },
});
const { data, meta } = await res.json();
import os, requests
r = requests.get(
"https://ledger.aapicos.com/api/v1/clients",
headers={"Authorization": f"Bearer {os.environ['INVOICEHUB_KEY']}"},
)
data = r.json()["data"]
{
"data": [
{
"id": "1b8d4e6f2a9c07",
"name": "Nordlicht Handels GmbH",
"taxId": "DE811234567",
"billingAddress": "Speicherstadt 12\n20457 Hamburg",
"country": "Germany",
"currency": "USD",
"paymentTerms": "Net 15 Days",
"contactPerson": "J. Becker",
"email": "ap@nordlicht.example",
"isActive": true,
"createdAt": "2026-08-02T10:01:44Z",
"updatedAt": "2026-09-11T07:22:10Z"
}
],
"meta": {
"page": 1,
"perPage": 25,
"total": 1,
"totalPages": 1,
"next": null,
"prev": null
}
}
Get a client
Get a clientclients.viewOne buyer.
idrequiredpath · string | The client's id (from a list response). |
curl https://ledger.aapicos.com/api/v1/clients/3f9a1c7e2b4d6a \ -H "Authorization: Bearer $INVOICEHUB_KEY"
const res = await fetch('https://ledger.aapicos.com/api/v1/clients/3f9a1c7e2b4d6a', {
headers: { Authorization: `Bearer ${process.env.INVOICEHUB_KEY}` },
});
const { data } = await res.json();
import os, requests
r = requests.get(
"https://ledger.aapicos.com/api/v1/clients/3f9a1c7e2b4d6a",
headers={"Authorization": f"Bearer {os.environ['INVOICEHUB_KEY']}"},
)
data = r.json()["data"]
{
"data": {
"id": "1b8d4e6f2a9c07",
"name": "Nordlicht Handels GmbH",
"country": "Germany",
"currency": "USD",
"isActive": true
}
}
List companies
List companiescompanies.viewThe exporting entities you invoice from.
qquery · string | Name contains. |
activequery · boolean | true or false. |
pagequery · integer | Page number, from 1. Default 1. |
per_pagequery · integer | Results per page, 1–100. Default 25. |
curl https://ledger.aapicos.com/api/v1/companies \ -H "Authorization: Bearer $INVOICEHUB_KEY"
const res = await fetch('https://ledger.aapicos.com/api/v1/companies', {
headers: { Authorization: `Bearer ${process.env.INVOICEHUB_KEY}` },
});
const { data, meta } = await res.json();
import os, requests
r = requests.get(
"https://ledger.aapicos.com/api/v1/companies",
headers={"Authorization": f"Bearer {os.environ['INVOICEHUB_KEY']}"},
)
data = r.json()["data"]
{
"data": [
{
"id": "9c2e7b1a0d3f55",
"name": "Rao Exports",
"legalName": "Rao Exports Private Limited",
"gstin": "27AABCR1234F1Z5",
"state": "Maharashtra",
"stateCode": "27",
"country": "India",
"defaultCurrency": "USD",
"defaultPaymentTerms": "Net 15 Days",
"isActive": true
}
],
"meta": {
"page": 1,
"perPage": 25,
"total": 1,
"totalPages": 1,
"next": null,
"prev": null
}
}
Get a company
Get a companycompanies.viewOne exporting entity.
idrequiredpath · string | The company's id (from a list response). |
curl https://ledger.aapicos.com/api/v1/companies/3f9a1c7e2b4d6a \ -H "Authorization: Bearer $INVOICEHUB_KEY"
const res = await fetch('https://ledger.aapicos.com/api/v1/companies/3f9a1c7e2b4d6a', {
headers: { Authorization: `Bearer ${process.env.INVOICEHUB_KEY}` },
});
const { data } = await res.json();
import os, requests
r = requests.get(
"https://ledger.aapicos.com/api/v1/companies/3f9a1c7e2b4d6a",
headers={"Authorization": f"Bearer {os.environ['INVOICEHUB_KEY']}"},
)
data = r.json()["data"]
{
"data": {
"id": "9c2e7b1a0d3f55",
"name": "Rao Exports",
"gstin": "27AABCR1234F1Z5",
"defaultCurrency": "USD",
"isActive": true
}
}
List exchange rates
List exchange ratesrates.viewRates you keep, newest date first. Quote currency defaults to INR.
currencyquery · string | Base currency, e.g. USD. |
quotequery · string | Quote currency. Default INR. |
fromquery · date | Rate date on or after. |
toquery · date | Rate date on or before. |
pagequery · integer | Page number, from 1. Default 1. |
per_pagequery · integer | Results per page, 1–100. Default 25. |
curl https://ledger.aapicos.com/api/v1/exchange-rates?currency=USD \ -H "Authorization: Bearer $INVOICEHUB_KEY"
const res = await fetch('https://ledger.aapicos.com/api/v1/exchange-rates?currency=USD', {
headers: { Authorization: `Bearer ${process.env.INVOICEHUB_KEY}` },
});
const { data, meta } = await res.json();
import os, requests
r = requests.get(
"https://ledger.aapicos.com/api/v1/exchange-rates?currency=USD",
headers={"Authorization": f"Bearer {os.environ['INVOICEHUB_KEY']}"},
)
data = r.json()["data"]
{
"data": [
{
"id": "5a0c3e9b7d1f42",
"fromCurrency": "USD",
"toCurrency": "INR",
"rate": 83.48,
"rateDate": "2026-10-03",
"source": "Customs (CBIC)"
}
],
"meta": {
"page": 1,
"perPage": 25,
"total": 1,
"totalPages": 1,
"next": null,
"prev": null
}
}
Rate for a date
Rate for a daterates.viewThe rate that applies on a date: the most recent one on or before it — the same rule Invoice Hub uses when raising an invoice. `exact` is false when an earlier rate was used.
currencyrequiredquery · string | Base currency, e.g. USD. |
datequery · date | Default: today (UTC). |
quotequery · string | Default INR. |
curl https://ledger.aapicos.com/api/v1/exchange-rates/lookup?currency=USD \ -H "Authorization: Bearer $INVOICEHUB_KEY"
const res = await fetch('https://ledger.aapicos.com/api/v1/exchange-rates/lookup?currency=USD', {
headers: { Authorization: `Bearer ${process.env.INVOICEHUB_KEY}` },
});
const { data } = await res.json();
import os, requests
r = requests.get(
"https://ledger.aapicos.com/api/v1/exchange-rates/lookup?currency=USD",
headers={"Authorization": f"Bearer {os.environ['INVOICEHUB_KEY']}"},
)
data = r.json()["data"]
{
"data": {
"id": "5a0c3e9b7d1f42",
"fromCurrency": "USD",
"toCurrency": "INR",
"rate": 83.48,
"rateDate": "2026-10-03",
"source": "Customs (CBIC)",
"exact": false
}
}
Versioning
v1 only ever gains fields and endpoints; nothing is removed or renamed within v1. Example values on this page are illustrative.