Skip to content

Admin & RBAC API

The Admin API covers authentication, multi-factor authentication, admin user management, role-based access control, session management, and API key lifecycle.

POST /api/v1/auth/login

Authenticates an admin and creates a session. No authentication required.

Request body (step 1 – password):

Field Type Required Description
email string Yes Admin email address.
password string Yes Admin password.
Terminal window
curl -X POST https://mail.example.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "your-password"}'

Response (no TOTP):

{
"data": {
"admin": {
"id": "0192abc0-def1-7000-8000-000000000050",
"email": "[email protected]",
"role": "super_admin",
"totp_enabled": false,
"last_login_at": "2026-04-03T18:30:00Z"
},
"session_id": "0192abc0-def1-7000-8000-000000000060",
"expires_at": "2026-04-05T12:00:00Z"
}
}

A vectis_session cookie is set automatically (HttpOnly, Secure, SameSite=Strict).

Response (TOTP required):

If the admin has TOTP enabled, the first call returns a temporary session:

{
"data": {
"requires_totp": true,
"totp_session": "a1b2c3d4e5f6..."
}
}

Request body (step 2 – TOTP code):

Field Type Required Description
totp_session string Yes Temporary token from step 1.
totp_code string Yes 6-digit TOTP code from authenticator app.
Terminal window
curl -X POST https://mail.example.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"totp_session": "a1b2c3d4e5f6...", "totp_code": "482910"}'

The TOTP session expires after 5 minutes. If the code is not provided in time, the admin must restart login from step 1.

GET /api/v1/auth/me

Returns the authenticated admin’s profile.

Terminal window
curl https://mail.example.com/api/v1/auth/me \
-H "Authorization: Bearer vectis_sk_abc123..."

Response:

{
"data": {
"id": "0192abc0-def1-7000-8000-000000000050",
"email": "[email protected]",
"role": "super_admin",
"totp_enabled": true,
"oidc_provider": null,
"last_login_at": "2026-04-04T12:00:00Z"
}
}
POST /api/v1/auth/logout

Invalidates the current session and clears the session cookie.

Terminal window
curl -X POST https://mail.example.com/api/v1/auth/logout \
-H "Authorization: Bearer vectis_sk_abc123..."
POST /api/v1/auth/logout-all

Invalidates all sessions for the current admin across all devices.

Terminal window
curl -X POST https://mail.example.com/api/v1/auth/logout-all \
-H "Authorization: Bearer vectis_sk_abc123..."
POST /api/v1/auth/totp/setup

Generates a TOTP secret and returns a provisioning URI for scanning with an authenticator app. The secret is stored encrypted but TOTP is not yet active – you must verify a code to complete enrollment.

Terminal window
curl -X POST https://mail.example.com/api/v1/auth/totp/setup \
-H "Authorization: Bearer vectis_sk_abc123..."

Response:

{
"data": {
"provisioning_uri": "otpauth://totp/Vectis:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=Vectis&algorithm=SHA1&digits=6&period=30"
}
}

Encode the provisioning_uri as a QR code for scanning, or manually enter the secret into an authenticator app.

POST /api/v1/auth/totp/verify

Completes TOTP enrollment by verifying the first code from the authenticator app. After this, TOTP will be required at login.

Field Type Required Description
code string Yes 6-digit TOTP code from authenticator app.
Terminal window
curl -X POST https://mail.example.com/api/v1/auth/totp/verify \
-H "Authorization: Bearer vectis_sk_abc123..." \
-H "Content-Type: application/json" \
-d '{"code": "482910"}'
DELETE /api/v1/auth/totp

Disables TOTP for the current admin. Requires the current TOTP code for verification to prevent unauthorized disabling.

Field Type Required Description
code string Yes Current valid TOTP code.
Terminal window
curl -X DELETE https://mail.example.com/api/v1/auth/totp \
-H "Authorization: Bearer vectis_sk_abc123..." \
-H "Content-Type: application/json" \
-d '{"code": "159263"}'

Vectis supports OpenID Connect (OIDC) SSO for admin authentication. Providers are configured in secrets.yaml.

GET /api/v1/auth/oidc/providers

Returns the list of configured OIDC providers. No authentication required.

GET /api/v1/auth/oidc/login/{provider}

Redirects the browser to the OIDC provider’s authorization endpoint.

GET /api/v1/auth/oidc/callback/{provider}

Handles the OIDC provider’s callback, creates a session, and redirects to the admin dashboard.

DELETE /api/v1/auth/oidc/disconnect

Removes the OIDC link from the current admin account. Requires authentication.

GET /api/v1/admins

Returns all admin accounts. Accessible to all authenticated roles.

Terminal window
curl https://mail.example.com/api/v1/admins \
-H "Authorization: Bearer vectis_sk_abc123..."

Response:

{
"data": [
{
"id": "0192abc0-def1-7000-8000-000000000050",
"email": "[email protected]",
"role": "super_admin",
"totp_enabled": true,
"last_login_at": "2026-04-04T12:00:00Z"
},
{
"id": "0192abc0-def1-7000-8000-000000000051",
"email": "[email protected]",
"role": "admin",
"totp_enabled": false,
"last_login_at": "2026-04-03T09:00:00Z"
}
]
}
POST /api/v1/admins

