For the complete documentation index, see llms.txt. This page is also available as Markdown.

Authentication & API Keys

Authenticate to the Platform API with workspace keys or device authorization, inspect the live permission catalog, and rotate or revoke credentials safely.

Provider M2M authentication. Backend services that need to act as a specific provider can use provider M2M clients - a client_credentials grant that mints short-lived provider-scoped tokens. See OAuth2 Clients - Provider M2M Clients for details.

For machine-to-machine integrations, the platform supports OAuth2 client credentials. See OAuth2 (Machine-to-Machine) for the token flow and OAuth2 Clients for client registration, scopes, and secret rotation.

The Platform API supports two authentication methods: workspace-scoped API keys (a static Bearer token, no login step) and the device code flow (interactive browser approval, documented below). This is a different mechanism from the Classic API's per-user JWT tokens.

Agent Forge CLI setup. Environment variables (PLATFORM_API_KEY, IDENTITY_URL), .env.platform.<env> file conventions, and forge auth login --platform are covered in the Agent Forge CLI documentation.

API Key Usage

Every Platform API request requires an API key as a Bearer token:

curl https://api.platform.amigo.ai/v1/{workspace_id}/agents \
  -H "Authorization: Bearer <YOUR_API_KEY>"

Each key is scoped to a single workspace. The key's workspace must match the workspace in the request path. Cross-workspace access is not permitted.

API Key Lifecycle

Save a new or rotated key immediately. Its plaintext value is returned only once. Revoke keys that are no longer needed or may have been compromised.

Create an API Key

Create an API key

post

Create a new API key for a workspace. The response includes the plaintext api_key — store it securely, it cannot be retrieved again.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
Body
namestring · min: 1 · max: 256 · nullableOptional
duration_daysinteger · min: 1 · max: 90Required
rolestring · max: 64OptionalDefault: member
permissionsstring[] · max: 128Optional

Permission names. Max 128 entries; each entry up to 128 chars.

Responses
201

Successful Response

application/json
key_idstringRequired
api_keystringRequired
namestring · nullableRequired
rolestringRequired
permissionsstring[]Required
expires_atstring · date-timeRequired
created_by_entity_idstring · uuid · nullableRequired
created_by_credential_idstring · uuid · nullableRequired
post/v1/{workspace_id}/api-keys
POST /v1/{workspace_id}/api-keys HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 72

{
  "name": "text",
  "duration_days": 1,
  "role": "member",
  "permissions": [
    "text"
  ]
}
{
  "key_id": "text",
  "api_key": "text",
  "name": "text",
  "role": "text",
  "permissions": [
    "text"
  ],
  "expires_at": "2026-01-01T00:00:00.000Z",
  "created_by_entity_id": "123e4567-e89b-12d3-a456-426614174000",
  "created_by_credential_id": "123e4567-e89b-12d3-a456-426614174000"
}

List API Keys

List API keys

get

List all API keys for a workspace with pagination. Requires ApiKey.view permission.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
Query parameters
sort_bystring[]OptionalDefault: []
limitinteger · max: 200OptionalDefault: 50
continuation_tokenanyOptional
mine_onlybooleanOptionalDefault: false
Responses
200

Successful Response

application/json
has_morebooleanRequired
continuation_tokenanyOptional
get/v1/{workspace_id}/api-keys
GET /v1/{workspace_id}/api-keys HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "items": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "workspace_id": "123e4567-e89b-12d3-a456-426614174000",
      "created_by_entity_id": "123e4567-e89b-12d3-a456-426614174000",
      "created_by_credential_id": "123e4567-e89b-12d3-a456-426614174000",
      "key_id": "text",
      "name": "text",
      "role": "text",
      "permissions": [
        "text"
      ],
      "expires_at": "2026-01-01T00:00:00.000Z",
      "last_used_at": "2026-01-01T00:00:00.000Z",
      "created_at": "2026-01-01T00:00:00.000Z",
      "updated_at": "2026-01-01T00:00:00.000Z"
    }
  ],
  "has_more": true,
  "continuation_token": null
}

Revoke an API Key

Delete an API key

delete

Revoke an API key. Requires ApiKey.delete permission.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
key_idstringRequired
Responses
204

Successful Response

No content

delete/v1/{workspace_id}/api-keys/{key_id}
DELETE /v1/{workspace_id}/api-keys/{key_id} HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*

