Sovra Sovra

API Reference

Complete REST API reference for the Sovra API Gateway. All endpoints except health probes require authentication via mTLS or JWT.

Base URL: https://<sovra-host>:<port>


Health & Metrics

These endpoints do not require authentication.

Method Path Description
GET /health Health check with component status
GET /ready Readiness probe
GET /live Liveness probe
GET /metrics Prometheus metrics

GET /health

Returns health status of all components.

Response:

{
  "status": "healthy",
  "version": "2026.4.82",
  "components": {
    "database": {"status": "healthy"},
    "vault": {"status": "healthy"},
    "opa": {"status": "healthy"}
  }
}

SSO Config

GET /api/v1/sso-config

Discover SSO configuration for client login. No authentication required.

Response: 200

{
  "issuer_url": "https://idp.example.org",
  "client_id": "sovra"
}

Workspaces

POST /api/v1/workspaces

Create a new workspace.

Request:

{
  "name": "genomics-data",
  "group_id": "group-123",
  "classification": "CONFIDENTIAL",
  "mode": "standard",
  "purpose": "Shared genomics research",
  "crk_signature": "<base64>"
}

The group_id binds the workspace to an identity group for access control. The deprecated participants array field is still accepted but group_id is preferred.

Response: 201 — Workspace object

GET /api/v1/workspaces

List all workspaces.

Query parameters:

Parameter Type Default Description
limit int 50 Maximum results
offset int 0 Result offset

Response: 200{"workspaces": [...], "count": 42}

GET /api/v1/workspaces/{id}

Get workspace by ID.

Response: 200 — Workspace object

PUT /api/v1/workspaces/{id}

Update a workspace.

Request:

{
  "purpose": "Updated purpose",
  "classification": "SECRET",
  "mode": "airgap",
  "signature": "<base64>"
}

All fields are optional.

Response: 200 — Updated workspace

DELETE /api/v1/workspaces/{id}

Delete a workspace.

Request:

{
  "signatures": {"org-a": "<base64>", "org-b": "<base64>"}
}

Response: 204

POST /api/v1/workspaces/{id}/encrypt

Encrypt data using workspace DEK.

Request:

{
  "plaintext": "<base64>",
  "context": {"key": "value"}
}

Response: 200{"ciphertext": "<base64>"}

POST /api/v1/workspaces/{id}/decrypt

Decrypt data using workspace DEK.

Request:

{
  "ciphertext": "<base64>",
  "context": {"key": "value"}
}

Response: 200{"plaintext": "<base64>"}

POST /api/v1/workspaces/{id}/rotate-dek

Rotate the Data Encryption Key.

Request:

{
  "signature": "<base64>"
}

Response: 204

POST /api/v1/workspaces/{id}/extend

Extend workspace expiration.

Request:

{
  "expires_at": "2027-01-01T00:00:00Z",
  "signature": "<base64>"
}

Response: 204

POST /api/v1/workspaces/{id}/invite

Invite an organization to a workspace.

Request:

{
  "org_id": "org-b",
  "signature": "<base64>"
}

Response: 201 — Invitation object

POST /api/v1/workspaces/{id}/accept-invitation

Request:

{
  "org_id": "org-b",
  "signature": "<base64>"
}

Response: 204

POST /api/v1/workspaces/{id}/decline-invitation

Request:

{
  "org_id": "org-b"
}

Response: 204

POST /api/v1/workspaces/{id}/request-access

Request access to a workspace (resolves via group membership).

Request:

{
  "group_id": "group-123",
  "signature": "<base64>"
}

Response: 200 — Access result

Workspace Admissions

Tiered admission control for workspace access. Admissions are required for SECRET and CRK-protected workspaces; CONFIDENTIAL workspaces auto-admit via group membership.

Method Path Description
POST /api/v1/workspaces/{id}/admissions Grant admission
GET /api/v1/workspaces/{id}/admissions List admissions
GET /api/v1/workspaces/{id}/admissions/{identityId} Get admission status
DELETE /api/v1/workspaces/{id}/admissions/{identityId} Revoke admission

POST /api/v1/workspaces/{id}/admissions

Grant an identity explicit admission to a workspace.

Request:

{
  "identity_id": "user-456",
  "identity_type": "user",
  "org_id": "org-a"
}

Identity types: admin, user, service, device

Response: 201 — WorkspaceAdmission object

