Tuneping API v1

一個 JSON API,告訴你網路電臺現在正在播什麼,以及播過什麼。基礎 URL 為 https://api.tuneping.com/v1。只處理中繼資料:本服務讀取每個串流公開的標題行,從不碰音訊。

公開測試版即時端點(搜尋、批次、單一電臺正在播放、電臺目錄、健康狀態與統計)不需金鑰即可使用,依 IP 位址限制用量。金鑰可在註冊頁面自助申請:Free 立即取得,Developer 與 Pro 在完成 Stripe Checkout 後取得。Business:請寫信至 [email protected]。

快速入門

現在誰在播 Madonna?

curl "https://api.tuneping.com/v1/now-playing/search?q=madonna&limit=3"

查詢已知 id 的電臺正在播放什麼(id 是 Radio Browser 的電臺 UUID):

curl "https://api.tuneping.com/v1/stations/159824f0-5475-4263-bcc8-59a48a213896/now-playing"

某個電臺過去 24 小時播了什麼(需要具備播放紀錄權限的金鑰,Developer 方案以上):

curl -H "Authorization: Bearer tp_live_…" \
  "https://api.tuneping.com/v1/stations/159824f0-5475-4263-bcc8-59a48a213896/history"

所有回應都是 JSON。錯誤為 application/problem+json(請見錯誤)。未知的查詢參數會以 400 拒絕,而不是被忽略,因此拼錯字會立刻浮現。

取得金鑰

在 tuneping.com/signup 自助申請:輸入電子郵件地址,在 60 分鐘內開啟寄來的連結,金鑰就會顯示一次。這兩個步驟同樣有 API 可用:以 {"email": "…", "plan": "free|developer|pro"} 呼叫 POST /v1/signup 會回應 202 並寄出郵件;以連結中的 {"token": "…"} 呼叫 POST /v1/signup/verify 會回應 201 並附上金鑰。Free 不需要其他步驟。Developer 與 Pro 會透過回應中的連結前往 Stripe Checkout;付款後一分鐘內,擁有者的方案等級即會變更,其名下所有金鑰也會跟著變更。

金鑰遺失了?用同一個地址再註冊一次:金鑰會輪替,舊金鑰在 24 小時內仍可使用。Free 與 Developer 一把正式金鑰,Pro 五把,Business 二十把;另外每個方案等級都有一把 tp_test_ 金鑰,在管理後台上線之前依申請核發。

驗證

以 Bearer 權杖的形式傳送金鑰,或放在 X-Api-Key 中:

Authorization: Bearer tp_live_a1b2c3…
X-Api-Key: tp_live_a1b2c3…

金鑰以 tp_live_ 或 tp_test_ 開頭,後接 43 個字元。沒有帶金鑰的請求會被視為匿名請求,依 IP 位址限制。格式錯誤、無法辨識或已撤銷的金鑰會立即回應 401,即使該端點原本以匿名方式也能使用。下方標示 金鑰 的端點,沒有金鑰時會回應 401 unauthenticated。

權限範圍(scope)。 除非簽發時指定了較窄的清單(例如唯讀),金鑰都帶有所有權限範圍(read、exports、webhooks、wishlists);GET /v1/me 會列出金鑰的權限範圍。願望清單與 webhook 分別需要 wishlists 與 webhooks 權限範圍(採用 webhook 傳送的願望清單兩者都需要,且會在檢查方案之前先檢查)。缺少權限範圍的金鑰會回應 403 forbidden_scope 並附上 required_scope,WWW-Authenticate 會帶有 error="insufficient_scope"。

測試金鑰。 tp_test_ 金鑰以 Free 的限制讀取同樣的即時資料,並擁有自己的願望清單、比對結果與 webhook 端點(livemode: false)。它永遠看不到也改不到正式環境的資料,因此測試套件可以 PUT 一組空的願望清單,而不會影響正式環境。測試模式的 webhook 只能指向 webhook.site。

