Authentication
Every request carries an API key in the Authorization header:
curl "https://rest.haasapi.com/v1/markets" \ -H "Authorization: Bearer hk_live_3f2504e0-4f89-41d3-9a0c-0305e82c3301"Create keys in Settings → API Keys. The full key is shown once, at creation - store it somewhere safe. Keys can be disabled (reversible) or deleted (permanent) from the same page.
The prefix tells you what a key can touch:
| Prefix | Environment |
|---|---|
hk_live_ |
Production - real accounts, real money |
The hk_live_ prefix is recognizable at a glance and registered for secret scanning, so a leaked
key in a public repo gets flagged.
What is not accepted
Section titled “What is not accepted”This API accepts API keys only. Browser session tokens, OAuth tokens, and legacy credential
pairs belong to other surfaces and are refused with a 401 - regardless of whether they are
valid there.
Scopes
Section titled “Scopes”A key carries scopes that bound what it can do. You choose them when you create the key, and they cannot be changed afterward - mint a new key to change them.
| Scope | Grants |
|---|---|
read |
Read-only access to every resource - accounts, markets, bots, scripts, labs, backtests, orders, positions |
bots |
Create, start, stop, and delete bots |
scripts |
Create, edit, and delete scripts |
labs |
Run and cancel backtests and labs |
trading |
Place and cancel orders directly |
A call that needs a scope the key lacks returns 403 insufficient_scope; each endpoint’s
reference page names the scope it requires. A key created with no scopes (the legacy
“full access” form) is unrestricted - it is also the only kind accepted on the non-REST
surfaces, so keep it for the local MCP server and older integrations, and prefer scoped keys
for everything on /v1.
Keys never belong in a browser
Section titled “Keys never belong in a browser”API keys are server-side credentials. The API deliberately serves no CORS headers, so browser JavaScript cannot call it directly - build a backend, or use MCP for interactive use. A key that ships in frontend code is a key someone else now owns.
Failure modes
Section titled “Failure modes”| Status | code |
Meaning |
|---|---|---|
401 |
unauthorized |
No credential, or not a bearer token |
401 |
invalid_api_key |
Wrong kind of token, or an unknown / disabled / revoked key |
503 |
temporarily_unavailable |
The key could not be verified right now. Retry with the same key - do not discard it |
That last row is deliberate: a transient backend fault will never tell you your key is dead.
Only a 401 means the key itself is the problem.