GET /api/v1/workspaces/{id}/admissions

List all admissions for a workspace.

Response: 200{"admissions": [...], "count": 3}

GET /api/v1/workspaces/{id}/admissions/{identityId}

Get admission status for a specific identity.

Response: 200 — WorkspaceAdmission object

DELETE /api/v1/workspaces/{id}/admissions/{identityId}

Revoke an identity’s admission to a workspace.

Response: 204

POST /api/v1/workspaces/{id}/archive

Archive a workspace.

Request:

{
  "signature": "<base64>"
}

Response: 204

POST /api/v1/workspaces/{id}/export

Export workspace as a portable bundle.

Response: 200 — WorkspaceBundle JSON

POST /api/v1/workspaces/import

Import workspace from a bundle.

Request: WorkspaceBundle JSON

Response: 201 — Created workspace


Federation

POST /api/v1/federation/init

Initialize federation for the organization.

Request:

{
  "org_id": "org-a",
  "crk_signature": "<base64>"
}

Response: 200 — Init result with federation certificate

POST /api/v1/federation/establish

Establish federation with a partner.

Request:

{
  "partner_org_id": "org-b",
  "partner_url": "https://partner.example.org",
  "partner_cert": "<base64>",
  "partner_csr": "<base64>",
  "crk_signature": "<base64>"
}

Response: 201 — Federation object

GET /api/v1/federation

List all federation partnerships.

Response: 200{"federations": [...], "count": 3}

GET /api/v1/federation/{partnerId}

Get federation status with a partner.

Response: 200 — Federation object

DELETE /api/v1/federation/{partnerId}

Revoke federation with a partner.

Request:

{
  "signature": "<base64>",
  "notify_partner": true,
  "revoke_certs": true
}

Response: 204

GET /api/v1/federation/health

Health check all federation partnerships.

Response: 200{"results": {...}}

POST /api/v1/federation/{partnerId}/renew-cert

Renew the federation certificate with a partner.

Request:

{
  "signature": "<base64>"
}

Response: 200 — Renewed certificate details

POST /api/v1/federation/certificate/import

Import a partner’s federation certificate.

Request:

{
  "partner_org_id": "org-b",
  "certificate": "<base64>",
  "signature": "<base64>"
}

Response: 204


Policies

POST /api/v1/policies

Create a new OPA Rego policy.

Request:

{
  "name": "data-access",
  "workspace": "ws-123",
  "rego": "package sovra.workspace...",
  "crk_signature": "<base64>"
}

Response: 201 — Policy object

GET /api/v1/policies/{id}

Get policy by ID.

Response: 200 — Policy object

PUT /api/v1/policies/{id}

Update a policy.

Request:

{
  "rego": "package sovra.workspace...",
  "signature": "<base64>"
}

Response: 200 — Updated policy

DELETE /api/v1/policies/{id}

Delete a policy.

Request:

{
  "signature": "<base64>"
}

Response: 204

GET /api/v1/policies/workspace/{workspaceId}

Get all policies for a workspace.

Response: 200{"policies": [...], "count": 2}

POST /api/v1/policies/evaluate

Evaluate a policy against input.

Request:

{
  "actor": "user@example.org",
  "role": "researcher",
  "operation": "decrypt",
  "workspace": "ws-123",
  "purpose": "data analysis",
  "metadata": {}
}

Response: 200{"allowed": true, "deny_reason": "", "eval_time_ms": 5}

POST /api/v1/policies/validate

Validate Rego policy syntax.

Request:

{
  "rego": "package sovra.workspace..."
}

Response: 200{"valid": true}


Audit

GET /api/v1/audit

Query audit events.

Query parameters:

Parameter Type Description
org_id string Filter by organization
workspace string Filter by workspace
event_type string Filter by event type
actor string Filter by actor
since string Start time (RFC3339)
until string End time (RFC3339)
limit int Maximum results (default: 100)
offset int Result offset

Response: 200{"events": [...], "count": 150}

GET /api/v1/audit/{id}

Get audit event by ID.

Response: 200 — AuditEvent object

POST /api/v1/audit/export

Export audit logs.

Request:

{
  "org_id": "org-a",
  "workspace": "ws-123",
  "event_type": "workspace.access",
  "since": "2026-01-01T00:00:00Z",
  "until": "2026-02-01T00:00:00Z",
  "format": "json"
}

Formats: json, csv