重試。 在需要金鑰或合作夥伴權杖的端點上,POST、PATCH 與 DELETE 接受 Idempotency-Key 標頭(每個邏輯請求一個 UUID);註冊端點不接受此標頭。以相同鍵值、相同請求重試時,會再次取得第一次成功的回應,並標示 Idempotent-Replayed: true,而不會建立第二個願望清單或端點。鍵值會保留 24 小時;將它重複用於不同的請求會得到 422 idempotency_key_reused,在第一個請求仍在執行時重試則會得到 409 idempotency_in_progress。錯誤不會被保留,因此出錯後重試會重新執行。帶有此標頭的請求不會因連線中斷而取消:它會執行完畢,成功的回應會被保留,你重試時就會拿到。執行超過 20 秒的請求會被取消且不做任何變更,並回應 503 unavailable 與 Retry-After: 1;請以相同鍵值重試。

合作夥伴應用程式(目前為 Tapelark)傳送的是經過簽署的使用權權杖,而不是金鑰:Authorization: Bearer TPE1-…。權杖會以合作夥伴的 Ed25519 公鑰離線驗證,並對應到下表中的合作夥伴方案;API 永遠不會知道終端使用者是誰。格式錯誤或無法辨識的權杖回應 401 token_invalid,已過期的回應 401 token_expired(請重新整理),發給其他對象的權杖回應 401 token_audience,已失效或撤銷的使用權則回應 403 entitlement_revoked。

速率限制與配額

方案等級速率配額批次 id 數播放紀錄
匿名(依 IP)2 req/s,突發 51,000 / 天20無
Free2 req/s,突發 51,000 / 天20無
Developer10 req/s,突發 20100,000 / 月1007 天
Pro50 req/s,突發 1001,000,000 / 月10012 個月
Business自訂自訂10012 個月
Tapelark(使用權權杖,依授權計)5 req/s,突發 102,000 / 天507 天

每秒限制採用權杖桶(token bucket)演算法。桶子空了,你會收到 429 rate_limited 並附上 Retry-After。配額用完時,你會收到 429 quota_exceeded,Retry-After 設為距離計算週期重設的秒數。

不可共用快取的已驗證回應,會帶有 IETF 速率限制欄位:

RateLimit-Policy: "burst";q=10;w=1, "monthly";q=100000;w=2592000
RateLimit: "burst";r=7;t=1

可共用快取的回應(搜尋、批次、單一電臺正在播放、電臺、統計、健康狀態時間序列)不帶速率限制標頭,因為邊緣節點可能把同一份內容提供給其他呼叫者。你剩餘的額度隨時可以在 GET /v1/me 查詢。

快取

即時回應可快取 5 秒(Cache-Control: public, max-age=5, s-maxage=5),並帶有弱 ETag。送出 If-None-Match,內容沒有變化時會得到 304;304 在源站不計入你的配額。電臺目錄快取 60 秒,單一電臺 300 秒。播放紀錄為 private, max-age=30。健康狀態與金鑰相關端點為 no-store。

每個回應都帶有 X-Request-Id。聯絡支援時請附上。

錯誤

錯誤遵循 RFC 9457 問題詳細資訊(problem details)格式,並有兩種擴充成員:code,穩定且機器可讀的字串;以及各端點特有的附加欄位,例如驗證失敗時的 errors[],或 403 時的 required_tier。

HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json

{
  "type": "https://tuneping.com/docs/errors/#validation_failed",
  "title": "Validation failed",
  "status": 422,
  "detail": "One or more query parameters are invalid.",
  "instance": "urn:tuneping:request:req_01a18837c239727fbacb40d6c488405a",
  "code": "validation_failed",
  "errors": [ { "field": "q", "code": "length", "message": "`q` is required and must be 2–120 characters." } ]
}

所有代碼及其意義請見錯誤目錄。你最先會遇到的是這些:

