Tuneping API v1

一个 JSON API,提供网络电台此刻正在播放的内容,以及它们播放过的内容。Base 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 提供:POST /v1/signup 携带 {"email": "…", "plan": "free|developer|pro"},返回 202 并发送邮件;POST /v1/signup/verify 携带链接中的 {"token": "…"},返回 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。

作用域。除非签发时指定了更窄的列表(例如只读),密钥默认拥有全部作用域(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 天

每秒限制采用令牌桶算法。桶空时会返回 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 问题详情格式,并带有两类扩展成员: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 h;匹配记录流的 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 录音时才会出现。
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 会把这些电台的读取间隔从 60 秒缩短为 30 秒,响应中会以 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 的行为符合预期。PUT /v1/wishlists 携带 {"data": [ … ]} 可一次替换你的整个集合:未变化的条目保留其 id 和匹配计数,其余条目被创建或删除。这是同步应用本地维护的列表最简单的方式。它的请求体最大可为 1 MiB;其他请求体限制为 64 KiB(413 payload_too_large)。

匹配记录是一个追加式记录流。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 秒(歌曲时长的中位数):只是提示,不是预测。匹配经由已关联的曲目或艺人 id 时,confidence 为 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 s、5 min、30 min、2 h、5 h、10 h、14 h、20 h 和 24 h 后重试,总计约三天,每个端点同一时间只投递一个。返回 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

事件流

以服务器发送事件 格式,通过一个长时间保持的 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 不提供台标或封面图。详见条款。