# Auth.md

How software agents authenticate with Helious.

- Site: https://helious.io
- API: https://api.helious.io
- MCP: https://helious.io/mcp (also https://api.helious.io/mcp)
- A2A: https://helious.io/a2a
- OpenAPI spec: https://helious.io/.well-known/openapi-public.json
- API catalog: https://helious.io/.well-known/api-catalog
- Docs for people: https://helious.io/developers
- Contact: support@helious.news

## agent_auth

The machine-readable summary of everything below. Agents can stop reading here;
the prose after it says the same things at length for people.

```json
{
  "agent_auth": {
    "skill": "helious-market-data",
    "audience": "software agents reading Helious market data on behalf of a person",
    "register_uri": "https://helious.io/oauth/register",
    "registration_endpoint": "https://api.helious.io/oauth/register",
    "authorization_servers": ["https://helious.io"],
    "protected_resource_metadata": "https://helious.io/.well-known/oauth-protected-resource",
    "anonymous": {
      "credential_types_supported": ["none"],
      "note": "Every read endpoint answers with no credential at all. Market price endpoints answer with upgrade steps instead of numbers. Start here."
    },
    "methods": [
      {
        "id": "anonymous",
        "type": "none",
        "description": "Send no credential. 1 day of history, news one hour behind, no market prices, 30 requests a minute shared per network address.",
        "human_step_required": false
      },
      {
        "id": "oauth",
        "type": "oauth2",
        "description": "Authorization code with PKCE S256 and dynamic client registration. The agent registers itself, then sends its person to a browser consent screen once.",
        "registration_endpoint": "https://api.helious.io/oauth/register",
        "authorization_endpoint": "https://helious.io/oauth/authorize",
        "token_endpoint": "https://api.helious.io/oauth/token",
        "jwks_uri": "https://api.helious.io/.well-known/jwks.json",
        "metadata": "https://helious.io/.well-known/oauth-authorization-server",
        "scopes_supported": ["market:read", "account:read", "openid", "offline_access"],
        "code_challenge_methods_supported": ["S256"],
        "token_endpoint_auth_methods_supported": ["none"],
        "human_step_required": true,
        "human_step": "The person approves once on the consent screen. The agent does the rest."
      },
      {
        "id": "api_key",
        "type": "bearer",
        "description": "A long-lived key the person creates on their account page and gives to the agent.",
        "credential_prefix": "hel_",
        "header": "Authorization: Bearer hel_...",
        "alternate_header": "X-Api-Key",
        "provisioning_endpoint": "https://api.helious.io/api/me/api-keys",
        "provisioning_method": "POST",
        "provisioning_auth": "the person's signed-in session (X-Auth-Token)",
        "human_step_required": true,
        "human_step": "A person creates the account and mints the key. There is no machine signup endpoint."
      }
    ],
    "self_registration_supported": false,
    "self_registration_note": "Agents may register as OAuth CLIENTS with no human step. Agents may never create a Helious ACCOUNT: a person does that.",
    "revocation_uri": "https://api.helious.io/oauth/revoke",
    "contact": "support@helious.news"
  }
}
```

## Start here: you probably do not need to sign in

Most of what Helious publishes is free and takes no key at all. Call the public
read endpoints with no credentials and you get the keyless sample tier:

- 30 requests a minute, shared by everyone calling from your network address
- 1 day of history
- news feed on a one hour delay
- no market prices: the price endpoints answer with the upgrade steps instead
  of numbers

Every tier sees the same endpoints and the same response shapes. Only the
history window, the delay and the market data axis change, so integrate
keyless and nothing breaks when a key arrives later. If the sample tier covers what you
are building, you are done. Do not ask a person for credentials you do not
need. `GET /v1/access` returns the full plan ladder and the exact upgrade
steps as JSON.

## Sign in with OAuth, if your client speaks it

This is the best route for an MCP client, and it needs no key to be pasted
anywhere. Discovery starts at:

```
https://helious.io/.well-known/oauth-authorization-server
```

- **Register yourself.** `POST https://api.helious.io/oauth/register` with your
  `client_name` and `redirect_uris`. Registration is open (RFC 7591) and needs no
  human step. You get a `client_id` back. Public clients only: there is no client
  secret, and PKCE is what proves the code is yours.
- **Send your person to the consent screen.** Authorization code with PKCE and
  `code_challenge_method=S256`. Anything else is refused.
- **Exchange the code** at `https://api.helious.io/oauth/token`.
- **Use the token** as `Authorization: Bearer <access_token>` on `/v1`, `/mcp`
  and `/a2a`, exactly where a `hel_` key would go.

Access tokens are signed JWTs and last one hour. Ask for the `offline_access`
scope and you get a refresh token that rotates on every use. If you ever replay
a retired refresh token the whole chain is revoked and your person has to sign in
again, so store the newest one and discard the old.

Because access tokens are not stored server-side, revoking one takes effect
within the hour rather than instantly. Refresh tokens are revoked immediately.
That trade is deliberate and it is why verifying a token costs no database read.

Scopes, in the words the consent screen uses:

