Management API
The management API is used by the dashboard and CLI. All endpoints require a JWT session token.
Base URL: http://localhost:3000/api
Authentication: Authorization: Bearer <jwt>
Obtain a JWT via POST /api/auth/login.
Authentication
Login
POST /api/auth/login
{ "email": "admin@example.com", "password": "your-password" }
Response:
{
"token": "eyJ...",
"refreshToken": "a3f8c2...",
"user": { "id": "uuid", "email": "admin@example.com", "role": "admin", "permissions": [] }
}
token— short-lived JWT (1 hour). Use asAuthorization: Bearer <token>on all other endpoints.refreshToken— permanent opaque token. Store securely; use it with POST /api/auth/refresh to obtain new access tokens without re-entering credentials.
Refresh
POST /api/auth/refresh
This endpoint is public (no Authorization header required).
{ "refreshToken": "a3f8c2..." }
Response:
{
"token": "eyJ...",
"user": { "id": "uuid", "email": "admin@example.com", "role": "admin", "permissions": [] }
}
Issues a new 1-hour access token. The refresh token itself is permanent and does not rotate. Returns 401 if the token is invalid or has been revoked.
The CLI and dashboard perform this refresh automatically — the CLI tries silently when the token expires or is within 5 minutes of expiry; the dashboard retries on any 401 response.
Setup
Check Setup Status
GET /api/setup/status
Returns { "configured": false } if no admin account exists yet; { "configured": true } otherwise.
Create First Admin
POST /api/setup/first-admin
Only available when configured: false.
{ "email": "admin@example.com", "password": "secure-password" }
Me (Current User)
Get Profile
GET /api/me
Update Profile
PUT /api/me
{ "email": "new@example.com", "currentPassword": "old", "newPassword": "new" }
Models
List Models
GET /api/models
Create Model
POST /api/models
{
"id": "gpt-5-mini",
"provider": "openai",
"apiKey": "sk-...",
"inputPrice": 0.25,
"outputPrice": 2.0,
"contextWindow": 128000,
"capabilities": ["functionCalling", "json"]
}
Get Model
GET /api/models/:id
Update Model
PUT /api/models/:id
Delete Model
DELETE /api/models/:id
Rotate Model API Key
POST /api/models/:id/apikey
{ "apiKey": "sk-NEW_KEY" }
Projects
List Projects
GET /api/projects
Create Project
POST /api/projects
{
"name": "My App",
"slug": "my-app",
"defaultTimeoutMs": 30000,
"models": ["gpt-5-mini"]
}
Get Project
GET /api/projects/:slug
Update Project
PUT /api/projects/:slug
Delete Project
DELETE /api/projects/:slug
Project Tokens
List Tokens
GET /api/projects/:slug/tokens
Create Token
POST /api/projects/:slug/tokens
{
"name": "production",
"limits": [
{
"metric": "cost",
"limit": 10.00,
"window": "monthly",
"mode": "extend"
}
]
}
Response includes the token value in plain text — returned once only.
Update Token
PUT /api/projects/:slug/tokens/:tokenId
Delete Token
DELETE /api/projects/:slug/tokens/:tokenId
Project Members
List Members
GET /api/projects/:slug/members
Add Member
POST /api/projects/:slug/members
{ "userId": "user-uuid", "role": "viewer" }
Update Member Role
PUT /api/projects/:slug/members/:userId
{ "role": "editor" }
Remove Member
DELETE /api/projects/:slug/members/:userId
Users
List Users
GET /api/users
Create User
POST /api/users
{ "email": "user@example.com", "password": "password", "role": "operator" }
Get User
GET /api/users/:id
Update User
PUT /api/users/:id
Delete User
DELETE /api/users/:id
Roles
List Roles
GET /api/roles
Create Role
POST /api/roles
{
"name": "billing_reviewer",
"permissions": ["project:read", "report:read"]
}
Update Role
PUT /api/roles/:name
Delete Role
DELETE /api/roles/:name
Usage
Query Usage Records
GET /api/usage
Query parameters:
| Parameter | Type | Description |
|---|---|---|
from | ISO date | Start of range |
to | ISO date | End of range |
project | string | Filter by project slug |
model | string | Filter by model ID |
outcome | string | success, error, budget_exceeded |
limit | number | Max records to return (default: 100) |
offset | number | Pagination offset |
Get Usage Record
GET /api/usage/:id
Returns the full record including the routing trace.
Settings
Get Settings
GET /api/settings
Update Settings
PUT /api/settings
{
"port": 3000,
"logLevel": "info",
"defaultTimeoutMs": 30000,
"publicUrl": "https://routerly.example.com"
}
Notifications
Test a Notification Channel
POST /api/notifications/test
{ "channelName": "my-smtp" }
Returns 200 OK on success or an error with details.
System
Get System Info
GET /api/system/info
Response:
{
"version": "1.2.3",
"uptime": 3600,
"node": "v22.0.0",
"platform": "darwin/arm64"
}