Skip to content

Developers

The event, from your own code.

ASCENT 27 has an open API: the programme, the speakers, the exhibitors and live totals as JSON, for an event app, a partner's site, a screen in the lobby or your own AI assistant. Badge printers and session scanners use the print-on-demand endpoints further down.

Base address and the demo key

Base address

https://ascent27.zephyr.events/api/public/v1

Demo key

ascent27_public_demo

Send it in the X-API-Key header, or as Authorization: Bearer. It opens the public read endpoints on this page and nothing else: the print-on-demand endpoints answer it with 401.

Your first request

curl -H "X-API-Key: ascent27_public_demo" "https://ascent27.zephyr.events/api/public/v1/sessions?day=wednesday&q=payments"

Content and totals only: no names, email addresses or other personal records leave through these endpoints. The text is the event's published content; records added or changed since the last reset count in the totals and stay out of the text. The demo resets every day at 06:00 UTC and the ids stay the same.

Run a GET

The panel calls the API from this page with the demo key and shows the JSON as it comes back.

The same request with curl
curl -H "X-API-Key: ascent27_public_demo" "https://ascent27.zephyr.events/api/public/v1/event"

Choose an endpoint or type a path, then run it. The demo key goes with the request.

Endpoints

Every endpoint answers GET with JSON: { "ok": true, ... }, or { "ok": false, "error": "..." } with the status below. Prices are in US cents, session times are Lisbon time with the offset of the day, and lang picks English, Spanish, French or German for the text. In the examples, long lists are cut to their first items.

The three lists, /sessions, /speakers and /exhibitors, page the same way: limit (1 to 100, 25 when not given) and offset pick the page, q searches, sort and dir order it, and the answer gives total (every match), offset, limit and count (on this page). Sessions are by day and time unless sorted by title, speakers and exhibitors A to Z unless sorted by company or booth.

GET/event

The event: names, dates, venue, the three days and the two passes with their prices.

ParameterMeaning
langen (the default), es, fr or de: the language of the text.
Request
curl -H "X-API-Key: ascent27_public_demo" "https://ascent27.zephyr.events/api/public/v1/event"
Response
{
  "ok": true,
  "event": {
    "id": "ascent27",
    "name": "Halvora ASCENT 27",
    "shortName": "ASCENT 27",
    "organiser": "Halvora",
    "fictional": true,
    "notice": "Halvora and ASCENT 27 are fictional, and this site is a Zephyr demonstration.",
    "tagline": "Rise to what's next.",
    "summary": "Three days in Lisbon with Halvora's customers, partners and teams to see what is coming and shape it: keynotes, hands-on labs, two evening events, and a dinner above the city for the few who apply.",
    "startDate": "2027-05-18",
    "endDate": "2027-05-20",
    "start": "2027-05-18T13:00:00+01:00",
    "end": "2027-05-20T23:00:00+01:00",
    "timezone": "Europe/Lisbon",
    "venue": {
      "name": "Tejo Congress Hall",
      "city": "Lisbon",
      "country": "PT",
      "countryName": "Portugal"
    },
    "days": [
      {
        "date": "2027-05-18",
        "name": "Basecamp",
        "label": "Tuesday 18 May",
        "summary": "Arrivals, studio tours and the opening night on the river."
      },
      {
        "date": "2027-05-19",
        "name": "The Climb",
        "label": "Wednesday 19 May",
        "summary": "Main stage keynotes, forty breakouts across four tracks, and the partner expo."
      },
      {
        "date": "2027-05-20",
        "name": "The Summit",
        "label": "Thursday 20 May",
        "summary": "Hands-on labs, the closing keynote and The Summit Circle dinner."
      }
    ],
    "passes": [
      {
        "id": "full",
        "name": "Full Summit Pass",
        "description": "All three days, every session, opening night on the river and the closing party.",
        "priceCents": 145000,
        "currency": "USD",
        "points": 145000,
        "earlyRateUntil": "2027-03-15",
        "days": [
          "2027-05-18",
          "2027-05-19",
          "2027-05-20"
        ],
        "labs": true,
        "expo": true
      },
      {
        "id": "day",
        "name": "Day Pass",
        "description": "Wednesday 19 May: the main stage keynotes, forty breakouts and the partner expo.",
        "priceCents": 65000,
        "currency": "USD",
        "points": 65000,
        "earlyRateUntil": "2027-03-15",
        "days": [
          "2027-05-19"
        ],
        "labs": false,
        "expo": true
      }
    ],
    "url": "https://ascent27.zephyr.events/",
    "register": "https://ascent27.zephyr.events/register"
  }
}

