{"openapi":"3.1.0","info":{"title":"FYN Radio","version":"1","description":"Read your FYN Radio account and start, stop and restart its stations, and the webhooks we send about it. Fields and events may be added within version 1; none are removed or renamed. See https://fynradio.com/help/integrations."},"servers":[{"url":"https://app.fynradio.com/api/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Integrations on your dashboard. Keep it on your server."}},"schemas":{"Meta":{"type":"object","properties":{"page":{"description":"This page.","type":"integer"},"per_page":{"description":"How many to a page.","type":"integer"},"total":{"description":"How many there are.","type":"integer"},"last_page":{"description":"The last page.","type":"integer"}},"required":["page","per_page","total","last_page"]},"Error":{"type":"object","properties":{"error":{"description":"What went wrong, for code.","type":"string","enum":["unauthenticated","forbidden","not_found","conflict","rate_limited"]},"message":{"description":"What went wrong, for a person.","type":"string"}},"required":["error","message"]},"Station":{"title":"Station","type":"object","properties":{"slug":{"description":"The station's address on our servers, and its id. Never changes.","type":"string"},"name":{"description":"Its name, as listeners see it.","type":"string"},"server":{"description":"Which server listeners connect to.","type":"string","enum":["icecast","shoutcast"]},"status":{"description":"Its subscription. What it is doing right now is state, in the API.","type":"string","enum":["pending","provisioning","active","suspended","cancelled","terminated"]},"listen_url":{"description":"The stream, for players.","type":"string"},"page_url":{"description":"Its public page.","type":"string"}},"required":["slug","name","server","status","listen_url","page_url"]},"StationDetail":{"title":"Station, from the API","type":"object","properties":{"slug":{"description":"The station's address on our servers, and its id. Never changes.","type":"string"},"name":{"description":"Its name, as listeners see it.","type":"string"},"server":{"description":"Which server listeners connect to.","type":"string","enum":["icecast","shoutcast"]},"status":{"description":"Its subscription. What it is doing right now is state, in the API.","type":"string","enum":["pending","provisioning","active","suspended","cancelled","terminated"]},"listen_url":{"description":"The stream, for players.","type":"string"},"page_url":{"description":"Its public page.","type":"string"},"plan":{"description":"The plan it is on.","$ref":"#/components/schemas/Plan"},"next_billing_at":{"description":"When it is next charged.","type":["string","null"],"format":"date-time"},"cancel_at":{"description":"When it ends, if it has been cancelled.","type":["string","null"],"format":"date-time"},"state":{"description":"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.","type":"string","enum":["on_air","silent","fallback","faulty","starting","restarting","stopping","stopped","pending","provisioning","suspended","cancelled","terminated","unknown"]},"listeners":{"description":"Listening now.","type":["integer","null"]},"now_playing":{"description":"The title on air now.","type":["string","null"]},"live":{"description":"Whether an encoder is connected.","type":["boolean","null"]},"default_audio":{"description":"Whether it is playing default audio, with nothing else to play.","type":"boolean"}},"required":["slug","name","server","status","listen_url","page_url","plan","next_billing_at","cancel_at","state","listeners","now_playing","live","default_audio"]},"Plan":{"title":"Plan","type":"object","properties":{"slug":{"description":"The plan's id.","type":"string"},"name":{"description":"Its name, as on the pricing page.","type":"string"},"max_listeners":{"description":"How many can listen at once.","type":"integer"},"bitrate_kbps":{"description":"The stream's bitrate.","type":"integer"}},"required":["slug","name","max_listeners","bitrate_kbps"]},"Invoice":{"title":"Invoice","type":"object","properties":{"number":{"description":"The invoice number, its id in the API.","type":"string"},"kind":{"description":"A monthly charge, a plan upgrade, or a top-up you started.","type":"string","enum":["charge","upgrade","topup"]},"description":{"description":"What it is for, as on the PDF.","type":"string"},"station":{"description":"The station's slug, for a charge or an upgrade.","type":["string","null"]},"amount_cents":{"description":"The total, in US cents.","type":"integer"},"due_cents":{"description":"What is still owed. 0 once paid or voided.","type":"integer"},"currency":{"description":"Always USD.","type":"string"},"status":{"description":"Whether it is settled.","type":"string","enum":["unpaid","paid","void"]},"period_start":{"description":"The first day it pays for.","type":["string","null"],"format":"date"},"period_end":{"description":"The last day it pays for.","type":["string","null"],"format":"date"},"issued_at":{"description":"When it was made.","type":"string","format":"date-time"},"due_at":{"description":"When stations stop if it is still unpaid.","type":"string","format":"date-time"},"paid_at":{"description":"When it was paid in full.","type":["string","null"],"format":"date-time"},"voided_at":{"description":"When it was voided.","type":["string","null"],"format":"date-time"},"url":{"description":"Its page on your dashboard.","type":"string"}},"required":["number","kind","description","station","amount_cents","due_cents","currency","status","period_start","period_end","issued_at","due_at","paid_at","voided_at","url"]},"Payment":{"title":"Payment","type":"object","properties":{"id":{"description":"The payment's id.","type":"integer"},"invoice":{"description":"The number of the invoice it paid.","type":["string","null"]},"method":{"description":"How it was paid.","type":"string","enum":["paypal","mpesa","cash"]},"reference":{"description":"The receipt or reference from PayPal or M-Pesa.","type":"string"},"amount_cents":{"description":"What it added to your balance, in US cents.","type":"integer"},"currency":{"description":"Always USD.","type":"string"},"paid_amount":{"description":"What was actually paid, in the currency paid in.","type":"string"},"paid_currency":{"description":"The currency it was paid in, such as KES.","type":"string"},"status":{"description":"Where it stands.","type":"string","enum":["pending","completed","failed","reversed"]},"created_at":{"description":"When it was started.","type":"string","format":"date-time"},"completed_at":{"description":"When the money arrived.","type":["string","null"],"format":"date-time"}},"required":["id","invoice","method","reference","amount_cents","currency","paid_amount","paid_currency","status","created_at","completed_at"]},"Track":{"title":"Track","type":"object","properties":{"id":{"description":"The track's id.","type":"integer"},"filename":{"description":"The name of the file you uploaded.","type":"string"},"title":{"description":"From its tags.","type":["string","null"]},"artist":{"description":"From its tags.","type":["string","null"]},"album":{"description":"From its tags.","type":["string","null"]},"duration_seconds":{"description":"Its length.","type":"integer"},"size_bytes":{"description":"Its size.","type":"integer"},"status":{"description":"Whether it can be played yet.","type":"string","enum":["uploading","processing","ready","failed"]}},"required":["id","filename","title","artist","album","duration_seconds","size_bytes","status"]},"Ticket":{"title":"Ticket","type":"object","properties":{"id":{"description":"The ticket's id.","type":"integer"},"reference":{"description":"As shown on your dashboard, such as #42.","type":"string"},"subject":{"description":"What you called it.","type":"string"},"status":{"description":"Whose turn it is.","type":"string","enum":["open","answered","closed"]},"station":{"description":"The station's slug, if it is about one.","type":["string","null"]},"url":{"description":"Its page on your dashboard.","type":"string"}},"required":["id","reference","subject","status","station","url"]}}},"paths":{"/account":{"get":{"operationId":"account","summary":"Your account","description":"The account the key belongs to, and its balance.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"name":{"description":"The account holder's name.","type":"string"},"email":{"description":"The address we email.","type":"string"},"balance_cents":{"description":"Credit, in US cents. Below zero means money is owed.","type":"integer"},"currency":{"description":"Always USD.","type":"string"},"stations":{"description":"How many stations the account has, of any status.","type":"integer"}},"required":["name","email","balance_cents","currency","stations"]}},"required":["data"]},"example":{"data":{"name":"Amina Otieno","email":"amina@kayufm.co.ke","balance_cents":2500,"currency":"USD","stations":2}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Over 120 requests a minute. Retry-After says when to come back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stations":{"get":{"operationId":"stations","summary":"List stations","description":"Every station on the account, closed ones included, with what each is doing now.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StationDetail"}}},"required":["data"]},"example":{"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}]}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Over 120 requests a minute. Retry-After says when to come back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stations/{slug}":{"get":{"operationId":"station","summary":"One station","description":"A station, with its plan and what it is doing now.","parameters":[{"name":"slug","in":"path","required":true,"description":"The station's slug, as in its address.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/StationDetail"}},"required":["data"]},"example":{"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}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Over 120 requests a minute. Retry-After says when to come back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stations/{slug}/now-playing":{"get":{"operationId":"nowPlaying","summary":"What is playing","description":"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":[{"name":"slug","in":"path","required":true,"description":"The station's slug, as in its address.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"station":{"description":"The station's slug.","type":"string"},"state":{"description":"What it is doing, as for a station.","type":"string"},"listeners":{"description":"Listening now.","type":["integer","null"]},"now_playing":{"description":"The title on air.","type":["string","null"]},"live":{"description":"Whether an encoder is on air. False while one is connected but sending silence.","type":["boolean","null"]},"default_audio":{"description":"Whether it is playing default audio.","type":"boolean"},"recent":{"description":"The last titles played, newest first, up to 20.","type":"array","items":{"type":"string"}}},"required":["station","state","listeners","now_playing","live","default_audio","recent"]}},"required":["data"]},"example":{"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"]}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Over 120 requests a minute. Retry-After says when to come back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stations/{slug}/schedule":{"get":{"operationId":"schedule","summary":"Shows and schedule","description":"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":[{"name":"slug","in":"path","required":true,"description":"The station's slug, as in its address.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"station":{"description":"The station's slug.","type":"string"},"timezone":{"description":"The station's time zone, which the week's times are in.","type":"string"},"now":{"description":"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.","type":["object","null"]},"next":{"description":"The next show to start, in the same shape.","type":["object","null"]},"week":{"description":"Every show's times, Monday first: day, start and end as HH:MM, and the show.","type":"array","items":{"type":"object"}}},"required":["station","timezone","now","next","week"]}},"required":["data"]},"example":{"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}}]}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Over 120 requests a minute. Retry-After says when to come back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stations/{slug}/events":{"get":{"operationId":"events","summary":"Station history","description":"What has happened to a station, newest first, in the same names and data as its webhooks.","parameters":[{"name":"slug","in":"path","required":true,"description":"The station's slug, as in its address.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Which page.","schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","required":false,"description":"How many to a page, up to 100.","schema":{"type":"integer","default":25}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"type":{"description":"The event, as a webhook would name it.","type":"string"},"data":{"description":"Its data, as in the webhook, without the station.","type":"object"},"created_at":{"description":"When it happened.","type":"string","format":"date-time"}},"required":["type","data","created_at"]}},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"example":{"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}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Over 120 requests a minute. Retry-After says when to come back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stations/{slug}/stats":{"get":{"operationId":"stats","summary":"Listener figures","description":"A row a day, oldest first, and where the listening came from. The same figures as the station's Reports page.","parameters":[{"name":"slug","in":"path","required":true,"description":"The station's slug, as in its address.","schema":{"type":"string"}},{"name":"days","in":"query","required":false,"description":"How far back.","schema":{"type":"integer","default":30,"enum":[7,30,90]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"station":{"description":"The station's slug.","type":"string"},"days":{"description":"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.","type":"array","items":{"type":"object"}},"audience":{"description":"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.","type":"object"}},"required":["station","days","audience"]}},"required":["data"]},"example":{"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}]}}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Over 120 requests a minute. Retry-After says when to come back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stations/{slug}/stop":{"post":{"operationId":"stop","summary":"Stop a station","description":"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.","parameters":[{"name":"slug","in":"path","required":true,"description":"The station's slug, as in its address.","schema":{"type":"string"}}],"responses":{"202":{"description":"Done. The station's server acts within seconds.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"station":{"description":"The station's slug.","type":"string"},"action":{"description":"What was asked.","type":"string","enum":["stop"]},"changed":{"description":"False when there was nothing to do: stopping a station already stopped, say.","type":"boolean"},"state":{"description":"What it is doing now, as for a station. Usually on its way: the station's server acts within seconds.","type":"string"}},"required":["station","action","changed","state"]}},"required":["data"]},"example":{"data":{"station":"kayufm","action":"stop","changed":true,"state":"stopping"}}}}},"200":{"description":"Nothing to do: it already was.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"station":{"description":"The station's slug.","type":"string"},"action":{"description":"What was asked.","type":"string","enum":["stop"]},"changed":{"description":"False when there was nothing to do: stopping a station already stopped, say.","type":"boolean"},"state":{"description":"What it is doing now, as for a station. Usually on its way: the station's server acts within seconds.","type":"string"}},"required":["station","action","changed","state"]}},"required":["data"]},"example":{"data":{"station":"kayufm","action":"stop","changed":true,"state":"stopping"}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key only reads. Make one that can control stations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Not now: a suspended, cancelled or closed station, or a restart of one that is not on air.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too soon after the last. Retry-After says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stations/{slug}/start":{"post":{"operationId":"start","summary":"Start a station","description":"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.","parameters":[{"name":"slug","in":"path","required":true,"description":"The station's slug, as in its address.","schema":{"type":"string"}}],"responses":{"202":{"description":"Done. The station's server acts within seconds.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"station":{"description":"The station's slug.","type":"string"},"action":{"description":"What was asked.","type":"string","enum":["start"]},"changed":{"description":"False when there was nothing to do: stopping a station already stopped, say.","type":"boolean"},"state":{"description":"What it is doing now, as for a station. Usually on its way: the station's server acts within seconds.","type":"string"}},"required":["station","action","changed","state"]}},"required":["data"]},"example":{"data":{"station":"kayufm","action":"start","changed":true,"state":"starting"}}}}},"200":{"description":"Nothing to do: it already was.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"station":{"description":"The station's slug.","type":"string"},"action":{"description":"What was asked.","type":"string","enum":["start"]},"changed":{"description":"False when there was nothing to do: stopping a station already stopped, say.","type":"boolean"},"state":{"description":"What it is doing now, as for a station. Usually on its way: the station's server acts within seconds.","type":"string"}},"required":["station","action","changed","state"]}},"required":["data"]},"example":{"data":{"station":"kayufm","action":"start","changed":true,"state":"starting"}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key only reads. Make one that can control stations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Not now: a suspended, cancelled or closed station, or a restart of one that is not on air.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too soon after the last. Retry-After says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stations/{slug}/restart":{"post":{"operationId":"restart","summary":"Restart a station","description":"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.","parameters":[{"name":"slug","in":"path","required":true,"description":"The station's slug, as in its address.","schema":{"type":"string"}}],"responses":{"202":{"description":"Done. The station's server acts within seconds.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"station":{"description":"The station's slug.","type":"string"},"action":{"description":"What was asked.","type":"string","enum":["restart"]},"changed":{"description":"False when there was nothing to do: stopping a station already stopped, say.","type":"boolean"},"state":{"description":"What it is doing now, as for a station. Usually on its way: the station's server acts within seconds.","type":"string"}},"required":["station","action","changed","state"]}},"required":["data"]},"example":{"data":{"station":"kayufm","action":"restart","changed":true,"state":"restarting"}}}}},"200":{"description":"Nothing to do: it already was.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"station":{"description":"The station's slug.","type":"string"},"action":{"description":"What was asked.","type":"string","enum":["restart"]},"changed":{"description":"False when there was nothing to do: stopping a station already stopped, say.","type":"boolean"},"state":{"description":"What it is doing now, as for a station. Usually on its way: the station's server acts within seconds.","type":"string"}},"required":["station","action","changed","state"]}},"required":["data"]},"example":{"data":{"station":"kayufm","action":"restart","changed":true,"state":"restarting"}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key only reads. Make one that can control stations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Not now: a suspended, cancelled or closed station, or a restart of one that is not on air.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too soon after the last. Retry-After says when.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/invoices":{"get":{"operationId":"invoices","summary":"List invoices","description":"Every invoice on the account, newest first.","parameters":[{"name":"page","in":"query","required":false,"description":"Which page.","schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","required":false,"description":"How many to a page, up to 100.","schema":{"type":"integer","default":25}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"}},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"example":{"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}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Over 120 requests a minute. Retry-After says when to come back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/invoices/{number}":{"get":{"operationId":"invoice","summary":"One invoice","description":"An invoice, by its number.","parameters":[{"name":"number","in":"path","required":true,"description":"The invoice number.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Invoice"}},"required":["data"]},"example":{"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"}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Over 120 requests a minute. Retry-After says when to come back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/payments":{"get":{"operationId":"payments","summary":"List payments","description":"Every payment, newest first, including ones that failed.","parameters":[{"name":"page","in":"query","required":false,"description":"Which page.","schema":{"type":"integer","default":1}},{"name":"per_page","in":"query","required":false,"description":"How many to a page, up to 100.","schema":{"type":"integer","default":25}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Payment"}},"meta":{"$ref":"#/components/schemas/Meta"}},"required":["data","meta"]},"example":{"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}}}}},"401":{"description":"No key, or a revoked one.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Over 120 requests a minute. Retry-After says when to come back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"station.ready":{"post":{"operationId":"stationReady","summary":"Set up and on air","description":"The station is set up and on air for the first time. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.ready"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"}},"required":["station"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.waiting":{"post":{"operationId":"stationWaiting","summary":"Waiting to be set up","description":"A station was ordered and is waiting to be set up. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.waiting"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"reason":{"description":"For payment to arrive, for room on a server, or for us to review the account.","type":"string","enum":["payment","capacity","review"]}},"required":["station","reason"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.stopped":{"post":{"operationId":"stationStopped","summary":"Stopped","description":"The station was stopped. It stays off air until started. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.stopped"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"by":{"description":"Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.","type":"string","enum":["client","api","support","billing"]}},"required":["station","by"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.started":{"post":{"operationId":"stationStarted","summary":"Started","description":"The station was started again. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.started"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"by":{"description":"Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.","type":"string","enum":["client","api","support","billing"]}},"required":["station","by"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.restarted":{"post":{"operationId":"stationRestarted","summary":"Restarted","description":"The station was restarted. Listeners reconnect within seconds. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.restarted"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"by":{"description":"Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.","type":"string","enum":["client","api","support","billing"]}},"required":["station","by"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.suspended":{"post":{"operationId":"stationSuspended","summary":"Suspended","description":"The station stopped because the balance stayed below zero past the grace period. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.suspended"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"reason":{"description":"Why.","type":"string","enum":["balance"]}},"required":["station","reason"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.resumed":{"post":{"operationId":"stationResumed","summary":"Resumed","description":"A suspended station is back on air because the balance cleared. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.resumed"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"}},"required":["station"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.plan_changed":{"post":{"operationId":"stationPlanChanged","summary":"Plan changed","description":"The station moved to another plan. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.plan_changed"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"from_plan":{"description":"The slug of the plan it was on.","type":"string"},"to_plan":{"description":"The slug of the plan it is on now.","type":"string"},"charged_cents":{"description":"What the move cost now, in US cents. 0 for a move at renewal.","type":"integer"},"by":{"description":"Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.","type":"string","enum":["client","api","support","billing"]}},"required":["station","from_plan","to_plan","charged_cents","by"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.plan_change_scheduled":{"post":{"operationId":"stationPlanChangeScheduled","summary":"Plan change scheduled","description":"A move to a smaller plan was set for the next renewal, or such a move was taken back. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.plan_change_scheduled"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"withdrawn":{"description":"True when a scheduled move was taken back. The fields below are then absent.","type":"boolean"},"to_plan":{"description":"The slug of the plan it will move to.","type":"string"},"takes_effect":{"description":"When it moves.","type":"string","format":"date-time"},"by":{"description":"Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.","type":"string","enum":["client","api","support","billing"]}},"required":["station","withdrawn","to_plan","takes_effect","by"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.cancellation_scheduled":{"post":{"operationId":"stationCancellationScheduled","summary":"Cancellation scheduled","description":"The station was cancelled. It stays on air until what is paid for runs out. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.cancellation_scheduled"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"ends_at":{"description":"When it goes off air.","type":"string","format":"date-time"},"by":{"description":"Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.","type":"string","enum":["client","api","support","billing"]}},"required":["station","ends_at","by"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.cancellation_withdrawn":{"post":{"operationId":"stationCancellationWithdrawn","summary":"Cancellation withdrawn","description":"A cancellation was taken back before the station ended. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.cancellation_withdrawn"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"by":{"description":"Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.","type":"string","enum":["client","api","support","billing"]}},"required":["station","by"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.cancelled":{"post":{"operationId":"stationCancelled","summary":"Cancelled","description":"A cancelled station reached its end and went off air. It can be resubscribed until it is closed. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.cancelled"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"}},"required":["station"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.resubscribed":{"post":{"operationId":"stationResubscribed","summary":"Resubscribed","description":"A cancelled station was subscribed again. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.resubscribed"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"by":{"description":"Who did it: you on the dashboard, your systems through the API, our support, or billing on its own.","type":"string","enum":["client","api","support","billing"]}},"required":["station","by"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"station.terminated":{"post":{"operationId":"stationTerminated","summary":"Closed","description":"The station was closed for good. Its music is deleted and its address freed. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"station.terminated"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"}},"required":["station"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"live.started":{"post":{"operationId":"liveStarted","summary":"Encoder connected","description":"An encoder connected, so a DJ is on air. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"live.started"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"}},"required":["station"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"live.ended":{"post":{"operationId":"liveEnded","summary":"Encoder disconnected","description":"The encoder disconnected. The AutoDJ takes over. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"live.ended"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"}},"required":["station"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"default_audio.started":{"post":{"operationId":"defaultAudioStarted","summary":"Default audio on","description":"Nothing else to play, so the station is on default audio: no DJ, and nothing in its playlist. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"default_audio.started"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"}},"required":["station"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"default_audio.ended":{"post":{"operationId":"defaultAudioEnded","summary":"Default audio off","description":"The station is playing your audio again. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"default_audio.ended"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"live":{"description":"Whether that is because a DJ connected.","type":"boolean"},"title":{"description":"What it is playing now.","type":["string","null"]}},"required":["station","live","title"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"track.changed":{"post":{"operationId":"trackChanged","summary":"Track changed","description":"A new title went on air, from a DJ or the AutoDJ. About one a song, so expect many. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"track.changed"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"title":{"description":"What is on air now.","type":"string"},"previous_title":{"description":"What was on before it.","type":["string","null"]},"live":{"description":"Whether it comes from a DJ.","type":"boolean"},"default_audio":{"description":"Whether it is default audio.","type":"boolean"},"listeners":{"description":"Listening at the change.","type":"integer"}},"required":["station","title","previous_title","live","default_audio","listeners"]}}},"example":{"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}}}}},"responses":{"2XX":{"description":"Received."}}}},"show.started":{"post":{"operationId":"showStarted","summary":"Show started","description":"A show on the station's week began, by its schedule. Whether its DJ is on air is live.started's to say. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"show.started"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"show":{"description":"The show: name, presenters, description, image (a URL, or null) and live, which is whether a DJ is expected rather than the AutoDJ.","type":"object"},"starts_at":{"description":"When this showing began.","type":"string","format":"date-time"},"ends_at":{"description":"When it ends.","type":"string","format":"date-time"}},"required":["station","show","starts_at","ends_at"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"media.ready":{"post":{"operationId":"mediaReady","summary":"Upload ready","description":"An uploaded track finished processing and can be played. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"media.ready"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"media":{"description":"The track.","$ref":"#/components/schemas/Track"}},"required":["station","media"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"media.failed":{"post":{"operationId":"mediaFailed","summary":"Upload failed","description":"An uploaded track could not be used. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"media.failed"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"media":{"description":"The track.","$ref":"#/components/schemas/Track"},"reason":{"description":"Why, in words for a person.","type":"string"}},"required":["station","media","reason"]}}},"example":{"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."}}}}},"responses":{"2XX":{"description":"Received."}}}},"media.deleted":{"post":{"operationId":"mediaDeleted","summary":"Track deleted","description":"A track was deleted from the library. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"media.deleted"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"station":{"$ref":"#/components/schemas/Station"},"media":{"description":"The track, as it was.","$ref":"#/components/schemas/Track"}},"required":["station","media"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"invoice.issued":{"post":{"operationId":"invoiceIssued","summary":"Invoice issued","description":"A monthly charge or a plan upgrade was invoiced. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"invoice.issued"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"invoice":{"description":"The invoice.","$ref":"#/components/schemas/Invoice"}},"required":["invoice"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"invoice.paid":{"post":{"operationId":"invoicePaid","summary":"Invoice paid","description":"An invoice was paid in full, by a payment or from credit. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"invoice.paid"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"invoice":{"description":"The invoice.","$ref":"#/components/schemas/Invoice"}},"required":["invoice"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"invoice.voided":{"post":{"operationId":"invoiceVoided","summary":"Invoice voided","description":"An invoice was cancelled. Nothing is owed on it. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"invoice.voided"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"invoice":{"description":"The invoice.","$ref":"#/components/schemas/Invoice"}},"required":["invoice"]}}},"example":{"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"}}}}}},"responses":{"2XX":{"description":"Received."}}}},"payment.succeeded":{"post":{"operationId":"paymentSucceeded","summary":"Payment received","description":"Money arrived and was added to the balance. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"payment.succeeded"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"payment":{"description":"The payment.","$ref":"#/components/schemas/Payment"},"balance_cents":{"description":"The balance after it, in US cents.","type":"integer"}},"required":["payment","balance_cents"]}}},"example":{"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}}}}},"responses":{"2XX":{"description":"Received."}}}},"payment.failed":{"post":{"operationId":"paymentFailed","summary":"Payment failed","description":"A payment did not go through. Nothing was added. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"payment.failed"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"payment":{"description":"The payment.","$ref":"#/components/schemas/Payment"}},"required":["payment"]}}},"example":{"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}}}}}},"responses":{"2XX":{"description":"Received."}}}},"balance.low":{"post":{"operationId":"balanceLow","summary":"Balance low","description":"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. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"balance.low"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"balance_cents":{"description":"The balance, in US cents.","type":"integer"},"currency":{"description":"Always USD.","type":"string"},"stations_stop_at":{"description":"When the stations stop.","type":"string","format":"date-time"}},"required":["balance_cents","currency","stations_stop_at"]}}},"example":{"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"}}}}},"responses":{"2XX":{"description":"Received."}}}},"ticket.replied":{"post":{"operationId":"ticketReplied","summary":"Support replied","description":"We answered one of your support tickets. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"ticket.replied"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"ticket":{"description":"The ticket.","$ref":"#/components/schemas/Ticket"},"message":{"description":"Our reply, as text.","type":"string"},"files":{"description":"How many files came with it. They are on the ticket's page.","type":"integer"}},"required":["ticket","message","files"]}}},"example":{"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}}}}},"responses":{"2XX":{"description":"Received."}}}},"webhook.test":{"post":{"operationId":"webhookTest","summary":"Test","description":"Sent by Send test on a webhook's page. Not something to subscribe to. Signed with FYN-Signature; answer with any 2xx within 10 seconds.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["id","type","test","created_at","data"],"properties":{"id":{"type":"string","format":"uuid","description":"The event's id. The same on a retry or a resend."},"type":{"type":"string","const":"webhook.test"},"test":{"type":"boolean","description":"True when sent by Send test."},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"message":{"description":"Says it is a test.","type":"string"}},"required":["message"]}}},"example":{"id":"6f1c2a8e-4d0b-4c7e-9a51-2b8d7f0e3c14","type":"webhook.test","test":false,"created_at":"2026-10-14T09:12:04Z","data":{"message":"A test from FYN Radio. Nothing happened on your account."}}}}},"responses":{"2XX":{"description":"Received."}}}}}}