API Reference
Streams API Documentation
Updated
The Streams API tells you what's happening on a station right now: whether it's on air, what's playing, how many people are listening, and where the audio stream is. Every custom player is built on it, including the ones in our HTML and Framer guides.
Base URL
All endpoints are relative to https://api.evenings.co/v1.
Authentication and limits
| Endpoint | Auth | Rate limit per IP |
|---|---|---|
| Get stream | None | 100 requests per minute |
| Get stream status | None | 50 requests per minute |
| Get listener count | Your API key, for your own station only | 100 requests per minute |
Every /v1 request counts toward the 100-per-minute limit, and Get stream status also has its own limit of 50. See Before you ship for how the limits work.
Endpoints
Get stream
Returns what's on air for a station, along with its stream URL. Most players only need this one.
- URL:
/streams/:slug/public - Method:
GET - Auth required: No
- URL parameters:
slug: the station's slug, the last part of its address (sample-radioforevenings.fm/sample-radio)
Example:
curl https://api.evenings.co/v1/streams/garage/publicResponse:
{
"id": "k9Xp2mQr",
"name": "Tuesday Sessions",
"host": "DJ Name",
"url": "https://example.com",
"description": "Weekly vibes",
"streamUrl": "https://media.evenings.co/s/k9Xp2mQr",
"image": "https://cdn.evenings.co/img/abc.jpg",
"online": true,
"listeners": 12
}| Field | What it is |
|---|---|
id | The station's channel ID. It's the last part of streamUrl, and it's what Get stream status takes. |
name, host, description, image | Details of whatever is on air right now (see the next table). Any of them can be an empty string or null if they haven't been filled in. |
url | A link for listeners. During Always On it's the playing track's link; otherwise it's the link from your station's live broadcast details. |
streamUrl | The audio stream. Point an <audio> element at it. |
online | true if anything is playing: a live broadcast, a scheduled show or Always On. |
listeners | How many people are listening right now. |
Where name, host, description and image come from depends on what's on air. How Evenings works explains which source wins when more than one could play.
| What's on air | Where the details come from |
|---|---|
| A scheduled show, or a live broadcast during one | The show |
| Always On | The track that's playing |
| A live broadcast with no show scheduled | The broadcast details you set on your dashboard (here's how), with your station photo as image |
| Nothing | The same as above, with online set to false |
Caching: responses carry Cache-Control: public, max-age=10, and we also cache them on our side for up to 30 seconds. When a station goes live, goes offline or changes its details, we clear that cache right away, so those changes usually show within 10 seconds. listeners on its own can lag by up to about 30 seconds.
Get stream status
Returns only online and listeners. It's a lighter call when you already have the channel ID and only want to know whether a station is live.
- URL:
/streams/:id/status - Method:
GET - Auth required: No
- URL parameters:
id: the channel ID, as returned inidby Get stream
Example:
curl https://api.evenings.co/v1/streams/k9Xp2mQr/statusResponse:
{ "online": true, "listeners": 12 }An unknown channel ID returns { "online": false, "listeners": 0 }, not a 404, so check the ID if a station you know is live keeps showing as offline.
Get listener count
Returns online and listeners for your own station.
- URL:
/streams/:slug/listeners - Method:
GET - Auth required: Yes, your API key. A session token isn't accepted here.
- URL parameters:
slug: your station's slug
Example:
curl https://api.evenings.co/v1/streams/garage/listeners \
-H "Authorization: Bearer YOUR_API_KEY"Response:
{ "online": true, "listeners": 12 }A slug for a station that isn't yours returns 404, the same as a slug that doesn't exist.
Play the stream
streamUrl is a plain MP3 stream at 160 kbps, so anything that can play audio from a URL can play it:
<audio controls src="https://media.evenings.co/s/k9Xp2mQr"></audio>It works like radio. Everyone listening hears the same moment, so a new listener joins wherever the station is right now, not at the start of a track.
When nothing is on air, streamUrl returns 404. If you're building a player, check online first, and if a station goes offline while someone's listening, try again after a short wait rather than giving up. The HTML player guide has a full example that does this.
Only set your <audio> element's src when streamUrl actually changes. Setting it again, even to the same URL, restarts the stream and cuts the audio. We learned this one the hard way in our own player guide.
Error responses
Every error body is JSON with title and error, as described in Read errors. Since October 2026, the errors that were plain text or used message are JSON with error.
| Status | When | Body |
|---|---|---|
401 Unauthorized | Get listener count with a missing or invalid API key | { "title": "The gate is closed 🌞", "error": "The API key or session token is missing or invalid. Send a current one as a Bearer token in the Authorization header." } |
404 Not Found | Get stream with an unknown slug, or Get listener count with a slug that isn't yours | Get stream: { "title": "No resource on the horizon 🌞", "error": "We couldn't find a station with that slug." }. Get listener count: { "title": "No resource on the horizon 🌞", "error": "We couldn't find a station with that slug on your account." } |
429 Too Many Requests | Rate limit exceeded | { "title": "Let the tide settle 🌞", "error": "We've received too many requests from your IP address. Try again after the number of seconds in the Retry-After header." }, with a Retry-After header in seconds |
500 Internal Server Error | Something failed on our end | Get stream and Get listener count: { "title": "Sun has set on the server 🌞", "error": "We couldn't finish this request on our end. Try again in a minute." }. Get stream status: { "title": "Sun has set on the server 🌞", "error": "We couldn't check this stream's status on our end. Try again in a minute." } |
Next steps
To show what's coming up as well as what's on now, add the Events API. If your player shows a station as offline when you know it's live, email contact@evenings.email with the slug and the time, including your time zone, and we'll check what our side saw.