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
- Open Organization → API Keys.
- Click Create API Key.
- Provide a description (e.g. “Production integration”).
- Choose the permissions to grant (see below).
- 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}/agentsA 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.
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-roleCallable 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 thechatrole.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/verifyValidates 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
- Never expose API keys in frontend code — proxy through your backend, and use assume-role tokens for end users.
- Grant least privilege — only the scopes an integration needs.
- Rotate keys — create replacements and delete old keys periodically.
- Separate keys per environment — distinct keys for dev, staging, and production.