mirror of
https://github.com/truewhile/MeBox.git
synced 2026-11-12 19:34:24 +08:00
390 lines
11 KiB
YAML
390 lines
11 KiB
YAML
openapi: 3.0.3
|
||
info:
|
||
title: MeBox Mobile API
|
||
version: 1.0.0
|
||
description: |
|
||
MeBox 安卓客户端的稳定接入契约。所有路径以 `/api` 为前缀挂载,
|
||
本文档描述 `/api/v1` 部分;既有 `/api` 与 Emby/Jellyfin 入口保持兼容。
|
||
|
||
约定:
|
||
- JSON 字段使用 snake_case;
|
||
- 时间点为 RFC 3339 UTC 字符串,播放位置与时长使用整数毫秒;
|
||
- 集合为空时返回 `[]`,未知字段客户端必须忽略;
|
||
- 错误响应统一为 `code`、`message`、`request_id`、`retryable`;
|
||
- 能力开关只有在接口实现且当前可运行时才为 true。
|
||
servers:
|
||
- url: /api
|
||
security:
|
||
- bearerAuth: []
|
||
tags:
|
||
- name: server
|
||
- name: auth
|
||
paths:
|
||
/v1/server-info:
|
||
get:
|
||
tags: [server]
|
||
summary: 匿名读取实例身份与移动端能力
|
||
security: []
|
||
responses:
|
||
'200':
|
||
description: 实例可连接
|
||
headers:
|
||
Cache-Control:
|
||
schema:
|
||
type: string
|
||
description: 固定为 no-store
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ServerInfo'
|
||
'503':
|
||
description: 暂时无法读取实例身份
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/MobileError'
|
||
/v1/auth/login:
|
||
post:
|
||
tags: [auth]
|
||
summary: 账号密码登录并创建认证会话
|
||
security: []
|
||
parameters:
|
||
- $ref: '#/components/parameters/RequestId'
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/LoginRequest'
|
||
responses:
|
||
'200':
|
||
description: 登录成功
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/AuthResponse'
|
||
'400':
|
||
$ref: '#/components/responses/InvalidArgument'
|
||
'401':
|
||
$ref: '#/components/responses/InvalidCredentials'
|
||
'403':
|
||
description: 账号被禁用或已到期
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/MobileError'
|
||
'429':
|
||
$ref: '#/components/responses/RateLimited'
|
||
'503':
|
||
$ref: '#/components/responses/ServiceUnavailable'
|
||
/v1/auth/refresh:
|
||
post:
|
||
tags: [auth]
|
||
summary: 使用刷新令牌轮换令牌对
|
||
security: []
|
||
description: |
|
||
刷新令牌必须由 v1 登录签发并关联认证会话。同一 refresh token 的
|
||
并发提交只会真正轮换一次;轮换后 60 秒内重复提交返回同一次结果。
|
||
会话被撤销后刷新返回 SESSION_REVOKED。
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/RefreshRequest'
|
||
responses:
|
||
'200':
|
||
description: 刷新成功,新令牌继续归属同一 auth_session_id
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/AuthResponse'
|
||
'400':
|
||
$ref: '#/components/responses/InvalidArgument'
|
||
'401':
|
||
description: 刷新令牌无效、过期或会话已撤销
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/MobileError'
|
||
'503':
|
||
$ref: '#/components/responses/ServiceUnavailable'
|
||
/v1/auth/session:
|
||
get:
|
||
tags: [auth]
|
||
summary: 读取当前用户与认证会话
|
||
responses:
|
||
'200':
|
||
description: 会话有效
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/SessionResponse'
|
||
'401':
|
||
$ref: '#/components/responses/SessionInvalid'
|
||
'503':
|
||
$ref: '#/components/responses/ServiceUnavailable'
|
||
/v1/auth/logout:
|
||
post:
|
||
tags: [auth]
|
||
summary: 撤销当前认证会话
|
||
description: 幂等;重复退出同样返回 200。
|
||
responses:
|
||
'200':
|
||
description: 已退出(本机与远端)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
status:
|
||
type: string
|
||
example: ok
|
||
'401':
|
||
$ref: '#/components/responses/SessionInvalid'
|
||
'503':
|
||
$ref: '#/components/responses/ServiceUnavailable'
|
||
components:
|
||
securitySchemes:
|
||
bearerAuth:
|
||
type: http
|
||
scheme: bearer
|
||
bearerFormat: JWT
|
||
parameters:
|
||
RequestId:
|
||
name: X-Request-ID
|
||
in: header
|
||
required: false
|
||
description: |
|
||
可选的诊断 ID(8—128 位 ASCII 字母、数字或 `-_.:`)。服务器会在
|
||
响应头与错误体回传同一个值;非法值会被替换为新 UUID。该值不参与鉴权。
|
||
schema:
|
||
type: string
|
||
responses:
|
||
InvalidArgument:
|
||
description: 请求字段缺失或格式错误
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/MobileError'
|
||
InvalidCredentials:
|
||
description: 用户名或密码错误
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/MobileError'
|
||
SessionInvalid:
|
||
description: 访问令牌无效、过期或认证会话已撤销
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/MobileError'
|
||
RateLimited:
|
||
description: 请求过于频繁
|
||
headers:
|
||
Retry-After:
|
||
schema:
|
||
type: integer
|
||
description: 建议等待秒数
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/MobileError'
|
||
ServiceUnavailable:
|
||
description: 暂时性服务/存储错误,可安全重试
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/MobileError'
|
||
schemas:
|
||
ServerInfo:
|
||
type: object
|
||
required:
|
||
- name
|
||
- server_id
|
||
- server_version
|
||
- api_version
|
||
- min_supported_app_version_code
|
||
- capabilities
|
||
properties:
|
||
name:
|
||
type: string
|
||
example: MeBox
|
||
server_id:
|
||
type: string
|
||
format: uuid
|
||
description: 实例持久身份;备份克隆成独立实例时必须显式重置。
|
||
server_version:
|
||
type: string
|
||
example: MeBox-v0.1.16
|
||
api_version:
|
||
type: string
|
||
example: v1
|
||
min_supported_app_version_code:
|
||
type: integer
|
||
minimum: 1
|
||
capabilities:
|
||
$ref: '#/components/schemas/ServerCapabilities'
|
||
ServerCapabilities:
|
||
type: object
|
||
required:
|
||
- device_sessions
|
||
- playback_sessions
|
||
- reader_progress_v1
|
||
- reader_content_batch
|
||
- local_transcode
|
||
properties:
|
||
device_sessions:
|
||
type: boolean
|
||
description: M1 起为 true
|
||
playback_sessions:
|
||
type: boolean
|
||
description: 播放会话接口未实现前必须为 false
|
||
reader_progress_v1:
|
||
type: boolean
|
||
description: v1 阅读锚点/版本冲突未实现前必须为 false
|
||
reader_content_batch:
|
||
type: boolean
|
||
description: v1 批量正文与资源引用未实现前必须为 false
|
||
local_transcode:
|
||
type: boolean
|
||
description: 移动端可用的本地转码会话未实现前必须为 false
|
||
MobileUser:
|
||
type: object
|
||
required: [id, username, role, tier, is_active, force_password_reset]
|
||
properties:
|
||
id:
|
||
type: string
|
||
username:
|
||
type: string
|
||
nickname:
|
||
type: string
|
||
role:
|
||
type: string
|
||
enum: [admin, user]
|
||
tier:
|
||
type: string
|
||
example: free
|
||
is_active:
|
||
type: boolean
|
||
force_password_reset:
|
||
type: boolean
|
||
expires_at:
|
||
type: string
|
||
format: date-time
|
||
nullable: true
|
||
TokenPair:
|
||
type: object
|
||
required: [access_token, refresh_token, expires_in, token_type]
|
||
properties:
|
||
access_token:
|
||
type: string
|
||
refresh_token:
|
||
type: string
|
||
expires_in:
|
||
type: integer
|
||
description: 访问令牌有效秒数
|
||
token_type:
|
||
type: string
|
||
example: Bearer
|
||
LoginRequest:
|
||
type: object
|
||
required: [username, password, device_id]
|
||
properties:
|
||
username:
|
||
type: string
|
||
password:
|
||
type: string
|
||
device_id:
|
||
type: string
|
||
maxLength: 128
|
||
description: App 安装随机生成,不使用 IMEI/MAC 等硬件标识。
|
||
device_name:
|
||
type: string
|
||
maxLength: 128
|
||
client_name:
|
||
type: string
|
||
maxLength: 64
|
||
example: MeBox Android
|
||
client_version:
|
||
type: string
|
||
maxLength: 64
|
||
RefreshRequest:
|
||
type: object
|
||
required: [refresh_token]
|
||
properties:
|
||
refresh_token:
|
||
type: string
|
||
AuthResponse:
|
||
type: object
|
||
required: [auth_session_id, user, tokens]
|
||
properties:
|
||
auth_session_id:
|
||
type: string
|
||
format: uuid
|
||
user:
|
||
$ref: '#/components/schemas/MobileUser'
|
||
tokens:
|
||
$ref: '#/components/schemas/TokenPair'
|
||
SessionDevice:
|
||
type: object
|
||
properties:
|
||
device_id:
|
||
type: string
|
||
device_name:
|
||
type: string
|
||
client_name:
|
||
type: string
|
||
client_version:
|
||
type: string
|
||
last_used_at:
|
||
type: string
|
||
format: date-time
|
||
expires_at:
|
||
type: string
|
||
format: date-time
|
||
SessionResponse:
|
||
type: object
|
||
required: [auth_session_id, user]
|
||
properties:
|
||
auth_session_id:
|
||
type: string
|
||
format: uuid
|
||
user:
|
||
$ref: '#/components/schemas/MobileUser'
|
||
session:
|
||
$ref: '#/components/schemas/SessionDevice'
|
||
MobileError:
|
||
type: object
|
||
required: [code, message, request_id, retryable]
|
||
properties:
|
||
code:
|
||
type: string
|
||
enum:
|
||
- INVALID_ARGUMENT
|
||
- INVALID_CREDENTIALS
|
||
- TOKEN_EXPIRED
|
||
- SESSION_REVOKED
|
||
- ACCOUNT_DISABLED
|
||
- ACCOUNT_EXPIRED
|
||
- PERMISSION_DENIED
|
||
- PROFILE_PIN_REQUIRED
|
||
- RATE_LIMITED
|
||
- UPSTREAM_UNAVAILABLE
|
||
- TRANSCODE_BUSY
|
||
- PLAYBACK_SESSION_NOT_FOUND
|
||
- RESOURCE_EXPIRED
|
||
- PROGRESS_CONFLICT
|
||
- SERVICE_UNAVAILABLE
|
||
message:
|
||
type: string
|
||
request_id:
|
||
type: string
|
||
retryable:
|
||
type: boolean
|
||
retry_after_sec:
|
||
type: integer
|
||
minimum: 0
|
||
details:
|
||
description: 可选的稳定结构化细节,未定义时客户端必须忽略。
|