Runner for agents and apps

Runner is a live-event concierge that runs in iMessage: set times, gates, leave-by, parking, merch and the organizer's official offers for the event a person is going to. Two APIs plug into it. The Connector API is for a person's own agent and needs no key. The Festival API is for organizers and takes a key.

Base URL
https://runner-cgxr.onrender.com
Auth
None for the Connector API. Bearer key for the Festival API.
Version
Path-versioned (/v1); every response carries Runner-Api-Version.

Connector API No key · read-only

This is how an agent finds Runner. Search the events Runner is running with the words the person used, read what Runner knows about one, and when the person wants Runner for the night, open the thread link. The thread is where the live part happens: leave-by texts, gate changes, parking, merch, official upgrades. Nothing in this API returns anything about a fan.

EndpointWhat it returns
GET /v1/public/events?q=Upcoming events Runner is running whose name, venue or city matches q. Optional city, limit (1–25), include_past=true.
GET /v1/public/events/{eventId}Dates and hours, venue, stages, set times, gates and drop-off, amenities, policies, the day's announcement, official offers, ticket status, and runner_thread.
GET /v1/public/events/{eventId}/handoffHow to open a Runner thread already about this event, and what Runner links back to if the organizer has their own app.
GET /v1/public/events/{eventId}/text-linkThe text-Runner link on its own: number, prefilled first text, sms: URL, short link, deep links.
GET /v1/public/events/{eventId}/qr.pngA QR that opens Messages with the event named. size 256–2048.

1. Find the event

curl "https://runner-cgxr.onrender.com/v1/public/events?q=austin"
{
  "data": [
    {
      "id": "evt_acl_2026",
      "name": "Austin City Limits Music Festival 2026",
      "kind": null,
      "dates": ["2026-10-02", "2026-10-03", "2026-10-04", "2026-10-09", "2026-10-10", "2026-10-11"],
      "timezone": "America/Chicago",
      "venue": { "name": "Zilker Park", "city": "Austin" }
    },
    {
      "id": "evt_usgp_2026",
      "name": "Formula 1 United States Grand Prix 2026",
      "kind": null,
      "dates": ["2026-10-23", "2026-10-24", "2026-10-25"],
      "timezone": "America/Chicago",
      "venue": { "name": "Circuit of The Americas", "city": "Austin" }
    }
  ]
}

Upcoming events only, by default. An event that has passed is still readable by id; pass include_past=true to find it by name.

2. Read what Runner knows