Response: 200 — Binary file download

GET /api/v1/audit/stats

Get audit statistics.

Query parameters:

Parameter Type Description
since string Start time (RFC3339)

Response: 200 — AuditStats object

POST /api/v1/audit/verify

Verify audit log integrity.

Request:

{
  "since": "2026-01-01T00:00:00Z",
  "until": "2026-02-01T00:00:00Z"
}

Response: 200{"valid": true, "since": "...", "until": "..."}


Edge Nodes

POST /api/v1/edges

Register a new edge node.

Request:

{
  "name": "edge-eu-west",
  "vault_address": "https://vault.eu-west.example.org:8200",
  "vault_token": "hvs.xxx",
  "vault_ca_cert": "<pem>",
  "classification": "CONFIDENTIAL",
  "region": "eu-west",
  "tags": {"env": "production"}
}

Response: 201 — EdgeNode object

GET /api/v1/edges

List edge nodes.

Response: 200{"edges": [...], "count": 5}

GET /api/v1/edges/{id}

Get edge node by ID.

Response: 200 — EdgeNode object

DELETE /api/v1/edges/{id}

Unregister an edge node.

Response: 204

GET /api/v1/edges/{id}/health

Health check an edge node.

Response: 200 — HealthStatus object

POST /api/v1/edges/{id}/sync/policies

Sync policies to an edge node.

Request:

{
  "policies": [...]
}

Response: 204

POST /api/v1/edges/{id}/sync/keys

Sync workspace keys to an edge node.

Request:

{
  "workspace_id": "ws-123",
  "wrapped_dek": "<base64>"
}

Response: 204

GET /api/v1/edges/{id}/sync/status

Get edge node sync status.

Response: 200 — SyncStatus object


Customer Root Keys (CRK)

POST /api/v1/crk/generate

Generate a new CRK with Shamir secret sharing.

Request:

{
  "org_id": "org-a",
  "total_shares": 5,
  "threshold": 3
}

Response: 200 — CRK result with shares

POST /api/v1/crk/sign

Sign data with CRK shares.

Request:

{
  "shares": [{"index": 1, "data": "<base64>"}, ...],
  "public_key": "<base64>",
  "data": "<base64>"
}

Response: 200{"signature": "<base64>"}

POST /api/v1/crk/verify

Verify a CRK signature.

Request:

{
  "public_key": "<base64>",
  "data": "<base64>",
  "signature": "<base64>"
}

Response: 200{"valid": true}

POST /api/v1/crk/rotate

Start CRK rotation ceremony.

Request:

{
  "org_id": "org-a",
  "threshold": 3
}

Response: 200 — Ceremony object

POST /api/v1/crk/ceremony/start

Start a key ceremony.

Request:

{
  "org_id": "org-a",
  "operation": "generate",
  "threshold": 3
}

Response: 200 — Ceremony object

POST /api/v1/crk/ceremony/{id}/share

Add a share to a ceremony.

Request:

{
  "share": {"index": 1, "data": "<base64>"}
}

Response: 204

POST /api/v1/crk/ceremony/{id}/complete

Complete a ceremony.

Request:

{
  "witness": "admin@example.org"
}

Response: 200 — Ceremony result

DELETE /api/v1/crk/ceremony/{id}

Cancel a ceremony.

Response: 204

CRK Generation Ceremony (Password-Protected Shares)

Method Path Description
POST /api/v1/crk/generate-ceremony/start Start generation ceremony
POST /api/v1/crk/generate-ceremony/{id}/seed Submit custodian seed
GET /api/v1/crk/generate-ceremony/{id} Get ceremony status
POST /api/v1/crk/generate-ceremony/{id}/complete Complete ceremony
DELETE /api/v1/crk/generate-ceremony/{id} Cancel ceremony
GET /api/v1/crk/shares/{crkId}/{index} Get encrypted share

POST /api/v1/crk/generate-ceremony/start

Start a password-protected CRK generation ceremony.

Request:

{
  "org_id": "org-a",
  "total_shares": 5,
  "threshold": 3
}

Response: 200 — GenerationCeremony object

POST /api/v1/crk/generate-ceremony/{id}/seed

Submit a custodian’s password-derived seed for share encryption.

Request:

{
  "index": 1,
  "custodian_name": "Alice",
  "derived_key": "<base64>",
  "salt": "<base64>"
}

Response: 204

