Skip to content

Authentication

All programmatic access to the oHallo API uses API keys. Keys are scoped to your account and carry explicit permissions that control which endpoints you can call.

API keys follow a structured format that identifies the environment:

sf_live_v1_a3Bx9kLmP2qR7wYz... (production)
sf_test_v1_j8Hn4vCf6dWs1xTe... (sandbox)
PrefixEnvironment
sf_live_v1_Production: real data, real conversations
sf_test_v1_Sandbox: safe for development and testing

The full key is a cryptographically random string. Only the SHA-256 hash is stored on the server side. The raw key is shown exactly once at creation, so store it securely.

  1. Open the oHallo dashboard and navigate to Settings > API Access.
  2. Click + New API key.
  3. Enter a descriptive name (e.g., “Reporting script”, “CRM sync”).
  4. Select the scopes you need (see the full list below).
  5. Optionally restrict the key to a specific brand or workspace.
  6. Optionally set an expiration date.
  7. Click Create and copy the key immediately. It will not be shown again.

Pass the key in the Authorization header as a Bearer token:

Terminal window
curl https://api.ohallo.eu/api/conversations \
-H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx"

In TypeScript:

const response = await fetch("https://api.ohallo.eu/api/conversations?workspaceId=ws_abc123", {
headers: {
"Authorization": "Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx",
"Content-Type": "application/json",
},
});
const data = await response.json();

Each API key carries a set of scopes that determine which endpoints it can access. Request only the scopes you need.

ScopeAccess
conversations:readList and read conversations, messages, attachments, attention items, consumption metrics, and agent activity
conversations:writeReply, compose, resolve, take over, release, assign, unassign, approve guardrail-gated actions, resolve attention items
kb:readList, search, and view pending knowledge base entries (including widget management reads)
kb:writeCreate, update, approve, reject, and delete KB entries; manage KB widgets
policy:readList, search, and view pending policy entries
policy:writeCreate, update, approve, reject, and delete policy entries
contacts:readList, search, and view contacts; read contact-form widgets
contacts:writeCreate, update, delete contacts; link contacts to accounts; manage contact-form widgets
accounts:readList, search, and view accounts; list account contacts
accounts:writeCreate and update accounts
agents:readList platform and custom agent definitions and their versions; list the models an agent can use
agents:writeCreate, update, and delete custom agents; update agent instructions; restore agent versions. Creating an agent, giving an agent MCP connections, and restoring a version also take mcp:write
channels:readList a workspace’s channels and read a channel’s configuration
channels:writeCreate, update, and delete channels; store channel credentials; test connectivity; retry provisioning
calendar:readList calendar connections, calendars, and bookings
calendar:writeUpdate or delete calendar connections
quality:readRead CSAT statistics, circuit breakers, CSAT config, and entity-level quality scores
quality:writeUpdate CSAT config and resolve circuit breakers
brands:readList and read brands; list a brand’s workspaces (together with workspaces:read)
brands:writeCreate, update, and delete brands; upload a brand’s logo and the assistant’s sender image
workspaces:readList and read workspaces
workspaces:writeCreate, update, and delete workspaces
cases:readList and read cases, case events, and case types
mcp:readList and read MCP connections, their tools, their guardrails, and their version history
mcp:writeRegister, test, change, and delete MCP connections; classify tools, set the assurance they require, and manage their guardrails; assign tools to agents, create an agent or give it connections, and restore an agent version (each together with agents:write)

The same key works over the REST API and over the oHallo MCP server, so these sets hold for both.

Use caseScopes
Read conversation data for reportingconversations:read, contacts:read, accounts:read
Manage conversations and CRM dataconversations:read, conversations:write, contacts:read, contacts:write, accounts:read
Sync knowledge base entries from documentationkb:read, kb:write
Write knowledge base entries and policies, and review proposalskb:read, kb:write, policy:read, policy:write
Set up a chat or email channelchannels:read, channels:write
Set up an agent: find the MCP connection and its tools, choose a model, create the agentmcp:read, agents:read, agents:write, mcp:write
Register an MCP connection, govern its tools, and assign them to agentsmcp:read, mcp:write, agents:write
Set up an account, from brand and workspaces to channels, knowledge, policies and agentsbrands:read, brands:write, workspaces:read, workspaces:write, channels:read, channels:write, kb:read, kb:write, policy:read, policy:write, mcp:read, mcp:write, agents:read, agents:write

Channels, knowledge base entries and policies belong to a workspace. Listing the workspaces to find one’s id takes workspaces:read; on the MCP server, get_context returns the workspaces a key reaches, whatever its scopes.

A key restricted to a brand or workspace also needs its restriction to cover what it acts on; see Scoping keys to brand or workspace.