curl "https://runner-cgxr.onrender.com/v1/public/events/evt_acl_2026"
{
  "event": {
    "id": "evt_acl_2026", "name": "Austin City Limits Music Festival 2026", "kind": null,
    "dates": ["2026-10-02", "2026-10-03", "2026-10-04", "2026-10-09", "2026-10-10", "2026-10-11"],
    "timezone": "America/Chicago", "gates_open": "12:00", "closes": "22:00"
  },
  "venue": { "name": "Zilker Park", "address": "2100 Barton Springs Rd, Austin, TX 78704", "city": "Austin", "lat": 30.2672, "lng": -97.7669 },
  "stages": [ { "name": "T-Mobile Stage", "lat": null, "lng": null }, { "name": "American Express Stage", ... }, ... 8 stages ],
  "schedule": [
    { "day": "2026-10-02", "artist": "Turnstile", "stage": "T-Mobile Stage", "start": "18:15", "end": "19:15", "headliner": true, "source": "promoter_supplied" },
    { "day": "2026-10-02", "artist": "Skrillex", "stage": "T-Mobile Stage", "start": "20:15", "end": null, "headliner": true, "source": "promoter_supplied" },
    ... 210 sets
  ],
  "policies": {
    "bag_policy": { "summary": "...", "rules": [ "Any bag 6\" x 9\" or smaller with no more than one pocket will be allowed past security (ACL Festival)", ... ], "citations": [ ... ] },
    "prohibited_items": [ ... ],
    "reentry_allowed": true,
    "cashless": false
  },
  "wayfinding": [
    { "key": "vip_entrance", "name": "vip_entrance", "type": "vip_entrance", "note": "New VIP-only entrance to the right of the Barton Springs East gates ...", "lat": 30.265443, "lng": -97.764592 },
    { "key": "dropoff", "name": "dropoff", "type": "dropoff", "note": "No parking at Zilker Park or the surrounding neighborhoods. Lyft is the rideshare partner ...", "lat": null, "lng": null },
    ...
  ],
  "amenities": [ { "key": "medical_by_t_mobile_stage", "name": "Medical by T-Mobile Stage", "type": "medical", "note": "...", "lat": 30.268146, "lng": -97.769571 }, ... 34 points ],
  "announcement": null,
  "offers": [
    { "id": "ae43c07a-…", "kind": "merch", "title": "ACL Fest Flag Hat", "detail": null, "price": "$40.00", "url": "https://store.aclfestival.com/products/acl-fest-flag-hat", "sponsor": null, "audience": "all", "image_url": "https://cdn.shopify.com/…", "starts_at": null, "ends_at": null },
    ...
  ],
  "ticket_status": [
    { "day": "Weekend 1", "tier": "Platinum 3-Day", "label": "Platinum 3-Day Weekend 1", "status": "sold_out", "on_sale_url": "https://www.aclfestival.com/tickets", "note": "Weekend One on waitlist (aclfestival.com/tickets, 2026-09-15)", "updated_at": "2026-09-15T22:38:33.409Z" },
    { "day": "Weekend 2", "tier": "Platinum 3-Day", "label": "Platinum 3-Day Weekend 2", "status": "on_sale", "on_sale_url": "https://www.aclfestival.com/tickets", "note": "Weekend Two available (aclfestival.com/tickets, 2026-09-15)", "updated_at": "2026-09-15T22:38:33.404Z" },
    ... 11 rows
  ],
  "runner_thread": {
    "code": "3DC5J4",
    "number": "+16463196190",
    "prefilled": "Runner: I'm going to Austin City Limits Music Festival 2026 (3DC5J4)",
    "sms": "sms:+16463196190&body=Runner%3A%20I'm%20going%20to%20Austin%20City%20Limits%20Music%20Festival%202026%20(3DC5J4)",
    "short": "https://heyrunner.app/e/3DC5J4",
    "deep_links": { "ios": "sms:+16463196190&body=…", "android": "sms:+16463196190?body=…", "android_intent": "intent://send/+16463196190#Intent;scheme=smsto;S.sms_body=…;end" },
    "qr_png": "https://runner-cgxr.onrender.com/v1/public/events/evt_acl_2026/qr.png"
  },
  "as_of": "2026-09-19T21:41:47.014Z"
}

Every field is read from rows an organizer, a partner or Runner's own research put there. Arrays are empty when nothing is on file; the response never fills a gap with a guess. schedule[].source says where each set time came from.

3. Hand the person to Runner

When they want Runner for the night, open runner_thread.sms on a phone or show runner_thread.short anywhere else. Either lands them in a thread already about this event; they never type a code. From there Runner texts them the leave-by, the gate, the set they said they cared about, and takes bookings in the thread.

How an agent should treat it

Access requirements

Errors

{ "error": { "code": "not_found", "message": "event not found" }, "request_id": "5b0c…" }

Codes: not_found (404), rate_limited (429), not_configured (503), internal (500).

Festival API Organizers · API key

The other direction: a festival's own app, site and systems push into Runner and read aggregate insights back. Lineup and set times, stages, gates and drop-off, policies, announcements, broadcasts, official offers and ticket status go in; anonymized counts and topics come out. Never a fan's phone, name, email or words.

Privacy

Neither API returns anything about a fan. The Connector API is event facts and a link; the Festival API's insights are counts and topics with small groups dropped. What Runner does with a fan's own messages is in the privacy policy; the terms cover the rest.

Contact

Building on Runner, or an organizer who wants an event on it: michael@moshpitprojects.com.