/api/v1/stations/{stationSlug}/graphql, with GET or POST. Every query needs a Bearer credential with listener:read. All data is published-only, matching the HTTP API.
Conventions
!means non-null. A field without!can benull; a required nullable field is still always present in the response when you select it.- IDs are strings. Content, broadcast, program, and presenter IDs are UUIDs; the station
idis a station identifier and is separate from theslug. Pagination cursors are opaque strings, even where the type isID. - Timestamps such as
startsAtandobservedAtare ISO 8601 strings in UTC. Dates such asfromDateare localYYYY-MM-DDstrings; interpret them in the station’stimezone. - Selection is required. GraphQL returns only the fields you list. There is no
*; ask for each field you need. contractVersionis exposed onStation,PublishedRecord,Schedule,Programs,CurrentBroadcast,NowPlaying, andTrackHistory. Check that it equals1in your client.ContentSchema,ContentCollection,Weather,Traffic, andRevisionPreviewdo not expose it in GraphQL.- Aliases let you call one field twice with different arguments in a single request.
Queries
station
profile holds the public station details once the station has saved them. resources lists the REST paths for each resource, and a null entry means that resource is disabled or not entitled. Check resources.<name> before querying a resource that can be disabled. resources.realtime tells a client where to follow the station’s public realtime feed.
REST equivalent: GET /api/v1/stations/{stationSlug}.
schemas
Returns the published content type definitions, or one type when
type is set. Use them to interpret the values of a record. Passing version without type returns VALIDATION_ERROR.
REST equivalent: GET …/schemas.
content
Returns published records of one type, newest first by default.
nextCursor is null on the last page. A cursor only works with the same sort and direction that produced it; otherwise the call returns VALIDATION_ERROR.
Returns NOT_FOUND when station.resources.content is null. Filtering on a field that is not a delivery field of the type, or is not a text or choice field, returns VALIDATION_ERROR. An unknown type returns an empty page, or NOT_FOUND when you pass a filter.
REST equivalent: GET …/content?type=<key>, with the same sort, direction, and filter parameters.
contentRecord
NOT_FOUND when the record is unpublished, belongs to another station, or the content resource is disabled. A non-UUID id returns VALIDATION_ERROR.
REST equivalent: GET …/content/{id}.
contentBySlug
The published record a slug names. A slug the record used before also resolves, and returns the record as it is now. Compare
values.slug with the slug you requested, and redirect to the current URL when they differ. Returns NOT_FOUND when no published record of that type has used the slug, or the content resource is disabled.
REST equivalent: GET …/content/{type}/by-slug/{slug}.
schedule
Broadcasts in the window, up to 31 inclusive days and 1000 broadcasts.
truncated is true when more broadcasts exist than were returned; narrow the window and request again.
REST equivalent: GET …/schedule.
programs
schedule. Returns the programs in the window with their presenters and regular slots, and echoes fromDate and throughDate.
REST equivalent: GET …/programs.
currentBroadcast
broadcast is null when nothing is on air. asOf is the instant the answer was computed.
REST equivalent: GET …/broadcast/current.
nowPlaying
track is null with freshness.status "empty" when nothing was reported. elapsedSeconds and endsAt are computed per request and are null when the duration is unknown or the track is not playing.
REST equivalent: GET …/now-playing.
trackHistory
Reported track observations for tracks that were playing, newest first, with cursor pagination. Duplicate titles at different times are separate entries.
REST equivalent:
GET …/track-history.
weather
null when weather redistribution is not enabled for the station; there is no error in that case. See Weather JSON for the shape of snapshots.
REST equivalent: GET …/weather.
traffic
null when traffic redistribution is not enabled. See Traffic JSON for the shape of snapshot.
REST equivalent: GET …/traffic.
Mutations
previewEditorial
POST and both headers:
input.stationId must match the station in the URL, otherwise the call returns NOT_FOUND. A missing X-Preview-Grant returns UNAUTHENTICATED. Call it from your server so the grant and token stay out of the browser.
REST equivalent: POST /api/v1/preview/editorial.
Object types
Station
StationProfile
Each nullable field is
null when the station has not filled it in.
StationAddress
StationSocialLink
StationResources
Each field exceptrealtime is a path (or path prefix) for the matching REST resource. A null value means the resource is disabled, unpublished, or not entitled.
StationRealtime
The station’s public realtime feed. Connect tourl without a credential. Pass the whole object to the SDK’s subscribePublicFeed, or let client.subscribe read it for you. See Public realtime feed and the TypeScript SDK.
StationDelivery
ContentSchema
ContentCollection
PublishedRecord
PublishedRelated
PublicMedia
url is the original file. Use variants for list pages and srcset, and width and height to reserve the aspect ratio.
PublicMediaVariants
Each field is a URL, ornull when the rendition does not exist, for example for audio.
Schedule
Broadcast
BroadcastProgram
ProgramSummary
ProgramSlot
A regular slot, such as “Saturday 10:00 for 120 minutes, every week”.BroadcastPresenter
Programs
CurrentBroadcast
NowPlaying
PlaybackTrack and HistoryEntry
HistoryEntry has the same fields as PlaybackTrack plus an id.
PlaybackFreshness
TrackHistory
Weather
Traffic
RevisionPreview
Enums
ContentSort
SortDirection
ContentFilterOp
Input types
ContentFilter
The REST equivalents are
field:value, field.contains:value, and field.anyOf:a,b.
PreviewInput
JSON scalar shapes
Fields typedJSON return arbitrary JSON, so you cannot select sub-fields. Parse them in your client. All units match Field types and empty states.
Schema field JSON
ContentSchema.fields is an array of field definitions:
kind is one of text, rich_text, number, boolean, datetime, choices, media, content, or group. See Field types and empty states for rendering guidance.
Weather JSON
Weather.snapshots is an array. Each element has this shape:
conditionCode is one of Clear, MostlyClear, PartlyCloudy, Cloudy, Fog, Drizzle, FreezingDrizzle, Rain, HeavyRain, FreezingRain, Snow, HeavySnow, Flurries, Showers, SnowShowers, Thunderstorm, or SevereThunderstorm.
Traffic JSON
Traffic.snapshot has this shape:
An empty
incidents array with freshness.status of fresh means no incidents on the watched roads.
Errors
A failed operation returns HTTP status from the most severe error code, plus a standard GraphQLerrors array. Branch on errors[i].extensions.code.
A switched-off module shows up as a
null resource and NOT_FOUND in GraphQL, not as the REST code MODULE_DISABLED.
Errors raised by GraphQL itself, such as an unknown field or a missing required variable, have no extensions.code. Fix the query rather than retrying.
When a query asks for several fields and one fails, the response can carry both data and errors. Check errors before trusting data.
Requests that fail before the query runs, such as an invalid token or an unknown station, return the REST error body { "error": { "code", "message", "requestId" } }. Every response includes an x-request-id header you can quote to support.
More examples
Several resources in one request
Aliases and fragments
Content types and their fields
Programs in a window
Weather and traffic
null when the station has no entitlement, so handle that before reading the JSON.
Follow pagination
nextCursor is null. Do not reuse a cursor across content types.
Simple read with GET
variables and extensions as JSON-encoded strings, and operationName as plain text. GET runs queries only.