Skip to content
BurnerByte

api

API Reference

BurnerByte REST API overview.

Base URL

All API endpoints are prefixed with /api/v1.

Authentication

Most endpoints require authentication via one of:

JWT Bearer Token

bash
Authorization: Bearer <access_token>

Obtain tokens via POST /auth/login or POST /auth/register. Access tokens expire after 15 minutes (configurable). Use POST /auth/refresh with the refresh token to get new tokens, and POST /auth/logout to revoke the current session. GET /auth/sso-status returns SSO configuration and password_policy settings.

Browser clients can pass use_cookie: true on login, register, login/resolve, refresh, and sso/exchange: the refresh token is then delivered as an httpOnly cookie (scoped to /api/v1/auth) and omitted from the JSON response, keeping it out of script-readable storage. refresh and logout fall back to that cookie when the body carries no token. API clients that never send the flag keep receiving both tokens in the body.

Session Limit Enforcement

When a user logs in via password and has reached their maximum number of active sessions, the API returns a 409 Conflict instead of automatically revoking the oldest session. The response includes a pending login token and the list of active sessions.

Login Response (409 — Session Limit Reached)

json
{  "error": "session limit reached",  "code": "session_limit",  "pending_token": "a1b2c3d4...",  "sessions": [    {      "id": "...",      "ip_address": "192.168.1.1",      "user_agent": "Mozilla/5.0 ...",      "last_used_at": "2026-04-28T10:30:00Z",      "created_at": "2026-04-25T08:00:00Z"    }  ],  "limit": 5}

Resolving the Conflict

To complete the login, call POST /auth/login/resolve with the pending token and the ID of the session to revoke:

json
{  "pending_token": "a1b2c3d4...",  "revoke_session_id": "550e8400-e29b-41d4-a716-446655440000"}

On success, returns the same 200 response as a normal login with user and tokens. If the session limit is still exceeded (race condition), returns another 409 with a fresh pending token and updated session list.

The pending token expires after 5 minutes. SSO logins go through the same interactive flow: the callback redirects to /login#session_conflict=true&pending_token=<token>&limit=<n>, and the frontend fetches the session list with GET /auth/login/pending-sessions?token=<token> before calling POST /auth/login/resolve. Only if the pending-login store (Redis) is unavailable does either path fall back to auto-revoking the oldest session.

The default session limit is 5 per user, configurable via defaults.max_sessions_per_user in config or PUT /admin/platform. Per-user overrides can be set via PATCH /admin/users/:id with max_sessions.

API Key

bash
Authorization: Bearer bb_<your-api-key>

API keys are scoped to a team with specific permissions. See API Keys.

Pagination

List endpoints support pagination:

bash
GET /inboxes?page=1&per_page=20

Response:

json
{  "data": [],  "total": 42,  "page": 1,  "per_page": 20,  "total_pages": 3}

Errors

json
{"error": "inbox not found", "code": "not_found"}
CodeMeaningcode value
400Bad request (validation error)validation_error
401Unauthorized (missing or invalid token)unauthenticated
403Forbidden (insufficient permissions)forbidden
404Resource not foundnot_found
409Conflict (duplicate resource or session limit reached)conflict or session_limit
429Rate limit exceededrate_limited
500Internal server errorinternal_error

Rate Limiting

Headers included in every response:

text
X-RateLimit-Limit: 100X-RateLimit-Remaining: 99X-RateLimit-Reset: 1709251200

Endpoint Groups