HTTPcode發生時機
400invalid_request未知的查詢參數或格式錯誤的請求
400invalid_cursor游標格式錯誤、已過期(24 小時;比對結果饋送的 since_cursor 為 30 天),或搭配了不同的篩選條件
401unauthenticated · invalid_api_key · key_revoked缺少金鑰、無法辨識或已撤銷
403forbidden_tier端點或參數需要更高的方案;required_tier 指出是哪一個
403forbidden_scope金鑰簽發時沒有該權限範圍;required_scope 指出是哪一個
404not_found · station_opted_out未知的 id,或該電臺要求不被索引
422validation_failed欄位錯誤列在 errors[] 中
429rate_limited · quota_exceeded請放慢速度;Retry-After 以秒為單位
503unavailable資料庫無法使用,或帶有 Idempotency-Key 的請求在 20 秒後被取消;請在 Retry-After 之後重試

GET/v1/now-playing/search 免金鑰 public, max-age=5 · ETag

哪些電臺現在正在播 q。支援模糊比對、不分重音符號:gronemeyer manner 可以找到 Grönemeyer – Männer。結果依相似度排序,其次依標題出現的時間先後。不提供分頁:索引每幾秒就會變動,分頁會造成跳過或重複。請改為調高 limit。

參數型別預設值說明
q字串,2–120 個字元必填藝人、曲名或兩者。三個字元以上使用三連詞(trigram)比對;較短的查詢使用子字串比對。
countryISO 3166-1 alpha-2,可重複不限只包含這些國家的電臺。
codec字串不限例如 MP3、AAC。
min_bitrate整數0kbit/s。
classification列舉songsong、ident、programme、ad_break、empty、junk、unknown 或 any。
max_age_seconds30–900180只包含電臺在這麼多秒內成功輪詢過的結果。
limit1–10020回傳的筆數;truncated: true 表示還有更多。

回應 · 200 · application/json

{
  "data": [
    {
      "station": { "id": "159824f0-5475-4263-bcc8-59a48a213896", "name": "Radio 10 80's Hits", "country": "NL",
                   "codec": "MP3", "bitrate": 128, "is_hls": false,
                   "stream_url": "http://…/TLPSTR20.mp3", "homepage": "http://www.radio10.nl/", "recordability": "recordable" },
      "raw_title": "Madonna - Holiday",
      "artist": "Madonna", "title": "Holiday",
      "track": { "id": "trk_c6f", "mbid": "d4708b79-62e7-4ce4-a6ca-247237d4ef4e", "artist_id": "art_fn" },
      "classification": "song", "match_grade": "high", "confidence": "high",
      "started_at": "2026-10-29T15:08:44.883Z", "start_uncertainty_seconds": 32,
      "observed_at": "2026-10-29T15:09:26.631Z", "confirmed_at": "2026-10-29T15:10:30.679Z",
      "method": "icy", "poll_interval_seconds": 60, "similarity": 0.5
    }
  ],
  "truncated": false,
  "query": { "q": "madonna", "normalized": "madonna", "max_age_seconds": 180 }
}

解讀一筆結果

started_at RFC 3339 · 估計值
目前標題的估計開始時間,前後誤差 ± start_uncertainty_seconds。
observed_at RFC 3339
Tuneping 第一次看到這個標題的時間。
confirmed_at RFC 3339
該電臺最近一次成功輪詢的時間:「截至此時仍在播放」。用它判斷資料新鮮度。
track 物件 · 選用
標題已連結到 MusicBrainz 錄音(recording)時才會出現。
similarity 0–1
依你自己的門檻值篩選。

GET/v1/now-playing 免金鑰 public, max-age=5 · ETag

批次查詢正在播放

一次呼叫取得一組電臺的目前標題,適用於收藏電臺畫面。

參數型別預設值說明
station_ids以逗號分隔的 UUID必填匿名或 Free 最多 20 個,Developer 起最多 100 個。id 在快取前會先排序並去除重複,因此收藏相同的兩個用戶端會共用同一份快取內容。
max_age_seconds30–86400900比這更舊的結果仍會回傳,但會標示 is_stale: true。
{ "data": [ { …same row shape as search, without similarity, plus "is_stale": false… } ],
  "missing": [ "ids that are unknown or opted out" ],
  "max_age_seconds": 900 }

GET/v1/stations/{id}/now-playing 免金鑰

單一電臺正在播放

