Authentication

Every credential Halo issues, which to use when, the header they go in, what scopes do, and how an API key acts as its person.

Each credential opens its own routes and no others, so the one you need follows from what you're building.

The credentials

CredentialLooks likeOpensMade whereLasts
API keyhak_…/v1/developer/* on api.usehalo.netThe portal90 days by default, at most 365
MCP tokenhpat_… (personal), hmat_… (OAuth)/mcp on mcp.usehalo.netHalo Data, under Account, AI tools, or an app's sign-inPersonal: up to a year. OAuth: an hour at a time, for up to 90 days
Embed secrethes_…Signs the JWTs that open one report through /v1/public/*Halo Data, under Settings, EmbeddingUntil rotated. A token it signs lasts at most 24 hours
Link tokenhlp_… (public), hle_… (embed)One report through /v1/public/*The report's Share dialogUntil it's turned off or reaches its expiry
Ingest tokenhci_…POST /v1/public/crm/ingest and POST /v1/public/crm/stats, for one webhook sourceHalo CRM, under SourcesUntil you make a new one
dbt tokenhdbt_…/v1/dbt/artifacts, to send a dbt project from CIHalo Data, on the connection, under Post from CIUntil it's revoked

Halo signs webhooks with a secret too. A webhook secret, whs_…, opens nothing: you check a request's signature with it.

The extranet, where a business looks after its record, signs people in with emailed links. Its routes are for its own pages, and aren't an API to build on.

None opens another's routes. A session cookie gets 401 on /v1/developer/*, an API key gets nothing on /v1/orgs/*, /mcp or the Console, and a personal token gets 401 on /v1/developer/*.

Which to use when

You're buildingUse
Code on your server that reads datasets, charts or reportsAn API key
An AI tool or agent that reads data as someoneAn MCP token: see Connect a client
Code that reads your websites or directoryAn API key: see Read websites and the directory
Your own system adding to the directoryAn ingest token: see Send listings to Halo
Something that reacts when the directory changesA webhook: see Webhooks
A report inside your own product, with each reader seeing their own rowsA JWT signed with the embed secret: see Signed embeds
A report anyone with the address can openA link: see Public links and snapshots

Choose an integration compares them in more detail.

The header

Send an API key on every request, in the Authorization header:

GET /v1/developer/whoami HTTP/1.1
Host: api.usehalo.net
Authorization: Bearer hak_…

The API reads nothing else: no cookies, and no key in the address. A request with access_token, api_key, apikey, key or token in its query string gets 400 key_in_query before anything looks at the value. URLs reach logs, histories and other sites' Referer headers, so roll the key if a URL with it may have been logged.

Keep keys on a server. Any origin may call the Developer API without credentials, so a browser would let you, but anyone who loads the page can then read the key. For a browser, use a signed embed.

Every answer carries Cache-Control: no-store and an X-Request-Id. Quote the id if you contact Halo about a request.

Scopes

A key carries some of three scopes. Left out when it's made, it gets all of them. Everything they allow reads, and nothing writes.

ScopeOpens
datasets.readGET /v1/developer/datasets, GET /v1/developer/datasets/{id}
data.queryPOST /v1/developer/datasets/{id}/query, GET /v1/developer/charts/{id}/data
content.readGET /v1/developer/charts, GET /v1/developer/charts/{id}, GET /v1/developer/reports, GET /v1/developer/reports/{id}, and websites, listings and businesses

GET /v1/developer/whoami needs no scope. A request outside the key's scopes gets 403 insufficient_scope.

Scopes only narrow what the person's role allows. A key with data.query whose person can't export still gets 403 export_not_allowed. MCP connections use the same three names: see The MCP server.

How a key acts as its person

A key is one person in one organization. It never carries authority of its own.

  • It reads what they can read. Requests go through the same services as Halo Data, with the person's access levels and row policies.

  • It follows them as they are now. Every request loads their account, membership, role and organization again, so a role change applies on the next call.

  • It ends with their access. Changing their password or two-factor, or leaving the organization, revokes it. See What stops a key.

  • It remembers how they signed in. If the organization later stops allowing that sign-in method, the key stops too.

  • It stays in one organization. To read from two, make a key in each.

Requests are logged and audited against the person. Keys owned by an organization rather than a person are planned.

Read more in The security model.