EasyDown API Docs

API 计费与额度

了解各平台积分费率、已确认处理成本且内容受限时的扣费条件、免费错误情况,以及实际扣费与余额响应头和缓存计费规则。

成功解析按平台费率扣 credits:其他大多数支持平台 1 credits,YouTube 3 credits,Threads 2 credits,快手 / Kwai 2 credits,小红书 / RedNote 10 credits。请求失败、返回为空或作品不可用,本身不构成扣费依据。未返回媒体时,仅在处理成本和明确的内容限制均已确认后才扣费;当前这一例外仅适用于抖音、今日头条。 不支持的 URL、参数校验失败、Token 无效或无平台权限、临时故障、超时和原因不明的空结果均扣 0 credits。内容不可用但未确认处理成本时也不扣费。

平台每次计费请求扣除
其他大多数支持平台1 credits
YouTube3 credits
Threads2 credits
快手 / Kwai2 credits
小红书 / RedNote10 credits

计费真源:GET /api/v1/capabilities → data.billing。

哪些请求消耗积分

请求结果扣费规则
成功返回媒体,包括缓存命中按平台费率扣一次
已确认处理成本,且明确确认内容受限(抖音/今日头条)按平台费率扣一次
API Token 无效、过期、吊销或无平台权限0
不支持的 URL 或参数校验失败0
临时故障、超时或原因不明的空结果0
内容不可用,但未确认处理成本0

API Token 权限不足不等于作品本身受限,前者不扣费。收取处理费用不代表 EasyDown 可以获取私密、删除或其他受限内容。

每次请求按平台费率扣一次,不因媒体数量、清晰度或内部处理次数叠加。缓存返回媒体仍按同一费率计费。重新提交是新请求,不承诺跨请求免费重试。

响应

商业 API 已扣费响应会返回实际扣费和余额,即使内容不可用:

  • X-Credits-Charged: {actual_credits_charged}
  • X-Credits-Remaining: {balance}
  • X-EasyDown-Cache: HIT | MISS | SUPABASE | BYPASS

X-Credits-Charged 返回本次实际扣费,包括已扣费的失败;X-Credits-Remaining 返回余额。已计费的内容不可用响应包含 X-Credits-Charge-Reason: content_unavailable。

REST 与 MCP 使用相同平台费率和已确认内容限制的计费例外。MCP 的 billing.creditsCharged 返回本次实际扣费,失败结果也可能包含非零扣费。

不能仅凭 HTTP 错误、data: null 或 content_unavailable 判断免费。缺少扣费响应头或网络中断时,扣费状态未知;重新提交前请核对后台用量记录。

如对扣费有疑问,请通过 [email protected] 提供平台、请求时间、错误码和用量记录信息,不要发送 API Token。历史扣费按原始记录逐笔核查,本次说明不改变历史交易。

失败响应结构示意

以下是响应结构示意,不是新采集的真实付费调用。示例对应平台专用接口 /api/v1/platforms/douyin/parse,余额仅作说明;通用接口的状态字段可能不同。

确认处理成本后内容不可用:扣 1 credit

HTTP/1.1 404
Content-Type: application/json
X-Credits-Charged: 1
X-Credits-Remaining: 9
X-Credits-Charge-Reason: content_unavailable

{
  "status": 404,
  "data": null,
  "msg": "Content unavailable after processing",
  "code": "content_unavailable"
}

积分不足:扣 0 credits

HTTP/1.1 402
Content-Type: application/json
X-Credits-Charged: 0
X-Credits-Remaining: 0

{
  "status": 402,
  "data": null,
  "msg": "Insufficient credits",
  "code": "insufficient_credits"
}

先核对扣费,再处理错误

先读取扣费响应头,再处理错误。不要对已扣费的内容受限结果盲目自动重试;再次提交可能再次产生费用。

const response = await fetch('https://api.easydown.org/api/v1/platforms/douyin/parse', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.EASYDOWN_API_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ url: "https://v.douyin.com/f-QpBB_oD9Y/" }),
});
const chargedHeader = response.headers.get('X-Credits-Charged');
const creditsCharged = chargedHeader === null ? null : Number(chargedHeader);
const chargeReason = response.headers.get('X-Credits-Charge-Reason');
const payload = await response.json();
console.log({ httpStatus: response.status, creditsCharged, chargeReason });
if (!response.ok || payload.status !== 200) {
  if (creditsCharged === null || !Number.isFinite(creditsCharged)) {
    console.warn('Charge unknown: check dashboard usage before resubmitting.');
  }
  // No automatic retry: another submission is a new request.
  throw new Error(payload.code || 'parse_failed');
}