媒体

上传素材

把一张图 / 一段视频变成本站可用的媒体 URL。发布用的媒体必须存在本站对象存储上(外链会过期),所以先用它拿到 mediaUrl,再填进新建 / 修改的 media[].dataUrl。mode=upload 回一条五分钟有效的直传地址,你自己按返回的 Content-Type 发 PUT(字节不经过本站服务器:图片 8MB、视频 500MB);mode=transload 由本站代抓你给的外链再转存,只收图片与封面,上限 8MB。只产出 URL,不会改动任何内容。

POST/api/v1/media
posts:write写档限流Idempotency-Key 可选

鉴权与护栏

  • 请求头 Authorization: Bearer <长期凭证>,凭证在设置页「接入外部系统 → 长期凭证」签发,见 鉴权与权限。
  • 凭证需带 scope posts:write;签发者在工作区里的角色也要允许该动作。
  • 限流:写档,每分钟 10 次(按凭证计),超出回 429 并带 Retry-After。
  • 幂等:带 Idempotency-Key 就按它去重,不带也能调。

请求体(application/json)

modeenum: upload · transload必填

upload = 拿直传地址自己 PUT;transload = 让本站代抓外链转存。

kindenum: image · cover · video必填

image 正文配图 · cover 封面 · video 视频。

contentTypestring可选

upload 档必填:image/jpeg | png | webp 或 video/mp4 | webm | quicktime。

bytesinteger可选

upload 档必填:文件字节数,超上限直接拒。

urlstring (http/https)可选

transload 档必填:要转存的外链(只支持图片 / 封面)。

clientRequestIdstring可选

幂等键(8–128 chars of [A-Za-z0-9_.:-]);推荐放在 Idempotency-Key 请求头,头与 body 都给时以头为准。

调用规则

  • 直传地址只活 5 分钟,拿到就传;过期重新申请即可。
  • 视频一律走 upload 档;transload 只收图片与封面。

响应

成功返回 HTTP 201,信封为 { data, meta };右侧(窄屏在本页末尾)给出了各状态码的示例。所有错误都是 { error: { code, message, params }, meta },按机器码处理而不是按 message 匹配,码表见 错误码。

状态码可能的错误码
400invalid_input
401unauthenticated
402plan_limit
403forbidden / workspace_not_found
404not_found
409no_account / needs_reauth / replay
429rate_limited
500internal
502platform_error
503external_writes_off

示例

请求
curl -X POST "https://popkit.loxily.com/api/v1/media" \
  -H "Authorization: Bearer popkit_it_••••••••" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: acme-2026-09-21-001" \
  -d '{
  "mode": "upload",
  "kind": "video",
  "contentType": "video/mp4",
  "bytes": 48213000
}'
响应
upload 档
{
  "data": {
    "mode": "upload",
    "kind": "video",
    "mediaUrl": "https://storage.googleapis.com/socialhub-media/ws_01J7…/media/01J8ZN….mp4",
    "uploadUrl": "https://storage.googleapis.com/socialhub-media/…?X-Goog-Signature=…",
    "contentType": "video/mp4",
    "expiresInSec": 300,
    "next": "PUT the file bytes to uploadUrl with Content-Type: video/mp4 within 300s, then pass mediaUrl in media[].dataUrl."
  },
  "meta": {
    "requestId": "6a1d0c9e-2b7f-4e3a-8c5d-1f0e9b8a7c73"
  }
}