Authentication
Every /v1 request is authenticated with an API key. There is no OAuth flow and no session cookie - just a key on every request. A dashboard session token will not work here, and a key will not work on the dashboard's own endpoints; the two are deliberately separate.
Getting a key
Mint one in the dashboard under Settings → Account → API access. Keys start with mh_live_ and you can hold up to 3 active at a time. Revoke one to make room for another.
The key is shown once, at the moment you create it. We store only a hash of it, so we cannot show it to you again and cannot recover it for you. Copy it straight into your secret store. Lost it? Revoke it and mint another.
Sending the key
Send it as an Authorization: Bearer header. An X-Api-Key header works too, if that fits your tooling better.
curl https://api.mastheads.app/v1/editions \
-H "Authorization: Bearer mh_live_your_key_here"Send only one. If the Authorization header starts with Bearer , that is the credential we check and X-Api-Key is never read - so a stale Bearer alongside a good X-Api-Key is a 401, not a fallback.
Plan access
The read-only content API is a Growth-plan feature. The gate is on creating a key, and it is enforced in the database rather than by the interface: on a plan without it, minting is refused outright.
Keys you already hold keep answering. /v1 itself performs no plan or billing check on a request - the only reasons a valid key stops working are revocation and the rate limit.
Key lifecycle
Keys are server-side secrets. Never ship one in browser code, in a mobile app, or in a public repository: it can read every article on your account. That includes the image endpoint, so an image URL from the API cannot be used as a public <img src>.
Revoke a key in Settings at any time. Revocation is checked on every request, so it takes effect immediately with no propagation delay and nothing to purge. The dashboard also shows when each key was last used, stamped at most once a minute so a busy puller does not pay for the bookkeeping.
Keys do not expire on a timer and there is no rotation deadline. If you want rotation, mint the new key first, move your integration over, then revoke the old one - you have three slots so the two can overlap.
When a key is rejected
A missing, malformed, unknown or revoked key is a 401 with the code invalid_key. The message is deliberately the same for all four, so a probe cannot tell which one it hit.
{
"error": {
"code": "invalid_key",
"message": "Missing, invalid, or revoked API key"
}
}Repeated failures from one address are throttled at 30 per minute and answer 429. If you are seeing that while testing, you are being counted with everyone else behind your address - wait a minute rather than retrying in a loop. The full table is on Rate limits & errors.