Developer Documentation

Public API Reference

Introduction

The Recite Public API lets you programmatically scan receipts, extract structured financial data, manage transactions and projects, run batch operations, and automate bookkeeping workflows. It is designed for AI agents, automation platforms (Zapier, Make, n8n), and custom integrations.

Base URL:https://recite.rivra.dev/apiV1/api/v1

Authentication

All requests require a Bearer token in the Authorization header. Create and manage API keys in Settings β†’ API Access.

Authorization: Bearer sk_live_YOUR_API_KEY
Key StateBehavior
activeRequests proceed normally
revokedImmediately returns 401 INVALID_API_KEY
expiredReturns 401 INVALID_API_KEY once expiry passes
!

Security: Never expose your API keys in client-side code, public repositories, or logs. If a key is compromised, rotate it immediately from the settings page.

Response Format

All API responses use a standard envelope. Choose the format via the ?format= query parameter or the Accept header.

// Success
{
  "success": true,
  "data": { ... },
  "meta": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "api_version": "v1",
    "processing_time_ms": 1234,
    "quota_limit": 200,
    "quota_remaining": 157
  }
}

// Error
{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Field 'amount' must be a positive number",
    "details": { "field": "amount" }
  },
  "meta": { "request_id": "...", "api_version": "v1", "processing_time_ms": 12 }
}

Supported formats: json (default) Β· csv Β· text

Rate Limits

Rate limits are enforced per API key using sliding window counters. When exceeded, the API returns 429 RATE_LIMITED with a Retry-After header.

WindowLimitRetry-After
Per minute100 requests60s window
Per hour500 requests3,600s window
Per day5,000 requestsContact support for higher limits

Response Headers

For better client-side throttling management, we include the following headers in every response:

X-RateLimit-LimitThe maximum number of requests you're permitted to make per window.
X-RateLimit-RemainingThe number of requests remaining in the current window.
X-RateLimit-ResetThe UTC epoch time (in seconds) at which the current rate limit window resets.
πŸ’‘

RATE_LIMITED vs QUOTA_EXCEEDED: Rate limits reset within minutes. Monthly scan quota (QUOTA_EXCEEDED) resets on your billing cycle date. Both return HTTP 429 but with different error codes.

Scopes & Permissions

Each API key can be restricted to specific scopes. If an endpoint requires a scope your key lacks, you'll receive a 403 INSUFFICIENT_SCOPE error. New keys include a set of default scopes; additional scopes must be explicitly granted at creation.

ScopeGrants Access ToDefault
scan:createPOST /scan, POST /batch/scansβœ“
scan:readGET /scan/:id, GET /batch/scans/:id/resultsβœ“
transactions:createPOST /transactions, POST /import/transactionsβœ“
transactions:readGET /transactions, GET /transactions/:id, GET /summaryβœ“
transactions:updatePATCH /transactions/:idβœ“
transactions:deleteDELETE /transactions/:idβ€”
batch:createPOST /batch/scansβ€”
batch:readGET /batch/scans/:id, GET /batch/scans/:id/resultsβ€”
bank_statements:createPOST /bank-statementsβ€”
bank_statements:readGET /bank-statements, GET /bank-statements/:idβ€”
bank_statements:deleteDELETE /bank-statements/:idβ€”
bank_transactions:readGET /bank-transactions, GET /bank-transactions/:idβ€”
bank_transactions:updatePATCH /bank-transactions/:idβ€”
bank_transactions:deleteDELETE /bank-transactions/:idβ€”
reconciliation:readGET /reconciliation/links, GET /reconciliation/summaryβ€”
reconciliation:writePOST /reconciliation/links, POST /reconciliation/auto-matchβ€”
projects:readGET /projectsβœ“
projects:writePOST /projects, PATCH /projects/:id, DELETE /projects/:idβ€”
usage:readGET /usageβœ“
export:createPOST /exportβ€”
webhooks:managePOST /webhooks, GET /webhooks, DELETE /webhooks/:idβ€”
rules:readGET /rulesβ€”
rules:writePOST /rules, PATCH /rules/:id, DELETE /rules/:idβ€”
preferences:readGET /categories, GET /vendorsβœ“
preferences:writePOST /categories, DELETE /categories/:name, POST /vendors, DELETE /vendors/:nameβ€”

Error Codes

We use standard HTTP status codes along with a machine-readable code field in the error response body.

