Public HTTP surfaces
The public product and integration surfaces exposed by BizHedge.
| Surface | Purpose |
|---|---|
| Health | Reports public application readiness without exposing private configuration. |
| Analysis | Translates an owner outcome into one reasoned market relationship or an honest no-fit result. |
| Sports | Builds promotion positions and keeps them separate from ordinary business-risk analysis. |
| Market Demand | Publishes safe, grouped evidence about missing markets. |
| Demand events | Records eligible product signals for later grouped publication. |
| Shared receipts | Creates a revocable, public-safe summary of one result. |
| Partner Demand API | Provides authenticated snapshots, changes, summaries and taxonomy. |
Each surface has its own schema and allowlist. A successful response from one surface does not grant access to another.
Route and method matrix
Every route accepts a fixed method set and answers the rest with a structured 405 carrying an Allow header. All bodies are JSON except POST /api/analyze, which returns a Server-Sent Events stream (Content-Type: text/event-stream) of ordered stage events.
| Route | Methods | Auth | Notes |
|---|---|---|---|
/api/health | GET, HEAD, OPTIONS | none | Always 200; inspect the body for degraded. |
/api/analyze | POST, OPTIONS | server-keyed | SSE stream; optional owner-supplied key in the body only. |
/api/sports-promos | GET, HEAD, OPTIONS | none | Bundled fallback when live data is unavailable. |
/api/gap-demand | GET, POST, OPTIONS | none | Public aggregate read; idempotent capture on POST. |
/api/receipts | GET, POST, OPTIONS | none | Public-safe shared receipts; 503 before its migration. |
/api/partner/v1/* | GET, HEAD, OPTIONS | bearer | Header-authenticated; no cross-origin browser access. |
Operator and scheduled routes exist but are private and are not documented here. Unknown paths return a structured 404. HEAD mirrors GET headers with no body. OPTIONS follows each route's own CORS contract; a bare 204 without CORS headers does not authorize a browser.
Status codes
Responses are sanitized: no route returns a stack trace, database error, or credential detail.
| Status | Meaning |
|---|---|
200 | Success. May still carry a degraded or fallback body; read it. |
202 | Optional capture or resumable refresh progress accepted; not a completion. |
400 | Malformed request, or a credential supplied in the query string. |
401 | Missing or invalid bearer token. Body is {"error":"unauthorized"} with no detail. |
403 | Fails closed: required server configuration is absent. |
404 | Unknown path. |
405 | Unsupported method. Carries an Allow header. |
409 | Partner sync checkpoint is stale; discard local state and take a new full snapshot. |
429 | Per-IP rate limit exceeded. |
503 | A persistence-backed surface is unavailable, sanitized. |
Authentication
Partner, operator, and scheduled routes take a bearer token in the header only:
Authorization: Bearer <token>Credentials in a query string are rejected with 400. The optional Analyze bring-your-own-key travels in the request body and is never logged, persisted, or returned. Tokens are compared with a constant-time check, and each credential class is a distinct secret of at least 32 bytes.
Origin policy
Each surface sets its own CORS contract. Public read-only health and Sports data are broadly readable. Analysis, Demand capture, and receipts accept same-host or explicitly allowlisted origins. Partner integration is header-authenticated and closed to cross-origin browser use entirely.
Availability is part of the contract
Some surfaces return a safe fallback; persistence-backed surfaces can report unavailability. A 200 health status can still carry a degraded body. Optional run capture can fail without changing the completed owner result. Private and authenticated surfaces fail closed when required configuration is absent.
Consumers must read the documented body state rather than infer readiness from a single status code.