GET/sessions

The programme by day and time (or by title), filtered by day, kind and text, a page at a time.

ParameterMeaning
dayA date (2027-05-19), a weekday (wednesday) or a day name (the climb).
kindkeynote, session, workshop, social, registration or exhibits.
qWords to find in the title, description, room and speakers, in English or in the language asked; every word must match.
sorttime (by day and time, the default) or title.
dirasc (the default) or desc.
limitHow many to return, 1 to 100, default 25.
offsetHow many matches to skip, default 0: 25 for the second page of 25.
langen (the default), es, fr or de: the language of the text.
Request
curl -H "X-API-Key: ascent27_public_demo" "https://ascent27.zephyr.events/api/public/v1/sessions?day=wednesday&q=payments"
Response
{
  "ok": true,
  "total": 3,
  "offset": 0,
  "limit": 25,
  "count": 3,
  "sessions": [
    {
      "id": "68a404ff-f2b6-4a89-8754-8e65b4909477",
      "day": "2027-05-19",
      "dayName": "The Climb",
      "dayLabel": "Wednesday 19 May",
      "start": "2027-05-19T09:00:00+01:00",
      "end": "2027-05-19T10:00:00+01:00",
      "kind": "keynote",
      "title": "Opening keynote: the next decade of rewards",
      "description": "What Halvora ships over the next twelve months, and why points and payments are becoming one thing.",
      "room": "Main stage",
      "speakers": [
        {
          "slug": "marco-dizon",
          "name": "Marco Dizon",
          "role": "Chief Product Officer",
          "company": "Halvora",
          "url": "https://ascent27.zephyr.events/speakers/marco-dizon"
        }
      ],
      "topics": [
        {
          "id": "payments",
          "name": "Payments"
        },
        {
          "id": "loyalty",
          "name": "Loyalty and rewards"
        },
        {
          "id": "roadmap",
          "name": "Halvora's roadmap"
        }
      ],
      "url": "https://ascent27.zephyr.events/programme/68a404ff-f2b6-4a89-8754-8e65b4909477"
    }
  ]
}

GET/sessions/{id}

One session with its speakers.

ParameterMeaning
id(path)The session id from /sessions.
langen (the default), es, fr or de: the language of the text.
Request
curl -H "X-API-Key: ascent27_public_demo" "https://ascent27.zephyr.events/api/public/v1/sessions/68a404ff-f2b6-4a89-8754-8e65b4909477?lang=es"
Response
{
  "ok": true,
  "session": {
    "id": "68a404ff-f2b6-4a89-8754-8e65b4909477",
    "day": "2027-05-19",
    "dayName": "La Escalada",
    "dayLabel": "miércoles, 19 de mayo",
    "start": "2027-05-19T09:00:00+01:00",
    "end": "2027-05-19T10:00:00+01:00",
    "kind": "keynote",
    "title": "Conferencia inaugural: la próxima década de las recompensas",
    "description": "Lo que Halvora lanzará en los próximos doce meses y por qué los puntos y los pagos están convirtiéndose en una sola cosa.",
    "room": "Escenario principal",
    "speakers": [
      {
        "slug": "marco-dizon",
        "name": "Marco Dizon",
        "role": "Director de Producto",
        "company": "Halvora",
        "url": "https://ascent27.zephyr.events/speakers/marco-dizon"
      }
    ],
    "topics": [
      {
        "id": "payments",
        "name": "Pagos"
      },
      {
        "id": "loyalty",
        "name": "Fidelización y recompensas"
      },
      {
        "id": "roadmap",
        "name": "La hoja de ruta de Halvora"
      }
    ],
    "url": "https://ascent27.zephyr.events/programme/68a404ff-f2b6-4a89-8754-8e65b4909477"
  }
}

GET/speakers

The speakers A to Z (or by company) with their role, company, biography and sessions, a page at a time.

