REST API

Every action in the Celerp interface is a REST endpoint - the same API the UI uses internally. Automate workflows, connect other systems, or build your own tools. The API runs locally with your data; nothing is sent to the cloud.

🔗 Base URL

http://localhost:8000

🔑 Auth

Bearer JWT from /auth/login

📦 Format

JSON in, JSON out

📖 Spec

GET /openapi.json (OpenAPI 3.1)

Which port? The API server runs on localhost:8000 by default (change it with --api-port). Port 8080 is the web UI for people - not the API.

Authentication

Celerp uses short-lived JSON Web Tokens. Log in with your Celerp email and password to get an access token, then send it as a Bearer header on every request.

1. Log in

curl -X POST http://localhost:8000/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "password": "your-password"}'

The response contains two tokens:

{
  "access_token": "eyJhbGciOiJI...",
  "refresh_token": "eyJhbGciOiJI..."
}

2. Call the API with the token

curl http://localhost:8000/items \
  -H "Authorization: Bearer eyJhbGciOiJI..."
  • The token identifies your user, role and company, so requests are automatically scoped to that company - no extra header needed.
  • Access tokens last up to 24 hours. When one expires, get a fresh pair by POSTing your refresh_token to /auth/token/refresh.
  • Belong to more than one company? List them with GET /auth/my-companies, then get a token scoped to another with POST /auth/switch-company/{company_id}.

Tokens carry your permissions. A viewer token can read but not write; cost figures need manager role or higher. Treat tokens like passwords - anyone holding one can act as you.

Making requests

All endpoints live under http://localhost:8000 and return JSON. List endpoints return an items array and a total count:

curl "http://localhost:8000/items?limit=20&offset=0" \
  -H "Authorization: Bearer $TOKEN"
{
  "items": [
    { "id": "item:...", "sku": "WIDGET-001", "name": "Widget", "quantity": 42 }
  ],
  "total": 142
}

Pagination: pass ?limit= (default 50) and ?offset=. Most list endpoints also accept a q= search term and column filters (e.g. ?status=available).

Creating data

POST JSON to create records. Writes return the new entity's id (and the underlying event_id - every change in Celerp is an event).

curl -X POST http://localhost:8000/crm/contacts \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "email": "ap@acme.com",
    "contact_type": "customer",
    "idempotency_key": "acme-2026-06-21"
  }'

Idempotency: include an idempotency_key on any write. A retried request with the same key won't create a duplicate - safe for flaky networks and batch jobs.

Conventions

  • Errors non-2xx responses return {"detail": "..."} with a standard HTTP status code.
  • Rate limits 60 requests/minute per IP by default; login is capped at 10/minute. Exceeding a limit returns 429.
  • Permissions endpoints are gated by your role: viewer → operator → manager → admin → owner.
  • Company scope every request acts on the company in your token; switch companies to act on another.

Common endpoints

A small slice to get you started. Every module adds its own - the full list is in the OpenAPI schema below.

MethodPathDescription
POST/auth/loginGet an access token (no auth required)
GET/healthService status (no auth required)
GET/itemsList inventory items
POST/itemsCreate an item
GET/docsList documents (invoices, POs, bills, …)
POST/docsCreate a document
GET/crm/contactsList customers & suppliers
POST/crm/contactsCreate a contact
GET/dashboard/kpisBusiness KPIs

Explore the full API

The complete, always-current reference is the OpenAPI 3.1 schema your own instance generates:

GET http://localhost:8000/openapi.json

Load it into any OpenAPI tool - Postman, Insomnia, Swagger UI, or a client generator - to browse every endpoint and model, try requests, and generate a typed client in your language. Celerp ships the schema itself rather than a hosted docs page, so your API surface stays private to your instance.

Prefer plain English? The AI assistant (Connect) calls this same API for you - ask it to pull a report or create a document in natural language. And remember: anything the API can do, it does with no special access - exactly what a signed-in user could do.

{% include "lightbox.html" %}