API Documentation
Integrate your expense management workflow with external services like N8N, Zapier, or your own applications.
Authentication
All API requests require a valid API key sent in the Authorization header. You can generate API keys from Settings → API Keys.
Authorization: Bearer lxi_your_api_key_hereSecurity note
API keys are hashed before storage and shown only once at creation. Treat them like passwords. If a key is compromised, revoke it immediately from Settings.
Base URL
All endpoints are relative to:
https://brilliant-hornet-477.convex.site/api/v1Responses are JSON with CORS enabled for all origins.
Receipts
/api/v1/receipts/uploadUpload a receipt image and process it through the full AI pipeline (OCR + categorization). Returns the extracted expense data.
Headers
Content-Type: image/jpeg (or image/png, application/pdf)
X-File-Name: receipt.jpg (optional, for naming)
Authorization: Bearer lxi_...Body
Send the file as the raw binary request body(not form-data, not base64). In N8N, use an HTTP Request node with "Send Body" enabled, body type "Raw/Binary", and pipe the file content directly. Max 20 MB.
N8N Example
HTTP Request Node:
Method: POST
URL: https://brilliant-hornet-477.convex.site/api/v1/receipts/upload
Authentication: Header Auth
Name: Authorization
Value: Bearer lxi_your_key
Send Headers: ON
Content-Type: image/jpeg
X-File-Name: receipt.jpg
Send Body: ON
Body Content Type: Raw
Content Type: image/jpeg
Body: {{ $binary.data }} (from previous node)Response
{
"success": true,
"jobId": "k17f...",
"expenseId": "j57d...",
"data": {
"merchant": "Main Street Restaurant",
"amount": 29.01,
"currency": "USD",
"date": "2017-04-07",
"category": "fine-dining",
"city": "Palo Alto",
"country": "USA",
...
}
}/api/v1/receipts/status?jobId={id}Check the processing status of a receipt upload job.
Query Parameters
jobId(required) — The receipt job ID returned from the upload endpoint.
Response
{
"_id": "k17f...",
"status": "complete", // uploading | parsing | analyzing | complete | failed
"expenseId": "j57d...",
"errorMessage": null
}Expenses
/api/v1/expensesList expenses with optional filters. Returns most recent first.
Query Parameters
category— Filter by category (e.g. fine-dining, travel, fashion)status— Filter by status (processed, pending, error)from— Start date in YYYY-MM-DD formatto— End date in YYYY-MM-DD formatlimit— Max results (default: 50, max: 100)
Example
GET /api/v1/expenses?category=travel&from=2026-01-01&limit=10/api/v1/expenses/{id}Get a single expense by its ID.
Response
{
"_id": "j57d...",
"merchant": "Main Street Restaurant",
"amount": 29.01,
"currency": "USD",
"date": "2017-04-07",
"time": "11:36",
"category": "fine-dining",
"city": "Palo Alto",
"country": "USA",
"tax": 0,
"subtotal": 25.23,
"paymentMethod": "DISCOVER",
"status": "processed",
"ocrRawText": "...",
"tags": ["personal"]
}/api/v1/expensesCreate an expense manually (without receipt upload).
Body (JSON)
{
"merchant": "Restaurant Name", // required
"amount": 42.50, // required
"currency": "MXN", // required
"date": "2026-03-31", // required (YYYY-MM-DD)
"time": "14:30", // optional, default "00:00"
"category": "fine-dining", // optional, default "other"
"city": "Mexico City", // optional
"country": "Mexico", // optional
"tax": 6.80, // optional, default 0
"subtotal": 35.70, // optional
"paymentMethod": "Visa", // optional
"notes": "Business lunch", // optional
"tags": ["business", "deductible"] // optional
}Response
{ "success": true, "id": "j57d..." }/api/v1/expenses/{id}Update fields on an existing expense. Send only the fields you want to change.
Body (JSON)
{
"category": "travel",
"tags": ["business", "deductible"],
"notes": "Updated note"
}/api/v1/expenses/{id}Permanently delete an expense.
Response
{ "success": true }Summary & Analytics
/api/v1/expenses/summaryGet aggregated expense statistics. Useful for dashboards and automated reports.
Query Parameters
from— Start date (YYYY-MM-DD)to— End date (YYYY-MM-DD)
Response
{
"totalExpenses": 16,
"totalAmount": 54826.01,
"totalTax": 4963.41,
"byCategory": {
"fine-dining": { "count": 5, "total": 4546.01 },
"fashion": { "count": 4, "total": 20650.00 },
"hotels": { "count": 3, "total": 10660.00 },
...
},
"byMonth": {
"2026-03": { "count": 5, "total": 12847.00 },
"2026-02": { "count": 11, "total": 41979.01 }
},
"byStatus": {
"processed": 15,
"pending": 1
}
}Code Examples
cURL — Upload a receipt
curl -X POST \
https://brilliant-hornet-477.convex.site/api/v1/receipts/upload \
-H "Authorization: Bearer lxi_your_key" \
-H "Content-Type: image/jpeg" \
-H "X-File-Name: receipt.jpg" \
--data-binary @receipt.jpgcURL — List expenses
curl -X GET \
"https://brilliant-hornet-477.convex.site/api/v1/expenses?category=travel&from=2026-01-01" \
-H "Authorization: Bearer lxi_your_key"JavaScript — Create expense
const response = await fetch(
"https://brilliant-hornet-477.convex.site/api/v1/expenses",
{
method: "POST",
headers: {
"Authorization": "Bearer lxi_your_key",
"Content-Type": "application/json",
},
body: JSON.stringify({
merchant: "Oxxo",
amount: 42.50,
currency: "MXN",
date: "2026-03-31",
category: "other",
}),
}
);
const data = await response.json();
console.log(data.id);Python — Get summary
import requests
response = requests.get(
"https://brilliant-hornet-477.convex.site/api/v1/expenses/summary",
headers={"Authorization": "Bearer lxi_your_key"},
params={"from": "2026-01-01", "to": "2026-03-31"}
)
data = response.json()
print(f"Total: {data['totalAmount']}")
print(f"Expenses: {data['totalExpenses']}")Error Handling
All errors return a JSON body with an error field:
{ "error": "Description of what went wrong" }| Status | Meaning |
|---|---|
400 | Bad request — missing or invalid parameters |
401 | Unauthorized — invalid or missing API key |
404 | Resource not found |
500 | Server error — pipeline or processing failure |
LUX INTELLECT API v1 · Questions? Contact support