ParameterMeaning
qWords to find in the name, role, company and biography, in English or in the language asked.
sortname (A to Z, the default) or company.
dirasc (the default) or desc.
limitHow many to return, 1 to 100, default 25.
offsetHow many matches to skip, default 0: 25 for the second page of 25.
langen (the default), es, fr or de: the language of the text.
Request
curl -H "X-API-Key: ascent27_public_demo" "https://ascent27.zephyr.events/api/public/v1/speakers?q=payments"
Response
{
  "ok": true,
  "total": 3,
  "offset": 0,
  "limit": 25,
  "count": 3,
  "speakers": [
    {
      "slug": "arun-kesavan",
      "name": "Arun Kesavan",
      "role": "Founder",
      "company": "Ostberg Freight",
      "bio": "Arun started Ostberg Freight with two vans and now moves goods for retailers in eleven countries. He explains how a rewards scheme for business customers cut their late payments by half.",
      "photo": "https://images.unsplash.com/photo-1629425733761-caae3b5f2e50?auto=format&fit=crop&crop=faces&h=1000&w=800&q=70",
      "sessions": [
        {
          "id": "f3ddb784-d449-482c-b313-4480557cc67a",
          "title": "Rewards for business customers",
          "start": "2027-05-19T15:00:00+01:00",
          "url": "https://ascent27.zephyr.events/programme/f3ddb784-d449-482c-b313-4480557cc67a"
        }
      ],
      "url": "https://ascent27.zephyr.events/speakers/arun-kesavan"
    }
  ]
}

GET/speakers/{slug}

One speaker.

ParameterMeaning
slug(path)The speaker slug from /speakers, such as marco-dizon.
langen (the default), es, fr or de: the language of the text.
Request
curl -H "X-API-Key: ascent27_public_demo" "https://ascent27.zephyr.events/api/public/v1/speakers/marco-dizon"
Response
{
  "ok": true,
  "speaker": {
    "slug": "marco-dizon",
    "name": "Marco Dizon",
    "role": "Chief Product Officer",
    "company": "Halvora",
    "bio": "Marco runs product across rewards, payments and travel, and spent a decade building checkout flows before that. His keynote sets out what Halvora ships over the next twelve months.",
    "photo": "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?auto=format&fit=crop&crop=faces&h=1000&w=800&q=70",
    "sessions": [
      {
        "id": "68a404ff-f2b6-4a89-8754-8e65b4909477",
        "title": "Opening keynote: the next decade of rewards",
        "start": "2027-05-19T09:00:00+01:00",
        "url": "https://ascent27.zephyr.events/programme/68a404ff-f2b6-4a89-8754-8e65b4909477"
      },
      {
        "id": "213e0ab1-fbdb-4b51-af5f-f9f62101aea4",
        "title": "Ask the product team",
        "start": "2027-05-20T12:30:00+01:00",
        "url": "https://ascent27.zephyr.events/programme/213e0ab1-fbdb-4b51-af5f-f9f62101aea4"
      }
    ],
    "url": "https://ascent27.zephyr.events/speakers/marco-dizon"
  }
}

GET/exhibitors

The exhibitors A to Z (or by booth), filtered by hall, product category and text, a page at a time.

ParameterMeaning
hallA or B.
categoryloyalty, payments, fraud, data, travel, cx, marketing or mobile.
qWords to find in the name, description, categories and booth.
sortname (A to Z, the default) or booth.
dirasc (the default) or desc.
limitHow many to return, 1 to 100, default 25.
offsetHow many matches to skip, default 0: 25 for the second page of 25.
langen (the default), es, fr or de: the language of the text.
Request
curl -H "X-API-Key: ascent27_public_demo" "https://ascent27.zephyr.events/api/public/v1/exhibitors?hall=A&category=payments&sort=booth&limit=2"
Response
{
  "ok": true,
  "total": 24,
  "offset": 0,
  "limit": 2,
  "count": 2,
  "exhibitors": [
    {
      "slug": "rosanix-cloud",
      "name": "Rosanix Cloud",
      "description": "Rosanix Cloud designs card issuing software for telecoms. Teams in 25 countries use it to settle partner points overnight.",
      "website": "https://rosanix-cloud.example",
      "categories": [
        {
          "id": "payments",
          "name": "Payments"
        },
        {
          "id": "data",
          "name": "Data and analytics"
        },
        {
          "id": "mobile",
          "name": "Mobile apps"
        }
      ],
      "hall": "A",
      "booth": "A103",
      "url": "https://ascent27.zephyr.events/exhibit/rosanix-cloud"
    },
    {
      "slug": "marodra",
      "name": "Marodra",
      "description": "Marodra makes fraud screening tools for retailers. Founded in 2011, it ships a new release every two weeks.",
      "website": "https://marodra.example",
      "categories": [
        {
          "id": "payments",
          "name": "Payments"
        },
        {
          "id": "marketing",
          "name": "Partner marketing"
        },
        {
          "id": "mobile",
          "name": "Mobile apps"
        }
      ],
      "hall": "A",
      "booth": "A107",
      "url": "https://ascent27.zephyr.events/exhibit/marodra"
    }
  ]
}

