Skip to content
Back to help

API rate limits

Per-endpoint reference

Goldenhour’s public surface uses in-memory token- bucket rate limiting on the customer-facing booking flow + the AI-vision endpoint. The MCP endpoints (the bulk of the AI-agent surface) have no per-IP limits: they’re aggressively edge-cached instead.

The token-bucket model

Each rate-limited endpoint has two parameters:

  • Capacity: burst allowance. You can hit this many times back-to-back from a cold start.
  • Refill rate: tokens regenerated per second. Sustained throughput converges to this once burst is exhausted.

On the 429 response, the body is { kind: "rate_limited" } + a Retry-After header in seconds. Wait that long + retry.

Rate-limited endpoints

Per-IP buckets

EndpointBurstSustainedNotes
/api/book/quote-travel2030/min30/minute sustained. Customer-facing live travel-fee quote endpoint as they type their address. Per-IP token bucket.
/api/book (submitBooking action)56/min6/minute sustained. Per-IP. Booking submission, waitlist signup, gift-card purchase share the same bucket.
/api/book/manage/[token] (cancel/reschedule)1012/min12/minute sustained. Token-protected + IP rate-limited as credential-stuffing defense.
/api/shade-analyzer (vision)51/min1/minute sustained. Pre-auth public surface (anonymous client on booking page). Anthropic billing per call; tight cap.

MCP + redirect endpoints

Cache-friendly, no per-IP cap

  • MCP endpoints (/api/mcp/manifest, /api/mcp/[tenant], etc.) have NO per-IP rate limit. Aggressively edge-cached at 5 min for tenant data + 60s for availability + 1h for manifests / spec.json.
  • QR codes (/api/qr/[tenant]) are 1h edge-cached + 6h stale-while-revalidate. A flood of unique-query-string requests would land at origin only on first miss per cache key.
  • Booking-link redirects (/api/booking-link/[tenant]) have Cache-Control: no-store. Unbounded: but each call is a cheap DB lookup + a 302; non-issue for any realistic call volume.

Best practices for callers

  • Cache aggressively on your side. Tenant data changes minute-scale; availability data changes minute-scale; manifests are essentially static. Respect Cache-Control headers.
  • Respect Retry-After when you do hit a 429. Don’t retry-loop tighter than the header value.
  • Polling cadence: for availability data, 60s is more than enough. The slot picture shifts when other customers book; sub-minute polling is paranoia, not freshness.
  • Send a real User-Agent. Helps us reach out if anything breaks on our side. Format preferred: <product>/<version> (<contact-email>).

Back to API quick-start