Webhooks and API
Connecting your own systems to FYN Radio. Written for the developer doing it.
Overview
There are two ways in, both under Integrations on the dashboard, on every plan, and most integrations use both.
- The API. Your systems ask, we answer: stations, what is playing, listener figures, invoices and payments, as JSON, and with a key made to, starts, stops and restarts stations. Most keys should only read.
- Webhooks. We tell your systems when something happens: a DJ goes live, a track changes, an invoice is issued. A signed POST to an address of yours, retried if it is down.
The API is at https://app.fynradio.com/api/v1. Everything here is also an
OpenAPI 3.1 document, for Postman,
Insomnia or generating a client. The account holder can try every request on
their own data from API reference on the dashboard, without a key.
Quick start
1. Ask the account holder for an API key, or make one under Integrations, API keys. Leave Can start, stop and restart stations off unless you need it. The key is shown once. Keep it in an environment variable or a secrets store on your server, never in a web page, an app or a repository: anything a browser loads, anyone can read.
2. Ask what is playing:
curl https://app.fynradio.com/api/v1/stations/kayufm/now-playing \
-H "Authorization: Bearer $FYN_API_KEY"
3. Add a webhook pointing at your system, choose its events, and press Send test. Then check the signature on what arrives, below.
Now playing on a website
With no code at all: every station's overview has an embed code for a player that shows what is playing. Use that if it is all you need.
For your own design, ask from your server, not the browser, since the browser would need the key. Cache the answer for ten seconds and let your page ask your server:
// On your server. The station reports every ten seconds, so asking more
// often than that gets the same answer.
let cached = null;
let fetchedAt = 0;
app.get('/now-playing', async (req, res) => {
if (Date.now() - fetchedAt > 10_000) {
const response = await fetch('https://app.fynradio.com/api/v1/stations/kayufm/now-playing', {
headers: { Authorization: `Bearer ${process.env.FYN_API_KEY}` },
});
cached = (await response.json()).data;
fetchedAt = Date.now();
}
res.json({ title: cached.now_playing, listeners: cached.listeners });
});
To update the page the moment a track changes, subscribe to
track.changed and keep the latest title yourself. It comes about once a
song. Read now-playing once when your service starts, so you have a
title before the first webhook.
Going live and off air
Choose Going live and off air on the webhook: live.started
and live.ended when an encoder connects and disconnects, and
default_audio.started and default_audio.ended around the
station having nothing to play. Studios use them for an on-air light, for posting
that a show has started, and for waking someone when default audio comes on, which
means no DJ and an empty playlist.
To know where things stand when your service starts, read state and
live from /stations/{slug}.
Keeping accounting in step
Choose Billing: invoice.issued, invoice.paid,
invoice.voided, payment.succeeded, payment.failed
and balance.low. Key invoices by their number. Money is whole US cents,
and a payment also says what was paid in the currency it was paid in, KES for M-Pesa.
Webhooks can be missed: your system may be down for longer than we retry. Once a day,
read /invoices and /payments and fill in anything you do not
have. Both are newest first, so stop once you reach ones you already know.
Listener figures
/stations/{slug}/stats?days=30 has a row a day: peak and average
listeners, listener minutes, minutes on air and bytes sent, and listening by country
and by player. They are the figures on the station's Reports page. Days are UTC, and
today's row is still filling in, so read yesterday's after midnight UTC.
A day with peak_listeners null is one we were not hearing from the
station's server. Treat it as unknown, not as nobody listening.
Starting and stopping
POST /stations/{slug}/stop, /start and /restart
do what the buttons on the station's page do, with the same rules, for a key made
to control stations. A read-only key gets 403. Studios use them to stop
an AutoDJ station overnight, or to restart from their own control screen.
- Every one disconnects everyone listening. A stopped station stays off air until started.
- It takes seconds, not milliseconds. The answer is
202with the state on its way, such asstopping. Read/stations/{slug}or wait for its webhook to see it done. - Asking twice is safe. Stopping a stopped station answers
200withchangedfalse. - There are limits. Six stops and starts in ten minutes, and
some minutes between restarts. Past them,
429withRetry-After. A suspended, cancelled or closed station cannot be started, and only one on air can be restarted:409. - It is on the record. The station's history and its webhooks say
byapi.
Receiving webhooks
Each is a POST with a JSON body and these headers: FYN-Event, the event;
FYN-Delivery, this delivery's own id; and FYN-Signature,
below. The body:
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "track.changed",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"title": "Sauti Sol - Suzanna",
"previous_title": "Nyashinski - Mungu Pekee",
"live": false,
"default_audio": false,
"listeners": 42
}
}
- Answer first, work after. Reply with any 2xx within 10 seconds, as soon as the signature checks out, and do the work afterwards. Anything else, a redirect included, is a failure.
- Expect repeats. A retry or a resend sends an event again with the
same
id. Keep the ids you have handled and skip ones you have seen. - Expect them out of order. Order by
created_at, not by arrival. - Tests say so.
testis true on anything sent by Send test, which carries sample data. Do not act on one as if it were real. - Ignore what you do not know. Fields and events are added over time. Code that refuses an unknown one will break.
A failed delivery is tried again after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 12 hours. A track change is tried twice more within about a minute, then dropped, since an old title is no use. If every delivery fails for three days we switch the webhook off and email the account holder. Every delivery, with what we sent and what you answered, is on the webhook's page, where any can be sent again.
The address has to be https and reachable from the internet. To develop against your own machine, use a tunnel such as ngrok or Cloudflare Tunnel and point a second webhook at it.
Checking signatures
Anyone can post to your address, so check every request. The header reads
t=1760433124,v1=5257a8…. v1 is the HMAC-SHA256 of
t, a full stop and the raw body, keyed with the webhook's signing secret
from its page. Work it out yourself, compare in constant time, and refuse a
t more than five minutes old. Use the body exactly as it arrived:
parsing and re-encoding the JSON changes it.
PHP
$body = file_get_contents('php://input');
parse_str(str_replace(',', '&', $_SERVER['HTTP_FYN_SIGNATURE'] ?? ''), $sig);
$expected = hash_hmac('sha256', ($sig['t'] ?? '').'.'.$body, getenv('FYN_WEBHOOK_SECRET'));
if (! hash_equals($expected, $sig['v1'] ?? '') || abs(time() - (int) ($sig['t'] ?? 0)) > 300) {
http_response_code(400);
exit;
}
$event = json_decode($body, true);
Node.js, with Express
import crypto from 'node:crypto';
app.post('/fyn-webhook', express.raw({ type: 'application/json' }), (req, res) => {
const sig = Object.fromEntries((req.get('FYN-Signature') ?? '').split(',').map((part) => part.split('=')));
const expected = crypto.createHmac('sha256', process.env.FYN_WEBHOOK_SECRET)
.update(`${sig.t}.${req.body}`)
.digest('hex');
const ok = sig.v1?.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(sig.v1), Buffer.from(expected));
if (!ok || Math.abs(Date.now() / 1000 - Number(sig.t)) > 300) {
return res.sendStatus(400);
}
const event = JSON.parse(req.body);
res.sendStatus(200);
});
Python, with Flask
import hashlib, hmac, os, time
from flask import abort, request
@app.post("/fyn-webhook")
def fyn_webhook():
body = request.get_data()
sig = dict(p.split("=", 1) for p in request.headers.get("FYN-Signature", "").split(",") if "=" in p)
expected = hmac.new(os.environ["FYN_WEBHOOK_SECRET"].encode(),
sig.get("t", "").encode() + b"." + body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig.get("v1", "")) or abs(time.time() - int(sig.get("t", 0))) > 300:
abort(400)
event = request.get_json()
return "", 200
Errors, limits and pages
Errors are JSON with error and message: 401
for a missing or revoked key, 403 for a read-only key asked to control a
station, 404 for something not on the account, 409 for a
station that cannot do what was asked right now, and 429 past 120
requests a minute for a key, 10 a minute for starting, stopping and restarting, or a
station's own limits, with Retry-After saying how many seconds to wait.
Lists take ?page= and ?per_page=, 25 by default and 100 at
most, and say where they are in meta: page,
per_page, total and last_page.
Versions
This is version 1, in the address. Within it we only add: new fields, new events, new endpoints. Nothing is removed or renamed, and no field changes type. Anything that would break an integration comes as a new version, announced ahead.
API reference
All under https://app.fynradio.com/api/v1, all with the key as a bearer token. Reading is GET; starting, stopping and restarting are POST, with no body.
Your account
GET /account
The account the key belongs to, and its balance.
Response
An object under data. It has:
-
namestring - The account holder's name.
-
emailstring - The address we email.
-
balance_centsinteger - Credit, in US cents. Below zero means money is owed.
-
currencystring - Always USD.
-
stationsinteger - How many stations the account has, of any status.
curl https://app.fynradio.com/api/v1/account \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": {
"name": "Amina Otieno",
"email": "[email protected]",
"balance_cents": 2500,
"currency": "USD",
"stations": 2
}
}
List stations
GET /stations
Every station on the account, closed ones included, with what each is doing now.
Response
A list under data. Each has:
-
slugstring - The station's address on our servers, and its id. Never changes.
-
namestring - Its name, as listeners see it.
-
serverstring -
Which server listeners connect to.
icecast,shoutcast -
statusstring -
Its subscription. What it is doing right now is state, in the API.
pending,provisioning,active,suspended,cancelled,terminated -
listen_urlstring - The stream, for players.
-
page_urlstring - Its public page.
-
planplan - The plan it is on.
-
next_billing_atdate-time or null - When it is next charged.
-
cancel_atdate-time or null - When it ends, if it has been cancelled.
-
statestring -
What it is doing right now. silent means an encoder is connected but sending silence, so the AutoDJ is playing. unknown means we have not heard from its server in the last minute, which does not mean it is off air.
on_air,silent,fallback,faulty,starting,restarting,stopping,stopped,pending,provisioning,suspended,cancelled,terminated,unknown -
listenersinteger or null - Listening now.
-
now_playingstring or null - The title on air now.
-
liveboolean or null - Whether an encoder is connected.
-
default_audioboolean - Whether it is playing default audio, with nothing else to play.
curl https://app.fynradio.com/api/v1/stations \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": [
{
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm",
"plan": {
"slug": "standard",
"name": "Standard",
"max_listeners": 250,
"bitrate_kbps": 128
},
"next_billing_at": "2026-11-03T00:00:00Z",
"cancel_at": null,
"state": "on_air",
"listeners": 42,
"now_playing": "Sauti Sol - Suzanna",
"live": false,
"default_audio": false
}
]
}
One station
GET /stations/{slug}
A station, with its plan and what it is doing now.
Parameters
-
slugstring, in the path - The station's slug, as in its address.
Response
An object under data. It has:
-
slugstring - The station's address on our servers, and its id. Never changes.
-
namestring - Its name, as listeners see it.
-
serverstring -
Which server listeners connect to.
icecast,shoutcast -
statusstring -
Its subscription. What it is doing right now is state, in the API.
pending,provisioning,active,suspended,cancelled,terminated -
listen_urlstring - The stream, for players.
-
page_urlstring - Its public page.
-
planplan - The plan it is on.
-
next_billing_atdate-time or null - When it is next charged.
-
cancel_atdate-time or null - When it ends, if it has been cancelled.
-
statestring -
What it is doing right now. silent means an encoder is connected but sending silence, so the AutoDJ is playing. unknown means we have not heard from its server in the last minute, which does not mean it is off air.
on_air,silent,fallback,faulty,starting,restarting,stopping,stopped,pending,provisioning,suspended,cancelled,terminated,unknown -
listenersinteger or null - Listening now.
-
now_playingstring or null - The title on air now.
-
liveboolean or null - Whether an encoder is connected.
-
default_audioboolean - Whether it is playing default audio, with nothing else to play.
curl https://app.fynradio.com/api/v1/stations/kayufm \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm",
"plan": {
"slug": "standard",
"name": "Standard",
"max_listeners": 250,
"bitrate_kbps": 128
},
"next_billing_at": "2026-11-03T00:00:00Z",
"cancel_at": null,
"state": "on_air",
"listeners": 42,
"now_playing": "Sauti Sol - Suzanna",
"live": false,
"default_audio": false
}
}
What is playing
GET /stations/{slug}/now-playing
The title on air, how many are listening, whether a DJ is live, and the last titles played. Read from what the station's server reported in the last ten seconds.
Parameters
-
slugstring, in the path - The station's slug, as in its address.
Response
An object under data. It has:
-
stationstring - The station's slug.
-
statestring - What it is doing, as for a station.
-
listenersinteger or null - Listening now.
-
now_playingstring or null - The title on air.
-
liveboolean or null - Whether an encoder is on air. False while one is connected but sending silence.
-
default_audioboolean - Whether it is playing default audio.
-
recentlist of string - The last titles played, newest first, up to 20.
curl https://app.fynradio.com/api/v1/stations/kayufm/now-playing \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": {
"station": "kayufm",
"state": "on_air",
"listeners": 42,
"now_playing": "Sauti Sol - Suzanna",
"live": false,
"default_audio": false,
"recent": [
"Sauti Sol - Suzanna",
"Nyashinski - Mungu Pekee"
]
}
}
Shows and schedule
GET /stations/{slug}/schedule
The show on now, the next, and the week of shows, as the station's page shows them. Times of day are on the station's clock; the moments are UTC.
Parameters
-
slugstring, in the path - The station's slug, as in its address.
Response
An object under data. It has:
-
stationstring - The station's slug.
-
timezonestring - The station's time zone, which the week's times are in.
-
nowobject or null - The show on now, with starts_at and ends_at, or null when no show is. Its show has name, presenters, description, image and live.
-
nextobject or null - The next show to start, in the same shape.
-
weeklist of object - Every show's times, Monday first: day, start and end as HH:MM, and the show.
curl https://app.fynradio.com/api/v1/stations/kayufm/schedule \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": {
"station": "kayufm",
"timezone": "Africa/Nairobi",
"now": {
"show": {
"name": "Morning Drive",
"presenters": "Wanjiru and Otieno",
"description": "News, traffic and the best of Kenyan music.",
"image": "https://cdn.fynradio.com/logos/2b9c41f0-6d3e-4f7a-9a51-8e0c7d2f1a64.png",
"live": true
},
"starts_at": "2026-10-19T03:00:00Z",
"ends_at": "2026-10-19T07:00:00Z"
},
"next": {
"show": {
"name": "Midday Mix",
"presenters": null,
"description": null,
"image": null,
"live": false
},
"starts_at": "2026-10-19T07:00:00Z",
"ends_at": "2026-10-19T10:00:00Z"
},
"week": [
{
"day": "monday",
"start": "06:00",
"end": "10:00",
"show": {
"name": "Morning Drive",
"presenters": "Wanjiru and Otieno",
"description": "News, traffic and the best of Kenyan music.",
"image": "https://cdn.fynradio.com/logos/2b9c41f0-6d3e-4f7a-9a51-8e0c7d2f1a64.png",
"live": true
}
}
]
}
}
Station history
GET /stations/{slug}/events
What has happened to a station, newest first, in the same names and data as its webhooks.
Parameters
-
slugstring, in the path - The station's slug, as in its address.
-
pageinteger, in the query, default 1 - Which page.
-
per_pageinteger, in the query, default 25 - How many to a page, up to 100.
Response
A list under data, and meta with page, per_page, total and last_page. Each has:
-
typestring - The event, as a webhook would name it.
-
dataobject - Its data, as in the webhook, without the station.
-
created_atdate-time - When it happened.
curl https://app.fynradio.com/api/v1/stations/kayufm/events \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": [
{
"type": "live.ended",
"data": {},
"created_at": "2026-10-14T09:58:21Z"
},
{
"type": "live.started",
"data": {},
"created_at": "2026-10-14T07:00:03Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 2,
"last_page": 1
}
}
Listener figures
GET /stations/{slug}/stats
A row a day, oldest first, and where the listening came from. The same figures as the station's Reports page.
Parameters
-
slugstring, in the path - The station's slug, as in its address.
-
daysinteger, in the query, default 30 - How far back. One of 7, 30, 90.
Response
An object under data. It has:
-
stationstring - The station's slug.
-
dayslist of object - A row a day since the station began, up to the days asked for. A day with peak_listeners null is one we were not hearing from its server, which is not the same as nobody listening. Each row has date, peak_listeners, average_listeners, listener_minutes, minutes_on_air and bytes_sent.
-
audienceobject - Listening by country and by player over the same days: country and player, each a list of label, hours and share, the share a fraction of 1.
curl https://app.fynradio.com/api/v1/stations/kayufm/stats?days=7 \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": {
"station": "kayufm",
"days": [
{
"date": "2026-10-13",
"peak_listeners": 61,
"average_listeners": 23,
"listener_minutes": 33120,
"minutes_on_air": 1440,
"bytes_sent": 3179520000
},
{
"date": "2026-10-14",
"peak_listeners": 48,
"average_listeners": 19,
"listener_minutes": 16410,
"minutes_on_air": 600,
"bytes_sent": 1575360000
}
],
"audience": {
"country": [
{
"label": "KE",
"hours": 702.5,
"share": 0.851
},
{
"label": "UG",
"hours": 63.2,
"share": 0.077
}
],
"player": [
{
"label": "Browser",
"hours": 512,
"share": 0.62
},
{
"label": "VLC",
"hours": 101.8,
"share": 0.123
}
]
}
}
}
Stop a station
POST /stations/{slug}/stop
Takes the station off air. Everyone listening is disconnected, and it stays off until started. A station already stopped answers 200 with changed false.
Needs a key made to control stations. A read-only key gets 403.
- 202
- Done. The station's server acts within seconds.
- 200
- Nothing to do: it already was.
- 409
- Not now: a suspended, cancelled or closed station, or a restart of one that is not on air.
- 429
- Too soon after the last. Retry-After says how many seconds to wait.
Parameters
-
slugstring, in the path - The station's slug, as in its address.
Response
An object under data. It has:
-
stationstring - The station's slug.
-
actionstring -
What was asked.
stop -
changedboolean - False when there was nothing to do: stopping a station already stopped, say.
-
statestring - What it is doing now, as for a station. Usually on its way: the station's server acts within seconds.
curl -X POST https://app.fynradio.com/api/v1/stations/kayufm/stop \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": {
"station": "kayufm",
"action": "stop",
"changed": true,
"state": "stopping"
}
}
Start a station
POST /stations/{slug}/start
Puts a stopped station back on air, within seconds. A station already on answers 200 with changed false.
Needs a key made to control stations. A read-only key gets 403.
- 202
- Done. The station's server acts within seconds.
- 200
- Nothing to do: it already was.
- 409
- Not now: a suspended, cancelled or closed station, or a restart of one that is not on air.
- 429
- Too soon after the last. Retry-After says how many seconds to wait.
Parameters
-
slugstring, in the path - The station's slug, as in its address.
Response
An object under data. It has:
-
stationstring - The station's slug.
-
actionstring -
What was asked.
start -
changedboolean - False when there was nothing to do: stopping a station already stopped, say.
-
statestring - What it is doing now, as for a station. Usually on its way: the station's server acts within seconds.
curl -X POST https://app.fynradio.com/api/v1/stations/kayufm/start \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": {
"station": "kayufm",
"action": "start",
"changed": true,
"state": "starting"
}
}
Restart a station
POST /stations/{slug}/restart
Restarts a station that is on air. Listeners are disconnected and reconnect within seconds. Restarts have to be some minutes apart: one too soon answers 429, with Retry-After.
Needs a key made to control stations. A read-only key gets 403.
- 202
- Done. The station's server acts within seconds.
- 200
- Nothing to do: it already was.
- 409
- Not now: a suspended, cancelled or closed station, or a restart of one that is not on air.
- 429
- Too soon after the last. Retry-After says how many seconds to wait.
Parameters
-
slugstring, in the path - The station's slug, as in its address.
Response
An object under data. It has:
-
stationstring - The station's slug.
-
actionstring -
What was asked.
restart -
changedboolean - False when there was nothing to do: stopping a station already stopped, say.
-
statestring - What it is doing now, as for a station. Usually on its way: the station's server acts within seconds.
curl -X POST https://app.fynradio.com/api/v1/stations/kayufm/restart \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": {
"station": "kayufm",
"action": "restart",
"changed": true,
"state": "restarting"
}
}
List invoices
GET /invoices
Every invoice on the account, newest first.
Parameters
-
pageinteger, in the query, default 1 - Which page.
-
per_pageinteger, in the query, default 25 - How many to a page, up to 100.
Response
A list under data, and meta with page, per_page, total and last_page. Each has:
-
numberstring - The invoice number, its id in the API.
-
kindstring -
A monthly charge, a plan upgrade, or a top-up you started.
charge,upgrade,topup -
descriptionstring - What it is for, as on the PDF.
-
stationstring or null - The station's slug, for a charge or an upgrade.
-
amount_centsinteger - The total, in US cents.
-
due_centsinteger - What is still owed. 0 once paid or voided.
-
currencystring - Always USD.
-
statusstring -
Whether it is settled.
unpaid,paid,void -
period_startdate or null - The first day it pays for.
-
period_enddate or null - The last day it pays for.
-
issued_atdate-time - When it was made.
-
due_atdate-time - When stations stop if it is still unpaid.
-
paid_atdate-time or null - When it was paid in full.
-
voided_atdate-time or null - When it was voided.
-
urlstring - Its page on your dashboard.
curl https://app.fynradio.com/api/v1/invoices \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": [
{
"number": "FYN-2026-0417",
"kind": "charge",
"description": "Kayu FM, Standard, 3 Oct to 2 Nov 2026",
"station": "kayufm",
"amount_cents": 1295,
"due_cents": 0,
"currency": "USD",
"status": "paid",
"period_start": "2026-10-03",
"period_end": "2026-11-02",
"issued_at": "2026-10-03T00:00:04Z",
"due_at": "2026-10-10T00:00:04Z",
"paid_at": "2026-10-04T08:12:40Z",
"voided_at": null,
"url": "https://app.fynradio.com/billing/invoices/417"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"last_page": 1
}
}
One invoice
GET /invoices/{number}
An invoice, by its number.
Parameters
-
numberstring, in the path - The invoice number.
Response
An object under data. It has:
-
numberstring - The invoice number, its id in the API.
-
kindstring -
A monthly charge, a plan upgrade, or a top-up you started.
charge,upgrade,topup -
descriptionstring - What it is for, as on the PDF.
-
stationstring or null - The station's slug, for a charge or an upgrade.
-
amount_centsinteger - The total, in US cents.
-
due_centsinteger - What is still owed. 0 once paid or voided.
-
currencystring - Always USD.
-
statusstring -
Whether it is settled.
unpaid,paid,void -
period_startdate or null - The first day it pays for.
-
period_enddate or null - The last day it pays for.
-
issued_atdate-time - When it was made.
-
due_atdate-time - When stations stop if it is still unpaid.
-
paid_atdate-time or null - When it was paid in full.
-
voided_atdate-time or null - When it was voided.
-
urlstring - Its page on your dashboard.
curl https://app.fynradio.com/api/v1/invoices/FYN-2026-0417 \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": {
"number": "FYN-2026-0417",
"kind": "charge",
"description": "Kayu FM, Standard, 3 Oct to 2 Nov 2026",
"station": "kayufm",
"amount_cents": 1295,
"due_cents": 0,
"currency": "USD",
"status": "paid",
"period_start": "2026-10-03",
"period_end": "2026-11-02",
"issued_at": "2026-10-03T00:00:04Z",
"due_at": "2026-10-10T00:00:04Z",
"paid_at": "2026-10-04T08:12:40Z",
"voided_at": null,
"url": "https://app.fynradio.com/billing/invoices/417"
}
}
List payments
GET /payments
Every payment, newest first, including ones that failed.
Parameters
-
pageinteger, in the query, default 1 - Which page.
-
per_pageinteger, in the query, default 25 - How many to a page, up to 100.
Response
A list under data, and meta with page, per_page, total and last_page. Each has:
-
idinteger - The payment's id.
-
invoicestring or null - The number of the invoice it paid.
-
methodstring -
How it was paid.
paypal,mpesa,cash -
referencestring - The receipt or reference from PayPal or M-Pesa.
-
amount_centsinteger - What it added to your balance, in US cents.
-
currencystring - Always USD.
-
paid_amountstring - What was actually paid, in the currency paid in.
-
paid_currencystring - The currency it was paid in, such as KES.
-
statusstring -
Where it stands.
pending,completed,failed,reversed -
created_atdate-time - When it was started.
-
completed_atdate-time or null - When the money arrived.
curl https://app.fynradio.com/api/v1/payments \
-H "Authorization: Bearer $FYN_API_KEY"
{
"data": [
{
"id": 905,
"invoice": "FYN-2026-0418",
"method": "mpesa",
"reference": "SJK4H7Q2XD",
"amount_cents": 2000,
"currency": "USD",
"paid_amount": "2600.00",
"paid_currency": "KES",
"status": "completed",
"created_at": "2026-10-04T08:11:02Z",
"completed_at": "2026-10-04T08:12:40Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"last_page": 1
}
}
Webhook events
Station, on air and music events carry the station under data.station,
and a webhook's station filter applies to them. Billing and support events are for the whole account.
Station
station.ready
The station is set up and on air for the first time.
With the station under data.station.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.ready",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
}
}
}
station.waiting
A station was ordered and is waiting to be set up.
With the station under data.station.
In data
-
reasonstring -
For payment to arrive, for room on a server, or for us to review the account.
payment,capacity,review
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.waiting",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"reason": "payment"
}
}
station.stopped
The station was stopped. It stays off air until started.
With the station under data.station.
In data
-
bystring -
Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.
client,api,support,billing
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.stopped",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"by": "client"
}
}
station.started
The station was started again.
With the station under data.station.
In data
-
bystring -
Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.
client,api,support,billing
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.started",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"by": "client"
}
}
station.restarted
The station was restarted. Listeners reconnect within seconds.
With the station under data.station.
In data
-
bystring -
Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.
client,api,support,billing
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.restarted",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"by": "support"
}
}
station.suspended
The station stopped because the balance stayed below zero past the grace period.
With the station under data.station.
In data
-
reasonstring -
Why.
balance
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.suspended",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"reason": "balance"
}
}
station.resumed
A suspended station is back on air because the balance cleared.
With the station under data.station.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.resumed",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
}
}
}
station.plan_changed
The station moved to another plan.
With the station under data.station.
In data
-
from_planstring - The slug of the plan it was on.
-
to_planstring - The slug of the plan it is on now.
-
charged_centsinteger - What the move cost now, in US cents. 0 for a move at renewal.
-
bystring -
Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.
client,api,support,billing
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.plan_changed",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"from_plan": "basic",
"to_plan": "standard",
"charged_cents": 412,
"by": "client"
}
}
station.plan_change_scheduled
A move to a smaller plan was set for the next renewal, or such a move was taken back.
With the station under data.station.
In data
-
withdrawnboolean - True when a scheduled move was taken back. The fields below are then absent.
-
to_planstring - The slug of the plan it will move to.
-
takes_effectdate-time - When it moves.
-
bystring -
Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.
client,api,support,billing
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.plan_change_scheduled",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"withdrawn": false,
"to_plan": "basic",
"takes_effect": "2026-11-03T00:00:00Z",
"by": "client"
}
}
station.cancellation_scheduled
The station was cancelled. It stays on air until what is paid for runs out.
With the station under data.station.
In data
-
ends_atdate-time - When it goes off air.
-
bystring -
Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.
client,api,support,billing
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.cancellation_scheduled",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"ends_at": "2026-11-03T00:00:00Z",
"by": "client"
}
}
station.cancellation_withdrawn
A cancellation was taken back before the station ended.
With the station under data.station.
In data
-
bystring -
Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.
client,api,support,billing
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.cancellation_withdrawn",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"by": "client"
}
}
station.cancelled
A cancelled station reached its end and went off air. It can be resubscribed until it is closed.
With the station under data.station.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.cancelled",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
}
}
}
station.resubscribed
A cancelled station was subscribed again.
With the station under data.station.
In data
-
bystring -
Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.
client,api,support,billing
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.resubscribed",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"by": "client"
}
}
station.terminated
The station was closed for good. Its music is deleted and its address freed.
With the station under data.station.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "station.terminated",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
}
}
}
On air
live.started
An encoder connected, so a DJ is on air.
With the station under data.station.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "live.started",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
}
}
}
live.ended
The encoder disconnected. The AutoDJ takes over.
With the station under data.station.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "live.ended",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
}
}
}
default_audio.started
Nothing else to play, so the station is on default audio: no DJ, and nothing in its playlist.
With the station under data.station.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "default_audio.started",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
}
}
}
default_audio.ended
The station is playing your audio again.
With the station under data.station.
In data
-
liveboolean - Whether that is because a DJ connected.
-
titlestring or null - What it is playing now.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "default_audio.ended",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"live": true,
"title": "Morning Drive with Wanjiru"
}
}
track.changed
A new title went on air, from a DJ or the AutoDJ. About one a song, so expect many.
With the station under data.station.
In data
-
titlestring - What is on air now.
-
previous_titlestring or null - What was on before it.
-
liveboolean - Whether it comes from a DJ.
-
default_audioboolean - Whether it is default audio.
-
listenersinteger - Listening at the change.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "track.changed",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"title": "Sauti Sol - Suzanna",
"previous_title": "Nyashinski - Mungu Pekee",
"live": false,
"default_audio": false,
"listeners": 42
}
}
show.started
A show on the station's week began, by its schedule. Whether its DJ is on air is live.started's to say.
With the station under data.station.
In data
-
showobject - The show: name, presenters, description, image (a URL, or null) and live, which is whether a DJ is expected rather than the AutoDJ.
-
starts_atdate-time - When this showing began.
-
ends_atdate-time - When it ends.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "show.started",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"show": {
"name": "Morning Drive",
"presenters": "Wanjiru and Otieno",
"description": "News, traffic and the best of Kenyan music.",
"image": "https://cdn.fynradio.com/logos/2b9c41f0-6d3e-4f7a-9a51-8e0c7d2f1a64.png",
"live": true
},
"starts_at": "2026-10-19T03:00:00Z",
"ends_at": "2026-10-19T07:00:00Z"
}
}
Music
media.ready
An uploaded track finished processing and can be played.
With the station under data.station.
In data
-
mediamedia - The track.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "media.ready",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"media": {
"id": 3120,
"filename": "suzanna.mp3",
"title": "Suzanna",
"artist": "Sauti Sol",
"album": null,
"duration_seconds": 214,
"size_bytes": 5146624,
"status": "ready"
}
}
}
media.failed
An uploaded track could not be used.
With the station under data.station.
In data
-
mediamedia - The track.
-
reasonstring - Why, in words for a person.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "media.failed",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"media": {
"id": 3120,
"filename": "suzanna.mp3",
"title": "Suzanna",
"artist": "Sauti Sol",
"album": null,
"duration_seconds": 214,
"size_bytes": 5146624,
"status": "failed"
},
"reason": "That is not an MP3 we can read."
}
}
media.deleted
A track was deleted from the library.
With the station under data.station.
In data
-
mediamedia - The track, as it was.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "media.deleted",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"station": {
"slug": "kayufm",
"name": "Kayu FM",
"server": "icecast",
"status": "active",
"listen_url": "https://kayufm.stream.fynradio.com/",
"page_url": "https://fynradio.com/kayufm"
},
"media": {
"id": 3120,
"filename": "suzanna.mp3",
"title": "Suzanna",
"artist": "Sauti Sol",
"album": null,
"duration_seconds": 214,
"size_bytes": 5146624,
"status": "ready"
}
}
}
Billing
invoice.issued
A monthly charge or a plan upgrade was invoiced.
In data
-
invoiceinvoice - The invoice.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "invoice.issued",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"invoice": {
"number": "FYN-2026-0417",
"kind": "charge",
"description": "Kayu FM, Standard, 3 Oct to 2 Nov 2026",
"station": "kayufm",
"amount_cents": 1295,
"due_cents": 1295,
"currency": "USD",
"status": "unpaid",
"period_start": "2026-10-03",
"period_end": "2026-11-02",
"issued_at": "2026-10-03T00:00:04Z",
"due_at": "2026-10-10T00:00:04Z",
"paid_at": null,
"voided_at": null,
"url": "https://app.fynradio.com/billing/invoices/417"
}
}
}
invoice.paid
An invoice was paid in full, by a payment or from credit.
In data
-
invoiceinvoice - The invoice.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "invoice.paid",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"invoice": {
"number": "FYN-2026-0417",
"kind": "charge",
"description": "Kayu FM, Standard, 3 Oct to 2 Nov 2026",
"station": "kayufm",
"amount_cents": 1295,
"due_cents": 0,
"currency": "USD",
"status": "paid",
"period_start": "2026-10-03",
"period_end": "2026-11-02",
"issued_at": "2026-10-03T00:00:04Z",
"due_at": "2026-10-10T00:00:04Z",
"paid_at": "2026-10-04T08:12:40Z",
"voided_at": null,
"url": "https://app.fynradio.com/billing/invoices/417"
}
}
}
invoice.voided
An invoice was cancelled. Nothing is owed on it.
In data
-
invoiceinvoice - The invoice.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "invoice.voided",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"invoice": {
"number": "FYN-2026-0417",
"kind": "charge",
"description": "Kayu FM, Standard, 3 Oct to 2 Nov 2026",
"station": "kayufm",
"amount_cents": 1295,
"due_cents": 0,
"currency": "USD",
"status": "void",
"period_start": "2026-10-03",
"period_end": "2026-11-02",
"issued_at": "2026-10-03T00:00:04Z",
"due_at": "2026-10-10T00:00:04Z",
"paid_at": null,
"voided_at": "2026-10-05T10:00:00Z",
"url": "https://app.fynradio.com/billing/invoices/417"
}
}
}
payment.succeeded
Money arrived and was added to the balance.
In data
-
paymentpayment - The payment.
-
balance_centsinteger - The balance after it, in US cents.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "payment.succeeded",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"payment": {
"id": 905,
"invoice": "FYN-2026-0418",
"method": "mpesa",
"reference": "SJK4H7Q2XD",
"amount_cents": 2000,
"currency": "USD",
"paid_amount": "2600.00",
"paid_currency": "KES",
"status": "completed",
"created_at": "2026-10-04T08:11:02Z",
"completed_at": "2026-10-04T08:12:40Z"
},
"balance_cents": 2500
}
}
payment.failed
A payment did not go through. Nothing was added.
In data
-
paymentpayment - The payment.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "payment.failed",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"payment": {
"id": 905,
"invoice": "FYN-2026-0418",
"method": "mpesa",
"reference": "SJK4H7Q2XD",
"amount_cents": 2000,
"currency": "USD",
"paid_amount": "2600.00",
"paid_currency": "KES",
"status": "failed",
"created_at": "2026-10-04T08:11:02Z",
"completed_at": null
}
}
}
balance.low
The balance is below zero, and the stations stop on a date unless it is topped up. Sent on the days we email about it.
In data
-
balance_centsinteger - The balance, in US cents.
-
currencystring - Always USD.
-
stations_stop_atdate-time - When the stations stop.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "balance.low",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"balance_cents": -1295,
"currency": "USD",
"stations_stop_at": "2026-10-10T00:00:04Z"
}
}
Support
ticket.replied
We answered one of your support tickets.
In data
-
ticketticket - The ticket.
-
messagestring - Our reply, as text.
-
filesinteger - How many files came with it. They are on the ticket's page.
{
"id": "6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14",
"type": "ticket.replied",
"test": false,
"created_at": "2026-10-14T09:12:04Z",
"data": {
"ticket": {
"id": 42,
"reference": "#42",
"subject": "Encoder will not connect",
"status": "answered",
"station": "kayufm",
"url": "https://app.fynradio.com/support/42"
},
"message": "The port is 10006, not 8000. Try that and tell us how it goes.",
"files": 0
}
}
Objects
The same in the API and in webhooks.
Station
-
slugstring - The station's address on our servers, and its id. Never changes.
-
namestring - Its name, as listeners see it.
-
serverstring -
Which server listeners connect to.
icecast,shoutcast -
statusstring -
Its subscription. What it is doing right now is state, in the API.
pending,provisioning,active,suspended,cancelled,terminated -
listen_urlstring - The stream, for players.
-
page_urlstring - Its public page.
Plan
-
slugstring - The plan's id.
-
namestring - Its name, as on the pricing page.
-
max_listenersinteger - How many can listen at once.
-
bitrate_kbpsinteger - The stream's bitrate.
Invoice
-
numberstring - The invoice number, its id in the API.
-
kindstring -
A monthly charge, a plan upgrade, or a top-up you started.
charge,upgrade,topup -
descriptionstring - What it is for, as on the PDF.
-
stationstring or null - The station's slug, for a charge or an upgrade.
-
amount_centsinteger - The total, in US cents.
-
due_centsinteger - What is still owed. 0 once paid or voided.
-
currencystring - Always USD.
-
statusstring -
Whether it is settled.
unpaid,paid,void -
period_startdate or null - The first day it pays for.
-
period_enddate or null - The last day it pays for.
-
issued_atdate-time - When it was made.
-
due_atdate-time - When stations stop if it is still unpaid.
-
paid_atdate-time or null - When it was paid in full.
-
voided_atdate-time or null - When it was voided.
-
urlstring - Its page on your dashboard.
Payment
-
idinteger - The payment's id.
-
invoicestring or null - The number of the invoice it paid.
-
methodstring -
How it was paid.
paypal,mpesa,cash -
referencestring - The receipt or reference from PayPal or M-Pesa.
-
amount_centsinteger - What it added to your balance, in US cents.
-
currencystring - Always USD.
-
paid_amountstring - What was actually paid, in the currency paid in.
-
paid_currencystring - The currency it was paid in, such as KES.
-
statusstring -
Where it stands.
pending,completed,failed,reversed -
created_atdate-time - When it was started.
-
completed_atdate-time or null - When the money arrived.
Track
-
idinteger - The track's id.
-
filenamestring - The name of the file you uploaded.
-
titlestring or null - From its tags.
-
artiststring or null - From its tags.
-
albumstring or null - From its tags.
-
duration_secondsinteger - Its length.
-
size_bytesinteger - Its size.
-
statusstring -
Whether it can be played yet.
uploading,processing,ready,failed
Ticket
-
idinteger - The ticket's id.
-
referencestring - As shown on your dashboard, such as #42.
-
subjectstring - What you called it.
-
statusstring -
Whose turn it is.
open,answered,closed -
stationstring or null - The station's slug, if it is about one.
-
urlstring - Its page on your dashboard.