RadioCult Online Radio API Reference

Introduction

The RadioCult radio API for developers follows REST principles and covers both sides of your station: read your schedule, artists, tracks and now playing data to power a website or app, and write back to create shows, build playlists and manage your library.

Everything below applies whether you are building a player, a schedule page, a mobile app, or an automation that runs every week.

Not a developer?

You do not need to write code to automate your station. Connect an AI assistant like Claude or ChatGPT to our MCP server and manage your station by asking: build next week of shows, tag a night of new tracks, or tidy a playlist that has grown too long. It calls the same endpoints documented here on your behalf.

If you work with an AI coding agent, our agent skills teach it to build against this API correctly, so you can ask for a player or a schedule page and get working code rather than a plausible guess.

To put RadioCult on your site without any of that, use our range of embeds - such as our chat rooms, weekly schedule and player components.

Don't have an account yet?

You need to create a RadioCult account before you can power your station with our APIs. Go to our sign up page to get started!

Why the RadioCult API?

It reads and writes. The API covers both sides of your station. Pull your schedule, artists, tracks and now playing data out to power a website or app, and push changes back in: create, update and delete shows, set up a repeating series, book artists onto events, and manage your tracks, playlists, tags and recordings. Anything you would otherwise click through the dashboard to do.

It is the same data that goes to air. There is no sync step and no second source of truth. A show created over the API is the show your listeners hear, and your now playing metadata is the track actually playing. That is also why you do not need a separate Content Management System sitting alongside RadioCult: your station data already lives here, so you can manage it in one place and read it out wherever you need it.

It is built for agents as well as people. The same endpoints back our MCP server, so an AI assistant can operate your station in plain language, and our agent skills teach a coding agent to build against the API properly. You can automate a job by asking for it once, or write it yourself and run it every week.

It is designed to be easy to work with. Clean JSON responses, standard HTTP status codes, real-time updates over WebSocket rather than polling, and request and response examples for every endpoint below.

Agent skills

Working with an AI coding agent like Claude Code, Codex or Gemini CLI? We publish ready-made agent skills that teach your agent to build against the RadioCult API correctly: realtime WebSocket updates instead of polling, correct audio element handling, efficient schedule queries with correct timezone handling, safe schedule writes with valid recurrence rules, safe API key usage and reliable upload workflows.

Using Claude? Download the skill zip. Add it to ~/.claude/skills/ for Claude Code, or upload it as a skill on claude.ai.

Using ChatGPT, Codex, Gemini or another agent? Copy the prompt into your agent's instructions, for example your project's AGENTS.md or GEMINI.md file, a Custom GPT's instructions, or a Gemini Gem.

Custom player skill

Helps your agent build a custom web player for your station: live now-playing metadata over WebSockets, an audio element that always joins at the live edge and disconnects cleanly on pause (keeping your listener analytics accurate), and publishable-key-only authentication.

Station website skill

Helps your agent build your station website from the API: weekly programme grids and schedule pages, artist directory and profile pages, and a recently-played tracks feed. It uses the expand param to hydrate artists and tags in one request only when they are shown, handles UTC to local timezone conversion, renders TipTap descriptions and builds artist pages from slugs.

Media upload skill Connect

Lets your agent upload tracks straight to your media library for you. Tell it "upload this folder to my station" and it validates the files (mp3 or m4a, under 750MB), confirms the list, uploads sequentially with rate-limit awareness and reports the results. Also covers metadata overrides, playlist and tag assignment, and building your own upload automations. Uses your secret key, so it belongs in server-side or CLI workflows.

Schedule automation skill Connect

Lets your agent build and maintain your schedule for you, and helps it write a sync that keeps RadioCult in step with a roster spreadsheet, a CMS or a booking form. Covers creating, updating and deleting events, repeating series with valid recurrence rules, booking artists onto shows, and the scope rules that decide whether a change hits one show or the whole series. It reads the range before it writes so a re-run does not double-book, converts show times through your station's timezone, and confirms destructive changes with you first.

MCP server Connect

Prefer to talk to your station rather than write code against it? Connect an AI assistant like Claude or ChatGPT to RadioCult over MCP (the Model Context Protocol) and manage your station in plain language. Ask it "what's playing right now?", "add these three artists", or "build me a playlist from last month's recordings" and it calls the API for you.

This is different from the agent skills above. Those teach a coding agent to build software against our REST API. MCP is a live connection that lets a chat assistant operate your station directly, no code required.

Connecting an AI agent requires Connect access: a Premium plan or higher, or the Connect add-on. This is the same access that the Connect endpoints (markedConnect) require.

What your agent can do

Over MCP your agent works with the same resources documented in the routes below: your schedule, artists, tracks, playlists, tags and recordings, plus playout history and now playing. A read connection gets the query tools only. A write connection also gets the tools that create, update and delete, including creating and changing events and booking artists onto them, so destructive actions are only ever available when you have explicitly connected with write scope.

Connection URL

Point your MCP client at the URL below. It speaks the Streamable HTTP transport.

RadioCult MCP server URL
https://mcp.radiocult.fm/mcp

Authentication

There is no API key to paste into your client. The first time your agent connects, RadioCult opens a consent screen in your browser. Approve it and your agent receives a scoped, revocable grant for your station. Your API key never touches the client.

When you connect you choose a scope:

  • Read. The agent can only query your station: now playing, schedule, artists, tracks, tags, playlists, recordings and playout history.
  • Write. The agent can also make changes, including creating and updating data and destructive actions such as deleting artists or clearing a playlist.

Choose read unless the agent genuinely needs to make changes. To switch scope later, reconnect and pick the other option.

Adding it to your agent

Claude Code. Add the server from your terminal:

Add the RadioCult MCP server to Claude Code
claude mcp add --transport http radiocult https://mcp.radiocult.fm/mcp

Claude desktop, ChatGPT, Cursor and others. Add a custom connector (or MCP server) in your client's settings and give it the connection URL above. Each client's screen is a little different, but they all need the same URL. Your browser will open the consent screen the first time the agent connects.

Managing connections

You can review the AI agents connected to your station, see their scope and revoke any of them at any time from the connected apps settings page.

Getting started

There are two ways to use RadioCult programmatically, and you can mix them freely.

Talk to your station. Connect an AI assistant over the MCP server (above) and manage everything in plain language. There is no code to write and no API key to handle.

Build against the API. Call the REST API directly from your own website, app or scripts. This needs an API key, which is covered next, and it powers everything documented below.

API keys

Generating an API key

To generate an API key for your station, simply head over to the API key settings page. On this page you will be able to generate new secret and publishable API keys. You can delete or roll API keys at any point.

Your station ID

You will also be able to find your unique stationId on the API key settings page. You will need to use your stationId to build the correct URLs for our REST API.