GET/exhibitors/{slug}

One exhibitor with its booth.

ParameterMeaning
slug(path)The exhibitor slug from /exhibitors, such as nordvale.
langen (the default), es, fr or de: the language of the text.
Request
curl -H "X-API-Key: ascent27_public_demo" "https://ascent27.zephyr.events/api/public/v1/exhibitors/nordvale"
Response
{
  "ok": true,
  "exhibitor": {
    "slug": "nordvale",
    "name": "Nordvale Air",
    "description": "Nordvale Air runs loyalty analytics for marketplaces. Teams in 23 countries use it to settle partner points overnight.",
    "website": "https://nordvale.example",
    "categories": [
      {
        "id": "loyalty",
        "name": "Loyalty and rewards"
      },
      {
        "id": "travel",
        "name": "Travel technology"
      },
      {
        "id": "mobile",
        "name": "Mobile apps"
      }
    ],
    "hall": "A",
    "booth": "A112",
    "url": "https://ascent27.zephyr.events/exhibit/nordvale"
  }
}

GET/totals

Live counts: confirmed registrations by pass, by day and by country, exhibitors, sponsors, booths and check-ins.

ParameterMeaning
daysHow many days of registrations by day, 1 to 90, default 14; the last day is today so far.
langen (the default), es, fr or de: the language of the text.
Request
curl -H "X-API-Key: ascent27_public_demo" "https://ascent27.zephyr.events/api/public/v1/totals?days=3"
Response
{
  "ok": true,
  "totals": {
    "asOf": "2026-11-12T22:15:44Z",
    "registrations": {
      "confirmed": 5690,
      "countries": 38,
      "byPass": {
        "full": 4162,
        "day": 1439,
        "expo": 89
      },
      "byDay": [
        {
          "date": "2026-11-10",
          "total": 79,
          "full": 62,
          "day": 17,
          "expo": 0
        },
        {
          "date": "2026-11-11",
          "total": 97,
          "full": 61,
          "day": 25,
          "expo": 11
        },
        {
          "date": "2026-11-12",
          "total": 8,
          "full": 7,
          "day": 0,
          "expo": 1
        }
      ],
      "byCountry": [
        {
          "country": "PT",
          "name": "Portugal",
          "count": 799
        },
        {
          "country": "GB",
          "name": "United Kingdom",
          "count": 624
        },
        {
          "country": "ES",
          "name": "Spain",
          "count": 554
        }
      ]
    },
    "exhibitors": 300,
    "sponsors": 40,
    "booths": {
      "total": 360,
      "sold": 300,
      "reserved": 22,
      "available": 38
    },
    "checkIns": {
      "people": 0,
      "today": 0,
      "sessionScans": 0
    }
  }
}

Limits and errors

Limits

Demo key60 requests a minute from one address
A key made in the admin600 requests a minute per key, shared with print on demand
MCP endpoint120 requests a minute from one address
Search text100 characters
Sessions, speakers or exhibitors a page100, 25 when not given

Every response carries Access-Control-Allow-Origin: * and Cache-Control: no-store, so a page on any site can call the API; OPTIONS preflights answer 204.

Errors

