Introduction
The belege.ai API is organized around REST. It has predictable, resource-oriented URLs, accepts form-encoded and multipart request bodies, returns JSON-encoded responses, and uses standard HTTP verbs, response codes, and authentication.
Use it to mirror your bookkeeping into your own systems: pull bank transactions and their matched documents, run full-text searches over every receipt and invoice we have collected, download the original files, and upload new documents that flow into the same extraction pipeline as Telegram and email.
Quick start
- 1Create a Public API token under Integrations → API tokens.
- 2Send it as a Bearer token in the
Authorizationheader. - 3Call
GET /api/v1/meto confirm the token works.
curl https://belege.ai/api/v1/me \
-H "Authorization: Bearer belege_live_..."const res = await fetch("https://belege.ai/api/v1/me", {
headers: { Authorization: "Bearer belege_live_..." },
});
const { data } = await res.json();import requests
res = requests.get(
"https://belege.ai/api/v1/me",
headers={"Authorization": "Bearer belege_live_..."},
)
data = res.json()["data"]{
"data": {
"id": "7b1e9c44-0c2a-4e3b-9f10-2a6d8e5b1c33",
"email": "marc@digitallyinduced.com",
"firstname": "Marc",
"lastname": "Scholten",
"companyName": "digitally induced GmbH",
"token": {
"id": "f0a1b2c3-d4e5-46f7-8a9b-0c1d2e3f4a5b",
"name": "Reporting",
"scope": "public_api:read"
},
"organizations": [
{
"id": "c2f4a9d1-3b7e-4a82-9d10-5e6f7a8b9c01",
"name": "digitally induced GmbH",
"parentOrganizationId": null
}
]
}
}Authentication
The API authenticates with personal Bearer tokens. Every request must carry an Authorization header — there is no cookie, session, or query-parameter auth. All requests must be made over HTTPS; plain HTTP requests fail.
Create a token under Integrations → API tokens. Pick "Public API", then choose the access level. The plaintext token is shown exactly once on creation — store it somewhere safe. Only a hash is kept in our database, so a lost token cannot be recovered, only replaced.
Token format
Public API tokens are prefixed with belege_live_ followed by a random secret. Treat them like passwords: never commit them to source control or expose them in client-side code.
Scopes
public_api:readreadpublic_api:writeread + writeKeep tokens server-side
A token grants access to all transactions and documents the issuing user can see. Use it only from backends you control, and revoke it from Integrations the moment it leaks.
Authorization: Bearer belege_live_2yQ8fK3mZ7xR...nA4curl https://belege.ai/api/v1/me \
-H "Authorization: Bearer belege_live_..."const res = await fetch("https://belege.ai/api/v1/me", {
headers: {
Authorization: "Bearer belege_live_...",
},
});import requests
session = requests.Session()
session.headers["Authorization"] = "Bearer belege_live_..."
res = session.get("https://belege.ai/api/v1/me"){
"error": {
"code": "invalid_bearer_token",
"message": "The bearer token is invalid, expired, revoked, or missing the public API scope."
}
}Making requests
The base URL is https://belege.ai/api/v1. Read endpoints take query parameters; the upload endpoint takes multipart/form-data. Successful responses return 200 (or 201 for uploads) with a top-level data field. List endpoints add a pagination object.
Conventions
EnvelopeobjectIDsstringMoneyintegerDatesstringScopingimplicitcurl -G https://belege.ai/api/v1/transactions \
-H "Authorization: Bearer belege_live_..." \
--data-urlencode "limit=2"const res = await fetch(
"https://belege.ai/api/v1/transactions?limit=2",
{ headers: { Authorization: "Bearer belege_live_..." } },
);
const { data, pagination } = await res.json();import requests
res = requests.get(
"https://belege.ai/api/v1/transactions",
headers={"Authorization": "Bearer belege_live_..."},
params={"limit": 2},
)
body = res.json(){
"data": [
{ "id": "a1d4f8e2-...", "amountCents": -4187, "status": "waiting_for_user" },
{ "id": "b2e5a9f3-...", "amountCents": -1990, "status": "invoice_found" }
],
"pagination": { "limit": 2, "offset": 0, "total": 184, "hasMore": true }
}Errors
belege.ai uses conventional HTTP status codes. 2xx means success, 4xx means the request was rejected (a missing parameter, a bad token, a file that is too large), and 5xx means something failed on our side. Every error response has the same shape.
Error envelope
The error object always carries a stable, machine-readable code and a human-readable message. Branch on code; show or log message.
Status codes
| Status | Meaning | Example codes |
|---|---|---|
400 | A parameter is missing or malformed. | invalid_frominvalid_statusinvalid_transaction_idunsupported_file_typefile_signature_mismatch |
401 | No valid bearer token was supplied. | missing_bearer_tokeninvalid_bearer_token |
403 | The token lacks the scope or cannot see the resource. | insufficient_scopeforbidden |
404 | The resource does not exist or is not visible. | not_found |
409 | The upload collides with an existing document. | document_already_linked |
413 | The uploaded file exceeds 128 MB. | file_too_large |
{
"error": {
"code": "invalid_status",
"message": "status contains unsupported value 'paid'. Allowed values: unprocessed, agent_running, ..."
}
}{
"error": {
"code": "file_too_large",
"message": "Maximum file size is 128 MB."
}
}Pagination
All list endpoints use limit/offset pagination and return a pagination object alongside the data array. Walk forward by increasing offset until hasMore is false.
Query parameters
limitinteger OptionalPage size, 1–200. Defaults to 50. Values above 200 are clamped.
offsetinteger OptionalZero-based number of records to skip. Defaults to 0.
Pagination object
limitintegeroffsetintegertotalintegerhasMoreboolean# Page through every transaction, 200 at a time
curl -G https://belege.ai/api/v1/transactions \
-H "Authorization: Bearer belege_live_..." \
--data-urlencode "limit=200" \
--data-urlencode "offset=0"let offset = 0;
const all = [];
while (true) {
const res = await fetch(
"https://belege.ai/api/v1/transactions?limit=200&offset=" + offset,
{ headers: { Authorization: "Bearer belege_live_..." } },
);
const { data, pagination } = await res.json();
all.push(...data);
if (!pagination.hasMore) break;
offset += pagination.limit;
}offset, all = 0, []
while True:
res = requests.get(
"https://belege.ai/api/v1/transactions",
headers={"Authorization": "Bearer belege_live_..."},
params={"limit": 200, "offset": offset},
).json()
all += res["data"]
if not res["pagination"]["hasMore"]:
break
offset += res["pagination"]["limit"]{
"pagination": {
"limit": 200,
"offset": 0,
"total": 184,
"hasMore": false
}
}Current account
/api/v1/mepublic_api:readReturns the user the token belongs to, the token's own metadata, and every organization the token can see. Use it to verify a token and to discover the organization IDs you can pass as filters.
Returns
A data object with the user, a token summary (id, name, scope), and an organizations array.
curl https://belege.ai/api/v1/me \
-H "Authorization: Bearer belege_live_..."const res = await fetch("https://belege.ai/api/v1/me", {
headers: { Authorization: "Bearer belege_live_..." },
});
const { data } = await res.json();import requests
res = requests.get(
"https://belege.ai/api/v1/me",
headers={"Authorization": "Bearer belege_live_..."},
)
data = res.json()["data"]{
"data": {
"id": "7b1e9c44-0c2a-4e3b-9f10-2a6d8e5b1c33",
"email": "marc@digitallyinduced.com",
"firstname": "Marc",
"lastname": "Scholten",
"companyName": "digitally induced GmbH",
"token": {
"id": "f0a1b2c3-d4e5-46f7-8a9b-0c1d2e3f4a5b",
"name": "Reporting",
"scope": "public_api:read"
},
"organizations": [
{
"id": "c2f4a9d1-3b7e-4a82-9d10-5e6f7a8b9c01",
"name": "digitally induced GmbH",
"parentOrganizationId": null
}
]
}
}The transaction object
A transaction is a single line from a connected bank account or payment provider. Each one moves through a status lifecycle as belege.ai finds and matches its document.
Attributes
idstringorganizationIdstring | nulltransactionDatestringbookingDatestring | nullamountCentsintegercurrencystringdescriptionstringcounterpartystring | nullibanstring | nullreferencestring | nulltransactionTypestring | nullbankAccountstring | nullbankAccountIdstring | nullstatusstringunprocessedagent_runningagent_failedwaiting_for_userwaiting_for_providerinvoice_foundignoredstatusNotestring | nullcreatedAtstringupdatedAtstringdocumentsarray{
"id": "a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34",
"organizationId": "c2f4a9d1-3b7e-4a82-9d10-5e6f7a8b9c01",
"transactionDate": "2026-03-04",
"bookingDate": "2026-03-05",
"amountCents": -4187,
"currency": "EUR",
"description": "AWS EMEA SARL",
"counterparty": "Amazon Web Services",
"iban": "LU12345678901234567890",
"reference": "EU-INV-2026-0042",
"transactionType": "debit",
"bankAccount": "Revolut Business",
"bankAccountId": "9d3b1c7a-2e4f-4a6b-8c10-1d2e3f4a5b6c",
"status": "waiting_for_user",
"statusNote": null,
"createdAt": "2026-03-05T08:12:44Z",
"updatedAt": "2026-03-05T08:12:44Z"
}List transactions
/api/v1/transactionspublic_api:readReturns a paginated list of transactions visible to the token, newest first. Combine the filters below to narrow the result; all are optional.
Query parameters
qstring OptionalFull-text search over description, counterparty, and reference. Minimum 2 characters.
fromstring OptionalOnly transactions on or after this date (YYYY-MM-DD).
tostring OptionalOnly transactions on or before this date (YYYY-MM-DD).
statusstring OptionalComma-separated statuses, e.g. waiting_for_user,invoice_found.
organizationIdstring OptionalRestrict to one visible organization (UUID).
limitinteger OptionalPage size, 1–200. Defaults to 50.
offsetinteger OptionalZero-based offset. Defaults to 0.
Returns
A data array of transaction objects plus a pagination object.
curl -G https://belege.ai/api/v1/transactions \
-H "Authorization: Bearer belege_live_..." \
--data-urlencode "q=AWS" \
--data-urlencode "from=2026-01-01" \
--data-urlencode "status=waiting_for_user,invoice_found" \
--data-urlencode "limit=25"const params = new URLSearchParams({
q: "AWS",
from: "2026-01-01",
status: "waiting_for_user,invoice_found",
limit: "25",
});
const res = await fetch(
"https://belege.ai/api/v1/transactions?" + params,
{ headers: { Authorization: "Bearer belege_live_..." } },
);
const { data, pagination } = await res.json();import requests
res = requests.get(
"https://belege.ai/api/v1/transactions",
headers={"Authorization": "Bearer belege_live_..."},
params={
"q": "AWS",
"from": "2026-01-01",
"status": "waiting_for_user,invoice_found",
"limit": 25,
},
)
body = res.json(){
"data": [
{
"id": "a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34",
"organizationId": "c2f4a9d1-3b7e-4a82-9d10-5e6f7a8b9c01",
"transactionDate": "2026-03-04",
"bookingDate": "2026-03-05",
"amountCents": -4187,
"currency": "EUR",
"description": "AWS EMEA SARL",
"counterparty": "Amazon Web Services",
"iban": "LU12345678901234567890",
"reference": "EU-INV-2026-0042",
"transactionType": "debit",
"bankAccount": "Revolut Business",
"bankAccountId": "9d3b1c7a-2e4f-4a6b-8c10-1d2e3f4a5b6c",
"status": "waiting_for_user",
"statusNote": null,
"createdAt": "2026-03-05T08:12:44Z",
"updatedAt": "2026-03-05T08:12:44Z"
}
],
"pagination": { "limit": 25, "offset": 0, "total": 1, "hasMore": false }
}Synchronize transaction changes
/api/v1/transactions/changespublic_api:readReturns transactions created or updated after a stored synchronization timestamp. The first response fixes a watermark, so changes arriving while you paginate are held for the next run instead of shifting pages.
Query parameters
sincestring OptionalRequired on the first page: an RFC 3339 timestamp. Results are strictly newer than this value.
cursorstring OptionalFor subsequent pages, pass nextCursor exactly as returned. Do not send since with a cursor.
limitinteger OptionalPage size, 1–200. Defaults to 200.
Safe synchronization loop
Start with your last completed watermark as since. Follow nextCursor until hasMore is false. Only then persist the response watermark as the since value for the next run. Cursors are opaque and must not be edited.
Use this endpoint for scheduled imports
The regular transaction list is ordered for people browsing newest transactions. This change feed is ordered by updatedAt and id for reliable machine synchronization.
curl -G https://belege.ai/api/v1/transactions/changes \
-H "Authorization: Bearer belege_live_..." \
--data-urlencode "since=2026-08-06T04:30:07Z" \
--data-urlencode "limit=200"let params = new URLSearchParams({
since: "2026-08-06T04:30:07Z",
limit: "200",
});
let watermark;
while (true) {
const res = await fetch(
"https://belege.ai/api/v1/transactions/changes?" + params,
{ headers: { Authorization: "Bearer belege_live_..." } },
);
const { data, sync } = await res.json();
await upsertTransactions(data);
watermark = sync.watermark;
if (!sync.hasMore) break;
params = new URLSearchParams({ cursor: sync.nextCursor, limit: "200" });
}
await saveCompletedWatermark(watermark);import requests
params = {"since": "2026-08-06T04:30:07Z", "limit": 200}
while True:
body = requests.get(
"https://belege.ai/api/v1/transactions/changes",
headers={"Authorization": "Bearer belege_live_..."},
params=params,
).json()
upsert_transactions(body["data"])
if not body["sync"]["hasMore"]:
save_completed_watermark(body["sync"]["watermark"])
break
params = {"cursor": body["sync"]["nextCursor"], "limit": 200}{
"data": [
{
"id": "a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34",
"transactionDate": "2026-08-06",
"amountCents": -4187,
"currency": "EUR",
"description": "AWS EMEA SARL",
"status": "invoice_found",
"createdAt": "2026-08-06T18:10:00Z",
"updatedAt": "2026-08-06T19:42:11Z"
}
],
"sync": {
"since": "2026-08-06T04:30:07Z",
"watermark": "2026-08-07T08:15:30.123Z",
"nextCursor": null,
"hasMore": false
}
}Retrieve a transaction
/api/v1/transactions/{transactionId}public_api:readFetches a single transaction by UUID, with its matched documents embedded under documents. Returns 404 if the transaction does not exist and 403 if the token cannot see it.
Path parameters
transactionIdstring RequiredUUID of the transaction to retrieve.
Returns
A data object: the transaction, plus a documents array of matched document objects.
curl https://belege.ai/api/v1/transactions/a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34 \
-H "Authorization: Bearer belege_live_..."const id = "a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34";
const res = await fetch(
"https://belege.ai/api/v1/transactions/" + id,
{ headers: { Authorization: "Bearer belege_live_..." } },
);
const { data } = await res.json();import requests
tx_id = "a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34"
res = requests.get(
f"https://belege.ai/api/v1/transactions/{tx_id}",
headers={"Authorization": "Bearer belege_live_..."},
)
data = res.json()["data"]{
"data": {
"id": "a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34",
"transactionDate": "2026-03-04",
"amountCents": -4187,
"currency": "EUR",
"description": "AWS EMEA SARL",
"counterparty": "Amazon Web Services",
"status": "invoice_found",
"createdAt": "2026-03-05T08:12:44Z",
"updatedAt": "2026-03-06T09:30:11Z",
"documents": [
{
"id": "invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44",
"sourceKind": "invoice_document",
"source": "gmail",
"fileName": "aws-invoice-2026-03.pdf",
"contentType": "application/pdf",
"documentType": "invoice",
"status": "matched",
"fileUrl": "/api/v1/documents/invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44/file"
}
]
}
}The document object
A document is any receipt, invoice, or file belege.ai has collected — from email, uploads, Telegram, connected platforms, or generated on your behalf. Documents from three internal stores are presented through one unified shape.
Document IDs are prefixed
Unlike transactions, a document id combines its source kind with a UUID, e.g. invoice_document:8f3c…. Always pass the full prefixed id to the retrieve and download endpoints.
Attributes
idstringsourceKindstringinvoice_documentdocument_extractionbusiness_meal_documentsourcestringgmailimapstripemocomollieshopifyteslamicrosofteigenbeleguploadtelegrambewirtungbrowseremail_exportlexwarereconciliationotherfileNamestringcontentTypestringfileSizeBytesinteger | nulldocumentDatestring | nullvendorstring | nullamountCentsinteger | nullcurrencystringtransactionIdstring | nullorganizationIdstring | nullsummarystring | nulldocumentTypestringinvoicereceiptcredit_notecontractbank_statementmulti_receipt_pdfreisekostenabrechnungbewirtungsbelegotherstatusstringmatchedunmatchedextractingfailedcreatedAtstringfileUrlstring{
"id": "invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44",
"sourceKind": "invoice_document",
"source": "gmail",
"fileName": "aws-invoice-2026-03.pdf",
"contentType": "application/pdf",
"fileSizeBytes": 48211,
"documentDate": "2026-03-04",
"vendor": "no-reply@aws.amazon.com",
"amountCents": null,
"currency": "EUR",
"transactionId": "a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34",
"organizationId": "c2f4a9d1-3b7e-4a82-9d10-5e6f7a8b9c01",
"summary": "Your AWS invoice for March 2026",
"documentType": "invoice",
"status": "matched",
"createdAt": "2026-03-06T09:30:11Z",
"fileUrl": "/api/v1/documents/invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44/file"
}List documents
/api/v1/documentspublic_api:readReturns a paginated list of documents visible to the token, newest first. Filters are optional and combine with AND.
Query parameters
qstring OptionalFull-text search over file name, vendor, and summary. Minimum 2 characters.
typestring OptionalComma-separated document types, e.g. invoice,receipt.
sourcestring OptionalComma-separated sources, e.g. gmail,upload.
transactionIdstring OptionalOnly documents linked to this transaction (UUID).
organizationIdstring OptionalRestrict to one visible organization (UUID).
limitinteger OptionalPage size, 1–200. Defaults to 50.
offsetinteger OptionalZero-based offset. Defaults to 0.
Returns
A data array of document objects plus a pagination object.
curl -G https://belege.ai/api/v1/documents \
-H "Authorization: Bearer belege_live_..." \
--data-urlencode "type=invoice,receipt" \
--data-urlencode "source=gmail,upload" \
--data-urlencode "limit=50"const params = new URLSearchParams({
type: "invoice,receipt",
source: "gmail,upload",
limit: "50",
});
const res = await fetch(
"https://belege.ai/api/v1/documents?" + params,
{ headers: { Authorization: "Bearer belege_live_..." } },
);
const { data, pagination } = await res.json();import requests
res = requests.get(
"https://belege.ai/api/v1/documents",
headers={"Authorization": "Bearer belege_live_..."},
params={"type": "invoice,receipt", "source": "gmail,upload", "limit": 50},
)
body = res.json(){
"data": [
{
"id": "invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44",
"sourceKind": "invoice_document",
"source": "gmail",
"fileName": "aws-invoice-2026-03.pdf",
"contentType": "application/pdf",
"documentDate": "2026-03-04",
"vendor": "no-reply@aws.amazon.com",
"transactionId": "a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34",
"documentType": "invoice",
"status": "matched",
"fileUrl": "/api/v1/documents/invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44/file"
}
],
"pagination": { "limit": 50, "offset": 0, "total": 1, "hasMore": false }
}Upload a document
/api/v1/documentspublic_api:writeUploads a file as multipart/form-data. The document enters the same extraction pipeline as email and Telegram: it is OCR'd, classified, and — if you link a transaction — matched. Requires a write token.
Body (multipart/form-data)
filefile RequiredThe document. PDF, JPG, JPEG, or PNG, up to 128 MB. The byte signature must match the extension.
transactionIdstring OptionalLink the upload to this transaction (UUID). Must be visible to the token.
organizationIdstring OptionalAssign to this organization (UUID). Must match the transaction's organization if both are given.
notestring OptionalFree-text note stored with the document.
Returns
201 Created with the new document under data. queued indicates whether extraction was scheduled. Duplicate files already linked elsewhere return 409 document_already_linked.
curl -X POST https://belege.ai/api/v1/documents \
-H "Authorization: Bearer belege_live_..." \
-F "file=@invoice.pdf" \
-F "transactionId=a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34" \
-F "note=Imported from our ERP"const form = new FormData();
form.append("file", fileInput.files[0]);
form.append("transactionId", "a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34");
const res = await fetch("https://belege.ai/api/v1/documents", {
method: "POST",
headers: { Authorization: "Bearer belege_live_..." },
body: form,
});
const { data } = await res.json();import requests
with open("invoice.pdf", "rb") as f:
res = requests.post(
"https://belege.ai/api/v1/documents",
headers={"Authorization": "Bearer belege_live_..."},
files={"file": ("invoice.pdf", f, "application/pdf")},
data={"transactionId": "a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34"},
)
data = res.json()["data"]{
"data": {
"id": "document_extraction:b9d1e3f5-7a2c-4b6d-8e90-1f2a3b4c5d6e",
"sourceKind": "document_extraction",
"fileName": "invoice.pdf",
"contentType": "application/pdf",
"fileSizeBytes": 50122,
"status": "pending",
"transactionId": "a1d4f8e2-9c3b-4f6a-8e21-7b9c0d1e2f34",
"organizationId": "c2f4a9d1-3b7e-4a82-9d10-5e6f7a8b9c01",
"queued": true,
"fileUrl": "/api/v1/documents/document_extraction:b9d1e3f5-7a2c-4b6d-8e90-1f2a3b4c5d6e/file"
}
}Retrieve a document
/api/v1/documents/{documentId}public_api:readFetches a single document's metadata by its prefixed id. To fetch the bytes, use the download endpoint below.
Path parameters
documentIdstring RequiredPrefixed id, e.g. invoice_document:<uuid>, document_extraction:<uuid>, or business_meal_document:<uuid>.
Returns
A data object holding the document. Malformed ids return 400 invalid_document_id.
curl https://belege.ai/api/v1/documents/invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44 \
-H "Authorization: Bearer belege_live_..."const id = "invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44";
const res = await fetch(
"https://belege.ai/api/v1/documents/" + encodeURIComponent(id),
{ headers: { Authorization: "Bearer belege_live_..." } },
);
const { data } = await res.json();import requests
doc_id = "invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44"
res = requests.get(
f"https://belege.ai/api/v1/documents/{doc_id}",
headers={"Authorization": "Bearer belege_live_..."},
)
data = res.json()["data"]{
"data": {
"id": "invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44",
"sourceKind": "invoice_document",
"source": "gmail",
"fileName": "aws-invoice-2026-03.pdf",
"contentType": "application/pdf",
"fileSizeBytes": 48211,
"documentDate": "2026-03-04",
"vendor": "no-reply@aws.amazon.com",
"documentType": "invoice",
"status": "matched",
"createdAt": "2026-03-06T09:30:11Z",
"fileUrl": "/api/v1/documents/invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44/file"
}
}Download a file
/api/v1/documents/{documentId}/filepublic_api:readStreams the raw bytes of a document with its original Content-Type and file name. This is the URL exposed as fileUrl on every document object. Follow redirects.
Path parameters
documentIdstring RequiredPrefixed id of the document to download.
Returns
The binary file (application/pdf, image/jpeg, or image/png) with a Content-Disposition file name.
curl -L https://belege.ai/api/v1/documents/invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44/file \
-H "Authorization: Bearer belege_live_..." \
-o invoice.pdfconst id = "invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44";
const res = await fetch(
"https://belege.ai/api/v1/documents/" + encodeURIComponent(id) + "/file",
{ headers: { Authorization: "Bearer belege_live_..." } },
);
const blob = await res.blob();import requests
doc_id = "invoice_document:e7c2b1a9-5d4f-4a3b-9c10-2e6f8a1b3c44"
res = requests.get(
f"https://belege.ai/api/v1/documents/{doc_id}/file",
headers={"Authorization": "Bearer belege_live_..."},
)
with open("invoice.pdf", "wb") as f:
f.write(res.content)HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="aws-invoice-2026-03.pdf"
%PDF-1.7
%...binary contents...OpenAPI schema
/api/v1/openapi.jsonpublicA machine-readable OpenAPI 3.1 description of every endpoint, parameter, and schema on this page. It needs no authentication, so you can generate typed clients and SDKs directly from it.
Point Stainless, openapi-generator, Speakeasy, or your tool of choice at the URL to scaffold a client in your language.
# No auth required — generate a typed client
npx @openapitools/openapi-generator-cli generate \
-i https://belege.ai/api/v1/openapi.json \
-g typescript-fetch \
-o ./belege-client