{"openapi":"3.1.0","info":{"title":"Runner Festival API","version":"2026-09-15","description":"Push lineup, venue, policies, announcements and offers into Runner; pull aggregated, anonymized insights. Never returns fan PII."},"servers":[{"url":"https://runner-cgxr.onrender.com"}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"rk_live_…","description":"Org API key from Control panel → Settings → Integrations. Scopes: events:read, lineup:write, venue:write, policies:write, announcements:write, broadcasts:write, offers:write, insights:read, links:read, app:write."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9_.:-]{8,128}$"},"description":"Retries with the same key and body replay the first response for 24h."}},"responses":{"Error":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthorized","forbidden","insufficient_scope","not_found","invalid_request","rate_limited","idempotency_mismatch","not_configured","internal"]},"message":{"type":"string"},"details":{}}},"request_id":{"type":["string","null"]}}},"Set":{"type":"object","required":["day","artist","start"],"properties":{"day":{"type":"string","format":"date"},"artist":{"type":"string"},"stage":{"type":["string","null"]},"start":{"type":"string","pattern":"^\\d{1,2}:\\d{2}$"},"end":{"type":["string","null"]},"headliner":{"type":"boolean"}}},"PresentedBy":{"description":"The sponsor who bought this place, as a name (\"Northpeak Energy\") or an object. Runner then names the place that way in fan replies, on the public event page and in the public API — and logs every time it does.","oneOf":[{"type":"string"},{"type":"object","required":["sponsor"],"properties":{"sponsor":{"type":"string"},"url":{"type":"string","format":"uri"},"style":{"type":"string","enum":["presented_by","by","sponsored_by","named"],"default":"presented_by"},"display_name":{"type":"string","description":"Required for `named`: the full name as sold, e.g. \"Driftline Hydration Station\"."}}}]},"SponsoredPlace":{"type":"object","required":["place","sponsor"],"properties":{"place":{"type":"string","description":"The name your set times and map already use."},"kind":{"type":"string","enum":["stage","amenity","area"]},"sponsor":{"type":"string"},"url":{"type":"string","format":"uri"},"style":{"type":"string","enum":["presented_by","by","sponsored_by","named"]},"display_name":{"type":"string"},"active":{"type":"boolean"}}},"Stage":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"lat":{"type":"number"},"lng":{"type":"number"},"capacity":{"type":"number"},"presented_by":{"$ref":"#/components/schemas/PresentedBy"}}},"Poi":{"type":"object","required":["name","type"],"properties":{"name":{"type":"string"},"type":{"type":"string","description":"entrance | vip_entrance | dropoff | pickup | box_office | accessible | gate — or an amenity type (water, medical, bar, food, restroom, merch, lockers, charging…)"},"lat":{"type":"number"},"lng":{"type":"number"},"note":{"type":"string"},"primary":{"type":"boolean","description":"For type=gate: also the main entrance."},"presented_by":{"$ref":"#/components/schemas/PresentedBy"}}},"Policies":{"type":"object","properties":{"bag_policy":{"type":"string"},"reentry":{"type":"string"},"reentry_allowed":{"type":"boolean"},"prohibited_items":{"type":"array","items":{"type":"string"}},"permitted_items":{"type":"array","items":{"type":"string"}},"age_policy":{"type":"string"},"cameras":{"type":"string"},"smoking":{"type":"string"},"cashless":{"type":"string"},"accessibility":{"type":"string"},"lost_and_found":{"type":"string"}}},"Audience":{"type":"object","description":"Standard broadcasts only. Omit for every attached fan.","properties":{"days":{"type":"array","items":{"type":"string","format":"date"}},"tiers":{"type":"array","items":{"type":"string"}},"artists":{"type":"array","items":{"type":"string"}},"onSite":{"type":"boolean"}}},"Offer":{"type":"object","required":["kind","title"],"properties":{"kind":{"type":"string","enum":["parking","transport","merch","upgrade","hotel","food","afterparty","experience","sponsor","tickets"]},"title":{"type":"string"},"detail":{"type":"string"},"price":{"type":"string"},"url":{"type":"string","format":"uri"},"sponsor":{"type":"string"},"audience":{"type":"string","enum":["all","no_ticket","ga","vip","driving","staying_over"]},"active":{"type":"boolean"},"starts_at":{"type":"string","format":"date-time"},"ends_at":{"type":"string","format":"date-time"}}},"TicketStatus":{"type":"object","required":["status"],"description":"Upserted by (day, tier). Omit day/tier for every day/tier.","properties":{"day":{"type":"string","description":"A date (YYYY-MM-DD) or the name fans use, e.g. 'weekend 2'."},"tier":{"type":"string"},"label":{"type":"string"},"status":{"type":"string","enum":["on_sale","low","sold_out","not_on_sale_yet"]},"on_sale_url":{"type":"string","format":"uri"},"note":{"type":"string"}}},"BroadcastProgress":{"type":"object","properties":{"broadcast_id":{"type":"string"},"class":{"type":"string","enum":["standard","emergency"]},"kind":{"type":"string"},"status":{"type":"string","enum":["pending_approval","queued","sending","done","cancelled"]},"counts":{"type":"object","properties":{"total":{"type":"integer"},"sent":{"type":"integer"},"failed":{"type":"integer"},"skipped":{"type":"integer"},"queued":{"type":"integer"}}},"started_at":{"type":["string","null"]},"finished_at":{"type":["string","null"]}}},"TextLink":{"type":"object","properties":{"event_id":{"type":"string"},"event_name":{"type":"string"},"number":{"type":"string"},"prefilled":{"type":"string"},"sms":{"type":["string","null"]},"short":{"type":["string","null"]},"deep_links":{"type":"object","properties":{"ios":{"type":"string"},"android":{"type":"string"},"android_intent":{"type":"string"}}},"qr_png":{"type":"string"},"embed":{"type":"string"}}},"PublicEventSummary":{"type":"object","required":["id","name","dates","timezone"],"properties":{"id":{"type":"string","example":"evt_acl_2026"},"name":{"type":"string"},"kind":{"type":["string","null"],"description":"concert | festival | sports | motorsport | tournament | comedy | theater | conference | other"},"dates":{"type":"array","items":{"type":"string","format":"date"}},"timezone":{"type":"string","example":"America/Chicago"},"venue":{"type":["object","null"],"properties":{"name":{"type":"string"},"city":{"type":["string","null"]}}}}},"Point":{"type":"object","required":["key","name","type"],"properties":{"key":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","description":"entrance | vip_entrance | dropoff | pickup | box_office | accessible | gate — or an amenity type (water, medical, bar, food, restroom, merch, lockers, charging…)"},"note":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]}}},"PublicOffer":{"type":"object","required":["id","kind","title"],"description":"An official offer the organizer listed on Runner. Never a third-party listing.","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["parking","transport","merch","upgrade","hotel","food","afterparty","experience","sponsor","tickets"]},"title":{"type":"string"},"detail":{"type":["string","null"]},"price":{"type":["string","null"]},"url":{"type":["string","null"]},"sponsor":{"type":["string","null"]},"audience":{"type":"string","enum":["all","no_ticket","ga","vip","driving","staying_over"]},"image_url":{"type":["string","null"]},"starts_at":{"type":["string","null"]},"ends_at":{"type":["string","null"]}}},"ThreadLink":{"type":"object","description":"How to open a Runner thread already about this event. `sms` opens Messages with the first text filled in; `short` is the permanent web link.","properties":{"code":{"type":["string","null"]},"number":{"type":["string","null"]},"prefilled":{"type":"string"},"sms":{"type":["string","null"]},"short":{"type":["string","null"]},"deep_links":{"type":["object","null"],"properties":{"ios":{"type":"string"},"android":{"type":"string"},"android_intent":{"type":"string"}}},"qr_png":{"type":"string"}}},"PublicEvent":{"type":"object","required":["event","schedule","policies","offers","ticket_status","as_of"],"properties":{"event":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":["string","null"]},"dates":{"type":"array","items":{"type":"string","format":"date"}},"timezone":{"type":"string"},"gates_open":{"type":["string","null"],"description":"HH:MM local"},"closes":{"type":["string","null"]}}},"venue":{"type":["object","null"],"properties":{"name":{"type":"string"},"address":{"type":["string","null"]},"city":{"type":["string","null"]},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]}}},"stages":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]}}}},"schedule":{"type":"array","description":"Set times as the organizer or the festival's own site published them, soonest first.","items":{"type":"object","required":["day","artist"],"properties":{"day":{"type":"string","format":"date"},"artist":{"type":"string"},"stage":{"type":["string","null"]},"start":{"type":["string","null"],"description":"HH:MM local"},"end":{"type":["string","null"]},"headliner":{"type":"boolean"},"source":{"type":"string","description":"official | promoter_supplied | venue_verified | scraped | inferred | manual | crowdsourced"}}}},"policies":{"type":"object","description":"Bag policy, re-entry, prohibited items, age, cashless and whatever else the organizer set. Keys as written; `reentry_allowed` and `cashless` are always present.","additionalProperties":true,"properties":{"bag_policy":{},"reentry":{},"reentry_allowed":{"type":"boolean"},"prohibited_items":{},"age_policy":{},"cashless":{"type":"boolean"}}},"wayfinding":{"type":"array","items":{"$ref":"#/components/schemas/Point"}},"amenities":{"type":"array","items":{"$ref":"#/components/schemas/Point"}},"announcement":{"type":["object","null"],"description":"The organizer's or venue's own words for the active day, attributed.","properties":{"text":{"type":"string"},"from":{"type":["string","null"]},"day":{"type":["string","null"]}}},"offers":{"type":"array","items":{"$ref":"#/components/schemas/PublicOffer"}},"ticket_status":{"type":"array","items":{"type":"object","properties":{"day":{"type":["string","null"]},"tier":{"type":["string","null"]},"label":{"type":["string","null"]},"status":{"type":"string","enum":["on_sale","low","sold_out","not_on_sale_yet"]},"on_sale_url":{"type":["string","null"]},"note":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"}}}},"sponsored_places":{"type":"array","description":"Places a sponsor bought, under the name the organizer sold. Wherever one of these places appears above (`stages[].name`, `schedule[].stage`, `amenities[].name`) it already carries this name; `base_name` / `stage_base` hold the plain one. Use the sponsored name when you name the place.","items":{"type":"object","properties":{"place":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["stage","amenity","area"]},"sponsor":{"type":"string"},"sponsor_url":{"type":["string","null"]}}}},"runner_thread":{"oneOf":[{"$ref":"#/components/schemas/ThreadLink"},{"type":"null"}]},"as_of":{"type":"string","format":"date-time"}}},"WebhookDelivery":{"type":"object","description":"Signed with Runner-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, \"t.body\")>. Types: fan_opted_in.count, broadcast.progress, questions.top, ping.","properties":{"id":{"type":"string"},"type":{"type":"string"},"api_version":{"type":"string"},"created_at":{"type":"string"},"event_id":{"type":["string","null"]},"data":{"type":"object"}}}}},"paths":{"/v1/festival/me":{"get":{"summary":"The calling key","security":[{"apiKey":[]}],"responses":{"200":{"description":"Key info"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events":{"get":{"summary":"Events your organization owns","security":[{"apiKey":[]}],"x-runner-scope":"events:read","responses":{"200":{"description":"Events"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/lineup":{"put":{"summary":"Bulk upsert lineup + set times","description":"mode=merge (default) upserts by act per day; mode=replace swaps each pushed day. Fans following a moved act get the existing set-time-change text.","security":[{"apiKey":[]}],"x-runner-scope":"lineup:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sets"],"properties":{"mode":{"type":"string","enum":["merge","replace"]},"sets":{"type":"array","items":{"$ref":"#/components/schemas/Set"}}}}}}},"responses":{"200":{"description":"Written"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/stages":{"put":{"summary":"Upsert stages by name","security":[{"apiKey":[]}],"x-runner-scope":"venue:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["stages"],"properties":{"stages":{"type":"array","items":{"$ref":"#/components/schemas/Stage"}}}}}}},"responses":{"200":{"description":"Counts"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/sponsored-places":{"put":{"summary":"Bind sponsors to stages and spots (\"Mirage presented by Northpeak Energy\")","security":[{"apiKey":[]}],"x-runner-scope":"venue:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["places"],"properties":{"places":{"type":"array","items":{"$ref":"#/components/schemas/SponsoredPlace"}}}}}}},"responses":{"200":{"description":"Every active sponsored place on the event"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/pois":{"put":{"summary":"Upsert gates, drop-off and amenities","security":[{"apiKey":[]}],"x-runner-scope":"venue:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pois"],"properties":{"pois":{"type":"array","items":{"$ref":"#/components/schemas/Poi"}}}}}}},"responses":{"200":{"description":"Written facts"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/parking-lots/{lot}/status":{"put":{"summary":"Mark a parking lot open, full or closed","description":"The lot must already be in the event's venue data (a parking POI). Fans whose plan or parking booking names it get one text naming the nearest lot marked open.","security":[{"apiKey":[]}],"x-runner-scope":"venue:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"name":"lot","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["open","full","closed"]},"from":{"type":"string"},"notify":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Stored, nobody texted"},"202":{"description":"Stored and queued"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/policies":{"put":{"summary":"Set policies (bag, re-entry, prohibited items…)","security":[{"apiKey":[]}],"x-runner-scope":"policies:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Policies"}}}},"responses":{"200":{"description":"Written keys"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/announcements":{"post":{"summary":"Post an announcement","description":"Stored for the brain; texted to attached fans (standard class) unless silent.","security":[{"apiKey":[]}],"x-runner-scope":"announcements:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","maxLength":420},"kind":{"type":"string","enum":["schedule","gate","weather","safety","general"]},"from":{"type":"string"},"day":{"type":"string","format":"date"},"silent":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Stored (silent)"},"202":{"description":"Queued"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/broadcasts":{"post":{"summary":"Create a broadcast","description":"class=standard queues immediately. class=emergency is filed as pending_approval and sends only after an owner or safety publisher approves it in the control panel.","security":[{"apiKey":[]}],"x-runner-scope":"broadcasts:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"class":{"type":"string","enum":["standard","emergency"]},"message":{"type":"string","maxLength":420},"kind":{"type":"string"},"from":{"type":"string"},"day":{"type":"string","format":"date"},"audience":{"$ref":"#/components/schemas/Audience"}}}}}},"responses":{"202":{"description":"Queued or pending approval"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/broadcasts/{broadcastId}":{"get":{"summary":"Broadcast progress (counts only)","security":[{"apiKey":[]}],"x-runner-scope":"broadcasts:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"name":"broadcastId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastProgress"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/offers":{"get":{"summary":"List offers & merch","security":[{"apiKey":[]}],"x-runner-scope":"offers:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"}],"responses":{"200":{"description":"Offers"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create an offer","security":[{"apiKey":[]}],"x-runner-scope":"offers:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Offer"}}}},"responses":{"201":{"description":"Created"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/offers/{offerId}":{"patch":{"summary":"Update an offer","security":[{"apiKey":[]}],"x-runner-scope":"offers:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"name":"offerId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Offer"}}}},"responses":{"200":{"description":"Updated"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete an offer","security":[{"apiKey":[]}],"x-runner-scope":"offers:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"name":"offerId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Deleted"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/ticket-status":{"get":{"summary":"List ticket statuses","security":[{"apiKey":[]}],"x-runner-scope":"offers:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"}],"responses":{"200":{"description":"Statuses"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"put":{"summary":"Set ticket status for a day/tier","security":[{"apiKey":[]}],"x-runner-scope":"offers:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TicketStatus"}}}},"responses":{"200":{"description":"Saved"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/insights":{"get":{"summary":"Aggregated, anonymized insights","description":"Reach counts, question topics (topics seen fewer than 3 times are withheld; no example texts), recent broadcast progress.","security":[{"apiKey":[]}],"x-runner-scope":"insights:read","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"name":"days","in":"query","schema":{"type":"integer","minimum":1,"maximum":90,"default":7}}],"responses":{"200":{"description":"Insights"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/text-link":{"get":{"summary":"Text-Runner kit: sms link, short link, deep links, QR, embed","security":[{"apiKey":[]}],"x-runner-scope":"links:read","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"}],"responses":{"200":{"description":"Kit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextLink"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/public/events":{"get":{"operationId":"searchEvents","summary":"Find events Runner is running","description":"Matches the words a person used against the event's name, its venue and its city. Upcoming events only unless `include_past=true`. Only events an organizer has claimed on Runner are listed; a fan's own imported tickets never appear here.","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Words from the event, venue or city — 'coachella', 'msg', 'miami'."},{"name":"city","in":"query","required":false,"schema":{"type":"string"},"description":"Only events in this city."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":25},"description":"1–25, default 10."},{"name":"include_past","in":"query","required":false,"schema":{"type":"boolean"},"description":"Also return events that already happened."}],"responses":{"200":{"description":"Events","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicEventSummary"}}}}}}},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/public/events/{eventId}":{"get":{"operationId":"getEvent","summary":"What Runner knows about an event","description":"Everything Runner will tell a fan before they text: dates and hours, the venue, stages, set times, gates and drop-off, amenities, policies, the organizer's announcement for the day, official offers, ticket status — and `runner_thread`, the link that opens a Runner thread already about this event. Read-only; nothing here is about a fan.","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"}],"responses":{"200":{"description":"Event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicEvent"}}}},"404":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/public/events/{eventId}/handoff":{"get":{"operationId":"getHandoff","summary":"Two-way handoff: open a Runner thread, and what Runner links back to","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"}],"responses":{"200":{"description":"Handoff"},"404":{"$ref":"#/components/responses/Error"}}}},"/v1/public/events/{eventId}/text-link":{"get":{"operationId":"getTextLink","summary":"Public text-Runner link (used by runner.js)","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"}],"responses":{"200":{"description":"Link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextLink"}}}},"404":{"$ref":"#/components/responses/Error"}}}},"/v1/public/events/{eventId}/qr.png":{"get":{"operationId":"getQr","summary":"QR code PNG that opens Messages with the event named","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"name":"size","in":"query","schema":{"type":"integer","minimum":256,"maximum":2048}},{"name":"target","in":"query","schema":{"type":"string","enum":["sms","web"]}}],"responses":{"200":{"description":"PNG","content":{"image/png":{}}},"404":{"$ref":"#/components/responses/Error"}}}},"/v1/festival/events/{eventId}/app":{"get":{"summary":"Your app's tie-in and which moment domains it owns","security":[{"apiKey":[]}],"x-runner-scope":"app:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"}],"responses":{"200":{"description":"Tie-in"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"put":{"summary":"Declare your app: deep links, and the moments it owns","description":"`organizer_owns` is enforced — Runner sends no unprompted message in those domains. `safety` cannot be owned and comes back in `ignored_domains`.","security":[{"apiKey":[]}],"x-runner-scope":"app:write","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"example":"evt_coachella_2026"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Saved"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}}},"webhooks":{"runnerEvent":{"post":{"summary":"Aggregate event from Runner","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"responses":{"2XX":{"description":"Acknowledge; anything else is retried with backoff (6 attempts)."}}}}}}