Creates a new admin account. Requires super_admin role.

Field Type Required Description
email string Yes Admin email address.
password string Yes Initial password.
role string No Role assignment (default admin).
Terminal window
curl -X POST https://mail.example.com/api/v1/admins \
-H "Authorization: Bearer vectis_sk_abc123..." \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "strong-password", "role": "domain_admin"}'
DELETE /api/v1/admins/{id}

Deletes an admin account. Requires super_admin role. All sessions for the admin are invalidated. Audit log entries are preserved with the admin ID set to null.

Terminal window
curl -X DELETE https://mail.example.com/api/v1/admins/0192abc0-... \
-H "Authorization: Bearer vectis_sk_abc123..."

Vectis uses three roles with escalating privileges:

Role Permissions
domain_admin Manage mailboxes and aliases for assigned domains only. View analytics for assigned domains. Send from assigned domains.
admin Everything domain_admin can do, plus: manage domains, manage webhooks, view abuse dashboard, manage Sieve filters, access all domains.
super_admin Everything admin can do, plus: manage other admins, manage configuration, orchestrator control, backup/restore, view audit logs, system health, cluster management.

Domain admins are assigned to specific domains via a junction table. They can only see and manage resources within those domains.

GET /api/v1/auth/sessions

Returns all active sessions for the current admin.

Terminal window
curl https://mail.example.com/api/v1/auth/sessions \
-H "Authorization: Bearer vectis_sk_abc123..."

Response:

{
"data": [
{
"id": "0192abc0-def1-7000-8000-000000000060",
"ip_address": "203.0.113.10",
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...",
"created_at": "2026-04-04T12:00:00Z",
"expires_at": "2026-04-05T12:00:00Z"
}
]
}
DELETE /api/v1/auth/sessions/{id}

Invalidates a specific session. Use this to sign out a particular device.

Terminal window
curl -X DELETE https://mail.example.com/api/v1/auth/sessions/0192abc0-... \
-H "Authorization: Bearer vectis_sk_abc123..."

API keys provide programmatic access to the Vectis API. They use the vectis_ prefix and authenticate via the Authorization: Bearer header. Keys inherit the role of the admin who created them and can be further scoped to specific domains.

GET /api/v1/api-keys

Returns API keys. super_admin sees all keys; other roles see only their own.

Terminal window
curl https://mail.example.com/api/v1/api-keys \
-H "Authorization: Bearer vectis_sk_abc123..."

Response:

{
"data": [
{
"id": "0192abc0-def1-7000-8000-000000000070",
"admin_id": "0192abc0-def1-7000-8000-000000000050",
"name": "Production sending key",
"key_prefix": "vectis_sk_abc1",
"scoped_domain_ids": ["0192abc0-def1-7000-8000-000000000001"],
"rate_limit": 60,
"last_used_at": "2026-04-04T11:55:00Z",
"expires_at": null,
"created_at": "2026-03-15T10:00:00Z"
}
]
}
POST /api/v1/api-keys

Creates a new API key. The raw key is returned only in this response – store it securely.

Field Type Required Default Description
name string Yes Descriptive name for the key.
scoped_domain_ids array No [] Restrict key to specific domains. Empty = all accessible domains.
rate_limit integer No 60 Requests per minute. Set to 0 for unlimited.
expires_in_days integer No (never) Number of days until the key expires. 0 or omit for no expiry.
Terminal window
curl -X POST https://mail.example.com/api/v1/api-keys \
-H "Authorization: Bearer vectis_sk_abc123..." \
-H "Content-Type: application/json" \
-d '{
"name": "Transactional sending",
"scoped_domain_ids": ["0192abc0-def1-7000-8000-000000000001"],
"rate_limit": 120,
"expires_in_days": 90
}'

Response (201 Created):

{
"data": {
"key": "vectis_sk_f8a2b1c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0",
"api_key": {
"id": "0192abc0-def1-7000-8000-000000000071",
"admin_id": "0192abc0-def1-7000-8000-000000000050",
"name": "Transactional sending",
"key_prefix": "vectis_sk_f8a2",
"scoped_domain_ids": ["0192abc0-def1-7000-8000-000000000001"],
"rate_limit": 120,
"expires_at": "2026-07-03T12:00:00Z",
"created_at": "2026-04-04T12:00:00Z"
}
}
}

The key field contains the full API key. It is only shown at creation time. The server stores only the SHA-256 hash – the raw key cannot be recovered.

DELETE /api/v1/api-keys/{id}

Revokes an API key immediately. Admins can revoke their own keys; super_admin can revoke any key.

Terminal window
curl -X DELETE https://mail.example.com/api/v1/api-keys/0192abc0-... \
-H "Authorization: Bearer vectis_sk_abc123..."
GET /api/v1/audit

Returns audit log entries. domain_admin users see only events related to their assigned domains.

Query parameters:

Parameter Type Description
cursor string Pagination cursor.
limit integer Items per page (default 50, max 200).
Terminal window
curl "https://mail.example.com/api/v1/audit?limit=20" \
-H "Authorization: Bearer vectis_sk_abc123..."
GET /api/v1/audit/export

Exports the full audit log. Requires super_admin role.