Developers
The Fun API
JSON under /api/v1, with application/problem+json errors. A person is the fun_at session cookie or a Network user token as a Bearer. No route needs a service token; the one outbound write uses the person's own token.
Local guide
GET /api/v1/guide?q=&kind=&accessible=&rainy=&kids=&cheap=&radius=- OSM places with attribution and a map link; Ticketmaster events when this server has them on (events_configured says so).
IRL quests
GET /api/v1/quests?limit=&cursor=&status=&city=- Public IRL quests, newest first.
GET /api/v1/quests/:slug- One quest with its vote and chat-check counts.
GET /api/v1/quests/boards/:id- One board and its suggestions (the share link).
POST /api/v1/quests/boards- A streamer opens a board; the Live channel and Network username must match.
POST /api/v1/quests/boards/:id/suggest{ title, brief?, category?, accessible? }, safety-filtered.POST /api/v1/quests/:slug/vote- One vote per person (or one per public chat username via the read-only chat job).
POST /api/v1/quests/:slug/accept|live|complete|verify- The streamer, or staff for verify;
{ via: "chat"|"moderator" }. POST /api/v1/quests/:slug/hide- Staff hides a public quest and tombstones its Search document.
Group plans
GET /api/v1/plans?limit=&cursor=&city=- Public plans, newest first.
GET /api/v1/plans/:slug- One plan with options, vote counts and the winner.
POST /api/v1/plans{ title, starts_at, timezone, options[] }; the owner decides.POST /api/v1/plans/:slug/options|vote|decide- Add an option, cast one vote, choose the winner (tie is refused).
POST /api/v1/plans/:slug/today- Adds the winner to the caller's own OpenVibe.Today with their token and an idempotency key.
POST /api/v1/plans/:slug/hide- Staff.
Search
Each public quest is one search.index-document@1 (owner fun, type quest, /q/<slug>); each public plan is type plan (/plans/<slug>). They are queued in fun_outbox and delivered to OpenVibe.Search within a minute; hiding or cancelling queues a tombstone.