Skip to main content

Authentication

Simple bearer-style tokens in headers.

The tokens

HeaderPurposeConfigured by
X-Ledger-TokenGET endpoints (all reads)LEDGER_TOKEN env
X-Ledger-Admin-TokenPOST / write endpoints (imports, jobs, cash-requests)LEDGER_ADMIN_TOKEN env

If LEDGER_ADMIN_TOKEN is unset, admin endpoints fall back to accepting the read token. In prod, always set both.

The check

ledger/auth.py — two Depends() functions:

def require_ledger_token(x_ledger_token: str = Header(...)) -> None:
if x_ledger_token != settings.ledger_token:
raise HTTPException(status_code=401, detail="invalid ledger token")

def require_admin_token(x_ledger_admin_token: str | None = Header(None), ...) -> None:
admin = settings.ledger_admin_token or settings.ledger_token
if (x_ledger_admin_token or x_ledger_token) != admin:
raise HTTPException(status_code=401, ...)

The webhook exception

POST /v1/india/webhooks/glomopay does NOT use X-Ledger-Token. It authenticates via HMAC-SHA256 over the request body using GLOMOPAY_WEBHOOK_SECRET. See Webhooks.

CORS

The API allows browser calls from origins listed in LEDGER_UI_ORIGINS:

http://localhost:3000,http://localhost:3100,http://127.0.0.1:3000

Add production origins to the env in Coolify.