v1 Base URL  https://app.doxbox.io Try it →

Developer reference

The Doxbox API

Read, upload, and export your account's financial documents — programmatically. Invoices, receipts, suppliers, and files, as clean JSON over HTTPS. Authenticate with a per-account key and you're one curl away.

REST · JSON Base path /api/v1 Auth Bearer dbx_… 7 endpoints
your first call
Request
curl https://app.doxbox.io/api/v1/documents?limit=1 \
  -H "Authorization: Bearer $DOXBOX_API_KEY"
200 · application/json
{
  "data": [{
    "id": 1042,
    "documentNumber": "INV-2026-118",
    "documentDate": "2026-07-14",
    "totalAmount": 1170.0,
    "currency": "ILS",
    "supplierName": "Acme Ltd"
  }],
  "nextCursor": 1041
}

Introduction

v1

The Doxbox API gives your account programmatic access to its financial documents — list and read invoices and receipts, fetch the original files, list suppliers, generate exports, and upload new documents. Everything is JSON over HTTPS, scoped to a single account.

Base URL
https://app.doxbox.io
Base path
/api/v1
Format
JSON, UTF-8
Access
Read by default; upload requires a write key

Quickstart

From zero to your first authenticated response in under a minute.

  1. Create a key. As an account admin: Account settings → Connections → API keys → Create key. Copy it — it's shown only once.
  2. Export it in your shell, then make the call:
first-call
# set once
export DOXBOX_API_KEY="dbx_..."

curl https://app.doxbox.io/api/v1/documents \
  -H "Authorization: Bearer $DOXBOX_API_KEY"

Authentication

A per-account API key, sent as a Bearer token on every request except /health.

header
Authorization: Bearer dbx_<prefix>_<secret>
!Shown once. The full key appears only at creation — Doxbox stores just a hash. Lose it? Revoke and create a new one. Revocation takes effect immediately, and a key can only ever touch its own account's data.

Scopes

Every key carries one of two permission levels, chosen at creation. Keys are read-only unless you opt in to write — calling a write endpoint with a read key returns 403 API_KEY_FORBIDDEN.

ScopeGrants
readRead documents & suppliers, generate exports (default)
writeEverything in read, plus uploading documents

Conventions

The handful of rules that hold across every endpoint.

Pagination

List endpoints use cursor pagination: ?limit= (1–100, default 25) and ?cursor= (the last id from the previous page). Responses carry nextCursor — an id, or null on the last page.

Rate limiting

Requests are limited per key — default 120 / minute. Every response carries the headers below; exceeding the limit returns 429 with a Retry-After.

response headers
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
X-RateLimit-Reset: 1785690000

Quotas

Uploads count against your plan's monthly document limit. At the limit, POST /documents returns 403 PLAN_LIMIT_EXCEEDED and no file in the batch is ingested — all-or-nothing, so you're never left with a partial upload.

Duplicate handling

Uploads are de-duplicated by file content. Re-uploading a file Doxbox already has doesn't create a second document — the response marks it "duplicate" and returns the existing id. Uploads are safe to retry.

Errors

A JSON body with a human message and, where useful, a machine-readable code.

error shape
{ "message": "API key has expired", "code": "API_KEY_EXPIRED" }
HTTPcodeMeaning
400Invalid request (bad parameters or body)
401API_KEY_MISSINGNo Authorization: Bearer header
401API_KEY_INVALIDUnknown key
401API_KEY_REVOKEDKey was revoked
401API_KEY_EXPIREDKey is past its expiry
403API_KEY_FORBIDDENKey lacks the required scope (e.g. write)
403PLAN_LIMIT_EXCEEDEDMonthly document quota reached
404Not found, or not in your account
429RATE_LIMITEDRate limit exceeded (see Retry-After)

Field reference

Enumerated values you'll see in responses.

documentTypeInvoice · Receipt · CreditInvoice · Other
paymentStatusPaid · Unpaid
currencyILS · USD · EUR · GBP · JPY · AUD

Amount fields are numbers in the document's currency. Dates are ISO 8601 strings, and may be null when Doxbox couldn't read them from the document.

The document object

Fields marked (detail) appear only on GET /documents/{id}; the list returns a lighter subset.

FieldTypeNotes
idnumberStable document id.
documentNumberstring | nullInvoice/receipt number, as read from the document.
documentTypeenumInvoice · Receipt · CreditInvoice · Other.
documentDateISO date | nullDate on the document.
poNumber (detail)string | nullPurchase-order number.
netAmount · vat · vatRate · totalAmountnumber | nullAmounts in currency; vatRate is a percentage.
currencyenumILS · USD · EUR · GBP · JPY · AUD.
paymentStatusenumPaid · Unpaid.
paymentDate (detail)ISO date | nullWhen it was marked paid.
description (detail)string | nullFree-text note.
uploadedAt (detail)ISO datetimeWhen it was added to Doxbox.
supplierName / supplier (detail)string / objectList returns the name; the detail endpoint returns { id, name, crn }.
images (detail)arrayPage image ids [{ id }] — fetch via /documents/{id}/file?image=.

GET/api/v1/healthno auth
no key needed

Service health and version. The one endpoint that needs no key — handy for uptime checks.

200 · ok
{ "status": "ok", "api": "v1" }
GET/api/v1/documents
uses your key ↑

List the account's documents, newest first. Cursor-paginated with limit and cursor.

QueryTypeNotes
limitinteger1–100, default 25
cursorintegerThe last document id from the previous page
request
curl "https://app.doxbox.io/api/v1/documents?limit=2" \
  -H "Authorization: Bearer $DOXBOX_API_KEY"