單一電臺的一筆結果。尚未觀察到任何標題時回應 404 not_found,電臺要求不被索引時回應 404 station_opted_out。

GET/v1/stations GET/v1/stations/{id} 免金鑰 max-age=60 · 300

電臺

電臺目錄,以社群維護的 Radio Browser 目錄為基礎,並加上 Tuneping 讀取每個電臺的方式等資訊。

參數型別預設值說明
q字串—電臺名稱,模糊比對。
countryalpha-2,可重複不限
tag字串,可重複不限必須符合所有指定的標籤。
codec, min_bitrate同搜尋。
has_now_playing布林值false只包含 Tuneping 目前有讀取標題的電臺。
sort列舉clickcountclickcount(熱門程度,遞減)、name、bitrate。
limit1–20050
cursor不透明字串—取自上一頁的 next_cursor;有效期 24 小時,且只能搭配相同的篩選條件使用。
{ "data": [ {
    "id": "159824f0-5475-4263-bcc8-59a48a213896", "name": "Radio 10 80's Hits", "country": "NL", "state": null,
    "language": "dutch", "tags": ["80s", "hits"], "codec": "MP3", "bitrate": 128, "is_hls": false,
    "stream_url": "http://…", "homepage": "http://www.radio10.nl/", "favicon_url": "https://…/favicon.png",
    "clickcount": 1234, "recordability": "recordable",
    "metadata": { "method": "icy", "poll_interval_seconds": 60, "lag_seconds": 9, "last_ok_at": "2026-10-29T15:10:30Z", "coverage": "live" },
    "created_at": "2026-10-29T10:12:03Z", "updated_at": "2026-10-29T15:10:30Z" } ],
  "next_cursor": "eyJ…" }

favicon_url 是直接從目錄轉傳的文字;Tuneping 從不複製或提供標誌。

GET/v1/stations/{id}/history 金鑰 · Developer 以上 private, max-age=30

播放紀錄

電臺播過的歌曲,最新的在前,附估計的開始與結束時間。可查詢的深度依方案而定:Developer 為 7 天,Pro 與 Business 為 12 個月。要求更早的 from 會回應 403 forbidden_tier 並附上 required_tier,絕不會悄悄縮短查詢區間。

參數型別預設值說明
from, toRFC 3339to = 現在,from = to − 24 h每次呼叫最多 31 天。
classification列舉song同搜尋。
limit1–20050
cursor不透明字串—查詢區間會固定在游標中。
{ "data": [ {
    "id": "pe_…", "station": { …station ref… },
    "raw_title": "Hecht - Charlotta", "artist": "Hecht", "title": "Charlotta",
    "track": { "id": "trk_…", "mbid": "…", "artist_id": "art_…" },
    "classification": "song", "match_grade": "high",
    "started_at": "2026-10-29T10:31:12Z", "start_uncertainty_seconds": 10,
    "ended_at": "2026-10-29T10:34:40Z", "duration_seconds": 208,
    "method": "icecast_json", "confidence": "high" } ],
  "next_cursor": null,
  "window": { "from": "2026-10-28T15:00:00Z", "to": "2026-10-29T15:00:00Z" } }

GET/v1/me GET/v1/me/usage 金鑰 no-store

金鑰與用量

/v1/me 回傳金鑰本身、其擁有者的方案與狀態、適用的限制,以及目前計算週期內的已用量。/v1/me/usage?from=&to= 回傳每日請求數(只計算源站請求;邊緣快取命中不計入)。

{ "key":   { "id": "key_…", "hint": "tp_live_a1b2c3…", "scopes": ["read", "exports", "webhooks", "wishlists"], "livemode": true,
             "created_at": "…", "last_used_at": "…" },
  "owner": { "id": "own_…", "tier": "developer", "status": "active",
             "current_period_start": "…", "current_period_end": "…" },
  "limits": { "requests_per_second": 10, "burst": 20, "requests_per_day": null, "requests_per_month": 100000,
              "history_days": 7, "batch_station_ids": 100, "webhooks": 0, "wishlists": 10,
              "sse_connections": 1, "tightened_stations": 200 },
  "usage":  { "period_requests": 41230, "today_requests": 1810, "resets_at": "…" } }

