Yappy API authentication
Most of this API needs no credentials. Every read endpoint under /api/v1, and both MCP servers, are open. Start there and only come back to this page if you hit a rate ceiling.
Discovery first
An agent should not guess. The two metadata documents describe everything:
| Document | URL |
|---|---|
| Protected resource metadata (RFC 9728) | [/.well-known/oauth-protected-resource](https://yappy.biz/.well-known/oauth-protected-resource) |
| Authorization server metadata (RFC 8414) | [/.well-known/oauth-authorization-server](https://yappy.biz/.well-known/oauth-authorization-server) |
| Prose walkthrough for agents | [/auth.md](https://yappy.biz/auth.md) |
Probing https://yappy.biz/agent/auth returns a 401 whose WWW-Authenticate: Bearer resource_metadata="…" header points at the first of those, so one request is enough to learn the rules.
Register a client
RFC 7591 dynamic client registration, no human in the loop:
curl -sX POST https://yappy.biz/oauth/register \
-H 'content-type: application/json' \
-d '{
"client_name": "my-agent",
"grant_types": ["client_credentials", "authorization_code"],
"response_types": ["code"],
"redirect_uris": ["https://example.com/callback"],
"token_endpoint_auth_method": "client_secret_basic",
"scope": "read:releases read:docs read:pricing"
}'
The response carries client_id, client_secret, and the issued scopes. Store the secret; it is not retrievable afterwards.
Get a token
Machine-to-machine, which is what an agent wants:
curl -sX POST https://yappy.biz/oauth/token \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&client_id=…&client_secret=…&scope=read:releases'
Authorization code with PKCE S256 is also supported, for the case where a token should be tied to a person rather than a program:
GET /oauth/authorize
?response_type=code
&client_id=…
&redirect_uri=https://example.com/callback
&scope=read:docs
&state=…
&code_challenge=…
&code_challenge_method=S256
S256 is the only challenge method accepted. Plain is refused.
Scopes
Least privilege is machine-readable — the same list appears in scopes_supported in the protected-resource metadata and in the OpenAPI security schemes.
| Scope | Grants |
|---|---|
read:releases | Release history and the current version |
read:docs | Documentation pages and search |
read:pricing | Pricing and plan data |
read:faq | Frequently asked questions |
export:docs | Starting and polling export jobs |
Ask for the narrowest set that does the job. A token with no scope still reads everything that is public — the scopes exist to raise limits and to gate exports, not to unlock secrets.
Use the credential
curl -s https://yappy.biz/api/v1/releases \
-H 'Authorization: Bearer <access_token>'
Bearer in the Authorization header is the only accepted method — no query parameter, no cookie. Tokens are opaque, expire in one hour, and carry the scopes they were issued with.
Errors
401 with WWW-Authenticate: Bearer error="invalid_token" means expired or malformed — get a new one. 403 with error="insufficient_scope" names the scope you needed in the header. Both bodies are RFC 9457 problem documents; see errors.
Revocation
RFC 7009:
curl -sX POST https://yappy.biz/oauth/revoke \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'token=<access_token>&client_id=…&client_secret=…'
Returns 200 whether or not the token existed, as the RFC requires. Revoking a client's secret revokes every token issued under it.