Skip to content

Authentication

Authentication

Every request to the Hutly API carries an Authorization: Bearer <token> header. There are two token types:

  • API keys — long-lived, for server-to-server integrations.
  • Assume-role tokens — short-lived (2 hours), for embedding chat or acting on behalf of an end user.

Both are bound to exactly one organization: that organization is the only one the token can reach, and it is implied by the token itself.

API Keys

API keys are the recommended way to authenticate programmatic access. Create and manage them in Organization → API Keys in the app.

Creating an API key

  1. Open Organization → API Keys.
  2. Click Create API Key.
  3. Provide a description (e.g. “Production integration”).
  4. Choose the permissions to grant (see below).
  5. Copy the generated key — it is shown once.

Only organization Owners and Admins can create, list, or manage API keys.

Using an API key

curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.intellia.com.au/orgs/{organizationId}/agents

A request authenticated with an API key acts as a programmatic (agent) caller on behalf of the key’s creator, scoped to the key’s organization.

Permissions

Each key stores a permission map:

{
  "agents": { "read": true, "write": true },
  "conversations": { "read": true, "write": false },
  "assume_role": { "write": true }
}

Available scopes include agents, conversations, knowledge_bases, tools, integrations, prompts, webhooks, and assume_role.

The assume_role.write scope is enforced directly: minting an assume-role token with an API key requires it. Other scopes in the map are recorded on the key, but route access is primarily governed by your organization’s plan and role capabilities rather than a per-route read/write check. Grant the minimum scopes you need, and treat a 403 as “this key/plan cannot reach this route.”

What API keys cannot do

Managing API keys themselves — create / list / get / update / delete under /orgs/{organizationId}/api-keys — rejects API keys outright: those endpoints require a signed-in user, and calling them with an API key returns 401/403.

POST /orgs/{organizationId}/assume-role/verify is the exception in the other direction — it takes no authentication (no session, no API key). It validates the assume-role token supplied in the request body via a pure signature check, so it proves its own auth. See Embedded Chat & SSO.

Assume-Role Tokens

Use assume-role tokens when you need a short-lived token scoped to a specific end user — for example, an embedded chat widget in your own application. Rather than sharing an API key with the browser, your backend mints an assume-role token and hands it to the frontend.

Mint a token

POST /orgs/{organizationId}/assume-role

Callable with a user session or with an API key that has the assume_role.write permission.

Request body:

{
  "userId": "user-123",
  "userEmail": "user@example.com",
  "userName": "Jane Doe",
  "permissions": ["chat"]
}
  • userId (required) — your identifier for the end user.
  • userEmail (optional) — if the user does not yet exist, they are created and added to the organization with the chat role.
  • userName (optional) — display name for a newly created user.
  • permissions (optional) — scopes embedded in the minted token.

Response:

{
  "token": "eyJhbGci...",
  "expiresAt": "2024-01-01T12:00:00Z",
  "userId": "user-123",
  "organizationId": "org-456",
  "role": "chat"
}

The minted token expires after 2 hours and grants the chat role. Mint a fresh token per session; never ship an API key to the browser.

Verify a token

POST /orgs/{organizationId}/assume-role/verify

Validates an assume-role token and returns its claims. This endpoint proves its own authentication from the token in the body, so it does not require a separate Authorization header.

Best Practices

  1. Never expose API keys in frontend code — proxy through your backend, and use assume-role tokens for end users.
  2. Grant least privilege — only the scopes an integration needs.
  3. Rotate keys — create replacements and delete old keys periodically.
  4. Separate keys per environment — distinct keys for dev, staging, and production.