Skip to content

API Authentication

Assumetr supports machine-to-machine API access through API clients — secure service accounts that exchange credentials for short-lived bearer tokens.

Overview

API clients allow your CI/CD pipelines, SIEM integrations, and automation tools to access Assumetr programmatically without borrowing a user session.

Key properties:

  • API clients are created per organization and bound to specific sites
  • Access is governed by scopes (what the client can do) and site bindings (which sites it can access)
  • Tokens are short-lived (15 minutes by default) and cannot be refreshed — exchange credentials again to get a new token

Creating an API Client

Required role: Organization Owner or Admin (manage:settings permission).

Create an API client via the Assumetr API:

bash
curl -X POST https://api.example.com/v1/org/api-clients \
  -H "Authorization: Bearer <SESSION_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CI Pipeline",
    "scopes": ["evidence:read", "sites:read"],
    "site_ids": ["<SITE_ID>"]
  }'

Response:

json
{
  "id": "7f83b162-...",
  "name": "CI Pipeline",
  "client_secret": "asc_...",
  "scopes": ["evidence:read", "sites:read"],
  "site_ids": ["<SITE_ID>"],
  "created_at": "2026-03-24T14:00:00Z"
}

Important: The client_secret is shown once on creation. Store it securely — it cannot be retrieved later.

Exchanging Credentials for a Token

Use the client credentials flow to obtain an access token:

bash
TOKEN=$(curl -s -X POST https://api.example.com/v1/auth/token \
  -u "<CLIENT_ID>:<CLIENT_SECRET>" \
  -d "grant_type=client_credentials" | jq -r '.access_token')

Response:

json
{
  "access_token": "eyJ...",
  "token_type": "bearer",
  "expires_in": 900,
  "scope": "evidence:read sites:read"
}

Using the Token

Include the token as a Bearer in the Authorization header:

bash
curl -H "Authorization: Bearer $TOKEN" \
  https://api.example.com/v1/sites/<SITE_ID>/status

Available Scopes

ScopeDescription
evidence:readRead evidence export runs, verify signatures, download packets
evidence:writeTrigger evidence exports, manage export jobs
sites:readRead site status, traffic, and session data
sites:writeManage site settings and privacy controls
org:readRead organization usage, plan, and posture data
org:adminManage users, invites, and workspace settings

Scopes are assigned at creation time and cannot be expanded beyond the creating user's permissions.

Bearer-Enabled Routes

The following routes accept API client bearer tokens:

MethodPathRequired Scope
GET/v1/sites/:siteID/statussites:read
GET/v1/sites/:siteID/evidence-export-runsevidence:read
GET/v1/sites/:siteID/evidence-export-runs/:runIDevidence:read
GET/v1/sites/:siteID/evidence-export-runs/:runID/verifyevidence:read
GET/v1/sites/:siteID/evidence-export-runs/:runID/downloadevidence:read

All other routes require session authentication via the web UI.

Error Responses

StatusCodeDescription
401invalid_clientInvalid credentials, revoked client, or expired client
403insufficient_scopeToken lacks the required scope for this route
403access_deniedClient is not bound to the requested site
429rate_limitedToo many token exchange attempts. Retry after the Retry-After header value

Client Lifecycle

Listing Clients

bash
curl -H "Authorization: Bearer <SESSION_TOKEN>" \
  https://api.example.com/v1/org/api-clients

Revoking a Client

bash
curl -X DELETE \
  -H "Authorization: Bearer <SESSION_TOKEN>" \
  https://api.example.com/v1/org/api-clients/<CLIENT_ID>

Revocation is immediate. In-flight tokens expire within 15 minutes.

Rotating a Client Secret

bash
curl -X POST \
  -H "Authorization: Bearer <SESSION_TOKEN>" \
  https://api.example.com/v1/org/api-clients/<CLIENT_ID>/rotate

During rotation, both old and new secrets are valid for a grace period (default: 24 hours). After the grace period, only the new secret works.

Rate Limits

Token exchange has per-client and per-IP rate limits:

  • Per client: 5 requests per minute
  • Per IP: 20 requests per minute

After 3 consecutive failures, exponential backoff applies (30s → 60s → 120s cap). The Retry-After header indicates when to retry.

Best Practices

  1. Store secrets securely — use a secrets manager, not source control
  2. Use minimum scopes — request only the scopes your integration needs
  3. Bind to specific sites — avoid broad access when site-specific is sufficient
  4. Handle token expiry — re-exchange credentials when the token expires (no refresh mechanism)
  5. Monitor for failures — 401 responses may indicate credential issues that need rotation