StatusCodeMeaning
400INVALID_REQUESTMissing or invalid fields in request body or params
400INVALID_IMAGEImage cannot be decoded or is unsupported format
401INVALID_API_KEYMissing, malformed, revoked, or expired Bearer token
403INSUFFICIENT_SCOPEKey lacks the scope required by this endpoint
404NOT_FOUNDResource does not exist or belongs to a different user
409DUPLICATEIdempotency key matched an existing request (cached response returned)
413FILE_TOO_LARGEImage or payload exceeds size limit
422EXTRACTION_FAILEDLLM could not extract structured data β€” try a clearer image
429RATE_LIMITEDToo many requests in the current window β€” see Retry-After header
429QUOTA_EXCEEDEDMonthly scan limit exhausted β€” resets on billing cycle date
500INTERNAL_ERRORServer-side error

Scanning

Extract structured data from receipts using AI vision. Supports image URLs, base64 data, and raw text. Optionally auto-create a transaction when confidence meets your threshold.

Transactions

Import

Bulk-create up to 500 transactions from a JSON array or CSV file in a single request. No image processing occurs β€” you supply field values directly.

Batch Scanning

Process up to 20 receipt images asynchronously in a single job. Items are processed concurrently. Poll the status endpoint or use a webhook to receive completion notification.

Bank Statements

Upload, list, and manage CSV bank statements.

Bank Transactions

Manage individual bank transactions parsed from bank statements.

Reconciliation

Match receipt transactions with bank transactions.

Projects

Projects are named buckets that organize transactions. Assign transactions to a project via project_id in any create or update call.

Summary

Aggregate financial statistics for dashboards and reports. Returns totals and an optional breakdown by category, vendor, payment method, or month.

Webhooks

Register HTTPS endpoints to receive real-time event notifications. Recite sends a signed POST request to your URL when an event fires.

EventFired When
transaction.createdA transaction is created (manual or auto-saved from scan)
transaction.updatedA transaction field is updated via PATCH
transaction.deletedA transaction is deleted via DELETE
scan.completedA single receipt scan finishes processing (via /scan)
batch.completedA batch scan job finishes processing

Signature Verification

Every webhook request includes an X-Recite-Signature header. Verify it using HMAC-SHA256 over the raw request body with the secret from your webhook registration.

const crypto = require('crypto');

function verifyWebhook(rawBody, signatureHeader, secret) {
  if (!signatureHeader) return false;

  const [algorithm, signature] = signatureHeader.split('=');
  if (algorithm !== 'sha256') return false;

  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  try {
    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(expectedSignature)
    );
  } catch (err) {
    return false;
  }
}

// Express handler:
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-recite-signature'];
  if (!verifyWebhook(req.body, sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  const event = JSON.parse(req.body);
  // Handle event.event, event.data, event.timestamp
  res.sendStatus(200);
});

Rules

Automation rules override extracted fields during scanning. Rules are shared between the web UI and the API β€” creating a rule here makes it available in Settings, and vice versa. Rules execute in ascending priority order; the first matching rule wins.

rule_typeFormatUse case
transaction_ruleRich conditions[] + actions[] arrays with AND/ORAdvanced multi-condition rules (same as web UI)
vendor_categorySimple condition + action objectsMap a vendor to a category
default_projectSimple objectsAuto-assign vendor/category to a project
processing_preferenceSimple objectsSet payment method or category for a vendor
Example 1 β€” transaction_rule (recommended):When vendor contains β€œStarbucks”, set category to β€œCoffee” and type to β€œExpense”:
{
  "rule_type": "transaction_rule",
  "conditions": [
    { "type": "vendor_contains", "value": "Starbucks" }
  ],
  "condition_operator": "AND",
  "actions": [
    { "type": "set_category", "value": "Coffee & Beverages" },
    { "type": "set_type", "value": "Expense" }
  ],
  "priority": 1
}
Example 2 β€” vendor_category (simple):
{
  "rule_type": "vendor_category",
  "condition": { "vendor": "Starbucks" },
  "action": { "set_category": "Coffee & Beverages" },
  "priority": 1
}

Categories & Vendors

Discover and manage categories and vendors. Recite ships with a set of default categories that cannot be deleted. You can add custom categories and vendors that are shared between the web UI and the API.

Default categories:

Advertising & Marketing, Office Supplies, Rent & Lease, Utilities, Telecommunications, Insurance, Legal & Professional Services, Software & Subscriptions, Travel, Meals & Entertainment, Salaries & Wages, Payroll Taxes, Contractors & Freelancers, Bank Charges & Fees, Interest Paid, Depreciation, Other

Export

Usage Metrics

Try It Now

Ready to test? Use our interactive playground to send real requests to the Recite API.

Interactive Playground

Test the API directly from your browser. Your API key is sent directly to the API and never stored on our servers.