Events API

Everything on events.xtech.dev is also available as JSON, as a calendar subscription, and as a card you can drop straight into your own website. No key, no signup, no rate-limit paperwork — just fetch it. Second Life has no events API of its own, so as far as we know this is the only one.

Start here

One request, no authentication:

curl https://events.xtech.dev/directory/live

Everything here is GET only, returns JSON, and sends Access-Control-Allow-Origin: * — so a plain fetch() from a browser on any origin works:

const r = await fetch('https://events.xtech.dev/directory/upcoming?hours=24');
const { events } = await r.json();
Times. Every field ending At is a Unix epoch in seconds, UTC. Fields ending SLT are wall-clock strings in Second Life Time (America/Los_Angeles), which is what a resident sees in their viewer. Use the epoch for arithmetic, and the SLT string when you want to show what the venue would have written on a poster.

Getting your venue listed

Nothing appears here until a venue owner turns it on. In Manage Venue → Public listing there are two separate switches:

Performers have their own switch, under Settings → Second Life profile. If someone turns it on, their name is withheld everywhere on this surface — their night still appears, listed as Line-up TBC. A person's choice overrides the venue's, always.

The widget and badge below are the exception: they work from your board link and need no public listing at all. Some venues want a live card on their own site without appearing in our directory, and that is a supported choice.

Who's playing now

GET https://events.xtech.dev/directory/live
Returns
acts[]People clocked in right now — name, job, since, endsAt, spanDays, image, colour, venue.
venues[]Every listed venue — live, crowd, onNow[], accent, image, logo, slurl, maturity.
generatedAtWhen we built this response.
Two nulls that mean something. endsAt: null means the person is working but we have no booking to read an end time from — show "on now" and no countdown; please don't guess a duration. crowd: null means that venue's in-world server has gone quiet, so we don't currently know. That is different from crowd: 0, which means it reported and nobody is there. A confidently wrong number is worse than an honest dash.

A name of null means the slot isn't confirmed or the performer has opted out. The two are deliberately indistinguishable — please render them identically, or the difference advertises the opt-out.

What's coming up

GET https://events.xtech.dev/directory/upcoming?hours=168&offset=0&limit=60
ParameterDefaultNotes
hours168 (7 days)Clamped 1–336.
offset0For paging. Results are ordered by start time, so page 2 continues exactly where page 1 stopped.
limit60Clamped 1–60.

Each event carries title, startsAt/endsAt, startSLT/endSLT, spanDays, inProgress, dj/dj2, hasPerformers, typeName, typeSlug, styleName, typeColour, styleColour, image, uncovered, recurring and venue. The response also carries total and truncated, so you can always tell whether you have everything.

Three things worth handling properly. inProgress: true means it has already started — show "on now", not a start time in the past. spanDays > 0 is a multi-day run: show a date range and never a minutes countdown, because the end time belongs to the final day. hasPerformers: false is a type with no line-up at all — a store sale has no DJ, so omit the performer line entirely rather than printing "TBC" on it.

Subscribe in a calendar app

https://events.xtech.dev/directory.ics          // every listed venue, 30 days
https://events.xtech.dev/directory.ics?days=90  // up to 90

Add it to Google Calendar, Apple Calendar or Outlook as a subscribed calendar and it keeps itself up to date. Event IDs are stable, so edits arrive as edits rather than piling up as duplicates, and times are published in UTC so your calendar shows them correctly in your own zone.

Individual venues also publish their own calendar from their board link — see Manage Venue → In-world boards.

Put a live card on your own site

Paste this anywhere you can put HTML. Your board token is on Manage Venue → In-world boards — use the public one.

<iframe src="https://events.xtech.dev/w/YOUR_PUBLIC_TOKEN"
        width="320" height="240" frameborder="0"
        title="What is on at our venue"></iframe>

An iframe rather than a script tag, on purpose: nothing of ours runs on your page, nothing collides with your CSS, and it works on Wix, Squarespace and hosted WordPress, all of which strip <script>.

OptionValuesWhat it does
railboth (default), live, nextWho's on, what's next, or both.
limit1–10, default 3How many upcoming events to list.
compact1A single line, for a narrow sidebar.
themeauto (default), light, darkauto follows your visitor's system setting. Set it explicitly if your site is always one or the other.

Your accent colour comes through automatically from Venue theme — the same colours as your in-world boards. The card sizes itself sensibly and scrolls internally, so the snippet above really is all you need. If you would rather it resize to fit exactly, it also broadcasts its height:

<script>
addEventListener('message', e => {
  if (e.data && e.data.xtechHeight)
    document.querySelector('iframe[src*="events.xtech.dev"]').height = e.data.xtechHeight;
});
</script>
Use the public token, never the staff one. Your board has two links, and the staff link shows staff notices and private events. It will simply return "not found" here — deliberately, so a wrong paste fails loudly instead of quietly publishing your team's notices to the web. If your widget shows nothing at all, that is almost certainly why. Regenerating the public token turns off the widget, the board and the calendar feed together.

A badge for forums and Marketplace

Forum signatures, blog sidebars and Marketplace listings usually allow images but ban iframes and JavaScript. A badge is an ordinary image:

<img src="https://events.xtech.dev/w/YOUR_PUBLIC_TOKEN/badge.svg"
     alt="What is on at our venue">

320×56, your accent colour, a red dot when you're live, and either whoever's playing or what's next. It refreshes about once a minute.

Browsable pages

If you would rather link than integrate, every event type has its own page:

https://events.xtech.dev/          // everything
https://events.xtech.dev/music     // DJ sets and live artists together
https://events.xtech.dev/quiz      // and one per type: sale, shopping, hunt, class...

The current list is always in sitemap.xml.

Limits and fair use

What you won't find

Building something with this? We'd like to hear about it — and if you need a field we don't return yet, ask.