# Agent registration and authentication

_Product Billboards - https://productbillboards.com/_

## Short version

The public API needs no authentication. There is no key to request, no OAuth
flow to complete, and no account to register. Send the request.

Everything an agent can read through it is what an anonymous visitor already
sees on the site: the billboard catalog, verified 7-day visitor counts,
founder AMA threads and release stories. Nothing private is exposed, so there
is nothing for a credential to protect.

## What is public

| Capability | Call | Auth |
| --- | --- | --- |
| `list_billboards` | `GET /api/feed` | none |
| `list_categories` | `GET /api/categories` | none |
| `get_billboard` | `GET /listing/{id}/llms.txt` | none |
| `search_products` | `GET /v1/search` | none |
| `get_leaderboard` | `GET /v1/leaderboard` | none |

Machine-readable equivalents of this table:

- OpenAPI: https://productbillboards.com/openapi.json
- API catalog (RFC 9727): https://productbillboards.com/.well-known/api-catalog
- MCP server card: https://productbillboards.com/.well-known/mcp/server-card.json
- Agent skills index: https://productbillboards.com/.well-known/agent-skills/index.json
- MCP endpoint: https://productbillboards.com/api/mcp (streamable HTTP, JSON-RPC 2.0, `authentication: none`)

## What is not public, and why there is still no agent token

Creating listings, replying in AMA threads, buying sponsor slots and reading a
founder's analytics all sit behind a signed-in human session held in a
first-party cookie, issued by Supabase Auth after email sign-in at
https://productbillboards.com/login. That session is not obtainable as a bearer token, is not
delegatable, and is not something an agent should be holding: it authorises
payments and public speech in a founder's name.

So there is no client registration endpoint and no scope list, because there
are no scopes: the API surface is entirely read and entirely open.

## Rate limits

60 requests per minute per IP, bursting to 120. Over the limit the API returns 429 with a Retry-After header. No key, no quota, no sign-up.

Over the limit you get `429 Too Many Requests` with a `Retry-After` header in
seconds. Respect it; retrying sooner extends the window rather than shortening
it. Use exponential backoff on repeated 429s.

## The unhappy paths

- **404** - the id does not exist, or the listing has been removed by its
  owner. Do not retry; re-list to get current ids.
- **406 Not Acceptable** - your `Accept` header asked for something the URL
  cannot produce. HTML and `text/markdown` are what pages offer; the API
  endpoints speak JSON. The response body says so.
- **429** - see above.
- **5xx** - transient. Back off and retry; the catalog is cached for five
  minutes at the edge, so a repeat within that window returns the same page
  anyway.
- **No expiry, refresh or revocation applies**, because no token is issued. If
  that changes, this document changes with it and the OpenAPI `security` array
  stops being empty. Treat a disagreement between the two as a bug and report
  it to hey@productbillboards.com.

## Identifying yourself

No credential is required, but a descriptive `User-Agent` with a contact URL
is appreciated and makes it far less likely that a burst gets mistaken for
scraping. Crawl preferences are declared in https://productbillboards.com/robots.txt, including a
`Content-Signal` directive covering search, AI input and AI training.

## Contact

hey@productbillboards.com - https://productbillboards.com/contact
