# auth.md — agent access to OGRECORDS™

OGRECORDS™ is an independent music distribution and marketing platform for
self-publishing artists and small labels, operated by OnlineBuilders LLC. This
document tells an autonomous agent how to obtain and use a credential for our
machine interfaces.

German version: <https://www.og-records.com/de/auth.md>

## Who this is for

Agents acting **on behalf of an existing OGRECORDS account holder** — an
artist or label that already distributes with us. Every credential is owned by
a human account and inherits that account's data scope: an agent sees the
owner's catalogue and nothing else.

There is no anonymous agent identity, and nothing described here creates an
account. OAuth client registration is open, but a client is only a name and a
redirect address — it can read nothing until an account holder approves it.

## Two ways to authenticate

1. **OAuth 2.1** — for MCP clients such as Claude, ChatGPT or Claude Code.
   The account holder signs in on our consent screen; no key is copied.
2. **API key** — for scripts and server integrations against the REST API.

Both yield a Bearer credential that every machine interface accepts, with the
same scopes, quota and usage log.

## OAuth 2.1 (connectors)

We are our own authorization server. Discovery:

- Protected resource (RFC 9728):
  <https://www.og-records.com/.well-known/oauth-protected-resource/api/agent/mcp>
- Authorization server (RFC 8414):
  <https://www.og-records.com/.well-known/oauth-authorization-server>

An unauthenticated call to the MCP endpoint answers `401` with
`WWW-Authenticate: Bearer resource_metadata="…"`, which is all a compliant MCP
client needs to start the flow on its own.

| Step | Endpoint |
|---|---|
| Dynamic client registration (RFC 7591) | `POST https://api.og-records.com/api/v1/oauth/register` |
| Authorization (consent screen) | `https://www.og-records.com/oauth/authorize` |
| Token | `POST https://api.og-records.com/api/v1/oauth/token` |
| Revocation (RFC 7009) | `POST https://api.og-records.com/api/v1/oauth/revoke` |

Rules:

- Authorization code flow only, **PKCE with S256 is mandatory**.
- Redirect URIs must be `https`, or `http` on `localhost` / `127.0.0.1`
  (the port of a loopback redirect may change between runs).
- Public clients (`token_endpoint_auth_method: none`) and confidential clients
  (`client_secret_post` / `client_secret_basic`) are both supported.
- Only **read** scopes can be granted over OAuth: `read:releases`,
  `read:stats`, `read:artists`, `read:smartlinks`, `read:earnings`. The user
  may untick any of them on the consent screen. Omitting `scope` requests all.
- Access tokens (`ogr_oat_…`) live 1 hour. Refresh tokens (`ogr_ort_…`) live
  60 days and rotate on every use — presenting a spent refresh token ends the
  connection.
- `resource`, if sent, must be `https://www.og-records.com/api/agent/mcp`.
- The account holder sees and disconnects every app at
  <https://www.og-records.com/dashboard/settings/connected-apps>.

To connect in Claude or ChatGPT, add a custom connector with the URL
`https://www.og-records.com/api/agent/mcp` and sign in when asked.

## API keys (scripts and integrations)

Provisioning is a human step, because a key grants access to a real catalogue
and to earnings figures:

1. The account holder signs in at <https://www.og-records.com/login>.
2. API keys are early-access gated. If the dashboard shows the early-access
   panel instead of the key form, request access from
   <mailto:support@og-records.com> — a human enables the flag.
3. At <https://www.og-records.com/dashboard/settings/api-keys> they create a
   key, choosing scopes and tier. **The secret is displayed exactly once**;
   it is stored only as an HMAC-SHA256 digest and cannot be recovered. Lost
   keys are rotated, not recovered.

Key format: `ogr_pk_<env>_<16 hex>.<secret>` — for example
`ogr_pk_live_a1b2c3d4e5f60718.<secret>`. The portion before the dot is a
public prefix that identifies the key in the dashboard and in usage logs; the
portion after it is the secret.

## Using the credential

Send an access token or a key either way — both are accepted on every
machine interface:

```http
Authorization: Bearer ogr_pk_live_a1b2c3d4e5f60718.<secret>
```

```http
X-API-Key: ogr_pk_live_a1b2c3d4e5f60718.<secret>
```

Verify a key before doing anything else. This endpoint requires no scope, so
it works for every valid key and tells you what the key may actually do:

```http
GET https://api.og-records.com/api/v1/public/whoami
Authorization: Bearer <key>

200 OK
{"authenticated":true,"scopes":["read:releases","read:stats"],
 "tier":"free","rate_limit_per_day":1000}
```

## Machine interfaces

| Interface | Endpoint | Notes |
|---|---|---|
| REST | `https://api.og-records.com/api/v1/public` | OpenAPI: <https://www.og-records.com/api-docs/openapi.json> · docs: <https://www.og-records.com/api-docs> |
| MCP (Streamable HTTP) | `https://www.og-records.com/api/agent/mcp` | JSON-RPC 2.0, `initialize` / `tools/list` / `tools/call` |
| A2A (JSON-RPC) | `https://www.og-records.com/api/agent/a2a` | Agent Card: <https://www.og-records.com/.well-known/agent-card.json> |
| Outbound webhooks | configured per account | HMAC-SHA256 signed; `release.delivered`, `release.live`, `release.rejected`, `release.takedown` |

The MCP and A2A endpoints are **read-only**. Writes (draft releases, smart
links, track metadata) exist only on the REST API and need the matching
`write:` scope.

## Scopes

`read:releases`, `read:smartlinks`, `read:stats`, `read:artists`,
`read:earnings`, `write:smartlinks`, `write:releases`, `write:tracks`.

Two endpoints intentionally require no scope: `whoami` (a key must be able to
discover its own capabilities) and `/api/v1/public/help` (the same product
documentation every signed-in user can read).

Distribution triggers — submit, resubmit, takedown, archive — are **not**
exposed to any key at any scope. They move real music into real stores and
stay behind a human action in the dashboard.

## Quota and errors

Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and
`X-RateLimit-Reset` (Unix seconds). Daily quota: 1 000 requests on the free
tier, 100 000 on business (granted by staff on request).

| Status | Meaning | What an agent should do |
|---|---|---|
| 401 | Missing, expired, invalid or revoked credential | OAuth: refresh the access token, or start the flow again if the refresh fails. API key: stop and ask for a new key. |
| 403 | Valid credential, missing scope | Stop. The message names the missing scope; the owner must grant it (reconnect, or mint a key that has it). |
| 429 | Daily quota exhausted | Honour `Retry-After` (seconds). The counter resets at `X-RateLimit-Reset`. |

## Bot identity

Requests that OGRECORDS itself sends outward (webhook deliveries, remote file
imports) are signed per Web Bot Auth (RFC 9421, `tag="web-bot-auth"`). Our
public keys:
<https://www.og-records.com/.well-known/http-message-signatures-directory>

## Further discovery

- API catalog: <https://www.og-records.com/.well-known/api-catalog>
- Agent skills: <https://www.og-records.com/.well-known/agent-skills/index.json>
- Site index for LLMs: <https://www.og-records.com/llms.txt>
- Every public page also answers `Accept: text/markdown` with a Markdown
  representation of itself.

## Contact

<mailto:support@og-records.com> · Security: <https://www.og-records.com/.well-known/security.txt>
