API keys
Turn on the API, make a key, pick its scopes and expiry, store it, roll it with a 24-hour overlap, revoke it, and know what stops it and what to do if one leaks.
A key lets your code read through the Developer API as you, in one organization. This page covers a key's whole life. You manage your keys at dev.usehalo.net/keys, signed in with your Halo account: a key can't make, roll or revoke keys.
Turn it on
The Developer API is off in every organization until one of its own Owners or Admins turns it on. Halo staff can't do it for you.
In Halo Data, go to Settings, API access.
Turn on Let members use the Developer API. It saves at once, and the audit log records it.
Turning it on makes no keys. Each member whose role has api.use then makes their own. If you aren't an Owner or Admin, your keys page says the API is off and gives you a link to send one of them. The playground's sample data works either way.
Who may make one
Your role has
api.use. Owner, Admin, Builder and Analyst do by default, and Viewer and External guest don't.The Developer API is on for the organization. It's off until an Owner or Admin turns it on.
Your session finished two-factor authentication, if you've set it up.
You aren't Halo staff viewing as someone.
You have fewer than 25 live keys in the organization. Playground keys don't count.
You've made or rolled fewer than 30 keys in the last hour.
You signed in within the last 15 minutes. If you didn't, Sign in again takes you through it and back here. Playground keys don't need this.
Make a key
Choose New key. Give it a Name that says what it's for, up to 200 characters, such as "Nightly sync". Then choose what It may do and when it Ends after, and choose Make key.
The key is shown once, and Test it checks that it works. Halo stores only a SHA-256 hash, and lists show only a hint: the prefix and first six characters.
Pick scopes
Give a key the fewest it needs. Scopes only narrow what your role allows.
| It may | Scope | Allows |
|---|---|---|
| See datasets and their fields | datasets.read | Names, descriptions and fields of the datasets you can see |
| Query data | data.query | Aggregate and read rows, and read a chart's rows. Your role must be able to export |
| See charts, reports, websites and the directory | content.read | List and read the charts and reports you can see, and websites, listings and businesses where you have a role in those products |
A job that copies rows from a dataset you already know needs only Query data.
Pick an expiry
Every key ends. You can pick 30 days, 90 days or a year, with 90 as the default. Pick the shortest you can keep rolling. You'll hear seven days before it ends.
Store it
Read it from the environment or a secret manager, and pass it in the Authorization header.
import os
headers = {"Authorization": f"Bearer {os.environ['HALO_API_KEY']}"}Never commit it, or put it in a URL, browser code, a mobile app, a log or a prompt.
Use one key per integration, so you can roll or revoke one without touching the others.
Keys start with
hak_, so a pre-commit hook or secret scanner can look for them.
Roll a key
Rolling replaces a key without downtime. Only the person who made a key can roll it, since rolling shows a secret.
Choose the key's roll button at the keys page, then Roll key. You get a new key, with the same name and scopes, that lasts as long as the old one did, counted from now.
Put the new secret where your code reads it, and deploy.
Check it with
GET /v1/developer/whoami:key.idandkey.expiresAtare the new key's.
Until it ends, the old key is marked Replaced in your list. It can be revoked, but not rolled again: 409 key_replaced.
The old key keeps working for 24 more hours, and never longer than it had left. A key that has already expired or been revoked can't be rolled, so make a new one.
Revoke a key
Revoking stops a key at once, and its record stays. You can revoke your own, and anyone with members.manage can revoke anyone's. It can't be undone.
What stops a key
Some changes revoke a key for good, in the same database transaction, whatever made the change. Undoing the change doesn't bring the key back. Others stop it only while they last.
| What changed | Which keys | What your code sees | Afterwards |
|---|---|---|---|
| The key reached its expiry, or was revoked | That key | 401 invalid_api_key | Make or roll another |
| The session that made a playground key ended, such as by signing out | That playground key | 401 invalid_api_key | Make another |
| The person's password changed | All theirs, in every organization | 401 invalid_api_key | Make another |
| Their two-factor was set up, changed or removed | All theirs, in every organization | 401 invalid_api_key | Make another |
| Their account was deleted | All theirs, in every organization | 401 invalid_api_key | Gone |
| Their membership was suspended or removed | All theirs in that organization | 401 invalid_api_key | Make another once they're back |
Their role no longer has api.use | All theirs in that organization | 403 forbidden | Works again with a role that has it |
| The API was turned off | Everyone's in that organization | 403 api_disabled | Works again when it's back on |
| The organization was suspended | Everyone's in that organization | 403 org_suspended | Works again when it's restored |
| The organization began requiring two-factor, and they haven't set it up | Theirs in that organization | 403 mfa_enrollment_required | Setting it up changes their two-factor, which revokes the key, so make another |
| The organization stopped allowing how they signed in when they made the key | Those keys | 403 sign_in_method_required | Works again if it's allowed again |
Because a key ends with its person, watch for 401 in production and alert someone. Keys owned by the organization are planned.
If a key leaks
Stop it. Revoke it at once if you can take the outage. Otherwise roll it, deploy the new secret, and revoke the old key right away rather than waiting out the 24 hours. Rolling alone leaves the leaked key working for a day.
See what it did. Your keys list has each key's last use and number of requests, and Recent requests has your latest 20, with their operation, result, rows and request id. Halo keeps the log for 90 days. An Owner or Admin can also see the address a key was last used from.
If you can't reach it, ask an Owner or Admin. They can revoke anyone's key.
Find the source. Remove it from wherever it leaked, and treat old copies, such as git history, as public.
A leaked key reads what its person can read, within its scopes, and can't change anything. 400 key_in_query means a key was in a URL: the request was refused, but something may have logged the URL, so roll that key.
Notices
Halo tells the key's person, in Halo and by email by default. Each notice links to the keys page.
| When | The notice says |
|---|---|
| A key is made | An API key was made on your account |
| A key is rolled | An API key was replaced on your account |
| A key ends within seven days, once per key | Your API key ends soon |
| An Owner or Admin revokes it | An admin revoked your API key |
| Halo revokes it | Halo revoked your API key |
If you get one you didn't expect, revoke the key. Playground keys send no notices. The changes in What stops a key don't send a key notice either.
What Owners and Admins can see and do
Owners and Admins have a page for this in Halo Data, under Settings, API access.
| On that page | Permission | What it does |
|---|---|---|
| Let members use the Developer API | org.manage | It starts off. On lets members make keys. Off stops every key on its next request, and they stay listed for when it's back on |
| Every member's keys | members.manage | Shows each key's name, hint, member, scopes, last use with its address, and end. Revoking one stops it at once and tells its person |
| Recent requests | members.manage | The latest 50 requests from any key |
Members see only their own keys and requests. No one can read a secret, and an Admin can't roll someone else's key, since that would show them one.
The audit log records api_key.created, api_key.rolled, api_key.revoked and api.settings_updated, never the secret. Reads appear there too: see The security model.