Download OpenAPI specification:Download
An API for working with the CHIRP Radio music library
Authenticate with email and password to retrieve a JSON Web Token (JWT) you can use to authorize against other API endpoints.
| email required | string |
| password required | string |
{- "email": "string",
- "password": "string"
}{- "password_reset_required": true,
- "message": "string",
- "email": "string"
}Search for an album, track, or artist, or search the text of a review
| term | string The search term |
| limit | integer [ 1 .. 100 ] Default: 50 The number of results to return. |
| offset | integer Default: 0 The offset of the first album to return. Use with limit to get the next page of results. |
| index | string Enum: "album" "artist" "track" Limit the search and results to albums, artists, or tracks |
| type | string Deprecated Enum: "album" "artist" "track" Use |
| album[is_compilation] | boolean |
| album[label] | string |
| album[local] | string Enum: "any" "current" "classic" |
| album[rotation] | string Enum: "any" "heavy" "light" |
| album[year] | integer |
| track[duration][gte] | integer Minimum track length in milliseconds |
| track[duration][lte] | integer Maximum track length in milliseconds |
| track[is_recommended] | boolean |
Retrieve a list of users in the system. Returns different data based on user permissions:
[ ]Create a new user account. Requires superuser privileges or volunteer coordinator role. A temporary password will be generated and returned.
| email required | string <email> |
| first_name required | string |
| last_name required | string |
| dj_name | string |
| roles | Array of strings Items Enum: "dj" "music_director" "traffic_log_admin" "reviewer" "volunteer_coordinator" |
| is_active | boolean Default: true |
{- "email": "user@example.com",
- "first_name": "string",
- "last_name": "string",
- "dj_name": "string",
- "roles": [
- "dj"
], - "is_active": true
}{- "user": {
- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "email": "user@example.com",
- "first_name": "string",
- "last_name": "string",
- "dj_name": "string",
- "date_joined": "2019-08-24T14:15:22Z",
- "last_login": "2019-08-24T14:15:22Z",
- "is_active": true,
- "is_superuser": true,
- "password_reset_required": true,
- "roles": [
- "dj"
]
}, - "temporary_password": "string",
- "message": "string"
}Change password for a user by providing their email and current password
| email required | string <email> |
| currentPassword required | string |
| newPassword required | string >= 12 characters |
{- "email": "user@example.com",
- "currentPassword": "string",
- "newPassword": "stringstring"
}{- "message": "string"
}Update specific fields of an existing user. Supports partial updates. Requires superuser privileges or volunteer coordinator role.
| id required | integer The unique identifier of the user to update |
string <email> User's email address (must be unique) | |
| first_name | string User's first name |
| last_name | string User's last name |
| dj_name | string User's DJ name/handle |
| roles | Array of strings Items Enum: "dj" "music_director" "traffic_log_admin" "reviewer" "volunteer_coordinator" Array of user roles |
| is_active | boolean Whether the user account is active |
{- "email": "user@example.com",
- "first_name": "string",
- "last_name": "string",
- "dj_name": "string",
- "roles": [
- "dj"
], - "is_active": true
}{- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "email": "user@example.com",
- "first_name": "string",
- "last_name": "string",
- "dj_name": "string",
- "date_joined": "2019-08-24T14:15:22Z",
- "last_login": "2019-08-24T14:15:22Z",
- "is_active": true,
- "is_superuser": true,
- "password_reset_required": true,
- "roles": [
- "dj"
]
}Returns albums with a given tag
| tag required | string Enum: "heavy_rotation" "light_rotation" "local_current" "local_classic" |
| limit | integer [ 1 .. 100 ] Default: 25 The number of albums to return. |
| offset | integer Default: 0 The index of the first album to return. Use with limit to get the next set of albums. |
Returns albums added after a given date and time that aren't in rotation ("library adds")
| timestamp | integer The number of milliseconds since January 1, 1970, 00:00:00 UTC (the ECMAScript epoch, equivalent to the UNIX epoch), with leap seconds ignored. Default: 28 days before the time of the request |
| limit | integer [ 1 .. 100 ] Default: 25 The number of albums to return |
| offset | integer Default: 0 The index of the first album to return. Use with limit to get the next set of albums. |
Get albums, tracks, and artists in a crate
| id required | integer |
| limit | integer [ 1 .. 100 ] Default: 100 The number of items to return |
| offset | integer Default: 0 The index of the first item to return. Use with limit to get the next set of items. |
Add a track, album, or artist to a crate by its key, or add a custom item
| id required | integer |
| key | array |
{- "key": [ ]
}{- "kind": "Track",
- "encodedKey": "string",
- "album": { },
- "artist": { },
- "track": { },
- "notes": "string",
- "categories": [
- "string"
]
}Move an item from one index to another
| id required | integer |
| index required | integer Zero-based index of the item to reorder (i.e., the first item is 0) |
| newIndex required | integer New zero-based index for the item (i.e., the second item is 1) |
nullUpdate a document's text or author. Only the document author, users with music_director or reviewer roles, or superusers can edit documents.
Author fields are mutually exclusive: Provide either author (for registered users) or author_name (for external authors), but not both. Setting one will automatically clear the other.
| __key required | array Datastore key path array for the document to update |
| unsafe_text required | string |
| author | array Datastore key path array for a User entity (mutually exclusive with author_name) |
| author_name | string Name string for external authors (mutually exclusive with author) |
{- "__key": [ ],
- "unsafe_text": "string",
- "author": [ ],
- "author_name": "string"
}{- "author": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "author_name": "string",
- "created": "2019-08-24T14:15:22Z",
- "doctype": "review",
- "modified": "2019-08-24T14:15:22Z",
- "revoked": true,
- "subject": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "unsafe_text": "string",
- "required": null
}Soft delete a document by marking it as revoked. Only the document author, users with music_director or reviewer roles, or superusers can delete documents.
| __key required | array Datastore key path array for the document to delete |
{- "__key": [ ]
}Returns the most recently played tracks and breaks
| start | integer The number of milliseconds since January 1, 1970, 00:00:00 UTC (the ECMAScript epoch, equivalent to the UNIX epoch), with leap seconds ignored. Default: 3 hours before the time of the request |
| end | integer The number of milliseconds since January 1, 1970, 00:00:00 UTC (the ECMAScript epoch, equivalent to the UNIX epoch), with leap seconds ignored. Default: The current time |
Returns playlist tracks from albums in rotation
| start | integer The number of milliseconds since January 1, 1970, 00:00:00 UTC (the ECMAScript epoch, equivalent to the UNIX epoch), with leap seconds ignored. Default: 7 days before the time of the request |
| end | integer The number of milliseconds since January 1, 1970, 00:00:00 UTC (the ECMAScript epoch, equivalent to the UNIX epoch), with leap seconds ignored. Default: The current time |
Generate and download a CSV report of all playlist entries for the specified date range. Returns chronological data for both album tracks and freeform tracks with fields: date, time, station, artist, track, album, label, local. Requires music director access.
| start required | string <date> Start date for the report (YYYY-MM-DD) |
| end required | string <date> End date for the report (YYYY-MM-DD) |
date,time,station,artist,track,album,label,local 2024-01-15,14:30:22,"WCXP-LP","Artist Name","Track Title","Album Title","Record Label",1 2024-01-15,14:35:15,"WCXP-LP","National Artist","Another Song","Another Album","Major Label",0
[- {
- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "id": 0,
- "created": "2019-08-24T14:15:22Z",
- "updated": "2019-08-24T14:15:22Z",
- "active": true,
- "title": "string",
- "type": "Live Read Promo"
}
]Only users with the traffic log admin role can add spots.
| id required | integer |
object (Key) | |
| active | boolean |
| title required | string |
| type required | string Enum: "Live Read Promo" "Recorded Promo" "Live Read PSA" "Recorded PSA" "Underwriting Spot" "Pledge Liner" "Station ID" |
{- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "active": true,
- "title": "string",
- "type": "Live Read Promo"
}{- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "id": 0,
- "created": "2019-08-24T14:15:22Z",
- "updated": "2019-08-24T14:15:22Z",
- "active": true,
- "title": "string",
- "type": "Live Read Promo"
}Add a bit of copy that could be read for a given spot. Only users with the traffic log admin role can add copy.
| spot_id required | integer |
object (Key) | |
| body required | string |
| expire_on | string <date-time> |
| start_on | string <date-time> |
{- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "body": "string",
- "expire_on": "2019-08-24T14:15:22Z",
- "start_on": "2019-08-24T14:15:22Z"
}{- "id": 0,
- "author": { },
- "created": "2019-08-24T14:15:22Z",
- "updated": "2019-08-24T14:15:22Z",
- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "body": "string",
- "expire_on": "2019-08-24T14:15:22Z",
- "start_on": "2019-08-24T14:15:22Z"
}Returns a list of traffic log entries for the given weekday and hour. Entries that have already been read have values for "logtime", "readtime", "reader", or "__key". Entries still to be read have a random copy but no values for those properties. They can be posted to the API to be saved to the database.
| dow | integer [ 1 .. 7 ] Default: "current weekday in Chicago" Weekday (1 = Monday, 7 = Sunday) |
| hour | integer [ 0 .. 23 ] Default: "current hour in Chicago" |
[- {
- "created": "2019-08-24T14:15:22Z",
- "log_date": "2019-08-24T14:15:22Z",
- "reader": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "readtime": "2019-08-24T14:15:22Z",
- "spot": {
- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "id": 0,
- "created": "2019-08-24T14:15:22Z",
- "updated": "2019-08-24T14:15:22Z",
- "active": true,
- "title": "string",
- "type": "Live Read Promo"
}, - "spot_copy": {
- "id": 0,
- "author": { },
- "created": "2019-08-24T14:15:22Z",
- "updated": "2019-08-24T14:15:22Z",
- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "body": "string",
- "expire_on": "2019-08-24T14:15:22Z",
- "start_on": "2019-08-24T14:15:22Z"
}, - "scheduled": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "dow": 0,
- "hour": 0,
- "slot": 0
}
]Mark the copy for a timeslot as read
object (Key) | |
| readtime | string <date-time> Nullable |
object (Spot) | |
object (SpotCopy) | |
object (Key) | |
| dow | integer |
| hour | integer |
| slot | integer |
{- "reader": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "readtime": "2019-08-24T14:15:22Z",
- "spot": {
- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "active": true,
- "title": "string",
- "type": "Live Read Promo"
}, - "spot_copy": {
- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "body": "string",
- "expire_on": "2019-08-24T14:15:22Z",
- "start_on": "2019-08-24T14:15:22Z"
}, - "scheduled": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "dow": 0,
- "hour": 0,
- "slot": 0
}{- "created": "2019-08-24T14:15:22Z",
- "log_date": "2019-08-24T14:15:22Z",
- "reader": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "readtime": "2019-08-24T14:15:22Z",
- "spot": {
- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "id": 0,
- "created": "2019-08-24T14:15:22Z",
- "updated": "2019-08-24T14:15:22Z",
- "active": true,
- "title": "string",
- "type": "Live Read Promo"
}, - "spot_copy": {
- "id": 0,
- "author": { },
- "created": "2019-08-24T14:15:22Z",
- "updated": "2019-08-24T14:15:22Z",
- "__key": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "body": "string",
- "expire_on": "2019-08-24T14:15:22Z",
- "start_on": "2019-08-24T14:15:22Z"
}, - "scheduled": {
- "id": 0,
- "name": "string",
- "kind": "string",
- "path": [ ],
- "required": null
}, - "dow": 0,
- "hour": 0,
- "slot": 0
}Generate and download a CSV report of traffic log entries for the specified date range. Returns data in the same format as the legacy Python implementation with fields: readtime, dow, slot_time, underwriter, title, type, excerpt (140 chars max). Requires traffic log admin access.
| start required | string <date> Start date for the report (YYYY-MM-DD) |
| end required | string <date> End date for the report (YYYY-MM-DD) |
| spot_type | string Enum: "Live Read Promo" "Recorded Promo" "Live Read PSA" "Recorded PSA" "Underwriting Spot" "Pledge Liner" "Station ID" "Other" Filter results to only include entries for the specified spot type |
| underwriter | string Filter results to only include entries with underwriter names containing this text (case-insensitive) |
readtime,dow,slot_time,underwriter,title,type,excerpt 2024-01-15 14:30:22,Monday,14:30,ACME Corp,Station ID,Station ID,Welcome to CHIRP Radio...
Request a password reset email. Always returns success to prevent email enumeration. Rate limited to 3 requests per minute per email address.
| email required | string <email> Email address of the user requesting password reset |
{- "email": "user@example.com"
}{- "success": true,
- "message": "If that email address is registered, you will receive password reset instructions."
}Reset a user's password using a valid reset token. Rate limited to 5 requests per minute.
| token required | string Valid password reset token |
| new_password required | string >= 12 characters New password (minimum 12 characters) |
{- "token": "string",
- "new_password": "stringstring"
}{- "success": true,
- "message": "Password reset successful. You can now log in with your new password."
}