Publishable vs secret keys

Public key

Publishable keys are used to access read-only endpoints that return data safe for public display. This means there is limited access if your key gets leaked.

In short, this means you're safe to use your publishable keys on your website.

If you wish to block access in the future then simply delete or roll your publishable key.

A publishable API key should look something like: pk_34c9a89dd5434676972834781b55ad40

Secret key

Secret keys allow access to all API endpoints, including Connect endpoints that modify your station's data. For example, uploading media, creating artists and more.

Due to the expanded access of secret keys, you should take precautions to prevent your secret key from being leaked (hence, the wonderfully apt name of a "secret" key).

You will most likely be using your secret key in your backend or as part of a CLI workflow. You should not use your secret key on your website.

If you wish to access read-only data, then you should use a publishable key, which can be safely stored and used in your frontend code.

A secret API key should look something like: sk_34c9a89dd5434676972834781b55ad40s78ahddha6884

Using your API key

Once you have your API key it is simple to use it. Simply include the API key in the x-api-key header on all requests to our API.

The x-api-key header value can be a publishable or a secret key. Use the correct API key for the endpoint in question.

In general, use a publishable API key for all GET requests. Use a secret key for any PUT, POST or DELETE requests.

An example of using your API key
fetch('https://api.radiocult.fm/api/station/:stationId/artists', {
  headers: {
    'x-api-key': <your_api_key_here>,
  },
});

API URL

The URL to use for all API endpoints is https://api.radiocult.fm. Make sure to direct requests there rather than the normal RadioCult URL.

RadioCult API URL
'https://api.radiocult.fm'

Connect endpoints

Throughout this reference some endpoints are marked withConnect. These manage your station's own library and schedule: uploading and organising media, creating and updating artists, managing playlists, tags and recordings, and every schedule write. Access requires a Premium or Business plan, which include Connect, or the Connect add-on on Starter or Growth.

Everything you need to build your station's players, websites, schedules and mobile apps (your schedule, what is playing now, your artists and your playout history) is available on any plan.

Errors

The RadioCult API uses conventional HTTP response codes to indicate the success or failure of each request.

In general: response status codes in the 2xx range indicate success. 4xx response codes indicate an error due to invalid information provided to the endpoint (e.g., missing or incorrect parameters). 5xx response codes indicate an error with our servers, and not your request (these are rare, if this does happen then we will have been alerted and on the case but feel free to reach out as well).

We try to be consistent with return values. In the case of an error, every reponse body should be an object containing at least the property success which will be set to false.

Three codes are worth calling out. 401 means the x-api-key header is missing or the key is not recognised. 403 means the key is recognised but is not allowed on that endpoint, most often a publishable key used on a write. 402 means the key and the request are both fine, but the station cannot use that endpoint on its current plan, either because the plan is not active or because it is a Connect endpoint and the station does not have Connect.

Error response
{
    success: false,
    error?: string
}

Rate limiting

To ensure fair usage, we enforce rate limits on key Connect endpoints. Limits are applied per station.

There are two layers of protection:

  • Burst limit — prevents a large number of requests being made within a short period (per minute)
  • Daily limit — caps the total number of requests per day

Every response includes headers so you can track your current usage and build smarter retry logic.

Rate limit response headers example
X-RateLimit-Limit-Burst: 20
X-RateLimit-Remaining-Burst: 17
X-RateLimit-Reset-Burst: 1743609600
X-RateLimit-Limit-Daily: 2000
X-RateLimit-Remaining-Daily: 1847
X-RateLimit-Reset-Daily: 1743638400

Handling a 429 response

When a rate limit is exceeded the API returns a 429 Too Many Requests response. The Retry-After header tells you how many seconds to wait before retrying. The response body includes additional detail about which limit was hit.

We recommend implementing exponential backoff in your integration. Monitor the X-RateLimit-Remaining-* headers to slow down proactively before hitting a limit.

429 response body
{
  "success": false,
  "error": "Too Many Requests",
  "limitType": "burst",
  "limit": 20,
  "remaining": 0,
  "retryAfter": 42,
  "resetsAt": "2025-01-01T12:01:00Z"
}

API routes

Below you will find an overview of all the API routes you can query to power your site and internal tools, along with an explanation of the objects and entities returned.

Schedule

The schedule endpoints can be used to work out what is playing on your stream now and what events are scheduled for the future.

You'll generally query the live now endpoint to build custom players and display what is currently being played on your stream. You'll want to use the range endpoint for building Schedule pages, displaying upcoming events for the week.

These endpoints will return Events. The Event object represents an instance of an scheduled event.

Endpoints
GET /api/station/:stationId/schedule?startDate=<iso_timestamp>&endDate=<iso_timestamp>
GET /api/station/:stationId/schedule/live

The Event object

Attributes

idstring

The unique ID of the event. For a repeating event this is generated per occurrence and is not a record you can address, so use originalId when building a URL to update or delete it

originalIdstring

The ID of the underlying event, and the one to use when updating or deleting. For a standalone event it matches id; for each occurrence of a repeating event it is the ID of the series

stationIdstring

The unique ID of the station that the event belongs to

titlestring

The title of the event

startDateUtcstring [UTC timestamp]

The start date of the event formatted as a ISO timestamp

endDateUtcstring [UTC timestamp]

The end date of the event formatted as a ISO timestamp

descriptionJSONContent | undefined

The event description represented in TipTap JSON format

durationMinutes (number)

The duration of the event expressed as minutes

timezonestring

The original timezone the event was created in

colorstring | undefined

The color of the event as a hex code

mediastring

The media attached to an event. Media can either be live, a mix or a playlist.

artistIdsArray<string> | undefined

An optional array of the IDs of artists attached to an event

tagIdsArray<string> | undefined

An optional array of the IDs of tags attached to an event. Pass expand=tags on the schedule range to hydrate these into full tag objects

isRecurringboolean