GET/v1/health GET/v1/health/series GET/v1/stats 免金鑰

健康狀態與統計

/v1/health 回應 200,status 為 ok 或 degraded;資料庫停擺時回應 503。可以把你的運作時間監控指向它。/v1/health/series?minutes=60(5–1440)回傳輪詢程式的每分鐘數據:polls、ok、titles_changed、songs、bytes_in、bytes_out、latency_p50_ms、latency_p90_ms、inflight_max、ips_paused、queue_lag_seconds,以及 by_method 細目。/v1/stats 是狀態頁面上顯示的公開涵蓋率快照:電臺總數、已輪詢數、提供即時中繼資料的電臺數、每分鐘標題變更數、歌曲占比、依讀取方式分布、依國家分布。

POST/v1/wishlists PUT/v1/wishlists GET/v1/wishlists/matches 金鑰 · Developer 以上 no-store

願望清單

指定一首歌、一位藝人或一段自由文字標題,在電臺開始播放時得知。每次標題變更在讀取時就會與你的願望清單比對,新建立的願望清單在 30 秒內生效。Developer 可保留 10 個願望清單,Pro 100 個,Business 1,000 個。比對結果保留 30 天。

欄位型別說明
kindartist · track · queryartist 與 track 接受來自搜尋結果的 id(art_…、trk_…),也能比對到正規化程式連結到該 id 的其他拼寫。query 接受自由文字,通常為 Artist - Title。
value字串,≤ 240id 或文字。
matchexact · fuzzy僅適用於 query。exact 比較正規化後的文字;fuzzy 接受三連詞相似度 0.6 以上。
station_filter物件station_ids(≤ 500)和/或 countries(alpha-2,大小寫不拘,回傳時為大寫)。標題所屬電臺在清單中,或位於清單中的國家,即算符合。不設篩選條件代表所有電臺。
delivery陣列poll(預設)、sse、webhook。webhook 傳送限 Pro 以上,需要 webhook_id,以及具備 webhooks 權限範圍的金鑰。
description字串,≤ 200由你自訂。
curl -H "Authorization: Bearer tp_live_…" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"kind":"query","value":"Daft Punk - One More Time","station_filter":{"countries":["FR","BE"]}}' \
  https://api.tuneping.com/v1/wishlists

明確指定 station_ids 清單時,在願望清單啟用期間,Tuneping 會改為每 30 秒(而非每 60 秒)讀取這些電臺一次,回應中會以 tightens: true 表示。你所列電臺的聯集有方案上限(/v1/me 中的 limits.tightened_stations);會超過上限的願望清單會回應 422 validation_failed,errors[] 中有一筆 code 為 tightened_stations_exceeded 的項目(欄位為 station_filter.station_ids,PUT 時則為 data)。國家篩選條件仍會比對,但以各電臺的一般間隔進行。

GET /v1/wishlists/{id}、PATCH(電臺篩選條件、比對方式、傳送方式、webhook、說明、status: enabled | paused)與 DELETE 的行為一如預期。以 {"data": [ … ]} 呼叫 PUT /v1/wishlists,可一次取代你的整組願望清單:未變更的項目保留原本的 id 與比對次數,其餘項目則會建立或刪除。這是同步應用程式在本機保存的清單最簡單的方法。它的主體最多可到 1 MiB;其他請求主體上限為 64 KiB(413 payload_too_large)。

比對結果是一個追蹤式饋送(tail feed)。GET /v1/wishlists/matches 涵蓋你所有的願望清單,GET /v1/wishlists/{id}/matches 只涵蓋其中一個。結果由舊到新排列。保留每次回應中的 next_cursor,下次以 since_cursor 送回:它永遠不會是 null,在 30 天保留期限內都有效,服務重新啟動後也仍然有效。不帶游標時會得到最新的比對結果。limit 為 1–500,預設 100。

