Evenings.fmEvenings Docs

API Reference

Tracks API Documentation

Updated

The Tracks API manages your station's library from your own code: upload recordings, fill in their details, add cover images and tidy up. Every endpoint here works on your own station's tracks only.

Base URL

All endpoints are relative to https://api.evenings.co/v1.

Authentication and limits

Send your API key as a Bearer token:

Authorization: Bearer YOUR_API_KEY

If you don't have a key yet, generate one on the Account tab. Every endpoint on this page also accepts the session token our dashboard uses.

Publish track and Unpublish track are the exception: they accept a session token only, so an API key on its own can't publish or unpublish a track yet. For now, use the Publish to Explore switch in the track's details in your Library.

All /v1 requests share a limit of 100 per minute per IP address. See Before you ship.

The track object

{
  "id": 4821,
  "title": "Tuesday Sessions 07.07.mp3",
  "description": "Two hours of records from the back of the shelf.",
  "host": "DJ Name",
  "tags": ["ambient", "late"],
  "url": "https://example.com",
  "image": "https://cdn.evenings.co/images/1751918400000.jpg",
  "location": "https://cdn.evenings.co/tracks/1751918400000.mp3",
  "filename": "1751918400000.mp3",
  "duration": 7214,
  "filetype": "audio/mpeg",
  "stationId": 112,
  "published": true,
  "publishedAt": "2026-07-08T09:12:44.000Z",
  "createdAt": "2026-07-07T22:03:10.000Z",
  "updatedAt": "2026-07-08T09:12:44.000Z",
  "listens": 38
}
FieldWhat it is
idThe track's ID, used in every /tracks/:id URL
title, description, host, urlThe track's details. url is a link for listeners. Any of them can be empty or null.
tagsAn array of strings, or null
imageThe cover image URL, or null
locationThe URL of the file as uploaded
filename, filetypeThe stored file name and its MIME type
durationLength in seconds. 0 means we couldn't read it from the file.
stationIdYour station's ID
published, publishedAtWhether the track is published to Explore, and when it was last published
createdAt, updatedAtUTC timestamps
listensHow many times the track has been listened to. Not included in the Upload track response.

Responses also include a few internal fields that aren't listed here. They can change without notice, so don't build on them.

Endpoints

List tracks

Returns your station's tracks, newest first, one page at a time.

  • URL: /tracks
  • Method: GET
  • Auth required: Yes
  • Query parameters:
    • page (optional): page number, starting at 0. Default 0.
    • limit (optional): tracks per page. Default 100.
    • tags (optional): comma-separated tags. Returns tracks that have any of them.

Example:

curl "https://api.evenings.co/v1/tracks?page=0&limit=20&tags=ambient,late" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response: an array of track objects.

Response headers:

  • x-page: the current page number
  • x-page-size: tracks per page
  • x-total: the total number of tracks that match

Browsers can read these headers from cross-origin requests too. A live broadcast's recording appears here once the broadcast has finished.

Upload track

Uploads an audio file and creates a track for it.

  • URL: /tracks
  • Method: POST
  • Auth required: Yes
  • Content-Type: multipart/form-data
  • Body:
    • audio (required): the audio file, up to 12 GB. Accepted types: .mp3, .wav, .aif, .aiff, .m4a, .flac, .webm, .ogg.

Example:

curl -X POST https://api.evenings.co/v1/tracks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "audio=@/path/to/episode.mp3"

Response: 200 with the new track object, without listens.

The title starts as the file's name, extension included, and the track starts unpublished. Set the title and other details with Update track.

Get track

Returns one track.

  • URL: /tracks/:id
  • Method: GET
  • Auth required: Yes

Response: a track object.

Update track

Changes a track's details.

  • URL: /tracks/:id
  • Method: PATCH
  • Auth required: Yes
  • Content-Type: application/json
  • Body:
{
  "title": "Tuesday Sessions, 7 July",
  "description": "Two hours of records from the back of the shelf.",
  "host": "DJ Name",
  "tags": ["ambient", "late"],
  "url": "example.com/tuesday"
}

