LibreTime 4.5.0 REST API 使用详解
LibreTime 4.5.0 REST API 使用详解:v2 全局约定(Basic/会话/legacy api_key 三种认证实测边界)、files/shows/show-instances/schedule/playlists/webstreams/users/preferences/playout-history 九大域逐条 curl 实测、创建排期全链路 201 回显、无服务端分页约定与错误格式、常见问题。
LibreTime 4.5.0 REST API 使用详解
目标:讲清 LibreTime 4.5.0 的 REST API 体系——三种认证方式的实测边界、九个核心资源域的端点/参数/请求/响应、从上传到排期开播的全链路调用实录,帮助运维与集成方用 API 完成排单、流管理与账号管理的自动化。全部请求与响应均在 4.5.0 实测环境 curl 实拍,无转述示例。
一、环境信息
- 操作系统:Ubuntu 22.04 x86_64(4C/8G)
- LibreTime:4.5.0(官方 Docker 编排全栈,入口 nginx
http://127.0.0.1:8142) - API 版本:v2(实测
{"api_version":"2.0.0"}) - 规范文件:官方 OpenAPI 3.0 规范(4.5.0 随仓库发布,共 74 个路径、38 个资源域 tag)
- 客户端工具:curl 7.81 + python3(json 解析)
- 测试账号:Web 管理员
admin/q1w2e3r4(role=A) - 内部 API Key:部署时
openssl rand -hex 32生成(本环境为867b550987df8c6ff65140584d9cd6e93a18e386e8ed69b5e4c00dc858e01b73,读者以自己的为准) - 实测日期:2026-10-29
二、前置条件
- LibreTime 4.5.0 全栈已部署并完成数据库迁移(见《LibreTime 4.5.0 Docker Compose 部署指南》)。
- 已知三类凭据:管理员账号口令(admin/q1w2e3r4)、config.yml 中的
general.api_key、Web 登录会话 cookie(PHPSESSID/sessionid)。 - 确认入口可达:
curl -s -o /dev/null -w 'login page: %{http_code}\n' http://127.0.0.1:8142/login
curl -s http://127.0.0.1:8142/api/v2/version
实测回显:
login page: 200
{"api_version":"2.0.0"}
三、API 总览
3.1 协议与入口
- 全部走 HTTP(生产建议反代加 TLS 后对外),统一入口为 nginx(本文 8142)。
- 两套 API 共存:
- v2 API(Python/Django 实现):
/api/v2/*,REST 风格,OpenAPI 3.0 规范覆盖,本文主体。 - legacy REST(PHP 实现):
/rest/*,仅少数端点(如媒体上传POST /rest/media),认证方式特殊(见 4.3)。
- v2 API(Python/Django 实现):
3.2 资源域清单
4.5.0 的 38 个资源域(OpenAPI tags 实查)按用途分组:
| 分组 | 域 |
|---|---|
| 媒体资产 | files、libraries、third-party-track-references |
| 排期播出 | shows、show-days、show-instances、show-rebroadcasts、show-hosts、schedule、playlists、playlist-contents、smart-blocks、smart-block-contents、smart-block-criteria、webstreams、webstream-metadata |
| 播客 | podcasts、podcast-episodes、imported-podcasts、station-podcasts |
| 播出记录与统计 | playout-history、playout-history-metadata、playout-history-templates、playout-history-template-fields、listener-counts、live-logs、timestamps |
| 流配置与状态 | stream(/api/v2/stream/preferences)、mount-names |
| 系统管理 | users、user-tokens、preferences、login-attempts、service-registers、celery-tasks、schema、info、version |
如何选:排单自动化主用 shows/show-instances/schedule;媒体接入用 files;对接播放器/统计用 playout-history 与 listener-counts;配置巡检用 preferences 与 stream/preferences。
3.3 认证方式(实测边界)
| 认证方式 | 形态 | 适用范围(实测) |
|---|---|---|
| HTTP Basic | curl -u 'admin:q1w2e3r4' | /api/v2/* 全部端点 |
| 会话 Cookie | 登录后携带 sessionid | Web 界面 + /api/v2/* |
| X-API-Key 头 | -H 'X-API-Key: <key>' | 仅少数 legacy 兼容端点(实测 /api/v2/version、/api/v2/info、/api/v2/stream/preferences 可用;/api/v2/files 等资源端点不认,返回 401) |
| legacy Basic(api_key:) | curl -u '<API_KEY>:' | /rest/*(用户名=api_key,密码留空) |
⚠️ 实测踩坑:用 X-API-Key 调
/api/v2/files会得到{"detail":"Authentication credentials were not provided."}(api 服务日志WARNING Forbidden: /api/v2/files)。资源端点一律用 Basic 或会话认证,X-API-Key 只在部分端点碰巧兼容,不要当通用凭证。
四、认证与首次调用
4.1 匿名端点:version 与 info
/api/v2/version 与 /api/v2/info 免认证(规范中 security 含空对象),可直接探测服务健康:
curl -s 'http://127.0.0.1:8142/api/v2/version'; echo
curl -s 'http://127.0.0.1:8142/api/v2/info'; echo
实测回显:
{"api_version":"2.0.0"}
{"station_name":"LibreTime"}
4.2 Basic 认证调用资源端点
curl -s -u 'admin:q1w2e3r4' 'http://127.0.0.1:8142/api/v2/users'
实测回显(节选):
[{"id":1,"role":"A","username":"admin","email":null,"first_name":"","last_name":"","login_attempts":0,"last_login":null,...}]
4.3 认证失败与 legacy 认证实录
无凭证调用受保护端点返回 401 与统一错误体:
curl -s 'http://127.0.0.1:8142/api/v2/shows' -w ' [%{http_code}]'
实测回显:
{"detail":"Authentication credentials were not provided."} [401]
legacy 上传端点用 api_key 做 Basic 用户名(密码留空),实测:
curl -s -u '867b550987df8c6ff65140584d9cd6e93a18e386e8ed69b5e4c00dc858e01b73:' \
-X POST 'http://127.0.0.1:8142/rest/media' \
-F 'file=@test-track.mp3;type=audio/mpeg' -o /tmp/up.json -w '%{http_code}\n'
实测回显:
201
查看响应(id 由服务端生成,import_status=1 表示分析中):
python3 -c "import json; d=json.load(open('/tmp/up.json')); print('file id:', d.get('id'), '| import_status:', d.get('import_status'), '| md5:', d.get('md5'))"
实测回显:
file id: 1 | import_status: 1 | md5: a30d22e4f630a36fc54d53f8963eabc1
五、各 API 域详解
5.1 files:媒体文件域
端点:/api/v2/files(GET 列表、POST 元数据创建)、/api/v2/files/{id}(GET/PUT/PATCH/DELETE)、/api/v2/files/{id}/download。
查询单文件元数据(等分析完成后 import_status=0):
curl -s -u 'admin:q1w2e3r4' 'http://127.0.0.1:8142/api/v2/files/1' \
| python3 -c "import sys,json; d=json.load(sys.stdin); print({k:d[k] for k in ('id','filepath','size','mime','length','bit_rate','import_status')})"
实测回显:
{'id': 1, 'filepath': 'imported/1/test-track.mp3', 'size': 4321533, 'mime': 'audio/mp3', 'length': '00:03:00.035918', 'bit_rate': 192000, 'import_status': 0}
⚠️ 注意:
POST /api/v2/files是元数据创建端点(要求 size/mime/accessed/name 等字段),不收文件本体;文件上传固定走 4.3 的 legacyPOST /rest/media。实测错误形态:
{"size":["This field is required."],"mime":["This field is required."],"accessed":["This field is required."],"name":["This field is required."]}
查询不存在的 id 返回 404:
{"detail":"No File matches the given query."} [404]
5.2 shows:节目域
端点:/api/v2/shows(GET/POST)、/api/v2/shows/{id}(GET/PUT/PATCH/DELETE)。
创建节目——布尔字段全部必填(实测省略即 400):
curl -s -u 'admin:q1w2e3r4' -X POST 'http://127.0.0.1:8142/api/v2/shows' \
-H 'Content-Type: application/json' \
-d '{"name":"Test Show","description":"forensic test show","genre":"various","linked":false,"linkable":false,"auto_playlist_enabled":false,"auto_playlist_repeat":false,"override_intro_playlist":false,"override_outro_playlist":false,"live_enabled":false}' \
-w '\n[%{http_code}]\n'
实测回显(节选):
{"id":1,"name":"Test Show","description":"forensic test show","genre":"various",...,"live_enabled":false,...}
[201]
漏字段的错误形态(实测省略布尔字段时):
{"linked":["This field is required."],"linkable":["This field is required."],"auto_playlist_enabled":["This field is required."],...}
查询单节目:
curl -s -u 'admin:q1w2e3r4' 'http://127.0.0.1:8142/api/v2/shows/1' \
| python3 -c "import sys,json; d=json.load(sys.stdin); print({k:d[k] for k in ('id','name','genre','live_enabled')})"
实测回显:
{'id': 1, 'name': 'Test Show', 'genre': 'various', 'live_enabled': False}
5.3 show-instances:期次域
端点:/api/v2/show-instances(GET/POST)、/api/v2/show-instances/{id}(GET/PUT/PATCH/DELETE)。时间统一 UTC ISO8601(Z 后缀),除 show/starts_at/ends_at 外还需 created_at、auto_playlist_built、record_enabled(实测缺一即 400):
curl -s -u 'admin:q1w2e3r4' -X POST 'http://127.0.0.1:8142/api/v2/show-instances' \
-H 'Content-Type: application/json' \
-d '{"show":1,"starts_at":"2026-10-29T10:26:00Z","ends_at":"2026-10-29T10:46:00Z","record_enabled":0,"modified":true,"created_at":"2026-10-29T10:24:00Z","auto_playlist_built":false}' \
-w '\n[%{http_code}]\n'
实测回显:
{"id":1,"show":1,"starts_at":"2026-10-29T10:26:00Z","ends_at":"2026-10-29T10:46:00Z",...}
[201]
缺字段错误形态(实测首次提交):
{"created_at":["This field is required."],"auto_playlist_built":["This field is required."]}
5.4 schedule:排期域(排单核心)
端点:/api/v2/schedule(GET/POST)、/api/v2/schedule/{id}(GET/PUT/PATCH/DELETE)。把文件排进期次(file=1 为 3 分钟曲目,排 10:26:00Z 开播):
curl -s -u 'admin:q1w2e3r4' -X POST 'http://127.0.0.1:8142/api/v2/schedule' \
-H 'Content-Type: application/json' \
-d '{"instance":1,"file":1,"starts_at":"2026-10-29T10:26:00Z","ends_at":"2026-10-29T10:29:00Z","length":"00:03:00.035918","position":0,"fade_in":"00:00:00","fade_out":"00:00:00","cue_in":"00:00:00","cue_out":"00:03:00.035918","broadcasted":0,"played":false}' \
-w '\n[%{http_code}]\n'
实测回显:
{"id":1,"starts_at":"2026-10-29T10:26:00Z","ends_at":"2026-10-29T10:29:00Z","length":"00:03:00.035918","fade_in":"00:00:00","fade_out":"00:00:00","cue_in":"00:00:00","cue_out":"00:03:00.035918","position":0,"position_status":1,"broadcasted":0,"played":false,"instance":1,"file":1,"stream":null}
[201]
到点播出后核对该条排期——broadcasted 置 1、played 置 true(播出闭环的 API 证据):
curl -s -u 'admin:q1w2e3r4' 'http://127.0.0.1:8142/api/v2/schedule/1' \
| python3 -c "import sys,json; d=json.load(sys.stdin); print({k:d[k] for k in ('id','starts_at','broadcasted','played')})"
实测回显:
{'id': 1, 'starts_at': '2026-10-29T10:26:00Z', 'broadcasted': 1, 'played': True}
stream 字段:排外部网络流时填 webstream 的 id(与 file 二选一),即 webstreams 域的排期用法。
5.5 playlists:播放列表域
端点:/api/v2/playlists(GET/POST)、/api/v2/playlists/{id}(GET/PUT/PATCH/DELETE)、/api/v2/playlist-contents(列表项管理)。列表查询:
curl -s -u 'admin:q1w2e3r4' 'http://127.0.0.1:8142/api/v2/playlists' -w '\n[%{http_code}]\n'
实测回显(空库初始状态):
[]
[200]
播放列表可挂在节目上作为自动填充(shows 的 auto_playlist 字段引用 playlist id),smart-blocks 域则提供按条件(流派/时长)动态生成的智能块,与 playlists 同构(blocks→block-contents 两级端点)。
5.6 webstreams:外部流域
端点:/api/v2/webstreams(GET/POST)、/api/v2/webstreams/{id}(GET/PUT/PATCH/DELETE)。用于把远端网络流登记为可排期资产(如转播友台),登记后经 schedule 的 stream 字段排入时间线。列表查询实测:
curl -s -u 'admin:q1w2e3r4' 'http://127.0.0.1:8142/api/v2/webstreams' -w '\n[%{http_code}]\n'
实测回显:
[]
[200]
5.7 users:用户域
端点:/api/v2/users(GET/POST)、/api/v2/users/{id}(GET/PUT/PATCH/DELETE)。PATCH 修改资料实测:
curl -s -u 'admin:q1w2e3r4' -X PATCH 'http://127.0.0.1:8142/api/v2/users/1' \
-H 'Content-Type: application/json' -d '{"first_name":"Radio"}' -w '\n[%{http_code}]\n'
实测回显:
{"id":1,"role":"A","username":"admin","email":null,"first_name":"Radio","last_name":"","login_attempts":0,...}
[200]
⚠️ 注意:API 修改密码需同时满足 Django 密码策略(实测
q1w2e3r4会被判This password is too common拒绝);部署期改密可用容器内libretime-api shell -c方式(见部署指南 4.7 节)。role 取值:A=admin、M=program manager、H=host、G=guest。
5.8 preferences:系统偏好域
端点:/api/v2/preferences(GET 全量、PUT 整体)、/api/v2/preferences/{key}(GET 单项)。实测全量 21 项:
curl -s -u 'admin:q1w2e3r4' 'http://127.0.0.1:8142/api/v2/preferences' \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d),'项'); [print(k,'=',v) for k,v in list(d.items())[5:10]]"
实测回显(节选):
21 项
default_fade_in = 0.500
default_fade_out = 0.500
default_intro_playlist = 0
default_outro_playlist = 0
default_station_name = LibreTime
5.9 stream 与 mount-names:流配置/状态域
/api/v2/stream/preferences 返回流输入/输出的运行时摘要:
curl -s -u 'admin:q1w2e3r4' 'http://127.0.0.1:8142/api/v2/stream/preferences'
实测回显:
{"input_fade_transition":0.0,"message_format":0,"message_offline":"LibreTime - offline","replay_gain_enabled":true,"replay_gain_offset":0.0}
/api/v2/mount-names 返回当前输出挂载点清单:
curl -s -u 'admin:q1w2e3r4' 'http://127.0.0.1:8142/api/v2/mount-names'
实测回显:
[{"id":1,"mount_name":"main"}]
5.10 playout-history:播出历史域
端点:/api/v2/playout-history?starts_at=<UTC>&ends_at=<UTC>(GET)。这是 v2 列表端点中少数服务端过滤参数真实生效的域(实测不同时间窗返回不同结果):
curl -s -u 'admin:q1w2e3r4' \
'http://127.0.0.1:8142/api/v2/playout-history?starts_at=2026-10-29T00:00:00Z&ends_at=2026-10-30T00:00:00Z'
实测回显:
[{"id":1,"starts":"2026-10-29T10:26:00Z","ends":"2026-10-29T10:29:00Z","file":1,"instance":1}]
配套的 listener-counts 域按流挂载点记录听众数时序(需 icecast admin_password 配置后才采集)。
六、分页/过滤/排序通用约定
实测结论(对全部 /api/v2/* 列表端点验证):
- 无服务端分页:传
page=2等参数被忽略,恒返回全量数组(实测/api/v2/files?page=2仍返回完整列表)。媒体库大时建议自行缓存或按starts_at/ends_at(playout-history 专用)切窗。 - 列表无服务端过滤:
/api/v2/schedule?instance=2实测返回全部 2 条(含 instance=1),过滤参数被忽略;需客户端拿到后自行筛选。例外是 playout-history 的时间窗参数(5.10,规范内定义、实测生效)。 - 排序:列表默认按 id 升序返回;无排序参数。
- 错误格式统一:401 返回
{"detail":"Authentication credentials were not provided."};404 返回{"detail":"No <Resource> matches the given query."};400 返回字段级字典{"<field>":["This field is required."]}。 - 时间格式:一律 UTC ISO8601 带
Z(2026-10-29T10:26:00Z);时长格式HH:MM:SS.ffffff(00:03:00.035918)。
七、常见问题
Q1:X-API-Key 为什么在部分端点 401? v2 资源端点(files/shows/schedule 等)只实现了 Basic 与会话认证;X-API-Key 是 legacy 兼容层,仅 version/info/stream 等端点接受。统一用 Basic(admin 账号)最稳。
Q2:POST /rest/media 报 Incorrect API key?
legacy REST 的 Basic 用户名必须是 config.yml 的 general.api_key 且密码留空(-u '<API_KEY>:');用 admin 账号或 X-API-Key 头都不行。另外路径是 /rest/media,不是 /rest/media/upload(后者把 upload 当 id 查库报 400)。
Q3:POST 创建一直 400? 4.5.0 的序列化器把大量布尔/审计字段设为必填:shows 要 6 个布尔全给,show-instances 要 created_at 与 auto_playlist_built。按 5.2/5.3 的实测最小体照抄,缺啥按 400 返回的字段字典补。
Q4:排了单没有播出?
检查三点:排期时间是否 UTC(北京时间要 -8 换算);playout/liquidsoap 是否运行(部署期启动顺序故障见部署指南 11.2);GET /api/v2/schedule/{id} 看 broadcasted/played 是否翻转,未翻转则查 docker logs libretime-450-stack-playout-1。
Q5:大列表怎么处理? 无服务端分页(第六章),一次全量。媒体库上万首时在网关层缓存或改用 schema 域了解字段后按 id 区间自行实现增量拉取。
八、参考链接
- 官方 API 文档:https://libretime.org/docs/api/
- OpenAPI 规范源文件:https://github.com/libretime/libretime/blob/main/docs/openapi.yaml
- Django REST framework 错误格式参考:https://www.django-rest-framework.org/api-guide/errors/
- Icecast 状态页(配合 listener-counts 排查):https://icecast.org/docs/icecast-2.4.4/
- 《LibreTime 4.5.0 介绍与选型指南》 《LibreTime 4.5.0 Docker Compose 部署指南》 《LibreTime 4.5.0 配置参数详解》