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.
https://runner-cgxr.onrender.com/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.
| Endpoint | What 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}/handoff | How 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-link | The text-Runner link on its own: number, prefilled first text, sms: URL, short link, deep links. |
GET /v1/public/events/{eventId}/qr.png | A 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
- Answer from the event, not about it. If the person asked when doors open, read
event.gates_openand say so. Don't summarise the whole object. - Cache lightly. Responses carry
Cache-Control;announcement,ticket_statusandofferschange on the day, so re-read them within a minute of use. - Only official offers are listed. An offer here was put there by the organizer. Runner never lists a third-party resale or a scraped deal as an offer.
- Nothing to log in to. There is no account, token or session on this API. The person's relationship with Runner lives in the iMessage thread.
Access requirements
- No account, plan or key. Read-only; every documented operation is a
GET. - Rate limit: 120 requests a minute and 3,000 an hour per caller address. A
429carriesRetry-After. - Only events an organizer has claimed on Runner are listed. A fan's own imported tickets never appear.
- The Runner thread is a US iMessage/SMS line; the API itself has no regional restriction. Carrier rates apply to the person's texts.
- CORS is open (
Access-Control-Allow-Origin: *), so a page can call it directly.
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.
- Contract: /v1/openapi.json (OpenAPI 3.1). It includes the Connector API's public paths, described once.
- Keys: Control panel → Settings → Integrations → API keys. Owners only; scoped; shown once; hashed at rest.
- Auth:
Authorization: Bearer rk_live_…. 120 requests a minute, 3,000 an hour per key. Writes acceptIdempotency-Key. - Webhooks: signed with
Runner-Signature(HMAC-SHA256), retried with backoff. - Drop-in button:
<script src="https://runner-cgxr.onrender.com/sdk/runner.js" data-event="evt_…" async></script>
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.