REST API
Everything the panel does goes through a versioned JSON API.
Every response is { data, error }.
| Method | Route | Auth |
|---|---|---|
* | /v1/auth/* | better-auth (email and password, GitHub) |
| GET | /v1/me | session |
| GET, POST | /v1/organizations, POST /v1/organizations/active | session |
| GET, POST | /v1/api-keys, DELETE /v1/api-keys/:id, GET /v1/api-keys/:id/secret | session |
| POST, GET | /v1/cli/auth, /v1/cli/auth/:pollToken (browser login for the CLI) | public, rate limited |
| GET, POST | /v1/cli/auth/requests/:code, /v1/cli/auth/approve | session |
| GET, DELETE | /v1/cli/status, /v1/cli/key (revokes the calling key) | API key (status also session) |
| GET, POST | /v1/sources, /v1/sources/summary, /v1/sources/import | session or API key |
| GET, PATCH, DELETE | /v1/sources/:name, POST /v1/sources/:name/test, POST /v1/sources/:name/oauth | session or API key |
| GET, POST | /v1/catalog, /v1/catalog/install | session or API key |
| GET, POST, PATCH, DELETE | /v1/memories, /v1/memories/:slug, /v1/memories/:slug/versions, /v1/memories/health, /v1/memories/import | session or API key |
| GET, POST, PATCH, DELETE | /v1/skills, /v1/skills/:slug, /v1/skills/:slug/files, /v1/skills/import | session or API key |
| GET | /v1/context/search, /v1/context/brief | session or API key |
| GET | /v1/activity/summary, /v1/onboarding, /v1/tools | session or API key |
* | /v1/mcp | API key |
| GET | /health | public |
API keys go in the Authorization: Bearer rnl_… header. Each key belongs to one organization and is rate limited (see Security).