EasyDown API Docs

API credits and billing

Understand platform credit rates, confirmed content-restriction charges, free error cases, balance headers, and cache billing.

Successful parses are charged by platform. Most other supported platforms: 1 credit; YouTube: 3 credits; Threads: 2 credits; Kuaishou / Kwai: 2 credits; RedNote / Xiaohongshu: 10 credits. A failed request, empty response, or unavailable post alone does not trigger a charge. A no-media request is charged only when both a processing cost and a clear content restriction are confirmed. This exception currently applies to Douyin and Toutiao only. Unsupported URLs, input validation failures, invalid or unauthorized API tokens, temporary failures, timeouts, and unexplained empty results cost 0 credits. Unavailable content without a confirmed processing cost is also free.

PlatformCredits per charged request
Most other supported platforms1 credit
YouTube3 credits
Threads2 credits
Kuaishou / Kwai2 credits
RedNote / Xiaohongshu10 credits

Source of truth: GET /api/v1/capabilities → data.billing.

When requests use credits

Request outcomeCredits charged
Downloadable media returned, including a cache hitPlatform rate, once
Confirmed processing cost AND confirmed content restriction (Douyin / Toutiao)Platform rate, once
Invalid, expired, revoked, or platform-unauthorized API token0
Unsupported URL or input validation failure0
Temporary failure, timeout, or unexplained empty result0
Unavailable content without a confirmed processing cost0

API token permission errors are not content restrictions and are free. Charging for processing does not mean EasyDown can retrieve private, deleted, or otherwise restricted content.

Each request is charged once at the platform rate, regardless of the number of media files, qualities, or internal processing attempts. Cache hits that return media use the same rate. A new submission is a new request, not a free retry.

Response

Charged commercial responses include the actual charge and balance, even when content is unavailable:

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

X-Credits-Charged reports the actual charge, including charged failures; X-Credits-Remaining reports the returned balance. Charged content-unavailable responses include X-Credits-Charge-Reason: content_unavailable.

REST and MCP use the same platform rates and confirmed content-restriction exception. MCP returns the actual charge in billing.creditsCharged, including on a failed result.

Do not infer a zero charge from an HTTP error, data: null, or the content_unavailable code. If a billing header is missing or the connection is interrupted, the charge is unknown: check dashboard usage records before resubmitting.

Billing question? Email [email protected] with the platform, request time, error code and usage-record details. Never send an API token. Historical charges are checked against their original records; this clarification does not change past transactions.

Illustrative failure responses

These are response-format illustrations, not newly captured paid requests. They show the platform-specific endpoint /api/v1/platforms/douyin/parse; balances are illustrative. Common endpoint status fields can differ.

Content unavailable after a confirmed processing cost: 1 credit charged

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"
}

Insufficient credits: 0 credits charged

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"
}

Check billing before handling an error

Read the billing headers before handling an error. Do not blindly retry a charged content-restriction failure; another submission can incur another charge.

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');
}