{ "data": [ {
    "id": "wm_…", "wishlist_id": "wl_…",
    "station": { "id": "…", "name": "…", "country": "FR", "codec": "MP3", "bitrate": 128, "is_hls": false,
                 "stream_url": "https://…", "homepage": "https://…", "recordability": "recordable" },
    "raw_title": "Daft Punk - One More Time", "track": { "id": "trk_…", "mbid": "…", "artist_id": "art_…" },
    "started_at": "2026-10-30T21:04:10Z", "start_uncertainty_seconds": 10,
    "observed_at": "2026-10-30T21:04:20Z", "matched_at": "2026-10-30T21:04:20Z",
    "confidence": "high", "expected_end_hint_at": "2026-10-30T21:07:52Z" } ],
  "next_cursor": "eyJ0Ijo…" }

started_at 已依看到標題的時間校正過,因此錄音程式可以顯示「約 N ± U 秒前開始」。expected_end_hint_at 是 started_at 加上 222 秒(歌曲長度的中位數):只是提示,不是預測。confidence 在經由已連結的曲目或藝人 id 比對時為 high,經由正規化後的藝人與曲名比對時為 medium,文字查詢則為 low。

POST/v1/webhooks GET/v1/webhooks/{id}/deliveries 金鑰 · Pro 以上 no-store

Webhook

事件一發生,Tuneping 就會以 POST 送到你的 HTTPS 端點。Pro 可設 5 個端點,Business 20 個。

事件發生時機Pro 需要
wishlist.matched在 webhook_id 中指定此端點的願望清單比對成功。—
station.title_changed電臺的標題行變更。filters.station_ids(≤ 200)
track.started已連結的曲目開始播放。filters.track_ids 或 artist_ids(≤ 200)
artist.started已連結的藝人開始播放。filters.track_ids 或 artist_ids(≤ 200)

篩選條件也可以列出 countries 與 classification。只依國家篩選,以及未篩選的標題變更事件流,限 Business 使用。每個端點每天的事件額度在 Pro 為 50,000 個,Business 為 500,000 個;超過後該端點會進入 paused_budget 狀態直到下一個 UTC 日,你也會收到電子郵件通知。

curl -H "Authorization: Bearer tp_live_…" -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/hooks/tuneping","events":["wishlist.matched"]}' \
  https://api.tuneping.com/v1/webhooks

回應中會附上簽章用的 secret(whsec_…),只顯示一次。傳送遵循 Standard Webhooks:標頭為 webhook-id、webhook-timestamp 與 webhook-signature: v1,<base64>,其中簽章是以密鑰的位元組,對 {webhook-id}.{webhook-timestamp}.{body} 計算的 HMAC-SHA256。請拒絕時間戳記誤差超過 5 分鐘的請求,並用 webhook-id 排除重複:重試時它保持不變。

{ "id": "evt_…", "type": "wishlist.matched", "created_at": "2026-10-30T21:04:20Z",
  "data": { "station_id": "…", "station": { …station ref… }, "wishlist_id": "wl_…", "match_id": "wm_…",
            "raw_title": "Daft Punk - One More Time", "artist": "Daft Punk", "title": "One More Time",
            "track_id": "trk_…", "artist_id": "art_…", "classification": "song",
            "started_at": "…", "start_uncertainty_seconds": 10, "observed_at": "…",
            "confidence": "high", "expected_end_hint_at": "…" },
  "links": { "station": "/v1/stations/…", "wishlist": "/v1/wishlists/wl_…" } }

請在 10 秒內以任何 2xx 回應。不會跟隨重新導向。傳送失敗時,會在 5 秒、5 分鐘、30 分鐘、2 小時、5 小時、10 小時、14 小時、20 小時與 24 小時後重試,總共約三天,每個端點一次只送一筆。回應 410,或連續五天傳送失敗的端點會被停用,你會收到電子郵件通知;修正後以 PATCH 將 status 設回 enabled 即可。

POST /v1/webhooks/{id}/rotate-secret 會回傳新的密鑰;接下來 24 小時內,每次傳送都會帶兩個簽章,新舊密鑰各一。POST /v1/webhooks/{id}/test 會送出一個 ping。GET /v1/webhooks/{id}/deliveries?status=pending|succeeded|failed 列出 30 天內的傳送紀錄,POST …/deliveries/{dl_id}/redeliver 會重新送出其中一筆。測試金鑰(tp_test_…)只能指向 webhook.site。

