Developer Docs · 10

API & Authentication

Browsers authenticate with JWTs; machines authenticate with scoped API keys. Plugins declare their own scopes and guard their endpoints.

Routes

All routes live under /api/v1/: /auth/ (register, login, logout, refresh), /user/, /tarif-plans/, /invoices/ and /admin/ (admin-role gated). A plugin mounts its blueprint under its own prefix via get_url_prefix().

JWT auth

POST /api/v1/auth/login
{ "email": "…", "password": "…" }  ->  { "token": "<jwt>", "user": {…} }

# then send it on every call
Authorization: Bearer <jwt>

API keys

Machine clients use a key from the api_key table, sent as X-API-Key. Each key carries a set of scopes; an endpoint is guarded by the scope it requires. Test a key with GET /api/v1/api-keys/health.

A plugin exposing its own scope

# 1. declare the scope on the plugin object
api_scopes = [
    {"key": "loopai:posts:create",
     "label": "Create CMS posts via LoopAI"},
]

# 2. guard the endpoint with the core decorator
@require_api_key("loopai:posts:create")
def create_post(): ...

The key is hashed at rest; the scope set is the only authority over what a key can do.