No content

RBAC Roles

Each API key carries a role:

Role
Access

owner

Full access including workspace deletion and ownership transfer

admin

Full read/write to all workspace resources

member

Read/write to most resources; restricted admin operations

operator

Read access plus operator actions: update operator state, control eligible runs, decide conversation-scoped integration approvals, and claim or review external write proposals where that private-preview flow is enabled (no general resource CRUD)

viewer

Read-only access

Attempting an operation beyond the key's role returns 403 Forbidden.

Permission Catalog

Use the live permission catalog instead of hard-coding role defaults in a client.

The caller needs ApiKey:View. Missing or invalid credentials return 401; insufficient permission returns 403.

Get the API-key role/permission catalog

get

Return the authoritative role→permission model: each role's default permission set (what an API key of that role may carry) plus the full permission universe. Clients use this to build the create-key form instead of hard-coding the matrix. Requires ApiKey.view permission.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
Responses
200

Successful Response

application/json

The authoritative role→permission model for API-key creation.

Serves the server-side source of truth (DEFAULT_ROLE_DEFINITIONS) so clients (console, SDK) stop hand-copying the matrix and drifting out of sync — a drift previously shipped Data:Query as a viewer default and made the default create flow 422. Human-facing labels/descriptions for individual permissions stay client-side (pure presentation); this payload is authorization truth only.

get/v1/{workspace_id}/api-keys/permission-catalog
GET /v1/{workspace_id}/api-keys/permission-catalog HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "roles": [
    {
      "name": "text",
      "priority": 1,
      "description": "text",
      "permission_names": [
        "text"
      ]
    }
  ],
  "permissions": [
    {
      "name": "text",
      "namespace": "text",
      "action": "text"
    }
  ]
}

Key Rotation

Rotation replaces a key's secret atomically. The old secret stops working immediately, and the new plaintext value is returned once.

Rotate an API key

post

Replace an API key secret in one step. The old secret stops working immediately, and the response includes the new plaintext api_key exactly once.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Path parameters
workspace_idstring · uuidRequired
key_idstringRequired
Body
duration_daysinteger · min: 1 · max: 90Required
Responses
200

Successful Response

application/json
key_idstringRequired
api_keystringRequired
namestring · nullableRequired
rolestringRequired
permissionsstring[]Required
expires_atstring · date-timeRequired
created_by_entity_idstring · uuid · nullableRequired
created_by_credential_idstring · uuid · nullableRequired
post/v1/{workspace_id}/api-keys/{key_id}/rotate
POST /v1/{workspace_id}/api-keys/{key_id}/rotate HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 19

{
  "duration_days": 1
}
{
  "key_id": "text",
  "api_key": "text",
  "name": "text",
  "role": "text",
  "permissions": [
    "text"
  ],
  "expires_at": "2026-01-01T00:00:00.000Z",
  "created_by_entity_id": "123e4567-e89b-12d3-a456-426614174000",
  "created_by_credential_id": "123e4567-e89b-12d3-a456-426614174000"
}

The rotated key inherits the original key's name, role, and permissions. You can only rotate keys you created (or any key if you have the api_key.delete permission).

Usage Visibility

API key responses include a last_used_at timestamp showing when the key was last used to authenticate a request. Use this to identify stale keys before rotating or revoking them.

Current Key Info

Use this operation to inspect the current key's workspace, expiration, and remaining validity.

Get auth info

get

Return information about the currently authenticated API key, including expiration.

Authorizations
AuthorizationstringRequired

API key issued via POST /v1/{workspace_id}/api-keys. Pass the returned api_key value as a Bearer token.

Responses
200

Successful Response

application/json
workspace_idstring · uuidRequired
key_idstringRequired
namestring · nullableRequired
expires_atstring · date-timeRequired
expires_in_secondsintegerRequired
get/v1/auth/me
GET /v1/auth/me HTTP/1.1
Host: api.platform.amigo.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
  "workspace_id": "123e4567-e89b-12d3-a456-426614174000",
  "key_id": "text",
  "name": "text",
  "expires_at": "2026-01-01T00:00:00.000Z",
  "expires_in_seconds": 1
}

Device Code Flow (CLI & Desktop Apps)