StatusWhen
400A parameter is wrong; the message names it.
{"ok":false,"error":"hall must be A or B"}
401No key, a wrong key, or the demo key on a print-on-demand endpoint.
{"ok":false,"error":"Invalid API key"}
404An unknown session id, speaker or exhibitor.
{"ok":false,"error":"Not found"}
429Over the limit; the Retry-After header gives the seconds to wait.
{"ok":false,"error":"Too many attempts. Try again in 12 seconds.","retryAfter":12}

Print on demand

For badge printers and session scanners: people, printing and session check-ins. These endpoints read and write personal records, so they need a key made in the admin under Settings, API keys, sent in X-API-Key or as a bearer token; the demo key gets 401. Base address https://ascent27.zephyr.events/api/pod/v1. Send Content-Type: application/json with every PUT and POST body.

  • The person id is the registration id, a lowercase UUID; wherever a path has {id} the confirmation number works too. Every record carries "event": "ascent27", and every GET takes an optional ?event=ascent27.
  • Record dates are UTC, ISO 8601 to the second. since takes ISO 8601 with Z, with an offset or with no time zone (read as UTC), inclusive to the second.
  • A badge prints when the status and the audience are in the printing lists set in the admin and nothing is owed; noPrintReason names the first rule that fails: status, balance_due or type.

GET/registrants/{id}

One person, by registration id or by confirmation number (ASC27-7KQ2MC, any case).

Request
curl -X GET -H "X-API-Key: ascent27_..." "https://ascent27.zephyr.events/api/pod/v1/registrants/3f2a9c1e-7b4d-4e8a-9c21-5d6e7f8a9b0c"
Response
{
  "ok": true,
  "record": {
    "id": "3f2a9c1e-7b4d-4e8a-9c21-5d6e7f8a9b0c",
    "event": "ascent27",
    "confirmationNumber": "ASC27-7KQ2MC",
    "status": "confirmed",
    "print": true,
    "noPrintReason": null,
    "printed": false,
    "printedAt": null,
    "attendance": "not_printed",
    "firstName": "Ana",
    "lastName": "Ribeiro",
    "email": "ana.ribeiro@lumenbank.example",
    "jobTitle": "Head of Operations",
    "company": "Lumen Bank",
    "city": "Lisbon",
    "country": "PT",
    "phone": "+351 21 000 0000",
    "registrationType": "Public",
    "registrationTypeId": "public",
    "pass": "Full Summit Pass",
    "passId": "full",
    "balanceDueCents": 0,
    "orderId": "3f2a9c1e-7b4d-4e8a-9c21-5d6e7f8a9b0c",
    "isLead": true,
    "addedAt": "2027-02-20T10:00:00Z",
    "createdAt": "2027-02-20T09:55:00Z",
    "modifiedAt": "2027-02-20T10:00:00Z",
    "cancelledAt": null,
    "sessions": []
  }
}

GET/registrants

Records added (by=added, the confirmation time) or modified (by=modified, the default) at or after a date-time, oldest first. Without since, every record.

Request
curl -X GET -H "X-API-Key: ascent27_..." "https://ascent27.zephyr.events/api/pod/v1/registrants?since=2027-05-18T08:00:00Z&by=modified"
Response
{
  "ok": true,
  "since": "2027-05-18T08:00:00Z",
  "by": "modified",
  "count": 1,
  "records": [
    {
      "id": "3f2a9c1e-7b4d-4e8a-9c21-5d6e7f8a9b0c",
      "event": "ascent27",
      "confirmationNumber": "ASC27-7KQ2MC",
      "status": "confirmed",
      "print": true,
      "noPrintReason": null,
      "printed": false,
      "printedAt": null,
      "attendance": "not_printed",
      "firstName": "Ana",
      "lastName": "Ribeiro",
      "email": "ana.ribeiro@lumenbank.example",
      "jobTitle": "Head of Operations",
      "company": "Lumen Bank",
      "city": "Lisbon",
      "country": "PT",
      "phone": "+351 21 000 0000",
      "registrationType": "Public",
      "registrationTypeId": "public",
      "pass": "Full Summit Pass",
      "passId": "full",
      "balanceDueCents": 0,
      "orderId": "3f2a9c1e-7b4d-4e8a-9c21-5d6e7f8a9b0c",
      "isLead": true,
      "addedAt": "2027-02-20T10:00:00Z",
      "createdAt": "2027-02-20T09:55:00Z",
      "modifiedAt": "2027-02-20T10:00:00Z",
      "cancelledAt": null,
      "sessions": []
    }
  ]
}

