Developers
Double-entry books: journal, chart of accounts, financial reports, exports.
GET /books/{companyId}/journal-lines List posted journal linesGET /books/{companyId}/accounts Chart of accounts with period balancesGET /books/{companyId}/opening-balances Opening balances for a yearPOST /books/{companyId}/opening-balances Set opening balances for a yearGET /books/{companyId}/consolidation Consolidated figuresGET /books/{companyId}/cost-centers/allocations Cost-centre allocationsGET /books/{companyId}/reports/profit-loss Profit & Loss (JSON)GET /books/{companyId}/reports/balance-sheet Balance sheet (JSON)GET /books/{companyId}/reports/trial-balance Trial balance (JSON)GET /books/{companyId}/reports/{report}/export Export a report as CSV / XLSX / PDF/books/{companyId}/journal-linesList posted journal lines
Paginated POSTED journal lines for a date range, optionally filtered by account-code prefix. Dates default to the current quarter. Amounts are decimal strings.
Required permission:
accounting:journal.read (Accounting › Journal › Read)
Pagination: Parameters page and limit. The response includes total, page, limit, hasMore.
| Name | In | Type | Description |
|---|---|---|---|
companyIdrequired | path | string | Your account id (must match the token's tenant). |
from | query | string (date) | |
to | query | string (date) | |
account | query | string | PGC account-code prefix filter, e.g. '400' or '7'. |
page | query | integer | Default: 1 |
limit | query | integer | Default: 100 · maximum: 500 |
200 Paginated journal lines · application/json
| Name | Type | Description |
|---|---|---|
data | object[] | |
data[].id | string | |
data[].entryDate | string (date) | |
data[].entryNumber | integernullable | |
data[].period | string | Accounting period, e.g. 2026-Q1 |
data[].reference | stringnullable | |
data[].entryDescription | string | |
data[].accountCode | string | |
data[].lineDescription | stringnullable | |
data[].debit | string | Decimal string, e.g. 1234.56 |
data[].credit | string | Decimal string, e.g. 0.00 |
data[].currency | string | |
pagination | object | |
pagination.page | integer | |
pagination.limit | integer | |
pagination.total | integer | |
pagination.hasMore | boolean | |
total | integer | Total items matching the filter. |
page | integer | Page returned (starts at 1). |
limit | integer | Page size applied. |
hasMore | boolean | There are more pages after this one. |
400 Invalid date format · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
401 Missing or invalid Bearer token. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
403 Token lacks the required permission, or the resource is outside the token's tenant. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
429 Rate limit exceeded. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
curl -X GET "https://app.bm.consulting/api/v1/books/<companyId>/journal-lines?limit=50" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/books/<companyId>/journal-lines?limit=50", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/books/<companyId>/journal-lines?limit=50",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /books/{companyId}/accountsChart of accounts with period balances
Chart of accounts with computed period balances (netBalance = openingBalance + debitTotal - creditTotal). Amounts are decimal strings.
Required permission:
accounting:ledger_accounts.read (Accounting › Chart of accounts › Read)
Pagination: Parameters page and limit. The response includes total, page, limit, hasMore.
| Name | In | Type | Description |
|---|---|---|---|
companyIdrequired | path | string | |
from | query | string (date) | |
to | query | string (date) | |
type | query | string | Values: asset, liability, equity, income, expense |
active | query | boolean | Default: true |
page | query | integer | Default: 1 |
limit | query | integer | Default: 200 · maximum: 500 |
200 Chart of accounts · application/json
| Name | Type | Description |
|---|---|---|
data | object[] | |
data[].code | string | PGC account code, e.g. 400 |
data[].name | string | |
data[].type | string | Values: asset, liability, equity, income, expense |
data[].isActive | boolean | |
data[].openingBalance | string | |
data[].debitTotal | string | |
data[].creditTotal | string | |
data[].netBalance | string | openingBalance + debitTotal - creditTotal |
pagination | object | |
pagination.page | integer | |
pagination.limit | integer | |
pagination.total | integer | |
pagination.hasMore | boolean | |
total | integer | Total items matching the filter. |
page | integer | Page returned (starts at 1). |
limit | integer | Page size applied. |
hasMore | boolean | There are more pages after this one. |
401 Missing or invalid Bearer token. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
403 Token lacks the required permission, or the resource is outside the token's tenant. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
429 Rate limit exceeded. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
curl -X GET "https://app.bm.consulting/api/v1/books/<companyId>/accounts?limit=50" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/books/<companyId>/accounts?limit=50", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/books/<companyId>/accounts?limit=50",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /books/{companyId}/opening-balancesOpening balances for a year
Seed (opening) balances per account for the requested fiscal year. Amounts are decimal strings.
Required permission:
accounting:opening_balances.read (Accounting › Opening balances › Read)
Pagination: Not paginated: returns the full set.
| Name | In | Type | Description |
|---|---|---|---|
companyIdrequired | path | string | |
year | query | integer |
200 Opening balances
401 Missing or invalid Bearer token. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
403 Token lacks the required permission, or the resource is outside the token's tenant. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
429 Rate limit exceeded. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
curl -X GET "https://app.bm.consulting/api/v1/books/<companyId>/opening-balances" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/books/<companyId>/opening-balances", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/books/<companyId>/opening-balances",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /books/{companyId}/opening-balancesSet opening balances for a year
Seeds per-account opening balances for a fiscal year. `replace=true` overwrites existing seeds. Amounts as decimal strings. `companyId` must match your account.
Required permission:
accounting:opening_balances.create (Accounting › Opening balances › Create)
Pagination: Not paginated: returns the full set.
| Name | In | Type | Description |
|---|---|---|---|
companyIdrequired | path | string | |
replace | query | boolean | Default: false |
application/json| Name | Type | Description |
|---|---|---|
yearrequired | integer | |
balancesrequired | object[] | |
balances[].accountCode | string | |
balances[].amount | string | Decimal string |
200 Opening balances stored
400 Validation error · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
401 Missing or invalid Bearer token. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
403 Token lacks the required permission, or the resource is outside the token's tenant. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
429 Rate limit exceeded. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
curl -X POST "https://app.bm.consulting/api/v1/books/<companyId>/opening-balances" \
-H "Authorization: Bearer $BMC_TOKEN" \
-H "Content-Type: application/json" \
-d '{"year":2026,"balances":[{"accountCode":"570","amount":"string"}]}' const res = await fetch("https://app.bm.consulting/api/v1/books/<companyId>/opening-balances", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"year": 2026,
"balances": [
{
"accountCode": "570",
"amount": "string"
}
]
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.post(
"https://app.bm.consulting/api/v1/books/<companyId>/opening-balances",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
json={
"year": 2026,
"balances": [{
"accountCode": "570",
"amount": "string",
}],
},
timeout=30,
)
res.raise_for_status()
data = res.json() /books/{companyId}/consolidationConsolidated figures
Consolidated balances across the account's companies. Amounts are decimal strings.
Required permission:
accounting:reports.read (Accounting › Reports (P&L, balance sheet, ledger) › Read)
Pagination: Not paginated: returns the full set.
| Name | In | Type | Description |
|---|---|---|---|
companyIdrequired | path | string | |
from | query | string (date) | |
to | query | string (date) |
200 Consolidation result
401 Missing or invalid Bearer token. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
403 Token lacks the required permission, or the resource is outside the token's tenant. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
429 Rate limit exceeded. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
curl -X GET "https://app.bm.consulting/api/v1/books/<companyId>/consolidation" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/books/<companyId>/consolidation", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/books/<companyId>/consolidation",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /books/{companyId}/cost-centers/allocationsCost-centre allocations
Allocations per cost centre with a summary. Amounts are decimal strings.
Required permission:
accounting:reports.read (Accounting › Reports (P&L, balance sheet, ledger) › Read)
Pagination: Not paginated: returns the full set.
| Name | In | Type | Description |
|---|---|---|---|
companyIdrequired | path | string | |
from | query | string (date) | |
to | query | string (date) |
200 Allocations + summary
401 Missing or invalid Bearer token. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
403 Token lacks the required permission, or the resource is outside the token's tenant. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
429 Rate limit exceeded. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
curl -X GET "https://app.bm.consulting/api/v1/books/<companyId>/cost-centers/allocations" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/books/<companyId>/cost-centers/allocations", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/books/<companyId>/cost-centers/allocations",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /books/{companyId}/reports/profit-lossProfit & Loss (JSON)
Cuenta de Pérdidas y Ganancias for a period. Dates default to the current quarter. Amounts are decimal strings.
Required permission:
accounting:reports.read (Accounting › Reports (P&L, balance sheet, ledger) › Read)
Pagination: Not paginated: returns the full set.
| Name | In | Type | Description |
|---|---|---|---|
companyIdrequired | path | string | |
from | query | string (date) | |
to | query | string (date) |
200 P&L report · application/json
| Name | Type | Description |
|---|---|---|
companyId | string | |
from | string (date) | |
to | string (date) | |
rows | object[] | |
rows[].accountCode | string | |
rows[].label | string | |
rows[].amount | string | Decimal string |
401 Missing or invalid Bearer token. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
403 Token lacks the required permission, or the resource is outside the token's tenant. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
429 Rate limit exceeded. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
curl -X GET "https://app.bm.consulting/api/v1/books/<companyId>/reports/profit-loss" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/books/<companyId>/reports/profit-loss", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/books/<companyId>/reports/profit-loss",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /books/{companyId}/reports/balance-sheetBalance sheet (JSON)
Balance (Activo/Pasivo) for a period. Amounts are decimal strings.
Required permission:
accounting:reports.read (Accounting › Reports (P&L, balance sheet, ledger) › Read)
Pagination: Not paginated: returns the full set.
| Name | In | Type | Description |
|---|---|---|---|
companyIdrequired | path | string | |
from | query | string (date) | |
to | query | string (date) |
200 Balance sheet · application/json
| Name | Type | Description |
|---|---|---|
companyId | string | |
from | string (date) | |
to | string (date) | |
rows | object[] | |
rows[].accountCode | string | |
rows[].label | string | |
rows[].amount | string | Decimal string |
401 Missing or invalid Bearer token. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
403 Token lacks the required permission, or the resource is outside the token's tenant. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
429 Rate limit exceeded. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
curl -X GET "https://app.bm.consulting/api/v1/books/<companyId>/reports/balance-sheet" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/books/<companyId>/reports/balance-sheet", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/books/<companyId>/reports/balance-sheet",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /books/{companyId}/reports/trial-balanceTrial balance (JSON)
Sumas y saldos for a period. Amounts are decimal strings.
Required permission:
accounting:reports.read (Accounting › Reports (P&L, balance sheet, ledger) › Read)
Pagination: Not paginated: returns the full set.
| Name | In | Type | Description |
|---|---|---|---|
companyIdrequired | path | string | |
from | query | string (date) | |
to | query | string (date) |
200 Trial balance · application/json
| Name | Type | Description |
|---|---|---|
companyId | string | |
from | string (date) | |
to | string (date) | |
rows | object[] | |
rows[].accountCode | string | |
rows[].label | string | |
rows[].amount | string | Decimal string |
401 Missing or invalid Bearer token. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
403 Token lacks the required permission, or the resource is outside the token's tenant. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
429 Rate limit exceeded. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
curl -X GET "https://app.bm.consulting/api/v1/books/<companyId>/reports/trial-balance" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/books/<companyId>/reports/trial-balance", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json(); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/books/<companyId>/reports/trial-balance",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /books/{companyId}/reports/{report}/exportExport a report as CSV / XLSX / PDF
Streams the chosen report as a file. `report` is one of `profit-loss`, `balance-sheet`, `trial-balance`, `libro-diario`, `libro-mayor`.
Required permission:
accounting:reports.export (Accounting › Reports (P&L, balance sheet, ledger) › Export)
Pagination: Not paginated: returns the full set.
| Name | In | Type | Description |
|---|---|---|---|
companyIdrequired | path | string | |
reportrequired | path | string | Values: profit-loss, balance-sheet, trial-balance, libro-diario, libro-mayor |
formatrequired | query | string | Values: csv, xlsx, pdf |
from | query | string (date) | |
to | query | string (date) |
200 The report file · text/csv
400 Missing or invalid ?format= · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
401 Missing or invalid Bearer token. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
403 Token lacks the required permission, or the resource is outside the token's tenant. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
429 Rate limit exceeded. · application/json
| Name | Type | Description |
|---|---|---|
error | string | Human-readable error message |
required_permission | string | Present on 403 - the missing permission (area:resource.action) |
curl -X GET "https://app.bm.consulting/api/v1/books/<companyId>/reports/profit-loss/export?format=csv" \
-H "Authorization: Bearer $BMC_TOKEN" \
-o fichero const res = await fetch("https://app.bm.consulting/api/v1/books/<companyId>/reports/profit-loss/export?format=csv", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
},
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const file = Buffer.from(await res.arrayBuffer()); import os
import requests
res = requests.get(
"https://app.bm.consulting/api/v1/books/<companyId>/reports/profit-loss/export?format=csv",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
contenido = res.content