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();
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:
- List us publicly — your venue and its public events appear in the directory and in this API.
- Publish our images — separate, and it asks you to confirm you hold the rights to have your posters republished. You can be listed without it; your cards just use a plain coloured panel instead.
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.
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. |
generatedAt | When we built this response. |
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
| Parameter | Default | Notes |
|---|---|---|
hours | 168 (7 days) | Clamped 1–336. |
offset | 0 | For paging. Results are ordered by start time, so page 2 continues exactly where page 1 stopped. |
limit | 60 | Clamped 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.
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>.
| Option | Values | What it does |
|---|---|---|
rail | both (default), live,
next | Who's on, what's next, or both. |
limit | 1–10, default 3 | How many upcoming events to list. |
compact | 1 | A single line, for a narrow sidebar. |
theme | auto (default), light,
dark | auto 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>
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
- No key, no quota. There is a per-IP rate limit, set generously enough that normal use never meets it.
- Responses are cached for about 30 seconds (5 minutes for the calendar). Polling faster returns the same bytes — once a minute is plenty for a "live now" display.
- Cache what you fetch if you're serving it to many visitors, rather than calling us per page view.
- Please link back to events.xtech.dev if you republish listings. Not a legal condition — just what keeps this worth running.
What you won't find
- No avatar UUIDs, anywhere, in any response. Names are stage names wherever a performer has set one.
- No private events and no staff notices. This surface only ever sees what a venue marked public.
- No visitor names.
crowdis a number and nothing more. - Only XTech venues. Linden Lab publishes no grid-wide events feed, so no directory can honestly claim full coverage — ours included.
Building something with this? We'd like to hear about it — and if you need a field we don't return yet, ask.