Honcho OpenAPI Spec Hosting Plan

Goal

Serve every published Honcho API spec (every major and minor version) from a branded, CDN-backed origin so agents, SDK generators, and docs tooling can consume them without hitting GitHub raw rate limits or depending on commit SHAs.

URL layout

One path per exact release (immutable), plus floating aliases:

spec.honcho.dev/v2.5.1/openapi.json      # pinned, immutable
spec.honcho.dev/v2.5.2/openapi.json
spec.honcho.dev/v3.0.0/openapi.json
spec.honcho.dev/v2/openapi.json          # alias → latest v2.x
spec.honcho.dev/v3/openapi.json          # alias → latest v3.x
spec.honcho.dev/latest/openapi.json      # alias → current stable
spec.honcho.dev/index.json               # discovery manifest

GitHub remains source of truth. This origin is a publish target.

Hosting

Cloudflare R2 + a Worker (or Pages project) in front of it.

  • Zero egress cost on R2.
  • Custom domain (spec.honcho.dev).
  • Bypasses raw.githubusercontent.com anonymous rate limits.
  • Reuses the Cloudflare footprint the landing page already lives on.

S3 + CloudFront or Bunny work equivalently if we need to avoid Cloudflare.

Cache policy

Biggest lever for correctness and cost.

  • Pinned release paths (/vX.Y.Z/...): Cache-Control: public, max-age=31536000, immutable
  • Floating aliases (/vX/..., /latest/..., /index.json): Cache-Control: public, max-age=300, s-maxage=300, stale-while-revalidate=86400

Short TTL on aliases so version bumps propagate quickly; immutable on pinned paths so consumers can cache forever without revalidation.

Discovery manifest (/index.json)

The piece agents actually consume. Agents hit one URL and pick the version.

{
  "versions": [
    {
      "version": "3.0.0",
      "major": "v3",
      "status": "stable",
      "released": "2026-03-01",
      "spec": "https://spec.honcho.dev/v3.0.0/openapi.json"
    },
    {
      "version": "2.5.2",
      "major": "v2",
      "status": "deprecated",
      "released": "2026-01-15",
      "sunset": "2026-09-01",
      "spec": "https://spec.honcho.dev/v2.5.2/openapi.json"
    }
  ],
  "aliases": {
    "latest": "3.0.0",
    "v3": "3.0.0",
    "v2": "2.5.2"
  }
}

Status values: stable, deprecated, sunset. Include sunset date when deprecating so agents can warn ahead of removal.

If the manifest schema ever needs to evolve, version it (index.v1.json, index.v2.json) so existing consumers don’t break.

CI publish flow

Wire into the Honcho repo release action.

  1. On tag vX.Y.Z, upload docs/vX/openapi.json to r2://spec-honcho-dev/vX.Y.Z/openapi.json.
  2. Update aliases (/vX/..., /latest/...). Two implementation options:
    • Copy-upload (simple, two writes, brief window of inconsistency).
    • Worker resolves aliases from the manifest at request time (atomic, single write, preferred).
  3. Regenerate /index.json with the new release and updated aliases.
  4. Purge the CDN cache for the affected alias keys.

Downstream wiring

Once spec.honcho.dev is live, update:

  • /.well-known/api-catalog on honcho.dev: service-descspec.honcho.dev/latest/openapi.json, service-metaspec.honcho.dev/index.json.
  • Docs site (honcho.dev/docs): point Mintlify/Scalar/Swagger UI version switcher at the manifest instead of hardcoded per-version files.
  • SDK generators: pin to an explicit vX.Y.Z/openapi.json in CI; don’t generate from latest (non-deterministic builds).

Gotchas

  • CORS on the bucket. Agents and browser tooling (Swagger UI, Scalar, Redocly) fetch cross-origin. Set Access-Control-Allow-Origin: *.
  • Content-Type. Serve application/openapi+json (or at least application/json). Don’t let R2 default to binary/octet-stream.
  • ETags + HTTP/2. Free on Cloudflare, saves bandwidth on pinned paths.
  • Never delete deprecated versions before their sunset date actually passes. Agents with cached references will break. “Deprecated” means “don’t build new clients against this,” not “gone.”
  • Don’t regenerate pinned files. Pinned paths are immutable. If a v3.0.0 build is wrong, ship v3.0.1.

Why not the alternatives

  • Keep using raw.githubusercontent.com: anonymous rate limit (~60/hr per IP), no branded URL, no CDN SLA, no manifest pattern.
  • Serve from honcho.dev/docs: works, but ties spec availability to docs deploy cadence and Mintlify quirks. Better to keep spec distribution independent of docs publishing.
  • Serve from api.honcho.dev/openapi.json: requires poking a hole in the auth gateway and couples spec availability to API uptime.
  • One merged spec with all versions: fails as soon as v2/v3 have incompatible shapes. Ours already do.