Quickstart
One API key and one JSON envelope for 165 social, e-commerce and web data endpoints. Only successful calls that return data are charged.
Four steps to a first call
Create an API key
Create a key in the console and, if you like, limit the endpoints it can call (scopes). The full key is shown once, when you create it, so save it right away: the server keeps only a hash and cannot show it again.
export QOVIA_KEY="sk-qovia-…"
Top up
A new account gets 50 trial calls on any endpoint, counted only when a call returns data; after that, calls are paid from a prepaid balance. Top up in the console by card or Alipay (through Stripe), or with USDT (TRC-20): a card or Alipay payment is credited as soon as it succeeds, USDT about a minute after the transfer confirms. When the balance cannot pay for a call, nothing runs and you get 402
Top upinsufficient_balance.Check the keyGET
/v1/accountConfirms the API key works and returns balance and plan. Not charged.
curl https://api.qovia.ai/v1/account \ -H "Authorization: Bearer $QOVIA_KEY"
Example response
{ "request_id": "00000000-0000-0000-0000-000000000000", "data": { "user": { "id": "00000000-0000-0000-0000-000000000000", "email": "you@example.com" }, "api_key": { "id": "00000000-0000-0000-0000-000000000000", "name": "production", "scopes": [ "*" ], "expires_at": null }, "billing": { "balance_usd": "10.000000", "plan": "payg", "rpm_limit": null } }, "meta": { "billed": false } }Make your first call
Try Bilibili video search (
GET /v1/raw/bilibili/search): it serves live data at $0.0005 per successful call.curl 'https://api.qovia.ai/v1/raw/bilibili/search?keyword=%E5%8F%B0%E7%A7%AF%E7%94%B5' \ -H "Authorization: Bearer $QOVIA_KEY"
Replace
$QOVIA_KEYwith your API key{ "request_id": "00000000-0000-0000-0000-000000000000", "data": { "items": [ { "id": "soc_bil_2913ac9c522a", "src": "social", "platform": "bilibili", "lang": "zh-CN", "text": "「小白」全球芯片代工王!万字台积电发展史", "author": { "uid_hash": "ca5fa000e345", "mid": "8969156", "name": "小白测评" }, "metrics": { "plays": 689248, "likes": 20365, "saves": 7230, "comments": 1348, "danmaku": 2676 }, "extra": { "source_id": "BV1DkoeYhExZ", "url": "https://www.bilibili.com/video/BV1DkoeYhExZ", "title": "「小白」全球芯片代工王!万字台积电发展史", "published_at": "2025-03-26T18:30:00+08:00", "category": { "id": 95, "name": "数码" }, "tags": [ "芯片", "数码", "台积电", "手机芯片" ], "cover": "https://i0.hdslb.com/bfs/archive/8f62d780e4e308bafa8c9f6c4d14ce5a28b2ce0b.jpg" }, "prov": { "hash": "0xc16f694e973143c1", "ts": "2026-10-20T12:00:00+08:00", "source": "live" } } ], "cursor": 2, "has_more": true }, "meta": { "billed": true, "charged_usd": "0.000500", "balance_usd": "9.999500", "empty": false } }Catalog sample, not live data
Only a successful call that returns data is charged; its
See this endpoint's full referencemetasays what it cost and the balance left (charged_usd,balance_usd). Empty results and failures are not charged.
Base URL and authentication
Every endpoint lives under one base URL:
https://api.qovia.aiSend the API key with every request, as a Bearer token in the Authorization header:
Authorization: Bearer $QOVIA_KEY- You can send
x-api-key: <API Key>instead; when both are present,Authorizationwins. - The key is read from these two headers only, never from the URL or a cookie.
- Call the API from your server: browser requests from other sites are refused (CORS), so the key never has to sit in web page code.
- A missing, malformed, revoked or expired key gets 401
invalid_api_key; 30 failed attempts from one IP within a minute get 429too_many_auth_failures.
Scopes
A key carries one or more scopes, picked when you create it; calling an endpoint outside them gets 403 scope_denied.
| scope | Grants |
|---|---|
* | Every endpoint |
search | Cross-domain search |
raw:* | Every raw endpoint |
raw:<platform> | Every raw endpoint of one platform: raw:douyin, raw:kuaishou, raw:bilibili, raw:xingtu, raw:tieba, raw:zhihu, raw:wechat, raw:xiaohongshu, raw:pgy, raw:tiktok, raw:youtube, raw:instagram, raw:x, raw:reddit, raw:weibo, raw:toutiao, raw:taobao, raw:jd, raw:shopee, raw:amazon, raw:fliggy, raw:news, raw:cljx, raw:huahuo |
Requests
- GET endpoints
- Parameters go in the query string and are converted to their declared types: integers as digits, booleans as
true/false/1/0/yes/no, and arrays by repeating the name (?id=1&id=2). - POST endpoints
- The body is one JSON object, sent with
Content-Type: application/json. A body that is not valid JSON, or not an object, gets 400invalid_params. - Validation
- Only the listed parameters are accepted. An unknown one, a missing required one, or a wrong type or format gets 400
invalid_params, not charged. Itsmessagestarts with the parameter's name (item_id: …); a missing or unknown parameter starts it withparams: …. - Defaults
- Optional parameters you leave out get their defaults on the server (see each parameter's Default).
Responses
A success is HTTP 200 with the shared envelope. Here is a paid call in full:
{
"request_id": "00000000-0000-0000-0000-000000000000",
"data": {
"items": [
{
"id": "soc_bil_2913ac9c522a",
"src": "social",
"platform": "bilibili",
"lang": "zh-CN",
"text": "「小白」全球芯片代工王!万字台积电发展史",
"author": {
"uid_hash": "ca5fa000e345",
"mid": "8969156",
"name": "小白测评"
},
"metrics": {
"plays": 689248,
"likes": 20365,
"saves": 7230,
"comments": 1348,
"danmaku": 2676
},
"extra": {
"source_id": "BV1DkoeYhExZ",
"url": "https://www.bilibili.com/video/BV1DkoeYhExZ",
"title": "「小白」全球芯片代工王!万字台积电发展史",
"published_at": "2025-03-26T18:30:00+08:00",
"category": {
"id": 95,
"name": "数码"
},
"tags": [
"芯片",
"数码",
"台积电",
"手机芯片"
],
"cover": "https://i0.hdslb.com/bfs/archive/8f62d780e4e308bafa8c9f6c4d14ce5a28b2ce0b.jpg"
},
"prov": {
"hash": "0xc16f694e973143c1",
"ts": "2026-10-20T12:00:00+08:00",
"source": "live"
}
}
],
"cursor": 2,
"has_more": true
},
"meta": {
"billed": true,
"charged_usd": "0.000500",
"balance_usd": "9.999500",
"empty": false
}
}Catalog sample, not live data
Success
| Field | Type | Description |
|---|---|---|
request_id | string | The call's ID (its usage record), also in the X-Request-Id header and in the console usage log. |
data | object | array | null | The endpoint's data; see each endpoint's response example. An empty result may be an empty structure (e.g. empty items) or null; check meta.empty. |
meta.billed | boolean | Whether this call was charged to the balance; false for empty results. |
meta.charged_usd | string | Amount charged in USD, 6 decimals; "0.000000" when nothing was charged. |
meta.balance_usd | string | Balance after settlement, USD, 6 decimals. |
meta.empty | boolean | The result is empty: not charged. |
An empty result is still HTTP 200 with meta.empty true, not charged; data may be an empty structure or null, so check meta.empty.
Errors
| Field | Type | Description |
|---|---|---|
error.code | string | The error code; see the error table. Branch on code. |
error.message | string | A short English explanation. One code can have several messages (the error table lists them all), so do not branch on it. Never contains the data source's own error text. |
error.request_id | string | Same as the X-Request-Id header (see below). |
error.support | string | Where to get help (Telegram); include the request_id so we can find the call. |
Response headers
| Header | Sent with | Description |
|---|---|---|
X-Request-Id | Every response except an unexpected plain-text 500 | Same as request_id in the body. For a reserved call (success, empty, or a failure after reservation) it is the usage record ID; a request refused before reservation keeps the X-Request-Id you sent, or gets a generated one. |
X-Qovia-Charged | Success (including empty)Errors: upstream_busy, upstream_timeout, upstream_error, upstream_rejected, not_found | Charged for this call, USD, 6 decimals; 0.000000 when nothing was charged or it was refunded. |
X-Qovia-Balance | Success (including empty)Errors: upstream_busy, upstream_timeout, upstream_error, upstream_rejected, not_found | Balance after settlement, USD, 6 decimals. |
Retry-After | Errors: too_many_auth_failures, rate_limited, too_many_unbilled, endpoint_busy, upstream_busy | Seconds to wait before retrying. |
WWW-Authenticate | Errors: invalid_api_key | Bearer realm="qovia". |
Allow | Errors: method_not_allowed | The methods this path supports. |
/v1 only takes GET and POST: other methods (e.g. PUT, DELETE) get a framework 405 {"detail": "Method Not Allowed"}, and an unexpected server error may be a plain-text 500. Neither is charged.
Billing
- Only successful calls that return data are charged.
- Failures, empty results and timeouts are not charged: the reserved charge is given back automatically.
- Calls are paid from a prepaid balance shared by every endpoint. Top up by card, Alipay or USDT (TRC-20); it is credited automatically.
- When the balance cannot pay for a call, nothing runs and you get 402
insufficient_balance. - Every call reports its charge in
metaand in theX-Qovia-Charged/X-Qovia-Balanceheaders.
Tiered prices
Each product is priced in marginal monthly tiers: within a calendar month, billed calls past a threshold are priced at the next tier.
| Product | Billed calls a month | Per 1k | Per call |
|---|---|---|---|
| Search | Any volume | $5 | $0.005 |
| Raw endpoints | 0 – 5M | $1.5 | $0.0015 |
| Raw endpoints | 5M+ | $1 | $0.001 |
Fixed-price endpoints
These endpoints are not tiered: every successful call costs a fixed price.
| Price | Endpoints |
|---|---|
| $0.0005 / call$0.5 per 1k | Douyin (8), Kuaishou (4), Bilibili (5), Douyin Xingtu (2) |
| $0.001 / call$1 per 1k | Douyin (3), Kuaishou (5), Bilibili (3), Douyin Xingtu (3), Zhihu (8), TikTok (8), YouTube (6), Instagram (3), X (Twitter) (6), Reddit (6), Weibo (7), Toutiao (3) |
| $0.0012 / call$1.2 per 1k | Douyin (1) |
| $0.0015 / call$1.5 per 1k | Cili Juxing (12), Huahuo (6) |
| $0.002 / call$2 per 1k | Instagram (3) |
| $0.005 / call$5 per 1k | Kuaishou (2), WeChat Official Accounts & Channels (4), Xiaohongshu (RedNote) (6), Xiaohongshu Pugongying (1) |
| $0.01 / call$10 per 1k | Douyin Xingtu (11), Xiaohongshu Pugongying (10) |
| $0.012 / call$12 per 1k | Douyin (1) |
| $0.0135 / call$13.5 per 1k | Taobao & Tmall (1) |
| $0.01691 / call$16.91 per 1k | Douyin (1), WeChat Official Accounts & Channels (1), Xiaohongshu (RedNote) (2), Taobao & Tmall (1) |
| $0.0195 / call$19.5 per 1k | JD.com (1) |
| $0.02536 / call$25.36 per 1k | Douyin (1), Douyin Xingtu (1), Xiaohongshu (RedNote) (3), Xiaohongshu Pugongying (1) |
| $0.08451 / call$84.51 per 1k | Douyin Xingtu (1) |
| $0.169 / call$169.02 per 1k | WeChat Official Accounts & Channels (1) |
| $0.2535 / call$253.53 per 1k | WeChat Official Accounts & Channels (1) |
Rate limits
- Accounts and endpoints
- No rate limits
- No rate limits: Qovia does not limit requests per minute per account or per endpoint. Only repeated failed authentication from one IP is throttled (429 `too_many_auth_failures`).
- When a 429 or 503 carries a
Retry-Afterheader, wait that many seconds before you retry. A 503endpoint_unavailablehas none: the endpoint is not live, so retrying will not help.
Errors
An error comes with its HTTP status and the error envelope:
{
"error": {
"code": "insufficient_balance",
"message": "insufficient balance for this request",
"request_id": "00000000-0000-0000-0000-000000000000"
}
}| code | HTTP | Billing | Description |
|---|---|---|---|
invalid_api_key | 401 | Not charged | The API key is missing, malformed, unknown, revoked or expired.
|
too_many_auth_failuresRetryable | 429 | Not charged | 30 failed authentications from this IP within a minute; try again in 60 seconds.
|
account_disabled | 403 | Not charged | The account is disabled.
|
payload_too_large | 413 | Not charged | The request body is over 64 KiB; nothing ran.
|
endpoint_not_found | 404 | Not charged | No such endpoint; check the method and path.
|
method_not_allowed | 405 | Not charged | The path exists but takes another method; the Allow header names it.
|
endpoint_disabled | 410 | Not charged | The endpoint has been retired.
|
scope_denied | 403 | Not charged | This API key lacks the scope the endpoint requires.
|
endpoint_unavailable | 503 | Not charged | The endpoint is not available right now (no data source connected yet, or no price configured); nothing ran.
|
invalid_params | 400 | Not charged | The parameters failed validation: a required one is missing, a type or format is wrong, an array has more items than allowed, an unknown one was sent, or the POST body is not a JSON object. An error in one parameter starts with its name (item_id: …); a missing or unknown parameter starts with params: ….
|
rate_limitedRetryable | 429 | Not charged | Over the account's per-minute limit (sliding 60-second window); wait for Retry-After.
|
too_many_unbilledRetryable | 429 | Not charged | In the last 10 minutes at least 50 of your calls to data sources, and over 80% of them, came back empty, not found or rejected; slow down.
|
endpoint_busyRetryable | 429 | Not charged | The endpoint's per-second capacity across all users is full; retry in 1 second. This does not count toward your per-minute limit.
|
insufficient_balance | 402 | Not charged | The balance cannot pay for this call; top up first.
|
upstream_busyRetryable | 503 | Refunded | The data source is busy or cooling down; refunded. Retry after Retry-After.
|
upstream_timeout | 504 | Refunded | The data source timed out; refunded.
|
upstream_error | 502 / 503 | Refunded | The data source failed; refunded.
|
upstream_rejected | 400 | Refunded | The data source rejected these parameters (well-formed, but not accepted); refunded.
|
not_found | 404 | Refunded | The data source has no such item (deleted, or the ID does not exist); refunded.
|
reservation_expired | 504 | Refunded | The call took too long and was refunded automatically; no data is returned.
|
Branch on error.code; message is for people and can be worded several ways.
For AI agents and tools
AI tools can call these endpoints directly over MCP, and the same catalog is published in machine-readable form for code generators:
https://api.qovia.ai/mcpOpenAPI 3.1Parameters, response examples and errors of all 165 endpoints.https://qovia.ai/openapi.jsonllms.txtAn index for language models: auth, billing and one line per endpoint.https://qovia.ai/llms.txt