PUT/registrants/{id}/printed

Mark a badge printed or not printed; POST works the same. Marking printed again keeps the first printedAt, and it is not a modification.

Request
curl -X PUT -H "X-API-Key: ascent27_..." -H "Content-Type: application/json" -d '{ "printed": true }' "https://ascent27.zephyr.events/api/pod/v1/registrants/3f2a9c1e-7b4d-4e8a-9c21-5d6e7f8a9b0c/printed"
Response
{
  "ok": true,
  "id": "3f2a9c1e-7b4d-4e8a-9c21-5d6e7f8a9b0c",
  "printed": true,
  "printedAt": "2027-05-18T07:58:31Z"
}

GET/sessions

Every session in order of day and start time, each with checkIn: whether it takes check-in.

Request
curl -X GET -H "X-API-Key: ascent27_..." "https://ascent27.zephyr.events/api/pod/v1/sessions"
Response
{
  "ok": true,
  "sessions": [
    {
      "sessionId": "s-keynote",
      "title": "Opening keynote: the next decade of rewards",
      "kind": "keynote",
      "day": "2027-05-19",
      "start": "2027-05-19T09:00:00+01:00",
      "end": "2027-05-19T10:00:00+01:00",
      "location": "Main stage",
      "checkIn": true
    }
  ]
}

POST/registrants/{id}/checkins

Check a person in to a session: 201 for a new check-in, 200 with the first checkedInAt when scanned again, 409 when the session takes no check-in or walk-ins are refused.

Request
curl -X POST -H "X-API-Key: ascent27_..." -H "Content-Type: application/json" -d '{ "sessionId": "s-keynote" }' "https://ascent27.zephyr.events/api/pod/v1/registrants/3f2a9c1e-7b4d-4e8a-9c21-5d6e7f8a9b0c/checkins"
Response
{
  "ok": true,
  "id": "3f2a9c1e-7b4d-4e8a-9c21-5d6e7f8a9b0c",
  "sessionId": "s-keynote",
  "booked": false,
  "checkedInAt": "2027-05-18T08:41:07Z",
  "status": "confirmed"
}

DELETE/registrants/{id}/checkins/{sessionId}

Undo a check-in; 404 when there is none.

Request
curl -X DELETE -H "X-API-Key: ascent27_..." "https://ascent27.zephyr.events/api/pod/v1/registrants/3f2a9c1e-7b4d-4e8a-9c21-5d6e7f8a9b0c/checkins/s-keynote"
Response
{
  "ok": true
}

GET/checkins

Who checked in to a session, in check-in order. Without session: 400.

Request
curl -X GET -H "X-API-Key: ascent27_..." "https://ascent27.zephyr.events/api/pod/v1/checkins?session=s-keynote"
Response
{
  "ok": true,
  "session": {
    "sessionId": "s-keynote",
    "title": "Opening keynote: the next decade of rewards",
    "kind": "keynote",
    "day": "2027-05-19",
    "start": "2027-05-19T09:00:00+01:00",
    "end": "2027-05-19T10:00:00+01:00",
    "location": "Main stage"
  },
  "checkins": [
    {
      "id": "3f2a9c1e-7b4d-4e8a-9c21-5d6e7f8a9b0c",
      "confirmationNumber": "ASC27-7KQ2MC",
      "firstName": "Ana",
      "lastName": "Ribeiro",
      "email": "ana.ribeiro@lumenbank.example",
      "company": "Lumen Bank",
      "registrationType": "Public",
      "status": "confirmed",
      "booked": false,
      "checkedInAt": "2027-05-18T08:41:07Z"
    }
  ]
}

OpenAPI

Both sets of endpoints in one OpenAPI 3.1 file, for Postman, Insomnia or a generated client. It needs no key.

Download the OpenAPI file

Connect your own AI

The same reads as an MCP server at https://ascent27.zephyr.events/mcp, for Claude, ChatGPT and other assistants that speak the Model Context Protocol.

The MCP page