Authentication
Sign up, log in, CLI auth flow, and API key management.
zectre-api has no global auth middleware. Routes enforce credentials only when their handler extracts AuthUser. Those routes are marked 🔒 in the other API pages.
Two credential types are accepted:
Authorization: Bearer <jwt>— HS256 token issued by/api/v1/auth/login(7-day expiry), or an RS256 token from zectre-catalog when JWKS is configured.X-API-Key: <key>— opaque key from/api/v1/api-keys.
POST /api/v1/auth/signup
Create a user account.
Body
- email (string): Must contain
@ - password (string): Minimum 8 characters
- name (string, optional)
Example
curl -X POST http://localhost:47080/api/v1/auth/signup \
-H 'Content-Type: application/json' \
-d '{"email":"alice@example.com","password":"hunter2abc","name":"Alice"}'// 201 Created
{ "id": "uuid", "email": "alice@example.com", "name": "Alice", "is_admin": false, "created_at": "..." }Errors — 400 INVALID_EMAIL, 400 WEAK_PASSWORD, 409 EMAIL_EXISTS
POST /api/v1/auth/login
Exchange email + password for a JWT.
Example
TOKEN=$(curl -sf -X POST http://localhost:47080/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"alice@example.com","password":"hunter2abc"}' \
| jq -r .token)// 200 OK
{
"token": "eyJ...",
"expires_at": "2026-04-03T10:00:00Z",
"user": { "id": "uuid", "email": "alice@example.com", "name": "Alice", "is_admin": false, "created_at": "..." }
}Errors — 401 INVALID_CREDENTIALS, 403 ACCOUNT_DISABLED
GET /api/v1/user 🔒
Returns the currently authenticated user.
curl -H "Authorization: Bearer $TOKEN" http://localhost:47080/api/v1/user{ "id": "uuid", "email": "alice@example.com", "name": "Alice", "is_admin": false, "created_at": "..." }CLI auth flow
The CLI opens a browser to authenticate. Three endpoints coordinate the handoff.
POST /api/v1/auth/cli/initiate
The CLI calls this first to get a one-time code and a browser URL.
Body — device_name (string, optional)
curl -X POST http://localhost:47080/api/v1/auth/cli/initiate \
-H 'Content-Type: application/json' \
-d '{"device_name":"My MacBook"}'// 200 OK
{
"code": "a1b2c3d4...",
"auth_url": "http://localhost:47081/auth/cli?code=a1b2c3d4...",
"expires_at": "2026-03-27T10:10:00Z"
}The CLI opens auth_url in the browser and begins polling.
GET /api/v1/auth/cli/status/
The CLI polls this until status is completed.
// still waiting
{ "status": "pending", "api_key": null, "user": null }
// done — CLI reads api_key and stores it
{ "status": "completed", "api_key": "zec_...", "user": { ... } }status is one of: pending, completed, expired.
POST /api/v1/auth/cli/complete
The dashboard submits the user's credentials once they log in.
Body
- code (string): From
initiate - email (string)
- password (string)
// 200 OK
{ "success": true, "api_key": "zec_...", "user": { ... } }API keys 🔒
API keys are long-lived credentials. The raw key is only shown once at creation — store it securely.
GET /api/v1/api-keys
List your keys. Raw secrets are never returned.
{
"data": [
{
"id": "uuid", "name": "CI key", "prefix": "zec_1234",
"scopes": ["*"], "expires_at": null, "last_used_at": "...", "created_at": "..."
}
]
}POST /api/v1/api-keys
Body
- name (string): Required
- scopes (array, optional): Defaults to
["*"] - expires_in_days (number, optional): Leave null for no expiry
curl -X POST http://localhost:47080/api/v1/api-keys \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name":"GitHub Actions","scopes":["*"],"expires_in_days":90}'// 201 Created — save key now, it will not be shown again
{ "id": "uuid", "name": "GitHub Actions", "key": "zec_1234abcd...", "prefix": "zec_1234", "created_at": "..." }DELETE /api/v1/api-keys/
204 No Content. Only deletes keys that belong to you.
Error codes
| Code | Meaning |
|---|---|
INVALID_EMAIL | Malformed email on signup |
WEAK_PASSWORD | Password shorter than 8 characters |
EMAIL_EXISTS | Email already registered |
INVALID_CREDENTIALS | Wrong email or password |
ACCOUNT_DISABLED | User account is inactive |
INVALID_CODE | CLI auth code not found |
CODE_EXPIRED | CLI auth code expired (10-minute window) |
SESSION_USED | CLI auth session already completed |