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.

Ordering what's on now. The feed is ordered by start time, and stays that way so paging works. But if you split out the inProgress ones to show as “on now”, sort those by endsAt ascending rather than by start. A week-long fair started days ago, so by start order it outranks a DJ set playing right this minute — and a few multi-day events will hold the top of your list all week. Ending soonest puts what someone is about to miss first. It is what events.xtech.dev itself does.
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.

Filtering by type and style

Both rails take type and style, using the same slugs the pages do:

GET /directory/live?type=music
GET /directory/upcoming?type=music&style=80s
GET /directory/types                    // the list, so you need not hardcode it

/directory/types returns every browsable type with its colour, the label that type uses for its style axis (“Genre” under music, “Subject” under a class), and its styles. It is derived from the live taxonomy, so a type added tomorrow appears without anyone redeploying — which is why type= takes a slug rather than a numeric id.

An unknown slug is a 400, not an empty list. ?type=musicc quietly returning nothing looks exactly like a quiet week, and that typo would ship. You get {"error": "Unknown type \"musicc\"…"} instead. A style without a type is also a 400 — styles belong to a type, and two types can have a style of the same name.

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
https://events.xtech.dev/music.ics             // or just one type
https://events.xtech.dev/v/your-venue.ics      // or just one venue

A venue's own feed is also what its page offers, and what a browser picks up if it offers to subscribe while you are looking at that venue.

Recurring nights are expanded to real dates for the whole range you ask for, so ?days=90 genuinely contains ninety days.

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.

If you're a DJ, host or live artist

The card above belongs to a venue. You get your own, and it follows you across every venue you work at — so one snippet on your website, blog or profile stays right without you touching it. Turn it on under Settings → Your live card, then paste:

<iframe src="https://events.xtech.dev/p/YOUR_CARD_TOKEN"
        width="320" height="220" frameborder="0"
        title="Where I am playing"></iframe>

There's a badge too, for forum signatures and Marketplace listings:

<img src="https://events.xtech.dev/p/YOUR_CARD_TOKEN/badge.svg" alt="Where I am playing">

It shows your next few bookings with the venue and time, a red dot and the venue name while you're actually on, and your profile picture. ?limit= and ?theme= work the same as the venue card.

Only venues that list publicly appear. A booking shows up on your card once that venue has switched on List us publicly under Manage Venue → Public listing. Until then the date stays private — publishing it would put that venue's schedule on the open web through you, which isn't yours to decide. Settings names the venues this is currently hiding, so you know who to ask; the dates appear by themselves once a venue opts in.

You also get your own calendar feed — add it to Google Calendar, Apple Calendar or Outlook as a subscribed calendar and your own dates keep themselves up to date. Share it and anyone following you can subscribe to the same thing:

https://events.xtech.dev/p/YOUR_CARD_TOKEN/calendar.ics

It's the same token and the same lifecycle: replacing your link changes the calendar with it, and turning the card off turns the calendar off too.

Covers are handled properly: a night you hand over drops off your card, and one you pick up appears. If you've turned off Show my name in public listings, that still holds everywhere else — the directory and venue cards keep showing you as “line-up TBC”. Your own card names you, because you made it.

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.

Share links

Every venue and every night has its own address, so you can paste one anywhere and it renders as a card with the poster, the title and the details — in Discord, on a forum, in a blog post:

https://events.xtech.dev/v/your-venue                     // your venue
https://events.xtech.dev/e/8000-2026-08-14/blues-night    // one night
https://events.xtech.dev/p/YOUR_CARD_TOKEN                // a performer

Event links keep working. The id and the date decide which night it is; the words after them are decorative, so renaming the event redirects the old link to the new one rather than breaking it. Every event in the JSON feeds carries its own shareUrl, so you never have to build one yourself.

Venue and event pages are indexable — they publish what a venue already chose to make public. A performer's card is not indexed: it is theirs to hand out rather than something a stranger should find by searching.

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.