The device authorization, MFA, IP allow-list, lockout, and identity-session routes below are served by the Identity API and are not published in the Platform API OpenAPI document. Their manually documented paths are retained only where the separate identity contract is required for the workflow.

For CLI tools, desktop apps, and other environments where the user authenticates in a browser, the Platform API supports the RFC 8628 Device Authorization Grant.

Flow Overview

  1. Your app requests a device code from POST /device/code

  2. The response includes a verification_uri_complete - your app opens this in the user's browser

  3. The user signs in (if needed) and clicks Authorize on the approval page

  4. Your app polls POST /token with grant_type=device_code until the user approves

  5. The token endpoint returns a workspace-scoped JWT

Step-by-Step

1. Request a device code:

Response:

2. Direct the user to the verification URL. Open verification_uri_complete in a browser. The user sees the device code and can approve or deny the request.

3. Poll for the token:

The authorization_pending response is expected, not an error. While the user hasn't approved yet, every poll returns 400 with {"error": "authorization_pending"}. Your app should keep polling every interval seconds (default: 5) until it gets a 200 or a terminal error.

Response
Meaning
Action

400 authorization_pending

User hasn't approved yet

Keep polling

400 slow_down

Polling too fast

Increase interval by 5 seconds

200

Approved

Extract access_token and refresh_token

300 workspace_selection_required

User has multiple workspaces

See Multi-Workspace below

400 expired_token

Code expired (15-min TTL)

Start over

400 access_denied

User clicked Deny

Show error to user

Multi-Workspace Users

If the user belongs to multiple workspaces, the token exchange returns HTTP 300 with a workspace list instead of a JWT. Your app must:

  1. Present the workspace list to the user

  2. Exchange the refresh_token from the 300 response for a workspace-scoped JWT:

Alternatively, pass workspace_id in the initial /token poll to pre-select a workspace.

Platform SDK (TypeScript)

The SDK provides loginWithDeviceCode() which handles the full flow - code issuance, browser open, polling, and workspace selection:

Use TokenManager with FileTokenStorage to persist credentials across CLI sessions (stored at ~/.amigo/credentials.json).

Security

  • Device codes expire after 15 minutes

  • User codes are 8 characters (XXXX-YYYY format), designed to be easy to verify visually

  • Rate-limited by IP address on the /device/code endpoint

  • The approval page requires the user to be signed in to the Console

Security Controls

The Platform API layers several account-level security controls on top of key and token authentication: SSO, multi-factor authentication, IP allowlists, account lockout, and session enforcement. The subsections below cover each control.

SSO Login

The Platform API supports single sign-on (SSO) via identity federation. Users authenticate with their organization's identity provider (e.g., Google Workspace), and the platform exchanges the provider's authorization code for an Amigo JWT. That is the same token format used for API key authentication.

SSO Exchange Flow

  1. The client application redirects the user to the identity provider for authentication

  2. After authentication, the identity provider returns an authorization code

  3. The client sends the authorization code to the Platform API token endpoint

  4. The platform exchanges the code with the identity provider server-to-server and issues a JWT

Multi-Workspace Selection

When a user has credentials on multiple workspaces, the token endpoint returns a workspace list instead of a JWT. The client re-calls the token endpoint with the selected workspace_id to complete authentication.

Auto-Provisioning

Organizations can configure provision policies that automatically create credentials for new users on first SSO login based on their email domain. Global provision policies expand access to all workspaces in the organization. This eliminates the need to manually create credentials for each user before they can log in.

Refresh Tokens

SSO sessions issue refresh tokens alongside the JWT. Refresh tokens are rotated on each use (the old token is invalidated when a new one is issued). Idle sessions expire after the configured timeout to meet compliance requirements.

Multi-Factor Authentication (MFA)

The platform supports TOTP-based multi-factor authentication for user accounts.

Enrollment Flow

  1. POST /mfa/enroll: generate a TOTP secret. Returns an otpauth:// URI for scanning with an authenticator app, plus one-time recovery codes.

  2. POST /mfa/verify: confirm enrollment by submitting a valid TOTP code from the authenticator app.

Once enrolled, the token endpoint requires a valid TOTP code (or recovery code) alongside credentials when MFA is enforced.

MFA Enforcement

MFA can be enforced per SSO connection. When enforce_mfa is enabled on a connection, users authenticating through that identity provider must complete MFA before receiving a token.

