# auth.md

Registration and authentication instructions for agents that call Octagon's
APIs.

This document is self-contained: the audience, the registration endpoints, the
supported methods and how to use the resulting credentials are all below, so an
agent needs nothing else to get from zero to an authenticated call. The OAuth
discovery documents are linked at the end for clients that prefer to resolve
them; where this document and the metadata disagree, the metadata wins.

## Agent audience

This is for autonomous software agents and MCP clients calling Octagon's
prediction-market and public-markets research APIs, usually on behalf of a
human user. It is not the path for browser sign-in.

An access token is issued for a specific audience. These are the resource
identifiers an agent can target:

| Audience (resource identifier) | What it is | Requires a credential |
| --- | --- | --- |
| `https://mcp.octagonai.co/mcp` | MCP server | Yes — OAuth bearer token, or an API key in the path |
| `https://api.octagonai.co/v1` | REST API | Yes — API key as a bearer token |
| `https://www.octagonai.co` | This site and its discovery documents | No — public |

## Registration endpoints

An agent provisions its own client here. No human has to create it first.

| Purpose | Endpoint | Method |
| --- | --- | --- |
| Register a client (RFC 7591 dynamic client registration) | `https://login.octagonai.co/oauth2/register` | `POST` |
| Authorize (human approves) | `https://login.octagonai.co/oauth2/authorize` | redirect |
| Device authorization, for headless clients | `https://login.octagonai.co/oauth2/device_authorization` | `POST` |
| Exchange for a token | `https://login.octagonai.co/oauth2/token` | `POST` |

API keys have **no** registration endpoint: they are issued to a human account
at <https://app.octagonai.co/subscribe>. An agent cannot mint its own key — ask
the user to supply one.

## Supported methods

Authorization server: `https://login.octagonai.co`.

- **Dynamic client registration** (RFC 7591) — open, no pre-shared credential.
- **Authorization code grant with PKCE** — `code_challenge_method=S256`, the
  only method supported. A human approves the grant, so this is not a fully
  unattended path.
- **Device code grant** —
  `urn:ietf:params:oauth:grant-type:device_code`, for clients with no browser.
- **Refresh tokens** — request the `offline_access` scope.
- **API key** — a bearer credential for the REST API, and a fallback for MCP
  clients that cannot do OAuth.

Scopes supported: `openid`, `profile`, `email`, `offline_access`.
Bearer methods supported: `header`.
Client authentication methods: `none`, `client_secret_post`, `client_secret_basic`.

### Registration flow, end to end

1. **Register.** `POST https://login.octagonai.co/oauth2/register` with your
   client metadata (`client_name`, `redirect_uris`, `grant_types`). You get back
   a `client_id`.
2. **Authorize.** Send the user to
   `https://login.octagonai.co/oauth2/authorize` using the authorization code
   grant with PKCE. Headless clients use the device code grant at
   `https://login.octagonai.co/oauth2/device_authorization` instead.
3. **Exchange.** `POST https://login.octagonai.co/oauth2/token` for an access
   token, plus a refresh token if you asked for `offline_access`.
4. **Call.** Present the token as described below.

## Credential use

Send the access token in the `Authorization` header. It is the only accepted
presentation — a token in a query string is rejected.

```http
POST /mcp HTTP/1.1
Host: mcp.octagonai.co
Authorization: Bearer <access_token>
```

For the REST API, an API key is presented the same way:

```http
GET /v1/... HTTP/1.1
Host: api.octagonai.co
Authorization: Bearer <OCTAGON_API_KEY>
```

MCP clients that cannot set headers may place the key in the path instead:
`https://mcp.octagonai.co/{OCTAGON_API_KEY}/mcp`. A key in a URL is exposed to
logs and browser history, so prefer the header, and never log or echo a key you
were given. Public Keys are a restricted key type with limited model and
endpoint access.

When a call returns `401`, the response carries
`WWW-Authenticate: Bearer resource_metadata="…"`. Follow that URL and re-run
discovery rather than hard-coding endpoints or retrying blindly.

## Revocation

There is no endpoint an agent can call to revoke its own access. A human
revokes API keys and OAuth refresh tokens from the account dashboard at
<https://app.octagonai.co/api-keys>. Treat a `401` that survives a fresh
discovery pass as revoked, and stop retrying.

## Discovery documents

Protected resource metadata (RFC 9728) is published once per resource, each
copy served from the origin it describes — RFC 9728 §3.3 makes a client discard
metadata whose `resource` value does not match the URL it was fetched from, so
there is no single document that covers both.

- This site: <https://www.octagonai.co/.well-known/oauth-protected-resource>
  (`resource` = `https://www.octagonai.co`)
- MCP endpoint: <https://mcp.octagonai.co/.well-known/oauth-protected-resource/mcp>
  (`resource` = `https://mcp.octagonai.co/mcp`) — the one to use when calling
  the MCP server, and the one its `401` points at.

Authorization server metadata (RFC 8414) is published only by the issuer, at
<https://login.octagonai.co/.well-known/oauth-authorization-server>. This site
serves none: RFC 8414 §3.3 applies the same identity rule as RFC 9728, so a
copy served from `www` would have to return an `issuer` that does not match the
origin it came from, and a conforming client would discard it.

The `agent_auth` registration block therefore lives in a document of this
site's own, which names the authorization server rather than impersonating it:
<https://www.octagonai.co/agent-auth.json>

Other:

- OpenID Connect discovery:
  <https://login.octagonai.co/.well-known/openid-configuration>
- API catalog (RFC 9727): <https://www.octagonai.co/.well-known/api-catalog>
- MCP server card: <https://www.octagonai.co/.well-known/mcp/server-card.json>

## Terms

Use of these APIs is governed by <https://www.octagonai.co/terms-of-service>.
Octagon publishes research, not investment advice; do not present model output
as a recommendation or execute trades on a user's behalf from it.
