Documentation
Reference for the 6 operations of this API
Technical reference for each operation of this API: action id, endpoint on this site, accepted inputs with their constraints, and the fields each operation returns.
Checking current availability and approved prices…
Endpoints and request shape
Each action has its own endpoint on this site and is called with POST: `post-1688-categories` at POST /api/v1/alibaba-1688/post-1688-categories, `post-1688-category-offers` at POST /api/v1/alibaba-1688/post-1688-category-offers, `post-1688-product-detail` at POST /api/v1/alibaba-1688/post-1688-product-detail, `post-1688-product-reviews` at POST /api/v1/alibaba-1688/post-1688-product-reviews, `post-1688-search` at POST /api/v1/alibaba-1688/post-1688-search and `post-1688-supplier-search` at POST /api/v1/alibaba-1688/post-1688-supplier-search. Inputs sit inside `body`. Only the contract field names are accepted: alternative key names such as `q`, `offerId`, `categoryId`, `pageNo` or `lang` are rejected as undeclared body keys.
post-1688-categoriespost-1688-category-offerspost-1688-product-detailpost-1688-product-reviewspost-1688-searchpost-1688-supplier-searchbody
Category tree
`post-1688-categories` has no required input. `body.language` is one of 9 values: `zh`, `en`, `ru`, `es`, `pt`, `fr`, `de`, `ja` or `ko`, with `en` as the default. `body.depth` is an integer from 1 to 3 and defaults to 2; depth 1 returns the 54 top-level categories, and the full 3 levels come to about 2.4 MB. Returns `items` with `id`, `name`, `name_zh`, `level`, `is_leaf` and either `children` or `child_count`, plus `count`, `language` and `depth`.
post-1688-categoriesbody.languagebody.depth
Category offers
`post-1688-category-offers` requires `body.category_id`, a string such as `1031910`, which can be taken from the category tree or from a search row. `body.page` is an integer from 1 to 200, default 1; pages hold a fixed 30 offers each, and unlike keyword search this operation genuinely paginates through the category. Returns `items` with `id`, `title`, `url`, `image`, `price`, `price_display`, `currency`, `moq`, `listed_on`, `fulfilment`, `certifications` and `sales`, plus `count`, `category_id`, `page` and `has_next`.
post-1688-category-offersbody.category_idbody.page
Offer detail and reviews
`post-1688-product-detail` and `post-1688-product-reviews` require `body.offer_id`, a string that is either the digits of an offer id such as `864971848115` or a full offer url. Detail returns `price` in CNY, `price_type`, `price_tiers`, `moq`, `stock`, `mix`, `sold_count`, `category`, `attributes`, `seller` and `variants`, whose `skus` carry `price`, `stock` and `weight_kg`; `weight_kg` is null where the supplier did not publish it. Reviews return one page of individual reviews: `rating` (out of 5), `rating_scale`, `good_percent`, `review_count` (a lower bound where 1688 prints 100+) and `reviews` with `content`, `buyer`, `quantity`, `spec`, `images`, `date` and `plus_user`.
post-1688-product-detailpost-1688-product-reviewsbody.offer_id
Keyword and factory search
`post-1688-search` and `post-1688-supplier-search` require `body.query`, a free-text string; Chinese terms give the richest results and English or pinyin terms also match. Offer search returns `items` with `id`, `price`, `seller`, `offer_repurchase_rate`, `shop_repurchase_rate`, `category_ids` and `is_ad`, plus `has_next`, which is always false for this operation: it returns a single shortlist of about 20 offers per keyword, its rows carry no MOQ or price ladder, and repeated calls rotate among roughly 38 distinct offers. Factory search returns `items` with `name`, `member_id`, `url`, `location`, `years_on_1688`, `workers`, `floor_area_sqm` (square metres), `makes`, `medal`, `medal_level`, `repeat_buyer_rate`, `on_time_rate`, `reply_rate_30d` (the 30-day reply rate), `third_party_audit`, `is_super_factory` and `offer_ids`, plus `count`, `query` and `note`. It is a curated shortlist per keyword rather than an index: some keywords return no factories, and an empty list is a real answer. `third_party_audit` shows whether an auditor such as SGS has audited the factory.
post-1688-searchpost-1688-supplier-searchbody.query
Shared optional input
Each of the 6 operations also accepts `body.max_rotations`, an integer from 1 to 8 with a default of 4. It sets how many attempts a call may make before giving up. Out-of-range values are rejected.
body.max_rotations
{
"body": {
"category_id": "1031910",
"page": 2
}
}Operation examples
Every public gateway operation uses POST /api/v1/{project}/{action}.
Category tree
POST /api/v1/alibaba-1688/post-1688-categories
Use a JSON object with the documented path, query, headers and body locations; omit unused locations. input.headers is schema-validated data, not browser request headers. Do not put credentials here. Keep body arrays, scalar values and null as documented; omission is different from null.
{
"body": {
"depth": 1,
"language": "ru"
}
}Example response
nullCategory offers
POST /api/v1/alibaba-1688/post-1688-category-offers
Use a JSON object with the documented path, query, headers and body locations; omit unused locations. input.headers is schema-validated data, not browser request headers. Do not put credentials here. Keep body arrays, scalar values and null as documented; omission is different from null.
{
"body": {
"category_id": "1031910"
}
}Example response
nullOffer detail
POST /api/v1/alibaba-1688/post-1688-product-detail
Use a JSON object with the documented path, query, headers and body locations; omit unused locations. input.headers is schema-validated data, not browser request headers. Do not put credentials here. Keep body arrays, scalar values and null as documented; omission is different from null.
{
"body": {
"offer_id": "864971848115"
}
}Example response
nullBuyer reviews
POST /api/v1/alibaba-1688/post-1688-product-reviews
Use a JSON object with the documented path, query, headers and body locations; omit unused locations. input.headers is schema-validated data, not browser request headers. Do not put credentials here. Keep body arrays, scalar values and null as documented; omission is different from null.
{
"body": {
"offer_id": "864971848115"
}
}Example response
nullKeyword search
POST /api/v1/alibaba-1688/post-1688-search
Use a JSON object with the documented path, query, headers and body locations; omit unused locations. input.headers is schema-validated data, not browser request headers. Do not put credentials here. Keep body arrays, scalar values and null as documented; omission is different from null.
{
"body": {
"query": "蓝牙耳机"
}
}Example response
nullFactory search
POST /api/v1/alibaba-1688/post-1688-supplier-search
Use a JSON object with the documented path, query, headers and body locations; omit unused locations. input.headers is schema-validated data, not browser request headers. Do not put credentials here. Keep body arrays, scalar values and null as documented; omission is different from null.
{
"body": {
"query": "蓝牙耳机"
}
}Example response
nullGateway reference
These rules apply to every API on this site that shows this section.
Making a call
Send POST /api/v1/<project>/<action> with a JSON body. Three headers are required:
x-api-key: a key created in your dashboard. Its scopes must include<project>:<action>, or<project>:*for every operation of the project, including operations added later.Content-Type: application/json. The body may be at most 64 KiB.Idempotency-Key: 8–128 letters, digits, colons, underscores or hyphens. Create one per intended request and keep it until you have a final answer.
Idempotency-Key
- Idempotency keys belong to your account: all of your API keys and live playground requests share one set of them.
- Same key and the same request (project, action and input) after the first one finished: its stored response is returned for 24 hours, without executing the operation again or a new charge.
- Same key with a different request: 409
IDEMPOTENCY_CONFLICT. - Same key while the first request is still running or its outcome is unconfirmed: 409
REQUEST_PENDING. - Same key after an unconfirmed request was released: 504
OUTCOME_UNKNOWN_RELEASED; nothing was charged. - Same key after the stored response of a successful request has expired: 410
RESULT_EXPIRED; the request is not executed or charged again. - A request refused before admission (the first group in the error table) does not record its key, so you can fix the problem and resend with the same key; the exception is
IDEMPOTENCY_CONFLICT, where the key already belongs to another request. Once a request is admitted, the key belongs to it, even if the request then fails.
Request body
The body is a JSON object with up to four optional members: path, query, headers and body. Put each parameter where the operation documents it and omit unused members. headers here is JSON data checked against the operation, not HTTP request headers; never put credentials in it.
Input that does not match the operation is refused before the request is executed and is not charged: INVALID_PARAM (before admission) when the input fails the operation’s schema, including an unknown member or an undeclared path, query or header parameter; INVALID_INPUT (after admission; the key is then used) when body contains an undeclared field, a value cannot be sent safely (for example "/" or "%" in a path parameter), or the request exceeds the transport limits.
Responses
{
"ok": true,
"data": "<the result of the operation>",
"meta": {
"requestId": "<request id>",
"chargedCreditUnits": "<price in credit units>",
"…": "…"
}
}data is the result of the operation. meta.requestId identifies the recorded request and meta.chargedCreditUnits is the amount charged.
{
"ok": false,
"error": {
"code": "OPERATION_TIMEOUT",
"message": "…"
},
"meta": {
"requestId": "<request id>",
"chargedCreditUnits": "0",
"status": "uncertain"
}
}meta.chargedCreditUnits is always "0" here. meta.status is "failure" when the request definitely did not succeed and "uncertain" when its outcome could not be confirmed.
{
"ok": false,
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "…"
},
"requestId": "<reply id>"
}This shape has no meta and nothing is charged. Read ok and error.code rather than relying on the HTTP status alone.
Billing
- A call is charged its listed price only when it succeeds. Failed calls are not charged.
- The price is reserved from your available balance when the request is admitted. If the available balance is lower than the price, the request is refused with
INSUFFICIENT_CREDITS. - When the outcome cannot be confirmed, the price stays reserved for up to 900 seconds (15 minutes) and is then released. It is never charged later.
- Amounts are integer credit units: 1 credit = 100 credit units, so
"250"means 2.5 credits.
Rate limits
Each admitted request counts against a limit for your account (a burst of 10 requests, then one more every 0.2 seconds) and against limits shared by every customer that apply to this operation or to a group of operations, including a cap on simultaneous requests. You can therefore receive RATE_LIMITED or CONCURRENCY_LIMIT even when your own traffic is low. Both replies carry a Retry-After header in seconds; wait at least that long and resend with the same Idempotency-Key.
Automatic suspension
An operation can be suspended automatically when its results repeatedly fail its documented contract, or when the cost of executing it is higher than, or can no longer be confirmed against, the cost its price is based on; the price you pay per call does not change because of this. The operator can also suspend it. While it is suspended, calls return 503 OPERATION_SUSPENDED; nothing is executed or charged. Some automatic suspensions are lifted after an hour so calls can show whether the operation has recovered; those calls are executed and charged like any other.
Verification status
In the availability table on this page, “Verified by live traffic” marks an operation for which a real call at its current price and contract completed successfully and passed this site’s automatic cost check for the operation.
Errors
| Code | HTTP | Charged | Meaning | What to do |
|---|---|---|---|---|
| Refused before admission — no meta; the key is not recorded (except IDEMPOTENCY_CONFLICT, where it already belongs to another request) | ||||
AUTH_FAILED | 401 | No | The x-api-key header is missing, malformed, unknown, revoked or expired. | Send a valid key. Never write the key to logs. |
ACCOUNT_FROZEN | 403 | No | The account is restricted or its email address is not verified, so it cannot start billable requests. | Check your account in the dashboard. Contact page |
SCOPE_DENIED | 403 | No | The key’s scopes include neither <project>:<action> nor <project>:*. | Use a key whose scopes cover this operation. |
UNSUPPORTED_MEDIA_TYPE | 415 | No | The Content-Type header is not application/json. | Correct the request and resend it; the same Idempotency-Key can be reused. |
PAYLOAD_TOO_LARGE | 413 | No | The request body is larger than 64 KiB. | Correct the request and resend it; the same Idempotency-Key can be reused. |
INVALID_ENCODING | 400 | No | The request body is not valid UTF-8. | Correct the request and resend it; the same Idempotency-Key can be reused. |
INVALID_REQUEST | 400 | No | The request body is not valid JSON. | Correct the request and resend it; the same Idempotency-Key can be reused. |
IDEMPOTENCY_KEY_REQUIRED | 400 | No | The Idempotency-Key header is missing or is not 8–128 letters, digits, colons, underscores or hyphens. | Send a valid Idempotency-Key. |
IDEMPOTENCY_CONFLICT | 409 | No | Your account already used this Idempotency-Key for a different project, action or input. | Use a new key for a new request. To read the earlier result, resend exactly the earlier request. |
OPERATION_NOT_FOUND | 404 | No | No registered operation matches this project and action. | Check the endpoint path against the documentation. |
INVALID_PARAM | 400 | No | The input fails the operation’s schema, including an unknown member or an undeclared path, query or header parameter. | Correct the request and resend it; the same Idempotency-Key can be reused. |
INSUFFICIENT_CREDITS | 402 | No | Your available balance (balance minus reserved amounts) is below this operation’s price. | Wait for reserved amounts to be settled or released, or top up when purchasing is available. |
OPERATION_DISABLED | 503 | No | The operation is not enabled for live calls. | Check the current availability on the API page before retrying. |
OPERATION_SUSPENDED | 503 | No | The operation is suspended, automatically or by the operator. Nothing was executed. | Retry later; check the current availability on the API page. |
OPERATION_HEALTH_UNAVAILABLE | 503 | No | The gateway could not confirm whether the operation is suspended, so it refused the call. | Retry later with the same Idempotency-Key. Do not retry in a tight loop. |
NOT_CONFIGURED | 503 | No | A required part of the service, such as the database, key protection or the operation’s configuration, is not available. | Retry later with the same Idempotency-Key. Do not retry in a tight loop. |
RATE_LIMITED | 429 | No | A rate limit was reached: your account’s, or a limit shared with other customers that applies to this operation or to a group of operations. | Wait the number of seconds in Retry-After, then resend with the same Idempotency-Key. |
CONCURRENCY_LIMIT | 429 | No | Too many requests to this operation, or to a group of operations that share a limit, are in progress at once (shared by all customers). | Wait the number of seconds in Retry-After, then resend with the same Idempotency-Key. |
| Admitted, then failed — meta.chargedCreditUnits is "0"; the Idempotency-Key now belongs to this request | ||||
INVALID_INPUT | 400 | No | body contains an undeclared field, a value cannot be sent safely (for example "/" or "%" in a path parameter), or the request exceeds the transport limits. The operation was not executed. | Correct the input and send it with a new Idempotency-Key. |
SERVICE_UNAVAILABLE | 503 | No | The operation cannot be executed at the moment because of a condition on the service side. This is not about your API key or your wallet balance. | Retry later with a new Idempotency-Key; this key keeps returning this failure. |
SERVICE_BUSY | 503 | No | The operation is temporarily at capacity on the service side. | Retry later with a new Idempotency-Key; this key keeps returning this failure. |
REQUEST_REJECTED | 502 | No | The operation rejected the request. | Check the input against the documentation; send a corrected request with a new Idempotency-Key. |
REQUEST_NOT_FULFILLED | 502 | No | The operation reported that it did not succeed. | Check the input against the documentation; send a corrected request with a new Idempotency-Key. |
OPERATION_FAILED | 502 | No | The operation did not complete and produced no result. | Retry later with a new Idempotency-Key; this key keeps returning this failure. |
OPERATION_TIMEOUT | 504 | No — price held up to 900 s, then released | The operation did not finish in time or reported a timeout; it may still have run. | Do not repeat automatically with a new Idempotency-Key: the operation may already have run. Decide deliberately whether to send a new request. |
OUTCOME_UNKNOWN | 504 / 502 | No — price held up to 900 s, then released | The operation failed or ended unexpectedly in a way that leaves its outcome unknown. | Do not repeat automatically with a new Idempotency-Key: the operation may already have run. Decide deliberately whether to send a new request. |
RESULT_INVALID | 502 | No — price held up to 900 s, then released | The result was not a recognised or valid response for this operation, or it failed the gateway’s final check. | Do not repeat automatically with a new Idempotency-Key: the operation may already have run. Decide deliberately whether to send a new request. |
RESULT_TOO_LARGE | 502 | No — price held up to 900 s, then released | The result exceeded the size limit. | Do not repeat automatically with a new Idempotency-Key: the operation may already have run. Decide deliberately whether to send a new request. |
| Without meta, possibly after the operation was executed (the key may then be recorded) | ||||
RESPONSE_TOO_LARGE | 502 | No — price held up to 900 s, then released | The operation returned a result, but the reply was too large for the gateway to store, so it was not delivered. | Do not repeat automatically with a new Idempotency-Key: the operation may already have run. Decide deliberately whether to send a new request. |
CREDIT_SCHEMA_UNAVAILABLE | 503 | Not charged unless the recorded request succeeded. | Credit accounting is not in its expected state (for example during a maintenance migration). Usually this happens before admission; rarely, after the operation was executed. | Retry later with the same Idempotency-Key: it runs the request only if it was never admitted, otherwise it returns the recorded state. |
INTERNAL_ERROR | 500 | Not charged unless the recorded request succeeded. | An unexpected server error, before or after the operation was executed. | Retry later with the same Idempotency-Key: it runs the request only if it was never admitted, otherwise it returns the recorded state. Keep the requestId. Contact page |
| Reusing the Idempotency-Key of an admitted request | ||||
REQUEST_PENDING | 409 | This retry: no. The original is charged only if it succeeds; otherwise released within 900 s. | The request with this key is still running or its outcome is unconfirmed. | Wait. Do not switch to a new key to retry it; after 900 seconds an unconfirmed request is released without charge. |
RESULT_EXPIRED | 410 | No | The request succeeded, but its stored response is older than 24 hours. It will not run again and is not charged again. | Use a new Idempotency-Key for a new request (charged again if it succeeds). |
OUTCOME_UNKNOWN_RELEASED | 504 | No | The outcome was never confirmed; the reserved price was released and nothing was charged. | Decide whether to send a new request with a new Idempotency-Key; it is charged if it succeeds. |
Some responses are not produced by the gateway: a method other than POST receives HTTP 405, and a call still running after 60 seconds is ended by the hosting platform with a response that is not this JSON format. In that case the key may already be recorded; resending with the same key either runs the request (if it was never admitted) or returns the recorded state.