GroupEndpoints
SetupGET /setup/status (adds a credential-stripped datastores object while setup is incomplete), POST /setup/complete, POST /setup/test-smtp, POST /setup/test-storage
Demo (Try It)GET /try/status, POST /try/inbox, GET /try/inbox/:inboxId/emails — public, see Demo Mode
AuthPOST /auth/register, POST /auth/login, POST /auth/login/resolve, POST /auth/refresh, POST /auth/logout, GET /auth/me, PATCH /auth/me, PUT /auth/me/password, DELETE /auth/me, POST /auth/forgot-password, POST /auth/reset-password, GET /auth/verify-email/:token, GET /auth/sso-status, GET /auth/datetime-settings, GET /auth/login/pending-sessions, POST /auth/sso/exchange
SessionsGET /auth/sessions, DELETE /auth/sessions/:id, DELETE /auth/sessions
SSOGET /auth/sso/:provider, GET /auth/sso/:provider/callback
SSO IdentitiesGET /auth/me/sso, DELETE /auth/me/sso/:provider
OrgsPOST /orgs, GET /orgs, GET /orgs/:id, PATCH /orgs/:id, DELETE /orgs/:id
Org SettingsGET /orgs/:id/settings, PATCH /orgs/:id/settings, PUT /orgs/:id/settings
MembersPOST /orgs/:id/members, POST /orgs/:id/members/add, GET /orgs/:id/members, GET /orgs/:id/members/me, GET /orgs/:id/members/search, PATCH /orgs/:id/members/:uid, POST /orgs/:id/members/:uid/deactivate
InvitesPOST /orgs/:id/invites, POST /orgs/:id/invites/bulk, GET /orgs/:id/invites, DELETE /orgs/:id/invites/:iid, GET /invites/:token/preview, POST /invites/:token/accept
DomainsPOST /orgs/:id/domains, GET /orgs/:id/domains, GET /orgs/:id/domains/:did, PATCH /orgs/:id/domains/:did, DELETE /orgs/:id/domains/:did, POST /orgs/:id/domains/:did/verify, GET /orgs/:id/domains/:did/impact, GET /orgs/:id/domains/:did/verification-history, POST /orgs/:id/domains/:did/transfer, POST /orgs/:id/domains/bulk-verify, POST /orgs/:id/domains/bulk-delete
TeamsPOST /orgs/:id/teams, GET /orgs/:id/teams, GET /orgs/:id/teams/:tid, PATCH /orgs/:id/teams/:tid, DELETE /orgs/:id/teams/:tid, POST .../teams/:tid/archive, POST .../teams/:tid/restore, GET .../teams/:tid/impact, POST .../teams/:tid/leave, POST .../teams/:tid/transfer
Team MembersPOST .../teams/:tid/members, GET .../teams/:tid/members, POST .../teams/:tid/members/bulk-add, POST .../teams/:tid/members/bulk-remove, PATCH .../teams/:tid/members/:uid, DELETE .../teams/:tid/members/:uid
Domain AssignmentsPOST .../teams/:tid/domains, GET .../teams/:tid/domains, PATCH .../teams/:tid/domains/:did, DELETE .../teams/:tid/domains/:did, GET /my/domains
InboxesPOST /inboxes, GET /inboxes, GET /inboxes/:id, POST /inboxes/:id/extend, DELETE /inboxes/:id, GET /orgs/:id/teams/:tid/inboxes
EmailsGET /inboxes/:id/emails, GET /emails/:id, PATCH /emails/:id, DELETE /emails/:id, GET /emails/:id/attachments/:aid, POST /inboxes/:id/emails/mark-all-read
WebhooksPOST .../webhooks, GET .../webhooks, PATCH .../webhooks/:wid, DELETE .../webhooks/:wid, GET .../webhooks/:wid/deliveries, GET .../webhooks/:wid/stats
API KeysPOST .../api-keys, GET .../api-keys, GET .../api-keys/:kid, PATCH .../api-keys/:kid, DELETE .../api-keys/:kid, POST .../api-keys/:kid/rotate, POST .../api-keys/bulk-revoke
AnalyticsGET /orgs/:id/analytics, GET /orgs/:id/analytics/emails-per-day, GET /orgs/:id/analytics/insights, GET /orgs/:id/analytics/domain-series, GET .../teams/:tid/analytics, GET .../teams/:tid/analytics/emails-per-day, GET .../teams/:tid/analytics/insights
AuditGET /orgs/:id/audit, GET /orgs/:id/audit/export, GET /admin/audit (system admin)
FilesGET /files?key= — local-filesystem attachment passthrough
AdminGET /admin/stats, GET /admin/orgs, GET /admin/health, GET /admin/users, PATCH /admin/users/:id, DELETE /admin/users/:id, DELETE /admin/users/:id/sessions, POST /admin/users/:id/migrate-auth, GET /admin/platform, PUT /admin/platform, GET /admin/version, POST /admin/infra/test-smtp, POST /admin/infra/test-storage, GET/PUT /admin/config/mailer, GET/PUT /admin/config/storage
Admin SSOGET /admin/sso/providers, POST /admin/sso/providers, GET /admin/sso/providers/:pid, PUT /admin/sso/providers/:pid, DELETE /admin/sso/providers/:pid, POST /admin/sso/test, POST /admin/sso/providers/:pid/domain-mappings, GET /admin/sso/providers/:pid/domain-mappings, PUT /admin/sso/providers/:pid/domain-mappings/:mid, DELETE /admin/sso/providers/:pid/domain-mappings/:mid, POST /admin/sso/domain-mappings/preview
Admin RolesPOST /admin/roles, PATCH /admin/roles/:roleId, DELETE /admin/roles/:roleId
NotificationsGET /notifications, POST /notifications/mark-all-read, PATCH /notifications/:id/read, DELETE /notifications, DELETE /notifications/:id
RolesGET /roles
WebSocketPOST /ws/ticket, GET /ws/inboxes/:id, GET /ws/notifications, GET /ws/admin-stats
DocsGET /docs, GET /api/v1/docs/openapi.json
HealthGET /healthz, GET /readyz, GET /metrics — root level, not under /api/v1; the metrics path is set by metrics.path, served only when metrics.enabled, and restricted to loopback and private source IPs

The domain and team POST .../transfer endpoints require a system admin.

WebSocket Endpoints

WebSocket endpoints authenticate with a single-use ticket, not the JWT directly. Call POST /api/v1/ws/ticket with your Bearer token to obtain a ticket (a UUID stored in Redis with a 30-second TTL), then connect with ?ticket=<ticket>.

Inbox Stream

text
GET /ws/inboxes/{inboxId}?ticket=<ticket>

Streams new emails to a specific inbox in real-time. Messages are JSON with type: "email.received" and the email data in data.

Notification Stream

text
GET /ws/notifications?ticket=<ticket>

Streams all notifications for the authenticated user. Powers the notification bell in the UI. Messages include type (e.g., email.received, inbox.created, inbox.expired) and data with event details.

Admin Stats Stream

text
GET /ws/admin-stats?ticket=<ticket>

Requires system admin. Streams real-time platform statistics. Messages have type: "admin.stats" with data containing:

FieldTypeDescription
total_emailsnumberTotal emails received
active_inboxesnumberCurrently active inboxes
total_domainsnumberRegistered domains
total_usersnumberPlatform users
total_teamsnumberTeams
storage_used_bytesnumberTotal storage used

Used by the dashboard for live stat updates when auto-refresh is enabled.

OpenAPI Specification

A machine-readable OpenAPI 3.0 specification is available at:

text
GET /docs/openapi.json

This can be imported into tools like Postman, Insomnia, or used to generate client SDKs.