Every field is optional, and only the fields you send change. title can't be empty. tags replaces the whole list. If url doesn't start with http:// or https://, we add https://. Any other field returns 400.

This endpoint doesn't change whether a track is published. It accepts a published field without error but ignores it, so use Publish track and Unpublish track instead.

Response: the updated track object.

Example:

curl -X PATCH https://api.evenings.co/v1/tracks/4821 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Tuesday Sessions, 7 July", "tags": ["ambient", "late"]}'

Add track image

Sets a track's cover image, replacing any image it already has.

  • URL: /tracks/:id/images
  • Method: POST
  • Auth required: Yes
  • Content-Type: multipart/form-data
  • Body:
    • image (required): the image file, up to 20 MB. Accepted types: .jpg, .jpeg, .png, .gif, .webp.

Example:

curl -X POST https://api.evenings.co/v1/tracks/4821/images \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "image=@/path/to/cover.jpg"

Response: the updated track object.

Delete track image

Removes a track's cover image.

  • URL: /tracks/:id/images
  • Method: DELETE
  • Auth required: Yes

Response: the updated track object, with image set to null.

Delete track

Deletes a track.

  • URL: /tracks/:id
  • Method: DELETE
  • Auth required: Yes

Response:

"Success! Replay deleted"

The body is a JSON string, not an object. Once deleted, the track no longer appears in List tracks and Get track returns 404 for it. You can't bring it back with your API key, so if you delete a track by mistake, email us and include its ID.

Publish track

Publishes a track to Explore, the same as the Publish to Explore switch in your Library.

  • URL: /tracks/:id/publish
  • Method: POST
  • Auth required: Yes, with a session token only. API keys aren't accepted here yet.

Response:

{ "message": "Success! Track published" }

Unpublish track

Takes a track off Explore again.

  • URL: /tracks/:id/publish
  • Method: DELETE
  • Auth required: Yes, with a session token only. API keys aren't accepted here yet.

Response:

{ "message": "Success! Track unpublished" }

Error responses

Every error body is JSON with title and error, as described in Read errors. Since October 2026, errors that used message or plain text use error instead.

StatusWhenBody
400 Bad RequestUpload track with no audio file{ "title": "A little cloudy 🌞", "error": "No audio file was attached. Send the file in the \"audio\" field." }
400 Bad RequestAdd track image with no image file{ "title": "A little cloudy 🌞", "error": "No image file was attached. Send the file in the \"image\" field." }
400 Bad RequestAn invalid query parameter or body field, such as a non-numeric limit or an unknown field in Update trackFor example, { "title": "A little cloudy 🌞", "error": "We couldn't accept the request body. \"image\" is not allowed." }
401 UnauthorizedA missing or invalid API key or token{ "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 FoundA track ID that doesn't exist or isn't on your station{ "title": "No resource on the horizon 🌞", "error": "We couldn't find that track on your station. Check the track ID." }
413 Payload Too LargeA file over the size limit{ "title": "Too heavy to carry 🌞", "error": "This file is over the 12 GB limit. Upload a smaller file." } (20 MB for images)
415 Unsupported Media TypeA file type we don't accept{ "title": "Not a shape we know 🌞", "error": "We don't accept this audio file type. Upload one of: .mp3, .wav, .aif, .aiff, .m4a, .flac, .webm, .ogg." }, or the image equivalent
429 Too Many RequestsRate 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 ErrorSomething failed on our end{ "title": "Sun has set on the server 🌞", "error": "We couldn't finish this request on our end. Try again in a minute." }

Publish track and Unpublish track currently return 500 rather than 404 for a track ID that doesn't exist, so if you see a 500 there, check the ID with Get track first.

Next steps

To put your schedule next to your library, see the Events API. If an upload fails in a way this page doesn't explain, email contact@evenings.email with the file's name, size and type, and we'll trace it on our side.