YumCut v0.1.0 API 使用详解

YumCut v0.1.0 User API 实测详解:Bearer Key 认证与 read/write 作用域、49 个 OpenAPI 路径按十大域分组,账户/代币/项目生命周期/审批状态机/签名上传授权逐条 curl 实测,含 Idempotency-Key 幂等强制与五类错误码速查排障。

YumCutYumCutNode.js2026/10/25

YumCut v0.1.0 API 使用详解

目标:把 YumCut v0.1.0 的 User API 讲透并逐条跑通——认证方式、API Key 作用域、账户/代币/设置、项目全生命周期(创建→审批→下载)、媒体上传授权、目录数据、调度与 Telegram 集成,以及统一错误码。全部示例为 curl 实测,回显逐行照抄(取值日期 2026-10-25,实测环境为部署篇搭建的四服务编排,地址 http://192.168.146.128:8130)。部署与 API Key 开通见《YumCut v0.1.0 Docker Compose 部署指南》,参数含义见《YumCut v0.1.0 配置参数详解》。

一、API 概览

YumCut 对外提供一套面向自动化的 User API(OpenAPI 3.1 文档,标题 YumCut User API),设计目标是让外部工具、定时任务与 AI Agent 端到端完成「建项目 → 审批 → 取成片」:

  • Base 路径:/api/user/v1(OpenAPI servers 定义为「当前部署」,即 https://<你的域名>/api/user/v1)
  • 认证:Authorization: Bearer <API Key>,Key 以 ycu_ 开头
  • 规模:实测 openapi.json 共 49 个路径,覆盖账户、代币、设置、项目、审批、下载、媒体授权、音色/模板/角色目录、调度器、Telegram 十大域
  • 幂等:所有「创建类」端点强制要求 Idempotency-Key 头(实测见 5.1)

💡 技术拓展:API 密钥认证不止 Bearer 一种形态。常见方案对比——

方案特点适用场景
Bearer Token一个头搞定,配合 HTTPS 使用服务端到服务端调用,YumCut 所用
HMAC 签名请求级签名防重放高安全开放平台和金融接口
OAuth2 Client Credentials可轮换、可过期多租户 SaaS 开放平台

YumCut 选 Bearer + 作用域(read/write)两档,胜在简单;代价是 Key 泄露即全权,务必只放服务端保管。

二、认证与 API Key

2.1 Key 的格式与存储

API Key 明文形如 ycu_ 加 43 位 base64url 随机串(32 字节),只在创建时可见;数据库 UserApiKey 表只存 SHA-256 摘要(tokenHash)与前 12 位前缀(tokenPrefix),泄露数据库不泄露 Key。创建方法见部署篇 5.3。

2.2 作用域(read / write)

Key 创建时可指定 scopes,缺省 ["read","write"] 全开。实测一把只有 read 作用域的 Key:

# 读接口:放行
curl -s -o /dev/null -w 'HTTP %{http_code}\n' \
  -H "Authorization: Bearer <read-only-key>" http://192.168.146.128:8130/api/user/v1/projects

实测回显:

HTTP 200
# 写接口:拒绝
curl -s -X PATCH -H "Authorization: Bearer <read-only-key>" \
  -H 'Content-Type: application/json' \
  http://192.168.146.128:8130/api/user/v1/account/language --data '{"language":"ru"}'

实测回显:

{"error":{"code":"FORBIDDEN","message":"User API key scope is insufficient"}}

不带 Key 与带错误 Key 一律 401:

curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://192.168.146.128:8130/api/user/v1/projects
curl -s -o /dev/null -w 'HTTP %{http_code}\n' -H "Authorization: Bearer wrong-key" http://192.168.146.128:8130/api/user/v1/projects

实测回显:

HTTP 401
HTTP 401

三、账户与代币

3.1 账户信息 GET /account

curl -s -H "Authorization: Bearer $KEY" http://192.168.146.128:8130/api/user/v1/account

实测回显:

{"id":"eb07c821-d05c-11f1-bcea-02755b8cf07b","email":"admin@yumcut.local","name":"admin","image":null,"preferredLanguage":"en","createdAt":"2026-10-25T10:14:52.388Z","tokenBalance":500,"isGuest":false}

tokenBalance 是代币余额,建项目与重生成都从这里扣费。

3.2 语言偏好 GET/PATCH /account/language

界面与产物的默认语言,实测只接受 en/ru:

curl -s -X PATCH -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  http://192.168.146.128:8130/api/user/v1/account/language --data '{"language":"ru"}'

实测回显:

{"language":"ru"}

传非法值返回字段级校验错误(改回 en 的实测回显为 {"language":"en"}):

{"error":{"code":"VALIDATION_ERROR","message":"Invalid account language payload","details":{"formErrors":[],"fieldErrors":{"language":["Invalid option: expected one of \"en\"|\"ru\""]}}}}

3.3 代币余额与价目 GET /tokens

curl -s -H "Authorization: Bearer $KEY" http://192.168.146.128:8130/api/user/v1/tokens

实测回显:

{"balance":500,"perSecondProject":1,"minimumProjectTokens":30,"minimumProjectSeconds":30,"characterProjectTokens":75,"characterProjectTokenCosts":{"high":75,"low":10},"actionCosts":{"scriptRevision":10,"imageGeneration":3,"audioRegeneration":40,"imageRegeneration":1,"characterImage":10},"signUpBonus":90}

解读:余额 500;计费规则为「每秒视频 1 代币、最低 30 秒起(即建项目至少 30 代币)」;角色项目 75 代币;各项重生成单独计价(改脚本 10、重配音 40、重配图 1 等);注册赠送 90。

3.4 代币流水 GET /tokens/history

curl -s -H "Authorization: Bearer $KEY" http://192.168.146.128:8130/api/user/v1/tokens/history

实测回显(输出节选,实测首尾):

{"items":[{"id":"efa7e5a1-29e5-4583-b99f-ffd155e92bbf","delta":30,"balanceAfter":500,"type":"PROJECT_FAILURE_REFUND","description":"Project failed refund","initiator":"system:project-failure-refund","metadata":{"projectId":"38c7b956-1227-4ab6-bf47-ec8f160cb665"},"createdAt":"2026-10-25T10:24:48.385Z"},{"id":"cbce6cb2-a3f0-43d3-a1ed-2eea97fa3bb7","delta":-30,"balanceAfter":470,"type":"PROJECT_CREAT...

这条流水是「建项目扣 30 → 项目失败自动退 30」的完整闭环,type 字段可区分消费(PROJECT_CREATION)与退款(PROJECT_FAILURE_REFUND)。

3.5 全局设置 GET/PATCH /settings

curl -s -H "Authorization: Bearer $KEY" http://192.168.146.128:8130/api/user/v1/settings

实测回显(输出节选):

{"includeDefaultMusic":true,"addOverlay":true,"includeCallToAction":true,"projectEmailsEnabled":true,"autoApproveScript":true,"autoApproveAudio":true,"watermarkEnabled":true,"captionsEnabled":true,"characterCreationSettings":{"addOverlay":false,"watermarkEnabled":false,"captionsEnabled":true,"includeCallToAction":true},"defaultDurationSeconds":null,"sidebarOpen":true,...

解读:autoApproveScript/autoApproveAudio 全开时项目可无人值守跑完;关掉则流水线停在对应审批节点等 API 确认(审批端点见第六章)。

四、项目创建与报价

4.1 报价预检 POST /project-cost

建项目前先问价,不扣费:

curl -s -X POST -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  http://192.168.146.128:8130/api/user/v1/project-cost --data '{"durationSeconds":30}'

实测回显:

{"tokenCost":30,"balance":500,"hasEnoughTokens":true,"balanceAfter":470,"detail":{"projectExperience":"story","durationSeconds":30,"languageCount":1,"languages":["en"]}}

hasEnoughTokens 与 balanceAfter 直接给出「能不能建、建完剩多少」。

4.2 创建项目 POST /projects(强制幂等)

该端点必须携带 Idempotency-Key 头,缺少时直接报错:

curl -s -X POST -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  http://192.168.146.128:8130/api/user/v1/projects --data '{}'

实测回显:

{"error":{"code":"VALIDATION_ERROR","message":"Idempotency-Key header is required for this endpoint"}}

带上幂等键后再逐项校验请求体(缺 durationSeconds 的实测报错):

curl -s -X POST -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: doc-test-0001' \
  http://192.168.146.128:8130/api/user/v1/projects --data '{}'

实测回显:

{"error":{"code":"VALIDATION_ERROR","message":"Duration is required","details":{"formErrors":[],"fieldErrors":{"durationSeconds":["Duration is required"]}}}}

⚠️ 幂等键的用法:同一个 Idempotency-Key 重复提交只会创建一次项目,网络重试/超时重发不会产生重复扣费。键值可用 UUID 或「业务单号」,由调用方保证唯一。POST /groups 等创建类端点同样强制该头。

4.3 项目查询与状态

列表 GET /projects(游标分页,limit 默认 50):

curl -s -H "Authorization: Bearer $KEY" http://192.168.146.128:8130/api/user/v1/projects

实测回显:

{"items":[{"id":"38c7b956-1227-4ab6-bf47-ec8f160cb665","title":"Explain why self-hosting sa...","status":"error","prompt":"Explain why self-hosting saves money, in a fun story style","finalVideoUrl":null,"finalVoiceoverUrl":null,"createdAt":"2026-10-25T10:16:04.923Z","updatedAt":"2026-10-25T10:24:48.412Z"}],"limit":50,"nextCursor":null}

详情 GET /projects/{projectId} 返回完整字段(含 rawScript、languageVariants 等,节选从略);轻量轮询用 GET /projects/{projectId}/status:

curl -s -H "Authorization: Bearer $KEY" \
  http://192.168.146.128:8130/api/user/v1/projects/38c7b956-1227-4ab6-bf47-ec8f160cb665/status

实测回显:

{"status":"error","statusInfo":{"message":"Script generation failed Refunded 30 tokens to user balance due to project failure."},"updatedAt":"2026-10-25T10:24:48.412Z"}

该项目失败于脚本生成(渲染脚本工作区为私有仓库,预期失败,见介绍篇),失败后系统自动退款。进行中的项目可用 POST /projects/{projectId}/stop 主动停止。

五、审批流端点

项目状态机为「脚本 → 配音 → 画面 → 成片」逐级推进,每一级都有对应的 request/approve/regenerate 端点:

阶段端点作用
脚本POST /projects/{id}/script/request请求生成/改写脚本
脚本POST /projects/{id}/script/approve批准脚本,进入配音
脚本POST /projects/{id}/script/final提交最终脚本定稿
配音GET /projects/{id}/audios、POST .../audios/request、.../audios/approve、.../audios/regenerate配音候选、请求、批准、重生成
画面POST /projects/{id}/images/regenerate、.../images/replace逐张重生成/替换
成片POST /projects/{id}/video/recreate用当前素材重新合成

状态不匹配时返回 CONFLICT 而不是静默失败。实测对 error 状态的项目批准脚本:

curl -s -X POST -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  http://192.168.146.128:8130/api/user/v1/projects/38c7b956-1227-4ab6-bf47-ec8f160cb665/script/approve --data '{}'

实测回显:

{"error":{"code":"CONFLICT","message":"Project is not awaiting script approval"}}

六、下载与媒体授权

6.1 成片/配图下载

GET /projects/{id}/downloads/video 与 .../downloads/image 返回带时效的下载 URL。成片未产出时返回 404:

curl -s -H "Authorization: Bearer $KEY" \
  http://192.168.146.128:8130/api/user/v1/projects/38c7b956-1227-4ab6-bf47-ec8f160cb665/downloads/video

实测回显:

{"error":{"code":"NOT_FOUND","message":"Final video not found"}}

6.2 上传授权 POST /storage/upload-token

向存储服务上传文件前,先向主应用换取一份 RSA 签名授权:

curl -s -X POST -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
  http://192.168.146.128:8130/api/user/v1/storage/upload-token \
  --data '{"kind":"user-image","contentType":"image/png","sizeBytes":1024}'

实测回显(签名值已截断):

{"data":"{\"expiresAt\":\"2026-10-25T10:52:36.240Z\",\"issuedAt\":\"2026-10-25T10:47:36.240Z\",\"maxBytes\":10485760,\"mimeTypes\":[\"image/png\",\"image/jpeg\",\"image/webp\"],\"nonce\":\"aa9efd0cef20bd7ae579524e95851950\",\"purpose\":\"user-character-image\",\"userId\":\"eb07c821-d05c-11f1-bcea-02755b8cf07b\",\"version\":1}","signature":"o6pvXevlwZQNuCkkxiaTahAwqjx5CrZKiEn70+vqqULn/DL2LimiFYv0Vt(已截断)"}

解读:data 是授权明文(5 分钟有效、限 10 MB、限三种图片类型、一次性 nonce),signature 是主应用私钥对它的签名;上传时把两者一并 POST 给存储服务,存储用公钥验签放行。相关角色端点还有 POST /characters/custom/upload(上传自定义角色图)与 POST /characters/custom/generate(生成角色)。

6.3 媒体访问授权 POST /media/grant

为媒体路径换取访问授权;路径不存在时返回:

{"error":{"code":"FORBIDDEN","message":"File not found"}}

七、目录数据端点

以下均为只读目录,供建项目时选音色/模板/角色:

端点实测回显(节选)说明
GET /voices{"voices":[],"providerAvailabilityRules":[{"projectExperiences":["character"],"modes":["idea"],"languages":["ru"],"providers":["inworld"]}]}音色列表按服务商可用性规则过滤;未配置 AI 服务商时为空
GET /templates[]视频模板,初始为空
GET /templates/{id}模板详情按 ID 取单条
GET /characters{"global":[{"id":"359d74c2-...","title":"Ada Mentor","description":"Precise host for educational narratives.","variations":[{"id":"3695ecba-...","imageUrl":"http://192.168.146.128:8129/api/media/characters/me-1.png","status":"ready"}]},...]}内置全局角色库,含变体与预览图(URL 即存储服务的 STORAGE_PUBLIC_URL 拼接结果)
GET /characters/catalog{"categories":[{"id":"brainrot","title":{"en":"Brainrot","ru":"Brainrot"},"subtitle":{"en":"Viral short-form characters with chaotic social energy",...}},...]}角色分类目录,多语言文案
GET /characters/{slug}、GET /characters/variations/{variationId}/preview-image角色详情/变体预览图按标识取单条
POST /characters/{slug}/favorite、DELETE 同址收藏/取消收藏写端点,需 write 作用域
POST /characters/mine、POST /characters/mine/{id}/variations、DELETE .../variations/{vid}我的角色与变体管理写端点
GET /image-pranks{"categories":[]}图片恶作剧目录
GET /image-pranks/{slug}、GET /projects/{id}/image-prank-reuse恶作剧详情/项目复用—
POST /groups项目分组创建强制 Idempotency-Key(实测同 4.2)

八、调度与集成端点

端点作用实测
GET/PATCH/POST /scheduler/settings定时发布设置实测返回 {"enabled":false}(ENABLE_PUBLISH_SCHEDULER=0)
POST /scheduler/channels绑定 YouTube 发布频道实测返回 {"error":{"code":"FORBIDDEN","message":"Scheduler is disabled"}}
DELETE /scheduler/channels/{channelId}、POST .../revoke解绑/撤销授权调度器关闭时同样被拦
POST /scheduler/projects/{projectId}、POST /scheduler/tasks/{taskId}/cleanup-request排期发布/清理任务同上
GET/DELETE /telegram/accountTelegram 绑定状态实测返回 {"connected":false,"account":null,"enabled":false}
POST /telegram/link-token生成绑定令牌需配置 TELEGRAM_BOT_TOKEN 后可用

这组端点的实测一致说明:调度与 Telegram 属于「配置驱动」能力,对应参数未开启时 API 返回明确的禁用错误而不是超时或 500。

九、错误码速查与排障

把全文实测到的错误归拢成一张速查表:

HTTPcode触发场景处理
401UNAUTHORIZED无 Key / Key 错误(Invalid user API key)检查 Authorization: Bearer 头
403FORBIDDEN作用域不足(scope is insufficient)、功能未启用(Scheduler is disabled)、媒体路径不存在换 write Key / 开启对应配置
404NOT_FOUND成片未产出(Final video not found)先查 /status,等流水线完成
409CONFLICT状态机不允许当前操作(not awaiting script approval)按 /status 的当前状态选正确端点
400VALIDATION_ERROR缺 Idempotency-Key、字段缺失/非法按 details.fieldErrors 逐项修正

排障通则:先 GET /projects/{id}/status 看状态机位置,再对照上表选端点;扣费疑问用 GET /tokens/history 的流水逐笔核对,失败项目会有 PROJECT_FAILURE_REFUND 自动退款。

十、参考链接