200 · application/json
{
  "data": [{
    "id": 1042, "documentNumber": "INV-2026-118",
    "totalAmount": 1170.0, "currency": "ILS",
    "documentType": "Invoice", "paymentStatus": "Unpaid",
    "supplierName": "Acme Ltd"
  }],
  "nextCursor": 1041
}
GET/api/v1/documents/{id}
uses your key ↑

A single document with full metadata and the ids of its image pages. A document that isn't in your account returns 404 — no cross-account existence leak.

200 · application/json
{
  "id": 1042, "documentNumber": "INV-2026-118",
  "documentType": "Invoice",
  "netAmount": 1000.0, "vat": 170.0, "totalAmount": 1170.0,
  "currency": "ILS", "paymentStatus": "Unpaid",
  "supplier": { "id": 9, "name": "Acme Ltd", "crn": "514123456" },
  "images": [{ "id": 5001 }, { "id": 5002 }]
}
GET/api/v1/documents/{id}/file

Returns a 302 redirect to a fresh, short-lived signed URL for the document's file — the storage bucket stays private. Optional ?image=<id> selects a specific page (defaults to the first).

follow the redirect, save the file
curl -L https://app.doxbox.io/api/v1/documents/1042/file \
  -H "Authorization: Bearer $DOXBOX_API_KEY" \
  -o invoice.pdf
POST/api/v1/documentsrequires write

Upload one or more documents. They run through the same pipeline as documents added in the app — OCR, supplier matching, de-duplication — and appear tagged as uploaded via the API. Send multipart/form-data with one or more files in the files field. Counts against your monthly quota; the batch is all-or-nothing.

request
curl -X POST https://app.doxbox.io/api/v1/documents \
  -H "Authorization: Bearer $DOXBOX_API_KEY" \
  -F "files=@invoice-july.pdf" \
  -F "files=@receipt-123.pdf"
201 · created
{
  "results": [
    { "filename": "invoice-july.pdf", "documentId": 1055, "status": "created" },
    { "filename": "receipt-123.pdf", "documentId": 980, "status": "duplicate" }
  ],
  "summary": { "total": 2, "created": 1, "duplicate": 1, "failed": 0 }
}

Per-file status is created, duplicate, or failed — a failed file carries a reason and never stops the rest of the batch.

GET/api/v1/suppliers
uses your key ↑

The account's suppliers (those with documents), with per-supplier aggregates, sorted by total amount.

200 · application/json
{
  "data": [
    { "id": 8, "name": "Globex", "crn": "514000222", "documentCount": 12, "totalAmount": 18400.0 },
    { "id": 9, "name": "Acme Ltd", "crn": "514123456", "documentCount": 5, "totalAmount": 5850.0 }
  ]
}
POST/api/v1/exports

Generate an export file for a month's documents. Returns a signed download URL valid ~12 hours. Exporting via the API never changes your documents.

FieldTypeNotes
exportTypestringexcel_monthly · csv · pdf_merged · zip
scopestringall_results (default) or selected
selectedDocumentIdsnumber[]required when scope is selected
filters.yearnumbere.g. 2026
filters.monthnumber112
request
curl -X POST https://app.doxbox.io/api/v1/exports \
  -H "Authorization: Bearer $DOXBOX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "exportType": "excel_monthly", "filters": { "year": 2026, "month": 7 } }'
200 · application/json
{
  "fileName": "Acme_2026-07.xlsx",
  "fileUrl": "https://storage.googleapis.com/.../signed...",
  "totalDocuments": 17, "skippedFiles": 0, "provider": "server"
}

fileUrl is a temporary signed URL, valid for about 12 hours.


Recipes

Common end-to-end flows, ready to adapt.

Paginate through every document

paginate.js
let cursor, all = [];
do {
  const url = `https://app.doxbox.io/api/v1/documents?limit=100` + (cursor ? `&cursor=${cursor}` : "");
  const { data, nextCursor } = await (await fetch(url, { headers })).json();
  all.push(...data); cursor = nextCursor;
} while (cursor);   // nextCursor is null on the last page

Automate a monthly export

monthly-export.sh
# create an Excel export for a month and download it
url=$(curl -s -X POST https://app.doxbox.io/api/v1/exports \
  -H "Authorization: Bearer $DOXBOX_API_KEY" -H "Content-Type: application/json" \
  -d '{ "exportType": "excel_monthly", "filters": { "year": 2026, "month": 7 } }' \
  | jq -r .fileUrl)
curl -L "$url" -o export.xlsx    # signed URL, ~12h

MCP server

Operate Doxbox from an AI client — Claude Desktop, Claude Code, Cursor — in plain language.

doxbox-mcp is a Model Context Protocol server that wraps this REST API as tools. Same per-account API key; every tool maps to an endpoint on this page. Ask your assistant to "list July's unpaid invoices", "upload this PDF", or "export last month to Excel".

Configure your client

mcp client config
// claude_desktop_config.json
{
  "mcpServers": {
    "doxbox": {
      "command": "npx",
      "args": ["-y", "doxbox-mcp"],
      "env": { "DOXBOX_API_KEY": "dbx_..." }
    }
  }
}

Tools

ToolMaps to
healthGET /health
list_documentsGET /documents
get_documentGET /documents/{id}
get_document_file_urlGET /documents/{id}/file
list_suppliersGET /suppliers
upload_documentsPOST /documents · needs write
create_exportPOST /exports

Read-safe by default — only upload_documents writes, and only with a write-scoped key. Source & setup: github.com/wmgltd/doxbox-mcp.

What it looks like

Show me July's unpaid invoices and their total.
▸ list_documents6 unpaid documents dated July 2026, totaling ₪12,480. Largest: INV-2026-118 (Acme Ltd, ₪1,170).
Export them to Excel.
▸ create_exportDone — Acme_2026-07.xlsx is ready (download link valid ~12h).