Skip to main content
POST
/
expenses
/
ai-categorize-batch
AI-categorize uncategorized expenses
curl --request POST \
  --url https://api.contazen.ro/v1/expenses/ai-categorize-batch \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "max": 123
}'
{
  "processed": 123,
  "categorized": 123,
  "skipped": 123,
  "errors": 123,
  "remaining": 123,
  "batch_size": 123,
  "cap": 123
}

Documentation Index

Fetch the complete documentation index at: https://docs.contazen.ro/llms.txt

Use this file to discover all available pages before exploring further.

When to use

After bulk-importing expenses (OCR, supplier sync, e-Factura SPV) the category_id is often null. This endpoint sweeps every such row and assigns a category from the firm’s existing list — system defaults plus custom categories, merged. Existing categorizations are never overwritten. Call repeatedly until remaining = 0. Each call processes up to cap expenses (a server-side constant returned in the response), so a large backlog can be drained in controlled passes rather than a single long-running request.

Permissions

Requires write permission on expenses.

Request

max
integer
Optional cap on the number of expenses to process this call. The server enforces its own ceiling (BATCH_MAX_PER_CALL), so very large values are clamped silently. Omit for “process up to the server cap.”

Response

{
  "data": {
    "processed":   50,
    "categorized": 47,
    "skipped":     2,
    "errors":      1,
    "remaining":   1242,
    "batch_size":  10,
    "cap":         50
  }
}
FieldMeaning
processedExpenses inspected this call.
categorizedExpenses that received a category_id.
skippedClassifier declined to assign a category (low confidence or no obvious match in the firm’s list).
errorsPer-row failures — logged server-side, retryable on next call.
remainingUncategorized expenses still queued. Stop when this hits 0.
batch_sizeExpenses per classifier call (informational).
capHard ceiling per invocation (informational).

Driver pattern

async function categorizeAll(client) {
  while (true) {
    const { data } = await client.post('/expenses/ai-categorize-batch');
    if (data.remaining === 0) return;
    // Optional: brief pause between passes.
    await new Promise(r => setTimeout(r, 500));
  }
}

Errors

  • 401 — missing / invalid bearer token
  • 403 — API key lacks write permission on expenses
  • 502 ai_unavailable — classifier call failed; safe to retry
  • 503 ai_not_configured — AI categorization is not enabled on this deployment

Authorizations

Authorization
string
header
required

Use your API key (sk_live_xxx or sk_test_xxx)

Body

application/json
max
integer

Optional override for the per-call cap. The server still enforces its own BATCH_MAX_PER_CALL ceiling, so very large values are silently clamped.

Response

Batch run summary

processed
integer

Expenses inspected this call.

categorized
integer

Expenses that received a category.

skipped
integer

Classifier declined to assign a category (low confidence or no match).

errors
integer

Per-row failures (logged server-side).

remaining
integer

Uncategorized expenses still in the queue. Call again until 0.

batch_size
integer

Expenses per classifier call (server constant).

cap
integer

Hard ceiling per invocation (server constant).