Draft 0.x The spec is not stable yet: fields can still change, be renamed or be dropped. Follow the discussion

Build on OTE

A directory, an app, a bot, a newsletter? Everything the project publishes is plain JSON at stable URLs, with an explicit license. Integrate once — every new adopter feeds your tool for free.

The data, at stable URLs

These URLs are contracts: they survive any reorganisation of the repos. Start with the registry — it's the feed-discovery entry point.

URLWhat it is
opentechevents.org/data/adopters.json The adopter registry: every community publishing an OTE feed — name, website, feed URL, and its ID in linked community directories. It's what renders the adopters section, and your entry point to discover feeds. Updated by reviewed PR via the registration pipeline, with a daily health check on every feed.
opentechevents.org/schema/v0.3/feed.schema.json
…/event.schema.json
The canonical JSON Schemas (these are the $id URLs). Validate anything you ingest or produce with any standard JSON Schema validator.
data.opentechevents.org/feed.json The aggregated feed: events from every registered source, unified into one OTE feed with per-event provenance and license. Also exported as feed.ics.
npm: @opentechevents/* The toolchain as packages: schema (the JSON Schemas), validate (validation with human-readable errors, CLI included), export-ics / export-rss (converters), import-ics / import-jsonld (importers from .ics and schema.org JSON-LD), build-feed (assemble, validate and export a feed). Pure functions, no network — for CI, build time or your own tools.

Consuming feeds is three lines

No SDK, no API key, no rate-limit negotiation: fetch the registry, fetch the feeds. Every feed validates against the published schema, so your parser has exactly one format to care about.

discover.mjs
// 1. Who publishes OTE? The registry knows.
const { adopters } = await fetch("https://opentechevents.org/data/adopters.json")
  .then((res) => res.json());

// 2. Every entry carries its feed URL.
for (const adopter of adopters) {
  const feed = await fetch(adopter.feed).then((res) => res.json());
  console.log(adopter.name, feed.events.length, "events", feed.license);
}

One obligation: respect the license. Every feed (and optionally every event) declares one — CC-BY-4.0 means attributing the community, and each entry tells you whom.

Feeds in the wild announce themselves like RSS does — a <link rel="alternate" type="application/ote+json"> in the community's site — so your crawler can discover feeds that haven't registered yet.

Tools to integrate with — or to claim

The ecosystem catalogue, sliced by what each piece does with the data. Most of it is proposed and up for grabs: if your integration needs a converter or an SDK that doesn't exist, claiming it in an issue is how it gets prioritised.