A boolean value indicating whether the event is standalone (i.e. doesn't repeat) or is repeating (i.e. is part of a series of events)

modifiedstring [UTC timestamp]

A UTC timestamp of when the event was last modified/updated.

createdstring [UTC timestamp]

A UTC timestamp of when the event was created.

The event object
{
    id: string;
    originalId: string;
    stationId: string;
    title: string;
    startDateUtc: string;
    endDateUtc: string;
    description?: JSONContent;
    duration: Minutes;
    timezone: string;
    color?: string;
    artistIds?: string[];
    tagIds?: string[];
    isRecurring: boolean
    media: 
      | {
        type: 'mix';
        trackId?: string | undefined;
      }
      | {
          type: 'playlist';
          playlistId: string;
        }
      | {
          type: 'live';
        };
}

Retrieve live now

Call the get live now endpoint to return what is currently playing.

This endpoint will return the "status" of your stream and the content being played. The "status" can be one of three things - either:

  1. schedule - which means a scheduled event is playing,
  2. offAir - which means your stream is off air and nothing is playing, or
  3. defaultPlaylist - which means there is no scheduled event and your default playlist is playing.

The content of the stream can be an Event (in the case of a scheduled show), an Off Air enum to indicate the stream is off air or the details associated with your default playlist.

The endpoint also returns:

  • the Metadata of the track details currently being played on the stream. See below for more details on the shape of the Metadata object.
  • the LiveMusicRecognition of the track currently detected to be playing on the stream. This object will only be defined if your RadioCult account has the 24/7 Music Recognition add-on. See below for more details on the shape of the LiveMusicRecognition object.
Endpoint
GET /api/station/:stationId/schedule/live
Response
{
  success: true;
  result:
    | { 
        status: 'schedule'; 
        content: Event; 
        metadata: Metadata; 
        musicRecognition?: LiveMusicRecognition; 
      }
    | { 
        status: 'offAir'; 
        content: 'Off Air'; 
        metadata: Metadata;
        musicRecognition?: LiveMusicRecognition; 
      }
    | {
        status: 'defaultPlaylist';
        content: {
          name: string;
          numberOfSongs: number;
          duration: Minutes;
        };
        metadata: Metadata;
        musicRecognition?: LiveMusicRecognition; 
  };
}

Real-time updates

For live updates on your station's metadata, we recommend using WebSockets.

With WebSockets, we send updates immediately when the metadata changes, ensuring the most up-to-date data. Using Websockets puts less load on our servers and results in a better experience for your listeners.

Unlike polling the "live now" endpoint every minute, which may result in a few seconds of delay, WebSockets provide instant updates. This is why all of our player embeds are powered by WebSockets.

Our WebSockets use Socket.IO, so you'll need the client version of Socket.IO to connect.

To authenticate, include your API key in the auth section when establishing the connection.

All metadata updates will be delivered under the player-metadata event.

We've included example code showing you how to connect and start consuming Websocket events.

Example code
import SocketIo from 'socket.io-client';

const io = SocketIo('https://api.radiocult.fm', {
  auth: {
    'x-api-key': <your API key here>,
  },
  transports: ['websocket'],
  query: {
    stationId: <your station ID here>,
  },
});

io.on('player-metadata', ({ status, content, metadata }) => {
  // Process the results here
});

The Metadata object

titlestring

The title of the current song (or, potentially, the metadata pushed via your live streaming client)

filenamestring

The filename of the current song

durationnumber (Seconds)

The duration of the current song in seconds

albumstring | undefined

The album of the current song

artiststring | undefined

The artist of the current song

playoutStartUnixTimestampnumber (unix timestamp)

The unix timestamp of when the current song started playing

playoutStartIsoTimestampstring (ISO timestamp)

The ISO timestamp of when the current song started playing

artworkmap | undefined

The artwork for the current song. If no artwork has been uploaded then this may be undefined. Once artwork has been uploaded it is automatically resized. The resizing happens asynchronously. As such, there is a possibility that any of the resize values may be undefined for a few seconds after the image has been uploaded. The time window is so small that you will be very unlikely to ever run into this.

notesstring | undefined

The notes of the current song

Metadata
type Metadata = {
  title: string;
  filename: string;
  duration: Seconds;
  album: string | undefined;
  artist: string | undefined;
  playoutStartUnixTimestamp: number;
  playoutStartIsoTimestamp: string;
  artwork: {
    original?: string;
    default?: string;
    '32x32'?: string;
    '64x64'?: string;
    '128x128'?: string;
    '256x256'?: string;
    '512x512'?: string;
  } | undefined;
  notes: string | undefined;
}

The LiveMusicRecognition object

status'match' | 'noMatch'

The status of the live music recognition indicating whether a song has been matched to what is currently being broadcast from the stream.

titlestring

The title of the currently matched song

durationnumber (Seconds) | 'unknown'

The duration of the currently matched song in seconds

albumstring | undefined | null

The album of the currently matched song

artiststring | undefined | null

The artist of the currently matched song

artworkmap | undefined

The artwork for the currently matched song. This may be undefined.

playoutStartUnixTimestampnumber (unix timestamp)

The unix timestamp of when the currently matched song started playing

playoutStartIsoTimestampstring (ISO timestamp)

The ISO timestamp of when the currently matched song started playing

scorenumber | undefined

The score (70-100) of the currently matched song indicating the confidence the system has that the matched track is the actual track being broadcasted.

spotifyTrackIdstring | null

The Spotify track ID for the currently matched song

spotifyAlbumIdstring | null

The Spotify album ID for the currently matched song

spotifyArtistIdsstring[] | null

The Spotify artist ID(s) for the currently matched song

youtubeVideoIdstring | null

The YouTube video ID for the currently matched song

Metadata
type LiveMusicRecognition = {
  status: 'match';
  metadata: {
    title: string;
    duration: Seconds | 'unknown';
    album: string | undefined | null;
    artist: string | undefined | null;
    artwork?: {
      original?: string;
      default?: string;
      '32x32'?: string;
      '64x64'?: string;
      '128x128'?: string;
      '256x256'?: string;
      '512x512'?: string;
    } | null;
    playoutStartUnixTimestamp: number;
    playoutStartIsoTimestamp: string;
    score: number | undefined;
    spotifyTrackId: string | null;
    spotifyAlbumId: string | null;
    spotifyArtistIds: string[] | null;
    youtubeVideoId: string | null;
  }
} | 
{
  status: 'noMatch';
  metadata: undefined;
}

Retrieve events in date range

Call the get events in range endpoint to return all events between specified start and end dates. The events will be returned sorted by start time.

startDate and endDate are required query params. They must be present for the endpoint to return successfully.

You may optionally pass an expand query param to expand the response. Multiple values can be passed as a comma-separated string (i.e. expand=artist,tags). Use expand=artist to hydrate the artistIds field with the full artist object for each event. Use expand=tags to hydrate the tagIds field with the full tag object for each event.

Endpoint
GET /api/station/:stationId/schedule?startDate=<iso_timestamp>&endDate=<iso_timestamp>
Query params (* required)
startDate*: ISO_Timestamp (indicating the beginning of the range you want events for)
endDate*: ISO_Timestamp (indicating the end of the range you want events for)
expand?: 'artist' | 'tags' | 'artist,tags' (optional)
Response
{
  schedules: Array<Event>,
  success: true,
}

Create an event Connect

Create a new event. Use your station's ID to build the URL.

duration is expressed in minutes and must be between 1 - 1440 (24 hours).

Provide an rrule to create a repeating event, or omit it to create a standalone event. It takes an RFC 5545 recurrence rule, the pattern only (e.g. FREQ=WEEKLY;BYDAY=MO;WKST=SU). You don't include a DTSTART; the series is anchored to startDateUtc.

Supported patterns match what the platform offers: daily, weekly (one or more days), and monthly on a day-of-month or a weekday-of-month, with an optional interval and WKST=SU. For monthly patterns the day-of-month or weekday-of-month must match startDateUtc. A weekday-of-month pattern takes a BYSETPOS of 1 to 5 for a fixed occurrence, or -1 for the last of that weekday in the month (FREQ=MONTHLY;BYSETPOS=-1;BYDAY=FR;WKST=SU), in which case startDateUtc must fall on the last such weekday. Anything else (e.g. FREQ=YEARLY or a COUNT) is rejected. Add an UNTIL to bound the series, or omit it to repeat indefinitely.

If provided, description must either be a string or TipTap JSON format. A string is stored as a single paragraph.

artistIds books artists onto the event. A maximum of 10 can be provided, and each one must already exist on the station.

Every ID referenced by media is checked before the event is created, so a track, playlist or relay that does not exist fails the whole request.

color is optional. If provided, it must be one of the palette colours below, any other value is rejected. Click a swatch to copy its hex code.

Click a colour to copy its hex code
Endpoint
POST /api/station/:stationId/schedule
Body (JSON)
{
  title: string,
  startDateUtc: ISO_Timestamp,
  duration: number,
  media:
    | { 
        type: 'mix',
        trackId?: string,
        intro?: 
          | {
            type: 'mix',
            trackId: string,
          }
          | {
            type: 'tag',
            tagId: string,
          }
          | null
        onMediaEnd?: 
          | {
            type: 'loop' | 'underrun',
          }
          | null
        overrun?: 
          | {
            enabled: true,
            // Expressed in seconds, must be between 60 - 7200
            maxOverrunDuration: number,
          }
          | null
      }
    | { 
        type: 'playlist',
        playlistId: string,
        intro?: 
          | {
            type: 'mix',
            trackId: string,
          }
          | {
            type: 'tag',
            tagId: string,
          }
          | null
        onMediaEnd?: 
          | {
            type: 'loop' | 'underrun',
          }
          | null
        overrun?: 
          | {
            enabled: true,
            // Expressed in seconds, must be between 60 - 7200
            maxOverrunDuration: number,
          }
          | null
      }
    | { 
        type: 'relay', 
        relayId: string,
        fallback?: {
          type: 'playlist',
          playlistId: string,
        }
      }
    | { 
        type: 'live',
        fallback?: {
          type: 'playlist',
          playlistId: string,
        }
      },
  color?: string,
  description?: string | JSONContent,
  doRecord?: boolean,
  artistIds?: string[],
  rrule?: string,
}
Response
{
  success: true,
  schedule: Event
}

Update an event Connect

Update an existing event. Use the event's originalId to form the URL.

Use scope to control which events are updated:

  • all updates the whole series. Always use all when updating a standalone event,
  • this only updates a single instance of a repeating event, identified by instanceStart (required), or
  • thisAndFollowing updates the target instance - identified by instanceStart (required) - and all following instances of a repeating event.

If provided, description must either be a string or TipTap JSON format. A string is stored as a single paragraph.

color is optional. If provided, it must be one of the palette colours below, any other value is rejected. Click a swatch to copy its hex code.

Click a colour to copy its hex code
Endpoint
PUT /api/station/:stationId/schedule/:scheduleId
Body (JSON)
{
  scope: 'all' | 'this' | 'thisAndFollowing',
  // Required when scope is 'this' or 'thisAndFollowing'
  instanceStart?: ISO_Timestamp,
  title?: string,
  description?: string | JSONContent,
  color?: string,
  media?:
    | { 
        type: 'mix',
        trackId?: string,
        intro?: 
          | {
            type: 'mix',
            trackId: string,
          }
          | {
            type: 'tag',
            tagId: string,
          }
          | null
        onMediaEnd?: 
          | {
            type: 'loop' | 'underrun',
          }
          | null
        overrun?: 
          | {
            enabled: true,
            // Expressed in seconds, must be between 60 - 7200
            maxOverrunDuration: number,
          }
          | null
      }
    | { 
        type: 'playlist',
        playlistId: string,
        intro?: 
          | {
            type: 'mix',
            trackId: string,
          }
          | {
            type: 'tag',
            tagId: string,
          }
          | null
        onMediaEnd?: 
          | {
            type: 'loop' | 'underrun',
          }
          | null
        overrun?: 
          | {
            enabled: true,
            // Expressed in seconds, must be between 60 - 7200
            maxOverrunDuration: number,
          }
          | null
      }
    | { 
        type: 'relay', 
        relayId: string,
        fallback?: {
          type: 'playlist',
          playlistId: string,
        }
      }
    | { 
        type: 'live',
        fallback?: {
          type: 'playlist',
          playlistId: string,
        }
      },
  doRecord?: boolean,
}
Response
{
  success: true,
  schedule: Event,
  series?: Event
}

Delete an event Connect

Delete an event. Use the event's originalId to form the URL.

Use scope to control which events are deleted:

  • all deletes the whole series. Always use all when deleting a standalone event,
  • this only deletes a single instance of a repeating event, identified by instanceStart (required), or
  • thisAndFollowing deletes the target instance - identified by instanceStart (required) - and all following instances of a repeating event.
Endpoint
DELETE /api/station/:stationId/schedule/:scheduleId
Query params (* required)
scope*: 'all' | 'this' | 'thisAndFollowing'
// Required when scope is 'this' or 'thisAndFollowing'
instanceStart?: ISO_Timestamp
Response
{
  success: true
}

Add an artist to an event Connect

Add an artist to an event. Use the event's originalId and the artist's ID to form the URL. The artist is added to the whole series.

Endpoint
PUT /api/station/:stationId/schedule/:scheduleId/artist/:artistId
Response
{
  success: true
}

Remove an artist from an event Connect

Remove an artist from an event. Use the event's originalId and the artist's ID to form the URL. The artist is removed from the whole series.

Endpoint
DELETE /api/station/:stationId/schedule/:scheduleId/artist/:artistId
Response
{
  success: true
}

Artists

The Artist object represents an instance of an artist (or presenter, or host, or whatever language you choose) in RadioCult. An Artist is someone who presents shows on your station.

An Artist encapsulates the common information for a host or presenter - such as name, description, social media links and more.

As Artists can be assigned to shows, you can fetch all shows an Artist is on via their ID. Additionally, Events will have the ID for any Artist on that show.

Endpoints
GET    /api/station/:stationId/artists
GET    /api/station/:stationId/artists/:artistId
GET    /api/station/:stationId/artists/:slug
POST   /api/station/:stationId/artists
PUT    /api/station/:stationId/artists/:artistId
PUT    /api/station/:stationId/artists/:artistId/image
DELETE /api/station/:stationId/artists/:artistId
GET    /api/station/:stationId/artists/:artistId/schedule?startDate=<iso_timestamp>&endDate=<iso_timestamp>

The Artist object

Attributes

idstring

The unique ID of the artist

namestring

The name of the artist. As you can create an artist with only an email, it is possible for this value to not be set

stationIdstring

The unique ID of the station that the artist belongs to

slugstring

An alternative and human-readable ID of the artist

socialsmap

Map containing socials related to the artist - e.g. twitter handle, website. This can be undefined, as can the properties within

shareableLinkIdstring

The shareable Link that gives 3rd parties editable access to the artist. This may be useful if you are building an internal tool for your station. You most likely will not want to render this on any public facing site.

descriptionJSONContent | undefined

The artists description represented in TipTap JSON format

logomap

The artwork for the artist. If no artwork has been uploaded then this may be undefined. Once artwork has been uploaded it is automatically resized. The resizing happens asynchronously. As such, there is a possibility that any of the resize values may be undefined for a few seconds after the image has been uploaded. The time window is so small that you will be very unlikely to ever run into this.

tagsArray<string>

A string array containing the tags assigned to the artist

genresArray<string>

A string array containing the genres of the artist

countrystring

The country of the artist (this could be their country of residence or their country of origin)

modifiedstring [UTC timestamp]

A UTC timestamp of when the artist was last modified/updated

createdstring [UTC timestamp]

A UTC timestamp of when the artist was created

The artist object
{
    id: string;
    name?: string;
    stationId: string; 
    slug?: string;
    socials?: {
      twitterHandle?: string;
      instagramHandle?: string;
      facebook?: string;
      mixcloud?: string;
      soundcloud?: string;
      site?: string;
    };
    shareableLinkId: string;
    description?: JSONContent | undefined;
    logo?:  {
        default: string;
        '1024x1024': string;
        '32x32'?: string;
        '64x64'?: string;
        '128x128'?: string;
        '256x256'?: string;
        '512x512'?: string;
    };
    tags: Array<string>;
    genres: Array<string>;
    country?: string;
    modified: string;
    created: string;
}

Retrieve all artists

Call the get all artists endpoint to return all of your artists.

Endpoint
GET /api/station/:stationId/artists
Response
{
  success: true,
  artists: Array<Artist>
} 

Retrieve an artist by ID

Use an artist's ID to fetch their details.

Use your station ID and the ID of the artist you are interested in to build the URL.

Endpoint
GET /api/station/:stationId/artists/:artistId
Response
{
  success: true,
  artist: Artist
} 

Retrieve an artist by slug

Use an artist's slug to fetch their details.

Use your station ID and the slug of the artist you are interested in to build the URL.

Endpoint
GET /api/station/:stationId/artists/:slug
Response
{
  success: true,
  artist: Artist
} 

Retrieve an artist's schedules

Use an Artist's ID to fetch all events between the specified start and end dates the artist has been assigned to. The events will be returned sorted by start time.

startDate and endDate are required query params. They must be present for the endpoint to return successfully.

Endpoint
GET /api/station/:stationId/artists/:artistId/schedule?startDate=<iso_timestamp>&endDate=<iso_timestamp>
Query params (* required)
startDate*: ISO_Timestamp (the beginning of the range you want events within)
endDate*: ISO_Timestamp (the end of the range you want eventswithin)
Response
{
  schedules: Array<Event>,
  success: true,
}

Create an artist Connect

Create a new artist.

Use your station's ID to build the URL.

You must provide either email or name in the request body to create an artist. If an email is provided, then it must be a valid email address.

If provided, site must be a valid URL.

Lastly, if provided, description must either be a string or TipTap JSON format

Endpoint
POST /api/station/:stationId/artists
Body (JSON)
{
    name?: string,
    email: string,
    slug?: string,
    site?: string,
    twitterHandle?: string,
    instagramHandle?: string,
    facebook?: string,
    mixcloud?: string,
    soundcloud?: string,
    description?: string | JSONContent,
    tags?: string[],
    genres?: string[],
} |
{
    name: string,
    email?: string,
    slug?: string,
    site?: string,
    twitterHandle?: string,
    instagramHandle?: string,
    facebook?: string,
    mixcloud?: string,
    soundcloud?: string,
    description?: string | JSONContent,
    tags?: string[],
    genres?: string[],
}
Response
{
  success: true,
  artist: Artist
} 

Update an artist Connect

Call this endpoint to update an existing artist. Use the artist's ID to form the URL.

All fields are optional. Only the fields you provide are updated; omitted fields are left unchanged. socials is merged onto the artist's existing handles, so you only need to send the ones you want to change. To clear a value, send tags: [] or genres: [], or a social handle as an empty string.

If provided, email must be a valid email address, site must be a valid URL, and description must be TipTap JSON format.

Endpoint
PUT /api/station/:stationId/artists/:artistId
Body (JSON)
{
  shareableLinkId?: string,
  socials?: {
    site?: string,
    twitterHandle?: string,
    instagramHandle?: string,
    facebook?: string,
    mixcloud?: string,
    soundcloud?: string,
    youtube?: string,
  },
  email?: string,
  slug?: string,
  name?: string,
  description?: JSONContent,
  tags?: string[] | null,
  genres?: string[] | null,
  phoneNumber?: string,
  phoneAreaCode?: string,
  country?: string,
}
Response
{
  success: true,
  artist: Artist
} 

Update an artist image Connect

Call this endpoint to set an artist's profile image. Use the artist's ID to form the URL.

The request takes a form data body, where artistImage is the image file you wish to upload. The file must be less than 10MB.

Uploaded images are re-encoded to JPEG. The updated artist is returned with its new logo map, so you do not need a follow-up request to read the URLs back.

An artist has a single image. Uploading a new one replaces the existing image, and the previous image is removed.


Example code
import { createReadStream } from 'node:fs';
import FormData from 'form-data';
import { request } from 'undici';

const imageFile = createReadStream(filePath, {
  autoClose: true,
});

const formData = new FormData();
formData.append('artistImage', imageFile);

await request(
  `https://api.radiocult.fm/api/station/${stationId}/artists/${artistId}/image`,
  {
    method: 'PUT',
    body: formData,
    headers: {
      ...formData.getHeaders(),
      'x-api-key': secretKey,
    },
  }
);
Endpoint
PUT /api/station/:stationId/artists/:artistId/image
Body (form data)
artistImage: image file (max 10MB)
Response
{
  success: true,
  artist: Artist
}

Delete an artist Connect

Call this endpoint to delete an artist. Use the artist's ID to form the URL.

If the artist is linked to a user, that user account is not deleted. Only the link between them is removed.

Endpoint
DELETE /api/station/:stationId/artists/:artistId
Response
{
  success: true,
} 

Last played

The last played endpoint can be used to retrieve the latest played tracks for your station.

Endpoint
GET    /api/station/:stationId/streaming/history/latest-results?limit=<number>

The Last played object

Attributes

playoutStartstring [UTC timestamp]

The start date of the last played track formatted as a ISO timestamp

titlestring

The title of the last played track

artiststring | null

The artist of the last played track

albumstring | null

The album of the last played track

artworkmap | null

The artwork of the last played track

The last played object
{
    playoutStart: string;
    title: string;
    artist: string | null;
    album: string | null;
    artwork: {
        default: string;
        '1024x1024': string;
        '32x32'?: string;
        '64x64'?: string;
        '128x128'?: string;
        '256x256'?: string;
        '512x512'?: string;
    } | null;
}

Get last played tracks

Call this endpoint to retrieve the latest played tracks for your station. The returned array will be sorted by playoutStart in descending order.

You may optionally pass a limit query param (expressed as an integer) to specify the number of latest played tracks to return. The minimum value is 1 and the maximum value is 100.

If not provided, the 5 last played tracks will be returned.

Endpoint
GET /api/station/:stationId/streaming/history/latest-results?limit=<number>
Query params
limit?: number (optional)
Response
{
    success: true,
    data: LastPlayed[]
} 

Tracks

The track endpoints can be used to interact with your track library.

You can upload files, tag them, add them to playlists, and more.

These endpoints need to be authenticated using your Secret Key.

Endpoints
GET    /api/station/:stationId/media/track
GET    /api/station/:stationId/media/track/:trackId/download-url
POST   /api/station/:stationId/media/track
PUT    /api/station/:stationId/media/track/:trackId
DELETE /api/station/:stationId/media/track/:trackId
POST   /api/station/:stationId/media/track/:trackId/upload/soundcloud
POST   /api/station/:stationId/media/track/:trackId/upload/mixcloud
PUT    /api/station/:stationId/media/track/:trackId/tag/:tagId
POST   /api/station/:stationId/media/playlist/:playlistId/entry  

The Track object

Attributes

idstring

The unique ID of the track

stationIdstring

The unique ID of the station that the track belongs to

mimeTypestring

The MIME type of the track

durationSeconds [number]

The duration of the track in seconds

titlestring

The title of the track

filenamestring

The file name of the track

artiststring

The artist of the track

albumstring

The album of the track

artworkmap | null

The artwork of the track

isrcstring

The ISRC of the track

fileSizeBytes [number]

The file size of the track in bytes

lastPlayedIsostring [UTC timestamp]

The last played date of the track formatted as a ISO timestamp

tagIdsArray<string> | undefined

An optional array of the IDs of tags assigned to the track

labelstring

The (music) label of the track

notesstring

The notes of the track

mixcloudUrlstring

The Mixcloud URL of the track (if successfully uploaded to Mixcloud)

soundcloudUrlstring

The Soundcloud URL of the track (if successfully uploaded to Soundcloud)

The track object
{
    id: string;
    stationId: string;
    mimeType: string;
    duration: Seconds;
    title: string;
    filename?: string;
    artist?: string;
    album?: string;
    artwork?: Artwork | null;
    isrc?: string;
    fileSize?: Bytes;
    lastPlayedIso?: string;
    tagIds?: string[];
    label?: string;
    notes?: string;
    mixcloudUrl?: string;
    soundcloudUrl?: string;
}

Retrieve all tracks Connect

Call the get all tracks endpoint to return all of your tracks.

Use your Secret Key when accessing this endpoint.

Endpoint
GET /api/station/:stationId/media/track
Response
{
    success: true,
    tracks: Array<Track>
} 

Retrieve a track's download URL Connect

Call the get track download URL endpoint to retrieve a signed URL that can be used to download the track.

The signed URL will expire after 30 minutes.

Use your Secret Key when accessing this endpoint.

Endpoint
GET /api/station/:stationId/media/track/:trackId/download-url
Response
{
    success: true,
    url: string
} 

Update a track Connect

Call this endpoint to update the metadata of an existing track. Use the track's ID to form the URL.

All body fields are optional - only the fields you provide will be updated.

If both cueIn and cueOut are provided, cueIn must be less than cueOut. If all of cueIn, cueOut, fadeIn and fadeOut are provided, then fadeIn + fadeOut must not exceed the playable duration (cueOut - cueIn).

Use your Secret Key when accessing this endpoint.

Endpoint
PUT /api/station/:stationId/media/track/:trackId
Body (JSON)
{
  title?: string,
  album?: string | null,
  artist?: string | null,
  isrc?: string | null,
  label?: string | null,
  isVisibleToDjs?: boolean,
  notes?: string (max 4000 characters),
  year?: number | null,
  genre?: string[] (1-10 items),
  bpm?: number | null,
  cueIn?: number,
  cueOut?: number,
  fadeIn?: number,
  fadeOut?: number,
}
Response
{
  success: true,
}

Delete a track Connect

Call this endpoint to delete a track from your track library. Use the track's ID to form the URL.

By default, if the track is still used by at least one playlist the request returns a 409 and the track is not deleted. Pass the optional force query param set to true to delete the track regardless of any playlist references.

Use your Secret Key when accessing this endpoint.

Endpoint
DELETE /api/station/:stationId/media/track/:trackId
Query params
force?: 'true' | 'false' (optional)
Response
{
  success: true,
}

Upload a track Connect

Call the upload endpoint to upload a file to your track library.

This endpoint is useful for building workflows and automating uploads when you have many Artists and shows.

The request takes a form data body, where stationMedia is the file you wish to upload.

The file must be mp3 or m4a. The file must be less than 750MB. The file must have a valid duration.

We use the metadata (or file name if metadata is not set) to set the track information.

OPTIONALLY: you can provide metadata overrides in the form data. This will override the metadata we extract from the file.

The notes field allows you to add custom notes, descriptions or comments to your tracks (max 4000 characters). These notes can be used for internal organization and will automatically populate as the default description when uploading to platforms like Mixcloud or Soundcloud from within RadioCult.

NOTE: To ensure we can properly validate the metadata overrides, you must attach it to your form data as valid JSON. You need to JSON.stringify the metadata overrides before adding them to the form data.

OPTIONALLY: you can provide playlistIds and/or tagIds in the form data. This will assign the uploaded track to the provided playlist(s) and/or tag(s).

NOTE: If the provided playlist(s) and/or tag(s) cannot be found, the track will still be uploaded without the intended assignment.


Example code
import { createReadStream } from 'node:fs';
import FormData from 'form-data';
import { request } from 'undici';

const audioFile = createReadStream(filePath, {
  autoClose: true,
});

const formData = new FormData();
formData.append('stationMedia', audioFile);
formData.append(
  'metadata',
  JSON.stringify({
    title: 'Title',
    album: 'Album',
    notes: 'Notes about this track',
  })
);

playlistIds.forEach((playlistId) => formData.append('playlistIds', playlistId));
tagIds.forEach((tagId) => formData.append('tagIds', tagId));

await request(
  `https://api.radiocult.fm/api/station/${stationId}/media/track`,
  {
    method: 'POST',
    body: formData,
    headers: {
      ...formData.getHeaders(),
      'x-api-key': secretKey,
    },
  }
);
Endpoint
POST /api/station/:stationId/media/track
Body (form data)
stationMedia: mp3 or m4a file (max 750MB),

// Optional metadata overrides
metadata?: Stringified JSON<{
  title?: string,
  filename?: string,
  album?: string,
  artist?: string,
  isrc?: string,
  notes?: string (max 4000 characters),
}>

// Optional assignment IDs
playlistIds: string[] (max 5);
tagIds: string[] (max 5);
Response
{
  success: true,
  track: {
    id: string
  }
  // Only returned if request contained playlistIds and/or tagIds
  assignments: {
    playlists: {
      succeeded: string[];
      failed: string[];
    }
    tags: {
      succeeded: string[];
      failed: string[];
    }
  }
}

Upload to Soundcloud Connect

Call this endpoint to upload an existing file from your RadioCult track library to your connected Soundcloud account.

This endpoint is useful for building workflows and automating uploads.

The request takes a form data body. Use the returned id from uploading a track to form the URL.

NOTE: To ensure we can properly validate the input, you must send valid JSON for all fields except artworkData. This means you must JSON.stringify the fields before sending them in the form data.


Example code
  const formData = new FormData();
  formData.append('tags', JSON.stringify(['rock', 'pop']));
  formData.append('title', JSON.stringify('Autumn Mix'));
  formData.append('embeddableBy', JSON.stringify('all'));
  formData.append('sharing', JSON.stringify('public'));
  formData.append('downloadable', String(true));
  formData.append('commentable', String(false));
Endpoint
POST /api/station/:stationId/media/track/:trackId/upload/soundcloud
Body (form data)
title: string,
tags: Array<string>,
embeddableBy: 'all' | 'me' | 'none',
sharing: 'public' | 'private',
downloadable: boolean,
commentable: boolean,
description?: string,
artworkData?: artwork file (max 2MB), 
Response
{
  success: true,
}

Upload to Mixcloud Connect

Call this endpoint to upload an existing file from your RadioCult track library to your connected Mixcloud account.

This endpoint is useful for building workflows and automating uploads.

The request takes a form data body. Use the returned id from uploading a track to form the URL.

Some fields (disableComments, hideStats and hosts) require a Mixcloud Pro account.

NOTE: To ensure we can properly validate the input, you must send valid JSON for all fields except the artwork file. This means you must JSON.stringify the fields before sending them in the form data.

Endpoint
POST /api/station/:stationId/media/track/:trackId/upload/mixcloud
Body (form data)
name: string,
tags: Array<string>,
unlisted: boolean,
description?: string,
storedArtworkUrl?: string,
artwork?: artwork file,

// Mixcloud Pro account only
disableComments?: boolean,
hideStats?: boolean,
hosts?: Array<string> (max 2),
Response
{
  success: true,
}

Tag a track Connect

Call this endpoint to add a tag to an uploaded track.

Use the returned track ID from uploading a file to form the URL.

You can get the ID of a tag from the URL displayed in the tag view. For example, when viewing a tag your browser will display a URL like: https://app.radiocult.fm/tags?tag=2sZyt9DQDz8cLOUvFiZ2xS5MTIi. The tag ID in this case would be 2sZyt9DQDz8cLOUvFiZ2xS5MTIi.

This endpoint is useful for building workflows and automating uploads.

Endpoint
PUT /api/station/:stationId/media/track/:trackId/tag/:tagId
Response
{
  success: true,
}

Add a track to a playlist Connect

Call this endpoint to add an uploaded track to a playlist.

Use the returned track ID from uploading a file to form the URL.

You can get the ID of a playlist from the URL displayed in the playlist view. For example, when viewing a playlist your browser will display a URL like: https://app.radiocult.fm/playlists?playlist=2sZyt9DQDz8cLOUvFiZ2xS5MTIi. The playlist ID in this case would be 2sZyt9DQDz8cLOUvFiZ2xS5MTIi.

This endpoint is useful for building workflows and automating uploads.

Endpoint
POST /api/station/:stationId/media/playlist/:playlistId/entry
Body (JSON)
trackId: string
Response
{
  success: true,
}

Tags

The tag endpoints can be used to manage your tags. These endpoints are helpful when building automations and CLI workflows.

Due to the sensitive nature use your Secret Key when calling these endpoints.

Endpoints
GET    /api/station/:stationId/media/tag
POST   /api/station/:stationId/media/tag
PUT    /api/station/:stationId/media/tag/:tagId
DELETE /api/station/:stationId/media/tag/:tagId

The Tag object

Attributes

idstring

The unique ID of the tag

stationIdstring

The unique ID of the station that the tag belongs to

namestring

The name of the tag

colorstring [hex code]

The hex color of the tag

The tag object
{
    id: string;
    stationId: string;
    name: string;
    color: string;
}

Retrieve all tags Connect

Call the get all tags endpoint to return all of your tags.

Use your Secret Key when accessing this endpoint.

Endpoint
GET /api/station/:stationId/media/tag
Response
{
    success: true,
    tags: Array<Tag>
} 

Create a tag Connect

Call this endpoint to create a new tag. Use your station's ID to build the URL.

Use your Secret Key when accessing this endpoint.

Endpoint
POST /api/station/:stationId/media/tag
Body (JSON)
name: string (max 250 characters),
Response
{
    success: true,
    tag: Tag
} 

Update a tag Connect

Call this endpoint to update an existing tag. Use the tag's ID to form the URL.

Use your Secret Key when accessing this endpoint.

Endpoint
PUT /api/station/:stationId/media/tag/:tagId
Body (JSON)
name: string (max 250 characters),
Response
{
  success: true,
}

Delete a tag Connect

Call this endpoint to delete a tag. Use the tag's ID to form the URL.

Deleting a tag also removes it from any tracks and playlists it was assigned to.

Use your Secret Key when accessing this endpoint.

Endpoint
DELETE /api/station/:stationId/media/tag/:tagId
Response
{
  success: true,
}

Playlists

The playlist endpoints can be used to manage your playlists. These endpoints are helpful when building automations and CLI workflows.

Due to the sensitive nature use your Secret Key when calling these endpoints.

Endpoints
GET    /api/station/:stationId/media/playlist
POST   /api/station/:stationId/media/playlist
DELETE /api/station/:stationId/media/playlist/:playlistId
DELETE /api/station/:stationId/media/playlist/:playlistId/entry
DELETE /api/station/:stationId/media/playlist/:playlistId/entries

The Playlist object

Attributes

idstring

The unique ID of the playlist

stationIdstring

The unique ID of the station that the playlist belongs to

namestring

The name of the playlist

durationSeconds [number]

The duration of the playlist in seconds

playOrderstring

The order in which the playlist entries will play out. Either in order (in_order) or shuffled (shuffle)

numberOfSongsnumber

The total number of entries in the playlist (songs and tags)

numberOfTagsnumber

The total number of tags in the playlist

The playlist object
{
    id: string;
    stationId: string;
    name: string;
    duration: Seconds;
    playOrder: 'in_order' | 'shuffle'
    numberOfSongs: number;
    numberOfTags: number;
}

Retrieve all playlists Connect

Call the get all playlists endpoint to retrieve a list of all of your playlists.

Use your Secret Key when accessing this endpoint.

Endpoint
GET /api/station/:stationId/media/playlist
Response
{
    success: true,
    playlists: Array<Playlist>
} 

Create a playlist Connect

Call this endpoint to create a new, empty playlist. Use your station's ID to build the URL.

Use your Secret Key when accessing this endpoint.

Endpoint
POST /api/station/:stationId/media/playlist
Body (JSON)
name: string
Response
{
    success: true,
    playlist: Playlist
} 

Delete a playlist Connect

Call this endpoint to delete a playlist. Use the playlist's ID to form the URL.

Use your Secret Key when accessing this endpoint.

Endpoint
DELETE /api/station/:stationId/media/playlist/:playlistId
Response
{
    success: true,
} 

Delete a playlist entry Connect

Call this endpoint to remove a single entry (a song or a tag) from a playlist. Use the playlist's ID to form the URL.

The sortRanking in the body identifies the specific entry to remove within the playlist.

Use your Secret Key when accessing this endpoint.

Endpoint
DELETE /api/station/:stationId/media/playlist/:playlistId/entry
Body (JSON)
sortRanking: string
Response
{
    success: true,
} 

Clear a playlist's entries Connect

Call this endpoint to remove all entries (e.g. songs and tags) from a playlist. This will result in an empty playlist.

This endpoint is useful when automating content for repeating shows.

For example, you can create an event, attach a playlist to the event and make note of the playlist ID. You can then build a workflow where you clear the playlist, upload any new tracks and add to the playlist. You have effectively removed the audio for the previous show and prepared the playlist for the next occurrence of the show. All via the API.

Use your Secret Key when accessing this endpoint.

Endpoint
DELETE /api/station/:stationId/media/playlist/:playlistId/entries
Response
{
    success: true,
    playlist: Playlist
} 

Recordings

The recordings endpoints can be used to manage your recordings. These endpoints are helpful when building automations and CLI workflows.

Due to the sensitive nature use your Secret Key when calling these endpoints.

Endpoints
GET    /api/station/:stationId/media/recording
GET    /api/station/:stationId/media/recording/:recordingId/download-url
PUT    /api/station/:stationId/media/recording/:recordingId
DELETE /api/station/:stationId/media/recording/:recordingId
POST   /api/station/:stationId/media/recording/:recordingId/copy

The Recording object

Attributes

idstring

The unique ID of the recording

stationIdstring

The unique ID of the station that the recording belongs to

scheduleIdstring

The unique ID of the schedule event that was recorded to generate the recording

mimeTypestring

The mime type of the recording

durationSeconds [number]

The duration of the recording in seconds

titlestring

The title of the recording

artiststring

The artist (name) of the recording

fileSizeBytes [number]

The file size of the recording in bytes

notesstring

The notes of the recording

mixcloudUrlstring

The Mixcloud URL of the recording (if successfully uploaded to Mixcloud)

soundcloudUrlstring

The Soundcloud URL of the recording (if successfully uploaded to Soundcloud)

The recording object
{
    id: string;
    stationId: string;
    scheduleId: string;
    mimeType: string;
    duration: Seconds;
    title: string;
    artist?: string;
    fileSize?: Bytes;
    notes?: string;
    mixcloudUrl?: string;
    soundcloudUrl?: string;
}

Retrieve all recordings Connect

Call the get all recordings endpoint to retrieve a list of all of your recordings.

Use your Secret Key when accessing this endpoint.

Endpoint
GET /api/station/:stationId/media/recording
Response
{
    success: true,
    recordings: Array<Recording>
} 

Retrieve a recording's download URL Connect

Call the get recording download URL endpoint to retrieve a signed URL that can be used to download the recording.

The signed URL will expire after 30 minutes.

Use your Secret Key when accessing this endpoint.

Endpoint
GET /api/station/:stationId/media/recording/:recordingId/download-url
Response
{
    success: true,
    url: string
} 

Update a recording Connect

Call this endpoint to update the metadata of an existing recording. Use the recording's ID to form the URL.

All body fields are optional - only the fields you provide will be updated.

Use your Secret Key when accessing this endpoint.

Endpoint
PUT /api/station/:stationId/media/recording/:recordingId
Body (JSON)
title?: string,
artist?: string,
notes?: string (max 4000 characters),
Response
{
  success: true,
}

Delete a recording Connect

Call this endpoint to delete a recording. Use the recording's ID to form the URL.

Use your Secret Key when accessing this endpoint.

Endpoint
DELETE /api/station/:stationId/media/recording/:recordingId
Response
{
  success: true,
}

Copy a recording to your track library Connect

Call this endpoint to copy a recording into your track library as a track. Use the recording's ID to form the URL.

This is useful for turning a recorded show into a reusable track that you can add to playlists, tag, or upload to Mixcloud and Soundcloud.

Use your Secret Key when accessing this endpoint.

Endpoint
POST /api/station/:stationId/media/recording/:recordingId/copy
Response
{
  success: true,
}

Have any questions?

Feel free to reach out if you need a hand! We're more than happy to help explain the API, best practices or even spar a new concept.

Build your station website & automate your station

The RadioCult API gives you programmatic access to your schedule, shows, and live now-playing data, and lets an AI agent manage them for you.

  • Real-time now-playing metadata
  • Full schedule and show data
  • Power custom websites and mobile apps
  • Automate file uploads and station management

Prefer to look first? Compare our plans.

Radio broadcaster on air
Hey AI, learn about us