Public API discovery
The public site exposes a small read-only API surface for discovery and health checks. These endpoints are public and do not require OAuth, OIDC, or agent registration.
Discovery resources
/.well-known/api-catalogreturns the linkset used for automated API discovery./api/openapi.jsonpublishes an OpenAPI 3.1 description of the public endpoints./api/healthreturns a 200 JSON health response for status checks./auth.mddocuments that the public site does not currently require authentication.
Endpoints
| Path | Method | Purpose |
|---|---|---|
/api/v1/health | GET | Health and availability check for automated clients. |
/api/v1/og?stack=... | GET | Generates the PNG social preview used for stack share links. |
/api/health, /api/og | GET | Unversioned aliases for the two above. Pin to /api/v1/ for a stable contract. |
Errors
Errors are returned as RFC 9457 problem details with the application/problem+json media type. Branch on code, which is stable; title and detail are human-readable and may be reworded. Each error's type URI links to its section below.
Method Not Allowed
405 · method_not_allowed — the endpoint was called with an unsupported HTTP method. Every endpoint on this surface is read-only and accepts only GET and HEAD. The response carries an Allow header listing the accepted methods. Retry with GET.
{
"type": "https://projects.dev/docs/api/#method-not-allowed",
"title": "Method Not Allowed",
"status": 405,
"code": "method_not_allowed",
"detail": "This endpoint only supports GET and HEAD. Received POST.",
"instance": "/api/health"
}Not Found
404 · not_found — no such endpoint. Unknown paths on this site return a real 404, never a 200 with an app shell, so a path that 404s does not exist. Any unrecognised path under /api/ answers with a problem document rather than an HTML or plaintext error page.
{
"type": "https://projects.dev/docs/api/#not-found",
"title": "Not Found",
"status": 404,
"code": "not_found",
"detail": "No such endpoint. This site exposes only GET /api/health and GET /api/og; see /api/openapi.json for the full description.",
"instance": "/api/does-not-exist"
}Outside /api/, a request carrying Accept: text/markdown gets a 404 with a markdown recovery body; browsers get the HTML 404 page, whose markdown copy is at /404.md.
Internal Error
500 · internal_error — an unexpected server-side failure. Safe to retry with backoff. Note that /api/og does not use this code: rendering failures there fall back to a generic preview card with a 200, because a broken image in a link unfurl is worse than a generic one.
Authentication and versioning
- No authentication. The OpenAPI document declares an empty root-level
securityarray and nosecuritySchemes. No OAuth or OIDC endpoints are published — see/auth.md. /api/v1/is the versioned surface to pin to. The unversioned paths are aliases that always resolve to the current major, so they may change whenv2ships. Av2prefix would be added alongsidev1, not in place of it.- The document itself is versioned by
info.versionusing semantic versioning. - Breaking changes are signalled at least 90 days ahead with RFC 9745
Deprecationand RFC 8594Sunsetheaders. Full policy on the developer resources page. - No rate limiting is applied, so no
RateLimitheaders are returned. An absent header here means no limit, not an undocumented one. If limits are introduced they will use the RFC 9331RateLimitheaders withRetry-Afteron429, announced under the same policy.