Scope checks apply to programmatic API-key callers only. Endpoints that accept both schemes (dual auth) do not gate dashboard JWT sessions on scopes. People signed in to the oHallo dashboard act with their role rather than scopes: owners and admins create, change, and delete brands, workspaces, channels, agents and MCP connections. The granular scopes documented above govern what an API-key integration can do.

By default, an API key has access to all data within your account. You can restrict a key to a specific scope:

Scope levelEffect
Organisation-wide (default)Key can access data across all brands and workspaces
BrandKey can only access data in workspaces belonging to that brand
WorkspaceKey can only access data in that specific workspace

This is useful when you have multiple integrations or partners that should only see a subset of your data.

Brands and workspaces with a restricted key

Section titled “Brands and workspaces with a restricted key”
ActionOrganisation-wideBrandWorkspace
List and read brandsAll brandsIts brandIts workspace’s brand
Create a brandYesNoNo
Update a brand, upload its imagesAny brandIts brandNo
Delete a brand without workspacesAny brandNoNo
List and read workspacesAll workspacesThe brand’s workspacesIts workspace
Create a workspaceUnder any brandUnder its brandNo
Update a workspaceAny workspaceThe brand’s workspacesIts workspace
Delete a workspaceAny workspaceThe brand’s workspacesNo

A brand or workspace outside the key’s restriction answers 404, as if it did not exist. An action the restriction does not cover, on a brand or workspace the key can see, answers 403 with "code": "key_lock".

An MCP connection carries its own scope, set when it is registered: the whole organisation, one brand, or one workspace. A key reaches a connection when its restriction and the connection’s scope agree.

ActionOrganisation-wideBrandWorkspace
List and read connectionsAll connectionsIts brand’s, and those of its brand’s workspacesIts workspace’s, and its brand’s
Register an organisation-wide connectionYesNoNo
Register a connection under a brandUnder any brandUnder its brandNo
Register a connection in a workspaceIn any workspaceIn a workspace of its brandIn its own workspace
Change a connection: instructions, tool risk, assurance, guardrails, assignments, test, restoreAny connectionIts brand’sIts own workspace’s
Delete a connectionAny connectionNoNo

A connection outside the key’s restriction answers 404; an action the restriction does not cover, on a connection the key can see, answers 403 with "code": "key_lock". An organisation-wide connection sits above every restriction, so a restricted key neither sees nor registers one.

oHallo’s own system connections, which carry the knowledge base, policies, the calendar and the web reader, are configured by oHallo. A key does not change their instructions or their tools’ risk classifications, and does not restore or delete one. What the account decides about them stays open to a key: guardrails, the assurance a tool requires, and which agents may call its tools.

A channel belongs to its workspace. A restricted key lists, reads, creates, changes and deletes the channels of the workspaces its restriction covers, and any other channel answers 404.

An agent serves wherever its MCP connections are active. A restricted key reads every agent. It changes an agent only when every connection the agent uses is inside its restriction, and receives 403 with "code": "key_lock" otherwise, and it gives an agent only connections its restriction covers. Assigning a connection’s tools to an agent changes the agent too, so a restricted key assigns them only to an agent whose every connection is inside its restriction, and another agent answers 403 with "code": "key_lock". It detaches an agent from any connection inside its restriction. Deleting an agent and restoring an agent version take a key without a restriction. Who can change an agent lists the scopes each agent action needs.

API keys can optionally have an expiration date. After expiry, any request using the key returns 401 Unauthorized. Non-expiring keys remain valid until manually revoked.

Set an expiration when creating keys for:

  • Temporary integrations or proof-of-concept projects
  • Third-party partners with time-limited access
  • Compliance policies that require key rotation

Rotate keys regularly. Create a new key, update your integration, then revoke the old key. There is no downtime: both keys work simultaneously during the transition.

Use minimum scopes. Grant only the permissions your integration actually needs. A reporting tool should not have conversations:write access.

Never expose keys in client-side code. API keys are server-side credentials. Do not embed them in browser JavaScript, mobile apps, or public repositories. If you need client-side access, proxy requests through your own backend.

Store keys in a secrets manager. Use your platform’s secrets management (a managed secrets vault, or environment variables in CI/CD) rather than hardcoding keys in source files.

Monitor key usage. The dashboard shows the last-used timestamp for each key. Revoke keys that have not been used recently or that belong to decommissioned integrations.

Returned when the API key is missing, malformed, expired, or revoked.

{
"error": "Unauthorized"
}

Returned when the API key is valid but does not have the required scope for the endpoint. missing_scopes names the scopes the key lacks.

{
"error": "Forbidden",
"missing_scopes": ["conversations:write"]
}

For example, calling POST /api/conversations/{id}/reply with a key that only has conversations:read scope returns 403.

A key restricted to a brand or workspace receives 403 with a code when its restriction does not cover the action, for example a brand-restricted key creating a brand:

{
"error": "This API key's brand or workspace restriction does not allow this action",
"code": "key_lock"
}