Developers
Sales invoices, credit notes and quotes.
GET /billing List sales documentsPOST /billing Create a sales documentGET /billing/{id} Get one sales document/billingList sales documents
Returns sales invoices, credit notes, quotes and proformas for your account. Dates filter on `issueDate` (inclusive).
Required permission:
sales:invoices.read (Sales › Invoices, proformas and credit notes › Read)
Pagination: Parameters page and limit. The response includes total, page, limit, hasMore.
| Name | In | Type | Description |
|---|---|---|---|
kind | query | string | Values: INVOICE, CREDIT_NOTE, QUOTE, PROFORMA, DELIVERY_NOTE |
status | query | string | Values: DRAFT, ISSUED, PAID, PARTIALLY_PAID, OVERDUE, CANCELLED, VOID |
dateFrom | query | string (date) | Inclusive lower bound on issueDate (YYYY-MM-DD). |
dateTo | query | string (date) | Inclusive upper bound on issueDate (YYYY-MM-DD). |
page | query | integer | Default: 1 |
limit | query | integer | Default: 50 · maximum: 500 |
200 List of billing documents · application/json
| Name | Type | Description |
|---|---|---|
documents | object[] | |
documents[].id | string | |
documents[].number | string | |
documents[].kind | string | Values: INVOICE, CREDIT_NOTE, QUOTE, PROFORMA, DELIVERY_NOTE |
documents[].status | string | Values: DRAFT, ISSUED, PAID, PARTIALLY_PAID, OVERDUE, CANCELLED, VOID |
documents[].accountName | stringnullable | |
documents[].accountNif | stringnullable | |
documents[].issuerName | string | |
documents[].issueDate | string (date) | |
documents[].dueDate | string (date)nullable | |
documents[].subtotal | number | |
documents[].ivaAmount | number | |
documents[].irpfAmount | number | |
documents[].total | number | |
documents[].amountPaid | number | |
documents[].currency | string | |
documents[].items | object[] | |
documents[].items[].id | string | |
documents[].items[].description | string | |
documents[].items[].quantity | number | |
documents[].items[].unitPrice | number | |
documents[].items[].discount | numbernullable | |
documents[].items[].ivaRate | number | |
documents[].items[].irpfRate | number | |
documents[].items[].lineTotal | number | |
documents[].items[].taxCode | stringnullable | SII regime code, e.g. S1 |
documents[].items[].accountCode | stringnullable | PGC account code, e.g. 700 |
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/billing?limit=50" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/billing?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/billing?limit=50",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json() /billingCreate a sales document
Creates an invoice, credit note, quote or proforma FOR YOUR ACCOUNT (the issuer/account is forced from the token). Amounts as numbers; the server computes totals and VeriFactu fields.
Required permission:
sales:invoices.create (Sales › Invoices, proformas and credit notes › Create)
Pagination: Not paginated: returns the full set.
application/json| Name | Type | Description |
|---|---|---|
kindrequired | string | Values: INVOICE, CREDIT_NOTE, QUOTE, PROFORMA |
issueDate | string (date) | |
dueDate | string (date)nullable | |
currency | string | |
notes | stringnullable | |
itemsrequired | object[] | |
items[].descriptionrequired | string | |
items[].quantityrequired | number | |
items[].unitPricerequired | number | |
items[].ivaRate | number | e.g. 21 |
items[].irpfRate | numbernullable | |
items[].accountCode | stringnullable | PGC account, e.g. 700 |
201 Document created · application/json
| Name | Type | Description |
|---|---|---|
id | string | |
number | string | |
kind | string | Values: INVOICE, CREDIT_NOTE, QUOTE, PROFORMA, DELIVERY_NOTE |
status | string | Values: DRAFT, ISSUED, PAID, PARTIALLY_PAID, OVERDUE, CANCELLED, VOID |
accountName | stringnullable | |
accountNif | stringnullable | |
issuerName | string | |
issueDate | string (date) | |
dueDate | string (date)nullable | |
subtotal | number | |
ivaAmount | number | |
irpfAmount | number | |
total | number | |
amountPaid | number | |
currency | string | |
items | object[] | |
items[].id | string | |
items[].description | string | |
items[].quantity | number | |
items[].unitPrice | number | |
items[].discount | numbernullable | |
items[].ivaRate | number | |
items[].irpfRate | number | |
items[].lineTotal | number | |
items[].taxCode | stringnullable | SII regime code, e.g. S1 |
items[].accountCode | stringnullable | PGC account code, e.g. 700 |
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/billing" \
-H "Authorization: Bearer $BMC_TOKEN" \
-H "Content-Type: application/json" \
-d '{"kind":"INVOICE","items":[{"description":"string","quantity":1,"unitPrice":1}]}' const res = await fetch("https://app.bm.consulting/api/v1/billing", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BMC_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"kind": "INVOICE",
"items": [
{
"description": "string",
"quantity": 1,
"unitPrice": 1
}
]
}),
});
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/billing",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
json={
"kind": "INVOICE",
"items": [{
"description": "string",
"quantity": 1,
"unitPrice": 1,
}],
},
timeout=30,
)
res.raise_for_status()
data = res.json() /billing/{id}Get one sales document
Full document including line items and tax lines.
Required permission:
sales:invoices.read (Sales › Invoices, proformas and credit notes › Read)
Pagination: Not paginated: returns the full set.
| Name | In | Type | Description |
|---|---|---|---|
idrequired | path | string |
200 Billing document · application/json
| Name | Type | Description |
|---|---|---|
id | string | |
number | string | |
kind | string | Values: INVOICE, CREDIT_NOTE, QUOTE, PROFORMA, DELIVERY_NOTE |
status | string | Values: DRAFT, ISSUED, PAID, PARTIALLY_PAID, OVERDUE, CANCELLED, VOID |
accountName | stringnullable | |
accountNif | stringnullable | |
issuerName | string | |
issueDate | string (date) | |
dueDate | string (date)nullable | |
subtotal | number | |
ivaAmount | number | |
irpfAmount | number | |
total | number | |
amountPaid | number | |
currency | string | |
items | object[] | |
items[].id | string | |
items[].description | string | |
items[].quantity | number | |
items[].unitPrice | number | |
items[].discount | numbernullable | |
items[].ivaRate | number | |
items[].irpfRate | number | |
items[].lineTotal | number | |
items[].taxCode | stringnullable | SII regime code, e.g. S1 |
items[].accountCode | stringnullable | PGC account code, e.g. 700 |
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) |
404 Resource not found (or belongs to a different 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/billing/<id>" \
-H "Authorization: Bearer $BMC_TOKEN" const res = await fetch("https://app.bm.consulting/api/v1/billing/<id>", {
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/billing/<id>",
headers={"Authorization": f"Bearer {os.environ['BMC_TOKEN']}"},
timeout=30,
)
res.raise_for_status()
data = res.json()