Project One

Project One — API Documentation

Programmatic reference for everything the platform exposes over HTTP: 38 endpoints across 11 resource groups — the console surface (/api/*) plus the versioned programmatic surface (/api/v1/*) — and the conventions they share. Written for three audiences at once: engineers integrating against the platform, AI agents driving it, and us, six months from now.

Integrating a machine? Start with platform-api-v1.md — the /api/v1 surface exists precisely for you (RFC 9457 errors, stable codes, credential-derived tenancy). The legacy /api/* routes serve the console UI.

Start here

  1. conventions.md — read this first. Demo vs live modes, the three auth tiers, rate limits, body limits, error envelopes, the approval gate, telemetry, and the complete environment-variable list. Every resource page assumes you know it.
  2. openapi.yaml — the machine-readable spec (OpenAPI 3.1). Feed it to codegen, Postman/Bruno, validators, or an LLM.
  3. llms.txt — the compact entry point for AI agents.

Resource map

Page Endpoints What lives there
leads-and-marketing.md POST /api/leads · POST /api/interest · GET/POST /api/unsubscribe Lead capture, tour-gate interest, CAN-SPAM/RFC 8058 unsubscribe
bookings.md GET/POST/OPTIONS /api/bookings · GET/POST /api/bookings/manage · POST /api/bookings/mark Slot sets, race-safe booking, the lead's manage link, host-marked outcomes
conductor-chat.md POST /api/conductor The member chat bar (live LLM or demo responder, jargon-guarded)
approvals.md POST /api/approvals The launch-gate decision endpoint (one-time capability tokens)
media.md POST /api/media (3 actions) · GET /api/vsl Photo library, VSL ticket→PUT→confirm, the stable VSL redirect
creatives-and-videos.md POST /api/creatives · POST /api/videos Creative decisions and the animate-this-ad video seeding flow
video-generation-provider.md (no HTTP endpoint — backend integration) The Gemini/Veo ("Nano Banana") video provider: external API contract, config, async lifecycle
onboarding-and-brand.md POST /api/onboarding · POST /api/brand-assets Tenant provisioning and brand intake
auth.md POST /api/auth/login · POST /api/auth/logout · GET /auth/confirm Sign-in/out and the magic-link landing (redirect surfaces)
public-pages.md GET /p/{instanceId} · GET /p/{instanceId}/thanks Served funnel pages
internal-cron.md POST /api/cron The scheduled tick (secret-gated)
platform-api-v1.md GET /api/v1/status · /approvals · /creatives · /videos · /performance · /positioning · /angles · /scripts · /landing-page · /brand · POST /api/v1/approvals/{id}/decision · /creatives/{id}/decision · /creatives/{id}/animate · /approvals/pause-request · /approvals/budget-request · PATCH /api/v1/angles/{id} The programmatic surface: problem+json errors, demo-labeled reads, fail-closed mutations

Five things to know before your first call

  1. Demo vs live is per-response, not per-deployment. Check every success for "mode": "demo" — it means nothing was persisted. See conventions §2.
  2. Send Content-Length. Body-guarded routes reject chunked requests with 411 before reading anything.
  3. Everything fails closed now. A configured live failure is an honest 500 on every route — "mode": "demo" means exactly one thing: the platform is keyless (API slice 0 ended the old fail-open-to-demo-ack behavior). Decisions additionally fail closed on input (exact lowercase "approve"/"reject").
  4. Real-world actions go through the approval gate. You never trigger a publish/launch directly — you decide a pending approval, and a server-side one-time token executes it. conventions §7.
  5. Some surfaces aren't JSON. Auth is 303 redirects; unsubscribe and booking-manage are HTML pages; cron errors are plain text. Each page flags its own shape.

How to keep these docs alive (the update contract)

The module is deliberately boring to update:

  • One resource group per file under resources/. Adding an endpoint to an existing group = edit that one file + add the path to openapi.yaml + one line in the table above. A brand-new group = new file following the shared template (summary paragraph → endpoint table → per-endpoint Request/Responses/Side effects/Notes → > Source: footer).
  • Conventions changes go in conventions.md only — resource pages link, never restate. If you're copy-pasting a rate-limit table into a resource page, stop.
  • Every page ends with > Source: file paths. When code and doc disagree, the code wins; fix the doc in the same PR as the behavior change. Treat a route diff without a docs diff as a review smell.
  • The OpenAPI spec is part of the definition of done for any endpoint change — it's what AI tooling and codegen consume, so it drifts loudest.
  • Keep the honesty notes (the "Notes for callers" gotchas). They document real behavior — silent drops, anti-enumeration 404s, demo fallbacks — and they're the part future-us will thank present-us for.

Docs generated 2026-07-22 from a source-grounded extraction of every route file; each fact traced to code. Suite state at generation: 319 tests passing.