API Reference — Batch 7
API Reference — Batch 7
Section titled “API Reference — Batch 7”This batch documents the remaining undocumented API endpoint groups: WebAuthn/FIDO2 hardware key authentication, conversation tags, IP allowlist admin, SCIM token management, and conversation search.
Base URL: https://api.arbitex.example.com
Authentication: All endpoints require Authorization: Bearer <token> unless noted. Admin endpoints require an admin-scoped token.
WebAuthn / FIDO2
Section titled “WebAuthn / FIDO2”Hardware security key and passkey registration, authentication, and management. Routes are in backend/app/api/webauthn.py.
Router prefixes:
- User endpoints:
/api/auth/webauthn - Admin endpoint:
/api/admin
POST /api/auth/webauthn/register/begin
Section titled “POST /api/auth/webauthn/register/begin”Start the WebAuthn credential registration ceremony for the currently authenticated user.
Returns PublicKeyCredentialCreationOptions for use with navigator.credentials.create(). The challenge is stored server-side and verified in the complete step.
Auth: Bearer token (user)
Response 200 OK:
{ "options": { "challenge": "<base64url>", "rp": { "name": "Arbitex", "id": "api.arbitex.example.com" }, "user": { "id": "<base64url-user-id>", "name": "user@example.com", "displayName": "User Name" }, "pubKeyCredParams": [ { "type": "public-key", "alg": -7 }, { "type": "public-key", "alg": -257 } ], "timeout": 60000, "attestation": "none", "authenticatorSelection": { "userVerification": "preferred" } }}POST /api/auth/webauthn/register/complete
Section titled “POST /api/auth/webauthn/register/complete”Complete the WebAuthn registration ceremony. Verifies the attestation response from navigator.credentials.create() and stores the credential.
Auth: Bearer token (user)
Request body:
{ "id": "<credential-id>", "rawId": "<base64url>", "response": { "clientDataJSON": "<base64url>", "attestationObject": "<base64url>" }, "type": "public-key"}Response 201 Created:
{ "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "credential_id": "<base64url-credential-id>", "name": "Security Key", "created_at": "2026-03-12T21:00:00Z", "last_used_at": null}POST /api/auth/webauthn/authenticate/begin
Section titled “POST /api/auth/webauthn/authenticate/begin”Start the WebAuthn authentication ceremony. Returns assertion options for use with navigator.credentials.get().
Auth: Public (no token required)
Request body:
{ "email": "user@example.com"}Response 200 OK:
{ "options": { "challenge": "<base64url>", "timeout": 60000, "rpId": "api.arbitex.example.com", "allowCredentials": [ { "type": "public-key", "id": "<base64url-credential-id>", "transports": ["usb", "nfc"] } ], "userVerification": "preferred" }}POST /api/auth/webauthn/authenticate/complete
Section titled “POST /api/auth/webauthn/authenticate/complete”Complete the WebAuthn authentication ceremony. Verifies the assertion from navigator.credentials.get() and issues JWT access and refresh tokens.
Auth: Public (no token required)
Request body:
{ "email": "user@example.com", "id": "<credential-id>", "rawId": "<base64url>", "response": { "clientDataJSON": "<base64url>", "authenticatorData": "<base64url>", "signature": "<base64url>", "userHandle": "<base64url>" }, "type": "public-key"}Response 200 OK:
{ "access_token": "eyJ...", "refresh_token": "eyJ...", "token_type": "bearer"}The issued access token carries mfa_verified: true when the user’s org has MFA enforcement enabled and WebAuthn satisfies the MFA requirement. See MFA Enforcement.
GET /api/auth/webauthn/credentials
Section titled “GET /api/auth/webauthn/credentials”List all WebAuthn credentials registered by the current user.
Auth: Bearer token (user)
Response 200 OK:
{ "items": [ { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "credential_id": "<base64url>", "name": "YubiKey 5C", "created_at": "2026-02-10T09:00:00Z", "last_used_at": "2026-03-12T08:30:00Z" } ], "total": 1}DELETE /api/auth/webauthn/credentials/{credential_id}
Section titled “DELETE /api/auth/webauthn/credentials/{credential_id}”Delete a registered WebAuthn credential. Users can only delete their own credentials.
Auth: Bearer token (user)
Path parameter: credential_id — credential record UUID
Response 200 OK:
{ "detail": "Credential deleted"}Errors: 404 Not Found if the credential does not exist or belongs to another user.
DELETE /api/admin/users/{user_id}/webauthn
Section titled “DELETE /api/admin/users/{user_id}/webauthn”Revoke all WebAuthn credentials for a user. Admin only. Used to recover access when a user loses all hardware keys.
Auth: Bearer token (admin)
Path parameter: user_id — target user UUID
Response 200 OK:
{ "revoked": 2}Notes: This permanently removes all credentials. The user will need to re-register hardware keys on next login. Also see MFA Enforcement: Admin MFA Management.
Conversation Tags
Section titled “Conversation Tags”User-scoped tagging for conversations — create, list, update, delete tags and assign/remove them from conversations. Routes are in backend/app/api/tags.py.
Router prefix: /api/tags
POST /api/tags
Section titled “POST /api/tags”Create a new tag for the current user.
Auth: Bearer token (user)
Request body:
{ "name": "work-projects", "color": "#3b82f6"}| Field | Required | Type | Notes |
|---|---|---|---|
name | Yes | string | Tag label |
color | No | string | Hex color code for UI display |
Response 201 Created:
{ "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "work-projects", "color": "#3b82f6", "created_at": "2026-03-12T21:00:00Z"}GET /api/tags
Section titled “GET /api/tags”List all tags belonging to the current user.
Auth: Bearer token (user)
Response 200 OK:
[ { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "work-projects", "color": "#3b82f6", "created_at": "2026-03-12T21:00:00Z" }]GET /api/tags/{tag_id}
Section titled “GET /api/tags/{tag_id}”Get a single tag by ID. Only returns the tag if it belongs to the current user.
Auth: Bearer token (user)
Response 200 OK: Tag object (same as create response).
Errors: 404 Not Found if the tag does not exist or belongs to another user.
PATCH /api/tags/{tag_id}
Section titled “PATCH /api/tags/{tag_id}”Update a tag’s name or color. Both fields are optional.
Auth: Bearer token (user)
Request body:
{ "name": "personal-projects", "color": "#10b981"}Response 200 OK: Updated tag object.
Errors: 404 Not Found if the tag does not exist.
DELETE /api/tags/{tag_id}
Section titled “DELETE /api/tags/{tag_id}”Delete a tag. Also removes all conversation-tag associations for this tag.
Auth: Bearer token (user)
Response 204 No Content
Errors: 404 Not Found if the tag does not exist.
POST /api/tags/conversations/{conversation_id}/assign
Section titled “POST /api/tags/conversations/{conversation_id}/assign”Assign a tag to a conversation.
Auth: Bearer token (user)
Path parameter: conversation_id — conversation UUID
Request body:
{ "tag_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"}Response 201 Created:
{ "conversation_id": "abc12345-...", "tag_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"}Errors:
404 Not Found— conversation or tag not found409 Conflict— tag is already assigned to this conversation
DELETE /api/tags/conversations/{conversation_id}/tags/{tag_id}
Section titled “DELETE /api/tags/conversations/{conversation_id}/tags/{tag_id}”Remove a tag from a conversation.
Auth: Bearer token (user)
Response 204 No Content
Errors: 404 Not Found if the tag assignment does not exist.
IP Allowlist (Admin)
Section titled “IP Allowlist (Admin)”CRUD management of IP allowlist entries. When the allowlist is non-empty, requests from IP addresses not matching any active CIDR range are blocked by the IP allowlist middleware. Routes are in backend/app/api/ip_allowlist.py.
Router prefix: /api/admin/ip-allowlist
All endpoints require admin authentication. Changes take effect immediately — the middleware cache is invalidated on every create, update, and delete.
GET /api/admin/ip-allowlist/
Section titled “GET /api/admin/ip-allowlist/”List all IP allowlist entries, ordered by creation date (newest first).
Auth: Bearer token (admin)
Response 200 OK:
[ { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "ip_range": "10.0.0.0/8", "description": "Internal network", "tenant_id": null, "is_active": true, "created_by_id": "user-uuid", "created_at": "2026-03-01T10:00:00Z" }]| Field | Type | Description |
|---|---|---|
ip_range | string | CIDR notation (e.g. 10.0.0.0/8, 203.0.113.0/24) |
description | string | Human-readable note |
tenant_id | string|null | Scope to a specific tenant org UUID, or null for global |
is_active | boolean | If false, entry exists but is not enforced |
created_by_id | string | Admin user who created the entry |
GET /api/admin/ip-allowlist/{entry_id}
Section titled “GET /api/admin/ip-allowlist/{entry_id}”Get a single IP allowlist entry by ID.
Auth: Bearer token (admin)
Response 200 OK: Entry object (same schema as list).
Errors: 404 Not Found if the entry does not exist.
POST /api/admin/ip-allowlist/
Section titled “POST /api/admin/ip-allowlist/”Create a new IP allowlist entry.
Auth: Bearer token (admin)
Request body:
{ "ip_range": "203.0.113.0/24", "description": "Office network", "tenant_id": null, "is_active": true}Response 201 Created: The created entry object.
Notes: The CIDR range is validated by the schema layer (must be valid IPv4 or IPv6 CIDR notation). The middleware cache is cleared on success so the new entry takes effect without delay.
PUT /api/admin/ip-allowlist/{entry_id}
Section titled “PUT /api/admin/ip-allowlist/{entry_id}”Update an existing IP allowlist entry. All fields are optional (partial update).
Auth: Bearer token (admin)
Request body:
{ "description": "Updated description", "is_active": false}Response 200 OK: Updated entry object.
Notes: The middleware cache is cleared on success.
Errors: 404 Not Found if the entry does not exist.
DELETE /api/admin/ip-allowlist/{entry_id}
Section titled “DELETE /api/admin/ip-allowlist/{entry_id}”Delete an IP allowlist entry. The change takes effect immediately.
Auth: Bearer token (admin)
Response 204 No Content
Errors: 404 Not Found if the entry does not exist.
SCIM Token Management (Admin)
Section titled “SCIM Token Management (Admin)”Per-org SCIM bearer token lifecycle: creation, listing, and revocation. Tokens are stored as SHA-256 hashes — the plaintext is returned only once at creation. Routes are in backend/app/api/scim_tokens.py.
Router prefix: /api/admin/scim/tokens
SCIM token management requires admin authentication. See SCIM Provisioning for using SCIM tokens to provision users and groups.
POST /api/admin/scim/tokens
Section titled “POST /api/admin/scim/tokens”Create a new SCIM bearer token for an organisation. The plaintext token is returned once and cannot be recovered — store it securely.
Auth: Bearer token (admin)
Request body:
{ "name": "Okta SCIM Integration", "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"}| Field | Required | Type | Notes |
|---|---|---|---|
name | No | string | Human-readable label (e.g. “Okta”, “Azure AD”) |
org_id | Yes | UUID | Organisation to create the token for |
Response 201 Created:
{ "id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "Okta SCIM Integration", "token": "scim_01HXYZ....", "created_at": "2026-03-12T21:00:00Z"}Security: Copy the
tokenvalue immediately. It is not stored in plaintext and cannot be retrieved after this response.
GET /api/admin/scim/tokens
Section titled “GET /api/admin/scim/tokens”List all SCIM tokens for the admin’s organisation. Does not return plaintext tokens.
Auth: Bearer token (admin)
Response 200 OK:
[ { "id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "Okta SCIM Integration", "created_at": "2026-03-12T21:00:00Z" }]DELETE /api/admin/scim/tokens/{token_id}
Section titled “DELETE /api/admin/scim/tokens/{token_id}”Revoke a SCIM token. The token is immediately invalidated — any SCIM requests using it will fail authentication.
Auth: Bearer token (admin)
Path parameter: token_id — token record UUID
Response 204 No Content
Conversation Search
Section titled “Conversation Search”Full-text search across the current user’s conversation titles and message content. Routes are in backend/app/api/search.py.
GET /api/search/conversations
Section titled “GET /api/search/conversations”Search conversations by title and message content. Case-insensitive. Returns paginated results with matching snippets.
Auth: Bearer token (user)
Query parameters:
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
q | Yes | string | — | Search query (1–500 characters) |
page | No | integer | 1 | Page number (1-based) |
per_page | No | integer | 20 | Results per page (1–100) |
date_from | No | ISO-8601 datetime | null | Filter: conversations created on or after this date |
date_to | No | ISO-8601 datetime | null | Filter: conversations created on or before this date |
Example request:
GET /api/search/conversations?q=kubernetes+deployment&page=1&per_page=20Response 200 OK:
{ "items": [ { "id": "conv-uuid", "title": "Kubernetes Deployment Troubleshooting", "snippet": "...the kubernetes deployment failed because the image pull policy...", "created_at": "2026-03-10T14:30:00Z", "updated_at": "2026-03-10T15:00:00Z", "mode": "single" } ], "total": 4, "page": 1, "per_page": 20, "pages": 1}| Field | Type | Description |
|---|---|---|
items | array | Matching conversation results |
items[].snippet | string | Excerpt of matching message content |
total | integer | Total number of matching conversations |
page | integer | Current page |
per_page | integer | Results per page |
pages | integer | Total pages |
Notes:
- Search is scoped to the authenticated user’s own conversations only.
- Archived conversations are included in results.
- The
snippetfield contains the matching text excerpt with the query term in context.
Related Pages
Section titled “Related Pages”- MFA Enforcement — WebAuthn integration with MFA policy
- SSO Configuration — SAML and SCIM provisioning
- SCIM Provisioning API — User and group sync via SCIM 2.0
- API Reference Batch 6 — Session management, DLP events, DLP stats
- Admin: IP Allowlist — Operational context for IP allowlist management