Getting started¶
Local¶
uv sync
cp .env.example .env
uv run alembic upgrade head
uv run python scripts/seed_demo.py
uv run uvicorn reckonflow.main:app --reload --port 8000
Open http://localhost:8000/docs
For durable receipt jobs (Redis running, .env has RECEIPT_QUEUE=arq):
Optional: set API_KEY in .env and send X-API-Key on all finance
/api/v1 calls (reads and writes). /health, /ready, and docs stay public.
Demo order¶
GET /api/v1/accounts— chart of accounts (after seed: CASH, TRAVEL)POST /api/v1/travel-requests— creates a pending approvalPOST /api/v1/approvals/{id}/transitionwith{"action":"approve"}POST /api/v1/expenses— amounts as strings; link to the approved tripPOST /api/v1/bank/transactions/upload— multipart CSVGET /api/v1/reconciliation/expenses/{id}/suggestionsPOST /api/v1/receipts— multipart form:file+ optionalexpense_id; returns 202; pollGET /api/v1/receipts/{id}
Always send money as JSON strings ("120.50"), never as numbers.
Deploy shape¶
| Piece | Host |
|---|---|
| API | Render |
| Receipt worker | Same Render process (arq when RECEIPT_QUEUE=arq) |
| Database | Neon |
| Idempotency + jobs | Upstash Redis |
Production checklist (Render env)¶
After each deploy, GET /ready should return HTTP 200 with "database": true.
GET /health is liveness (always 200 while the process is up). If redis is
false on either probe, idempotency is fail-open.
DATABASE_URL— Neon URL withpostgresql+asyncpg://andssl=requireREDIS_URL— Upstashrediss://URL (TLS). Rotate the token if it was ever exposed, then paste the new value into Render.API_KEY— required; production refuses to boot if empty- Confirm start logs include
alembic upgrade headreaching revision005
Details: Phase 6. Docs site: https://ikrame-ih.github.io/reckon-flow/