GET /api/v1/crk/generate-ceremony/{id}

Get the status of a generation ceremony.

Response: 200 — GenerationCeremony object

POST /api/v1/crk/generate-ceremony/{id}/complete

Complete the ceremony and generate the CRK with encrypted shares.

Response: 200 — Ceremony result with encrypted shares

DELETE /api/v1/crk/generate-ceremony/{id}

Cancel a generation ceremony.

Response: 204

GET /api/v1/crk/shares/{crkId}/{index}

Get an encrypted share by CRK ID and share index.

Response: 200 — EncryptedCRKShare object


Identities

Admins

Method Path Description
POST /api/v1/identities/admins Create admin
GET /api/v1/identities/admins List admins
GET /api/v1/identities/admins/{id} Get admin
PUT /api/v1/identities/admins/{id} Update admin (including enable/disable via active field)
DELETE /api/v1/identities/admins/{id} Delete admin
POST /api/v1/identities/admins/{id}/mfa/enable Enable MFA
POST /api/v1/identities/admins/{id}/mfa/verify Verify MFA token

POST /api/v1/identities/admins:

{
  "email": "admin@example.org",
  "name": "Admin User",
  "role": "security_admin"
}

Roles: super_admin, security_admin, operations_admin, auditor

POST /api/v1/identities/admins/{id}/certificate/renew

Renew an admin’s mTLS certificate.

Response: 200 — New certificate

PUT /api/v1/identities/admins/{id}:

{
  "email": "new@example.org",
  "name": "New Name",
  "role": "auditor",
  "active": false
}

All fields are optional. Set active to false to disable, true to enable.

POST /api/v1/identities/admins/{id}/mfa/verify:

{
  "totp_code": "123456"
}

Users

Method Path Description
POST /api/v1/identities/users/sso Create user from SSO
GET /api/v1/identities/users List users
GET /api/v1/identities/users/{id} Get user
DELETE /api/v1/identities/users/{id} Delete user

POST /api/v1/identities/users/sso:

{
  "provider": "azure_ad",
  "subject": "sub-123",
  "email": "user@example.org",
  "name": "User Name",
  "groups": ["researchers"]
}

Providers: azure_ad, okta, google

Services

Method Path Description
POST /api/v1/identities/services Create service
GET /api/v1/identities/services List services
GET /api/v1/identities/services/{id} Get service
DELETE /api/v1/identities/services/{id} Delete service
POST /api/v1/identities/services/{id}/rotate Rotate credentials

POST /api/v1/identities/services:

{
  "name": "data-pipeline",
  "description": "ETL pipeline service",
  "auth_method": "approle"
}

Auth methods: approle, kubernetes, cert

Devices

Method Path Description
POST /api/v1/identities/devices Enroll device
GET /api/v1/identities/devices List devices
GET /api/v1/identities/devices/{id} Get device
POST /api/v1/identities/devices/{id}/revoke Revoke device

POST /api/v1/identities/devices:

{
  "device_name": "edge-sensor-1",
  "device_type": "sensor",
  "cert_serial": "AA:BB:CC",
  "cert_expiry": "2027-01-01T00:00:00Z"
}

Groups

Method Path Description
POST /api/v1/identities/groups Create group
GET /api/v1/identities/groups List groups
GET /api/v1/identities/groups/{id} Get group
PUT /api/v1/identities/groups/{id} Update group
POST /api/v1/identities/groups/{id}/members Add member
DELETE /api/v1/identities/groups/{id}/members/{identityId} Remove member
POST /api/v1/identities/groups/{id}/join-requests Submit join request
GET /api/v1/identities/groups/{id}/join-requests List join requests
POST /api/v1/identities/groups/{id}/join-requests/{requestId}/approve Approve join request
POST /api/v1/identities/groups/{id}/join-requests/{requestId}/deny Deny join request

POST /api/v1/identities/groups:

{
  "name": "researchers",
  "description": "Research team",
  "vault_policies": ["read-genomics"]
}

GET /api/v1/identities/groups/{id}:

{
  "id": "group-123",
  "name": "researchers",
  "description": "Research team",
  "vault_policies": ["read-genomics"],
  "members": [
    {"identity_id": "user-456", "identity_type": "user"}
  ],
  "created_at": "2026-01-01T00:00:00Z"
}

POST /api/v1/identities/groups/{id}/members:

{
  "identity_id": "user-456",
  "identity_type": "user"
}

