Programme Data

Everything you need to build against the CHI programme is a single JSON file. No API key, no sign-up, no approval step. You can start right now.

https://chidigitalexperience.org/data/chi2027/latest.json

That file contains the complete conference programme — sessions, events, contributions ("contents"), people, rooms, and tracks — and it updates as the programme changes, including during the conference itself.

Available now

FeedWhat it is
/data/chi2026/latest.jsonThe full CHI 2026 programme. Real data, frozen. Best starting point.
/data/chi2025/latest.jsonThe full CHI 2025 programme. Real data, frozen.
/data/chi2024/latest.jsonThe full CHI 2024 programme. Real data, frozen.
/data/chi2023/latest.jsonThe full CHI 2023 programme. Real data, frozen.
/data/sandbox/latest.jsonA synthetic programme at CHI 2027 scale. Deliberately awkward — see Test against the sandbox.

Available from April 2027

FeedWhat it is
/data/chi2027/latest.jsonThe real CHI 2027 programme, updating through to the end of the conference.

The 2027 feed is published to everyone at the same URL, with no credentials. There is nothing to apply for and nothing to wait on — the structure is identical to the feeds above.

Checking for updates

Read this bit even if you skip the rest. It is the one thing that is easy to get wrong, and getting it wrong means your app shows attendees a room that changed twenty minutes ago.

Each feed publishes a tiny version.json alongside the programme:

{
  "edition": "chi2027",
  "revision": 17,
  "generated_at": "2027-05-12T09:14:22-04:00",
  "latest_url": "https://chidigitalexperience.org/data/chi2027/latest.json",
  "revision_url": "https://chidigitalexperience.org/data/chi2027/revisions/017.json"
}

Poll version.json with a unique query string, compare the revision to what you already hold, and only fetch the programme when it has moved:

const BASE = 'https://chidigitalexperience.org/data/chi2027';

async function fetchProgrammeIfChanged(knownRevision) {
  // The ?t= makes every request a distinct URL, so no cache can answer it.
  const res = await fetch(`${BASE}/version.json?t=${Date.now()}`, {
    cache: 'no-store'
  });
  const { revision, revision_url } = await res.json();

  if (revision === knownRevision) return null;      // nothing new

  const programme = await fetch(revision_url).then(r => r.json());
  return { revision, programme };
}

Poll once a minute during the conference and you will never be more than a minute behind.

Why the ?t=. Our hosting applies ten minutes of browser caching to every file and we cannot change that. A unique URL each time steps around it. The revision files it points you to never change once published, so you can cache those as long as you like — forever, ideally.

About latest.json. It always holds the current programme, and it is perfectly good for exploring the data, for scripts, and for apps that load once at startup. But because of that same ten-minute caching,latest.json can be up to ten minutes out of date in a browser. If your app needs to reflect live changes during the conference, use the pattern above instead. If it doesn't, latest.json is simpler and entirely fine.

Fair use: poll version.json no more than once every 30 seconds (once a minute is plenty), and fetch the immutable revision files rather than re-downloading latest.json in a loop.

What's in the file

The published feed is the conference system's native export (schemeVersion: 7): camelCase field names, epoch-millisecond dates, and top-level collectionssessions / events / contents /people / rooms / tracks / and more. There is currently no status,status_note, or last_modified field, and no soft-delete guarantee. The closest analogue to a content "revision" inside the file itself is publicationInfo.version, not a top-level revision field (that lives inversion.json, described above).

Times are epoch milliseconds. IDs are integers, stable within an edition.

For a full field-by-field breakdown of every collection — conference, sessions, events, contents,people, rooms, tracks, and more — see the Schema Reference. The machine-readable version is published at /data/schema/v1.json, for generating types or validating locally.

Test against the sandbox

/data/sandbox/latest.json is synthetic, sized like a real CHI, and seeded on purpose with things that break conference apps: very long author lists, non-Latin scripts, very long and very short abstracts, overlapping sessions, nulls in optional fields, and more.

There is no live-changing sandbox feed. Test your update-handling logic by hand: fetch sandbox, note the revision, wait for a change to be published, fetch again, and confirm your app picks it up.

What we don't provide

We provide programme data, and nothing about the person using your app. There is no login endpoint, no attendee directory. Personalisation is yours to build — keep it in memory for the session, or inlocalStorage on the attendee's own device.

The simplest way to pass the data protection hurdle is to not collect anything. See Judging.

Full text or PDFs of papers are not provided. Link out via each contribution's DOI / ACM Digital Library link instead.

Licence

The programme data is published under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0).

The full licence text and this project's specific attribution line are at /data/LICENCE. The licence also travels in each feed's own cc_licence field.

Questions

Anything unclear, anything that looks wrong in the data, anything missing: app@chi2027.acm.org.