GET/v1/stream 金鑰 · Developer 以上 text/event-stream

事件串流

同樣的事件,以 server-sent events 格式透過單一長時間 HTTP 回應送出,適用於伺服器與原生應用程式。傳入 station_ids(最多 100 個)或 wishlist_id(all,或單一 wl_… id)其中之一。

curl -N -H "Authorization: Bearer tp_live_…" -H "Accept: text/event-stream" \
  "https://api.tuneping.com/v1/stream?station_ids=159824f0-5475-4263-bcc8-59a48a213896"
retry: 3000

id: evt_1m675e1tkfdxtn7axmq6qktz8
event: station.title_changed
data: {"id":"evt_1m675e1tkfdxtn7axmq6qktz8","type":"station.title_changed","created_at":"…","data":{…}}

: ping
參數預設值說明
station_ids—以逗號分隔的電臺 id,最多 100 個。
wishlist_id—all 或某個願望清單 id。送出 wishlist.matched。
eventsstation.title_changed用於電臺串流,可為 station.title_changed、track.started、artist.started 中的任意幾項。
classificationsongsong 或 any,用於電臺串流。

data 與 webhook 收到的 JSON 相同。連續 20 秒沒有事件時會送出一則 : ping 註解,因此請把用戶端的閒置逾時設為 60 秒以上。連線中斷時,請重新連線,並把 Last-Event-ID 標頭設為你最後看到的 id:過去 10 分鐘內的事件會重新播送。更早的位置會收到 event: gap,附上最早可用的 id;中間的缺口請從播放紀錄或比對結果饋送補齊。每把金鑰可開啟的串流數:Developer 1、Pro 5、Business 20、Tapelark 每部裝置 1。再多開一條會回應 429 too_many_connections。

瀏覽器在這裡無法使用 EventSource,因為它無法送出 Authorization 標頭,而金鑰絕不接受放在 URL 中。請改用 fetch() 讀取串流。

欄位與列舉值

classification 列舉
song · ident(電臺名稱或標語)· programme · ad_break · empty · junk · unknown。只有歌曲會成為播放紀錄;所有內容都會保留在即時結果中。
match_grade 列舉
high · medium · none。標題與 MusicBrainz 錄音連結的程度。
confidence 列舉
high · medium · low。依每筆結果的分類、比對等級、電臺最近一次確認的時間,以及電臺過往的表現計算。公開說明,方便你稽核。
method 列舉
Tuneping 讀取該電臺的方式:icy(串流內中繼資料)、icecast_json(伺服器狀態 JSON)、shoutcast_stats(狀態 XML)、shoutcast_currentsong、seven_html。這些是內部識別碼,不代表背書;如果要顯示,請顯示為「串流內」與「狀態頁面」。
recordability 列舉
從錄音用戶端的角度來看,該電臺的串流是否為單純、可錄製的 HTTP 串流。僅供參考。
Id
電臺使用其 Radio Browser UUID。曲目為 trk_…,藝人為 art_…,播放事件為 pe_…,金鑰為 key_…,擁有者為 own_…,願望清單為 wl_…,比對結果為 wm_…,webhook 為 wh_…,傳送紀錄為 dl_…,事件為 evt_…。請一律視為不透明字串。
時間戳記
RFC 3339、UTC,來源有提供時精確到毫秒。

OpenAPI

本 API 的機器可讀描述位於 /docs/openapi-v1.yaml(OpenAPI 3.1)。它是產生用戶端程式碼的依據;operation id 保持穩定。

出處標示與合理使用

Free 方案與匿名使用時,須在顯示資料的地方放上可見的「Data by Tuneping」連結(徽章)。播放是從電臺中繼資料偵測而來,並非經認證的監播;作為證據呈現時,請註明「根據電臺中繼資料偵測」。電臺名稱為文字;Tuneping 不提供標誌或封面圖片。請參閱服務條款。