Identity types: admin, user, service, device

Roles

Method Path Description
POST /api/v1/identities/roles Create role
GET /api/v1/identities/roles List roles
GET /api/v1/identities/roles/{id} Get role
POST /api/v1/identities/roles/{id}/assign Assign role
DELETE /api/v1/identities/roles/{id}/assignments/{identityId} Unassign role

POST /api/v1/identities/roles:

{
  "name": "data-reader",
  "description": "Read-only data access",
  "permissions": [{"resource": "workspace", "action": "read"}]
}

GET /api/v1/identities/roles/{id}:

{
  "id": "role-123",
  "name": "data-reader",
  "description": "Read-only data access",
  "permissions": [{"resource": "workspace", "action": "read"}],
  "assignments": [
    {"identity_id": "user-456", "identity_type": "user", "assigned_by": "admin-123"}
  ],
  "created_at": "2026-01-01T00:00:00Z"
}

POST /api/v1/identities/roles/{id}/assign:

{
  "identity_id": "user-456",
  "identity_type": "user",
  "assigned_by": "admin-123"
}

Certificates

Method Path Description
POST /api/v1/certificates/issue Issue certificate
POST /api/v1/certificates/revoke Revoke certificate
GET /api/v1/certificates List certificates
GET /api/v1/certificates/{serial} Get certificate by serial
GET /api/v1/certificates/ca-chain Get CA certificate chain
POST /api/v1/certificates/tidy Clean up expired certificates

POST /api/v1/certificates/issue

Request:

{
  "common_name": "api.example.org",
  "alt_names": ["api2.example.org"],
  "ttl": "8760h"
}

Response: 200 — Certificate with private key, certificate chain, serial number

POST /api/v1/certificates/revoke

Request:

{
  "serial_number": "AA:BB:CC:DD"
}

Response: 204

POST /api/v1/certificates/tidy

Request:

{
  "safety_buffer": "72h"
}

Response: 200{"message": "tidy operation started"}


Emergency Access

Break-glass emergency access for critical situations.

Method Path Description
POST /api/v1/emergency-access/request Request emergency access
GET /api/v1/emergency-access List requests
GET /api/v1/emergency-access/{id} Get request
POST /api/v1/emergency-access/{id}/approve Approve request
POST /api/v1/emergency-access/{id}/deny Deny request
POST /api/v1/emergency-access/{id}/complete Complete request
POST /api/v1/emergency-access/{id}/verify Verify with CRK

POST /api/v1/emergency-access/request

Request:

{
  "org_id": "org-a",
  "reason": "Critical security incident"
}

Response: 201 — AccessRequest object

GET /api/v1/emergency-access

Query parameters:

Parameter Type Description
org_id string Filter by organization

POST /api/v1/emergency-access/{id}/verify

Request:

{
  "signature": "<base64>"
}

Response: 204


Account Recovery

Recovery using CRK share reconstruction.

Method Path Description
POST /api/v1/account-recovery/initiate Initiate recovery
POST /api/v1/account-recovery/{id}/share Submit recovery share
POST /api/v1/account-recovery/{id}/complete Complete recovery

POST /api/v1/account-recovery/initiate

Request:

{
  "admin_id": "admin-123",
  "recovery_type": "lost_credentials",
  "reason": "Lost credentials"
}

Recovery types: lost_credentials, locked_account

Response: 201 — Recovery object


Compliance Reports

On-demand compliance report generation.

Method Path Description
POST /api/v1/compliance/reports/summary Compliance summary
POST /api/v1/compliance/reports/gdpr-dsar GDPR DSAR report
POST /api/v1/compliance/reports/access-review Access review report

POST /api/v1/compliance/reports/summary

Request:

{
  "org_id": "org-a",
  "since": "2026-01-01T00:00:00Z",
  "until": "2026-02-01T00:00:00Z"
}

Response: 200 — ComplianceReport object

POST /api/v1/compliance/reports/gdpr-dsar

Request:

{
  "org_id": "org-a",
  "subject_id": "user-123"
}

Response: 200 — ComplianceReport object

POST /api/v1/compliance/reports/access-review

Request:

{
  "org_id": "org-a",
  "since": "2026-01-01T00:00:00Z",
  "until": "2026-02-01T00:00:00Z"
}

Response: 200 — ComplianceReport object


Rotation Policies