Service accounts (client_credentials with service_account principal type) are exempt from MFA enforcement since automated services cannot interact with an authenticator app.

Recovery Codes

Recovery codes are generated during enrollment for account recovery if the authenticator device is lost. Each code can only be used once. Recovery codes are stored securely with one-way hashing.

Admin MFA Management

Endpoint
Description

GET /admin/mfa/coverage

MFA enrollment statistics across the workspace

POST /admin/mfa/reset/{entity_id}

Reset MFA enrollment for a specific user (requires re-enrollment)

Requires identity:admin scope.

IP Allowlists

Per-workspace IP allowlists restrict which IP addresses can authenticate. When configured, only requests from allowed CIDR ranges are accepted on the token endpoint.

Allowlist Behavior

  • Allowlists are configured as CIDR ranges (e.g., 10.0.0.0/8, 203.0.113.45/32).

  • When an allowlist is active, authentication requests from non-matching IPs are rejected with 403.

  • Allowlist changes may take a few minutes to propagate.

  • Service accounts are exempt from IP allowlist checks (required for automated service-to-service auth).

  • IP checks fail open: if an allowlist cannot be evaluated, authentication proceeds rather than locking out all access.

Admin IP Allowlist Management

Endpoint
Description

POST /admin/ip-allowlists

Add a CIDR range to the workspace allowlist

GET /admin/ip-allowlists

List all allowed CIDR ranges

DELETE /admin/ip-allowlists/{id}

Remove a CIDR range

POST /admin/ip-allowlists/test

Test whether a specific IP address matches the current allowlist

Requires identity:admin scope.

Account Lockout & Brute Force Protection

The platform enforces progressive account lockout on failed authentication attempts:

Failures
Lock Duration

5+

5 minutes

10+

30 minutes

20+

Permanent (requires admin unlock)

Lockout is tracked per entity (API key or client) and per IP address. Successful authentication clears the lockout counter.

Per-IP rate limiting applies to unauthenticated grant types (api_key, client_credentials, personal_access_token, google_oauth, device_code, email_otp, magic_link) at 60 requests/minute on the /token endpoint. Already-authenticated grants (agent_session, refresh_token) are exempt.

Lockout protection fails open: if lockout tracking is temporarily unavailable, authentication proceeds normally.

Admin lockout management (requires identity:admin scope):

Endpoint
Description

POST /admin/lockout/unlock/{identifier}

Unlock a locked account

GET /admin/lockout/locked-accounts

List all currently locked accounts

GET /admin/lockout/status/{identifier}

Check lockout status for an identifier

Locked responses return 403 with a Retry-After header for timed lockouts.

Session Enforcement

Sessions are enforced with idle timeouts and concurrent session limits. Idle and expired sessions are revoked automatically.

Idle Timeout

Sessions are revoked after a configurable period of inactivity:

Session Type
Default Idle Timeout
Notes

Console user sessions

15 minutes

Default idle timeout

Agent sessions (voice calls)

1 hour

Matches agent session TTL; voice agents don't refresh mid-call

Configurable per-session between 5 minutes and 24 hours. Activity is tracked on each authenticated request.

Concurrent Session Limits

Each entity is limited to a maximum number of active sessions per workspace:

Session Type
Max Concurrent Sessions
Eviction Behavior

User sessions

5

Oldest session evicted when limit reached

Agent sessions

50

Oldest session evicted when limit reached

Agent sessions have a higher limit because a single service entity (e.g., a voice agent) handles many simultaneous calls.

Session Metadata

Sessions track IP address and user agent for audit and security visibility.

Session Management Endpoints

These endpoints manage authentication sessions (tokens and logins). They are unrelated to the conversation Sessions API, which opens WebSocket text conversations.

User endpoints (any authenticated user):

Endpoint
Description

GET /sessions

List active sessions for the current entity

DELETE /sessions

Revoke all sessions for the current entity (logout everywhere)

DELETE /sessions/{session_id}

Revoke a specific session

Admin endpoints (requires identity:admin scope):

Endpoint
Description

GET /sessions/admin

List all active sessions with optional entity/workspace filters, pagination

DELETE /sessions/admin/{entity_id}

Revoke all sessions for a specific entity (optional workspace scope)

All revocation actions are audit-logged.

Last updated

Was this helpful?