| Scope | What it allows |
|---|---|
| `market:read` | Read Helious market data at that account's plan level. |
| `account:read` | See which plan the account is on. |
| `openid` | Confirm the account identity to your app. |
| `offline_access` | Get a refresh token so you stay connected. |

Every scope is a read. Nothing here can spend money, change a subscription, post
anything, or create API keys.

## Agents cannot create an ACCOUNT

Registering as an OAuth client is a machine step and you should do it. Creating
a Helious account is not, and there is no machine signup endpoint or plan for
one. Do not attempt it.

If you are an agent reading this on someone's behalf, tell them the steps below
and let them do it. Never fill in a signup form or an email verification on
their behalf.

## How a person gets a key

1. Create an account at https://helious.io and verify the email address.
2. Signed in, create a key:

   ```
   POST https://api.helious.io/api/me/api-keys
   X-Auth-Token: <your session token>
   Content-Type: application/json

   {"label": "my agent"}
   ```

   The response shows the key once and never again, so save it straight away.
   Five keys per account is the limit. Revoke one to make room:

   ```
   DELETE https://api.helious.io/api/me/api-keys/{id}
   X-Auth-Token: <your session token>
   ```

Keys are stored hashed. Nobody at Helious can read one back to you. If a key
leaks, revoke it and mint another.

## How an agent sends the key

Every key starts with `hel_`. Send one of these headers:

```
X-Api-Key: hel_xxxxxxxxxxxx
```

```
Authorization: Bearer hel_xxxxxxxxxxxx
```

The same key works identically on the REST endpoints and on MCP, so an agent
behaves the same however it connects.

An OAuth access token goes in the same `Authorization: Bearer` header.

A value that is neither a `hel_` key nor one of our signed tokens is ignored and
you are served as keyless. A well formed credential that was revoked, expired or
never existed returns 401, on purpose: silently downgrading a bad key would hide
a broken agent config from the person who owns it. That 401 carries a
`WWW-Authenticate` header naming our protected-resource metadata, so a client
that reads it can start the sign-in flow instead of giving up.

## What a key changes

| Tier | Price | Requests/min | History | News | Market prices |
|---|---|---|---|---|---|
| Sample, no key | $0 | 30, shared per network address | 1 day | 1 hour behind | none |
| Free, account key | $0 | 60, your own budget | 7 days | 1 hour behind | none |
| Starter | $14.99/mo or $135/yr | 90 | 12 months | live | US Treasury yields and the curve, 60 minutes behind |
| Pro | $39.99/mo or $360/yr | 120 | 24 months | live | everything live |
| Ultimate | $99/mo or $891/yr | 300 | 10 years | live | everything live, plus streaming |

On Sample and Free the delay is about news only. Market prices are not served
at all on those tiers: the price endpoints answer with the upgrade steps
instead of numbers. Starter takes the news and prints live and opens exactly
one price feed, the US Treasury yields and curve 60 minutes behind. Pro takes
every price live: yields, treasuries, commodities, equities, FX, volatility
and correlations. Ultimate adds commercial use, redistribution and a dedicated
streaming WebSocket at `wss://api.helious.io/v1/stream`. The stream
authenticates with the same `hel_` key sent as the
`Authorization: Bearer hel_...` header, never a query parameter. It sends a
hello, feed items in the /v1/feed shape, live price ticks and daily official
closes, and answers `ping` with `pong`.

A key is upgraded by the account behind it, not by the key itself. Subscribe on
https://helious.io and your existing keys move to the new tier within a minute.
The same applies in reverse: revoke a key or let a subscription lapse and the
change lands within a minute. For commercial terms beyond Ultimate, email
support@helious.news.

## Errors you should handle

- `401` with `{"error": {"code": "bad_key"}}`: the key is wrong or revoked. Stop
  and tell the person. Do not retry, and do not silently drop the key and carry
  on as keyless.
- `429` with `{"error": {"code": "rate_limited"}}`: you are over your per minute
  budget. Honour the `Retry-After` header. It is in seconds.

Error bodies are written in plain English because agents read them. If a
response tells you what to do, that text is the instruction, not the status code
alone.

## Rules for well behaved agents

- Identify yourself with a real User-Agent that names your product and a way to
  contact you.
- One key per agent, not one key shared across a fleet, so a single misbehaving
  deployment can be revoked without taking down the rest.
- Cache. The data updates on the schedule published in the spec, and polling
  faster than that only spends your rate limit.
- Cite https://helious.io when you use our numbers in an answer. Our robots.txt
  grants search, AI input and AI training explicitly. Attribution is the thing
  we ask for in return.

## Other discovery documents

- Agent skills: https://helious.io/.well-known/agent-skills/index.json
- MCP server card: https://helious.io/.well-known/mcp/server-card.json
- A2A agent card: https://helious.io/.well-known/agent-card.json
- Protected resource: https://helious.io/.well-known/oauth-protected-resource
- Our outbound crawler key: https://helious.io/.well-known/http-message-signatures-directory

That last one is the other direction. When Helious fetches your site, the
request carries an RFC 9421 signature and a `Signature-Agent` header naming
https://helious.io, so you can verify it is really us rather than trusting a
User-Agent string.