Automatic key rotation policies for workspaces.

Method Path Description
GET /api/v1/rotation-policies List all policies
PUT /api/v1/workspaces/{id}/rotation-policy Set rotation policy
GET /api/v1/workspaces/{id}/rotation-policy Get rotation policy
DELETE /api/v1/workspaces/{id}/rotation-policy Delete rotation policy

PUT /api/v1/workspaces/{id}/rotation-policy

Request:

{
  "max_age": "720h",
  "enabled": true
}

Response: 200 — RotationPolicy object

GET /api/v1/workspaces/{id}/rotation-policy

Response: 200 — RotationPolicy object (or 404 if none set)


Backups

Encrypted backup and restore operations. Backup payloads are encrypted at rest using the organization’s KEK via Vault transit. Restore is restricted to the same organization or a clean (empty) instance.

Method Path Description
POST /api/v1/backups Create a backup
GET /api/v1/backups List backups
GET /api/v1/backups/{id} Get backup details
POST /api/v1/backups/{id}/restore Restore from backup

POST /api/v1/backups

Create an encrypted backup of the caller’s organization data (workspaces, federations, policies).

Request:

{
  "type": "full",
  "crk_signature": "<base64>"
}

Response: 201 — Backup object

GET /api/v1/backups

List all backups for the caller’s organization.

Response: 200

{
  "backups": [...],
  "count": 2
}

GET /api/v1/backups/{id}

Get details of a specific backup.

Response: 200 — Backup object

POST /api/v1/backups/{id}/restore

Restore from a backup. The caller’s organization must match the backup’s organization, or the target instance must be clean (no existing organizations). The encrypted payload is decrypted and its SHA-256 checksum is verified before re-importing data.

Request:

{
  "crk_signature": "<base64>"
}

Response: 204 — No Content


Admin Enrollment

Unauthenticated endpoints for initial admin setup.

Method Path Description
POST /api/v1/bootstrap/admin Bootstrap first admin
GET /api/v1/enrollment/admins/{id}/setup Get enrollment setup info
POST /api/v1/enrollment/admins/{id} Complete admin enrollment

POST /api/v1/bootstrap/admin

Bootstrap the first admin on a clean instance. Only succeeds when no admins exist.

Request:

{
  "email": "admin@example.org",
  "name": "First Admin",
  "crk_signature": "<base64>"
}

Response: 201 — Admin object with enrollment token

POST /api/v1/enrollment/admins/{id}

Complete enrollment using the enrollment token. Generates mTLS certificate.

Request:

{
  "enrollment_token": "<token>",
  "csr": "<base64-pem>"
}

Response: 200 — Signed certificate


Messages

End-to-end encrypted direct messaging between organizations.

Method Path Description
POST /api/v1/messages Send message
GET /api/v1/messages List inbox
GET /api/v1/messages/sent List sent messages
GET /api/v1/messages/{id} Read message
DELETE /api/v1/messages/{id} Delete message
POST /api/v1/messages/deliver Deliver federated message

POST /api/v1/messages

Send a direct message.

Request:

{
  "recipient_org_id": "org-b",
  "recipient_id": "admin-456",
  "subject": "Federation certificate renewal",
  "body": "<base64-encrypted>",
  "expires_at": "2026-03-01T00:00:00Z"
}

Response: 201 — Message object

GET /api/v1/messages

List inbox messages.

Query parameters:

Parameter Type Description
limit int Maximum results (default: 50)

Response: 200{"messages": [...]}

GET /api/v1/messages/sent

List sent messages.

Response: 200{"messages": [...]}

GET /api/v1/messages/{id}

Read a message. Marks it as read.

Response: 200 — Message object

POST /api/v1/messages/deliver

Deliver a message from a federated partner (server-to-server).

Request: Message object

Response: 201


Activity

Activity feed for audit and monitoring.

Method Path Description
GET /api/v1/activity List activity events
POST /api/v1/activity/export Export activity log

GET /api/v1/activity

List recent activity events.

Query parameters:

Parameter Type Description
since string Start time (RFC3339)
until string End time (RFC3339)
limit int Maximum results (default: 100)

Response: 200{"events": [...]}

POST /api/v1/activity/export

Export activity log to file.

Request:

{
  "since": "2026-01-01T00:00:00Z",
  "until": "2026-02-01T00:00:00Z",
  "format": "json"
}

Response: 200 — Binary file download