Getting Started
Search in a market you choose, keep the product ids you care about, then poll their prices and follow their reviews — three requests, all JSON.
1. Get your API key
Create an account and generate a FetchLayer API key from your dashboard. There is no AliExpress affiliate program to join and no open-platform app key to request.
Create free account →2. Search in a pinned market
curl -X POST https://api.fetchlayer.dev/aliexpress/search-products \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"query":"mechanical keyboard","shipTo":"US","currency":"USD","language":"en_US"}'One page is 60 products, each with its productId, price and original price, discount, rating, sold count, ship-from country and category id. The response echoes the market it was read in. Currencies USD, EUR, GBP, CAD, AUD, NZD, BRL, MXN, CLP, COP, PEN, ARS, JPY and KRW, and languages en_US, de_DE and pt_BR are accepted; anything else is a 400.
Tip
pages (each page counts as one request), or pass nextCursor back as cursor. Consecutive pages can repeat a product, so de-duplicate by productId. 3. Check prices in one request
curl -X POST https://api.fetchlayer.dev/aliexpress/product-prices \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"products":["1005009494458560","1005006994630464"],"shipTo":"US","currency":"USD"}'Up to 20 products per request, each back in request order with its own status: ok, unavailable, not_found, or failed — which means check that one again later. Pass { "product": "…", "skuId": "…" } to track one variant; the skuIds are on /product-details.
Retry a 503 here
503 is temporary: wait and retry. Search and reviews are not affected. Keep shipTo and currency fixed between checks — a price in another market is a different price, not a change. 4. Follow the reviews
curl -X POST https://api.fetchlayer.dev/aliexpress/product-reviews \
-H "Authorization: Bearer ss-your-key" \
-H "Content-Type: application/json" \
-d '{"product":"1005009494458560","sort":"latest","shipTo":"US","language":"en_US"}'Twenty reviews per page with the star distribution, each with the text translated into your language and the reviewer's original words, country, the variant bought and any seller reply. Many AliExpress reviews are a rating with no text.
Tip
/resolve-url turns any AliExpress URL into the product id, variant id, search query or category id the other endpoints take. It makes no upstream request and does not consume a credit. Error responses
Every error, on every route, is JSON in one shape: error (what went wrong, in words), status, code, retryable and requestId, which also comes as the X-Request-Id header. Branch on code and retryable rather than on the text; on a 5xx the text is generic. Quote requestId when reporting a problem.
{
"error": "Missing required parameter: url",
"status": 400,
"missing": ["url"],
"code": "invalid_input",
"retryable": false,
"requestId": "922874e3-c0d0-40d8-8866-d198af132420"
}| code | Status | Retryable | Meaning |
|---|---|---|---|
| invalid_input | 400 | no | The request needs fixing; error names the field. A missing required parameter also lists it in missing. |
| unauthorized | 401 | no | The API key is missing or not valid. |
| insufficient_credits | 402 | no | Nothing left to spend: no credits, a used-up free trial, or a monthly allowance and credit balance both spent. error says which. Waiting does not help; topping up does. |
| forbidden | 403 | no | This key or account is not allowed this request. |
| not_found | 404 | no | What the request names does not exist or is not public. |
| expired | 410 | no | What the request refers to is no longer available; ask for it afresh. |
| quota_exceeded | 429 | no | A request-rate limit was reached; error says which. Slow down before sending more. |
| cancelled | 499 | no | The caller closed or cancelled the request before it finished. The work was stopped and nothing was charged. |
| time_limit | 503 | yes | Your timeoutMs ran out before there was anything to return; ask again, or allow more time. |
| temporarily_unavailable | 503 | yes | Not available right now; ask again shortly. |
| posts_unavailable | 403 | no | TikTok user videos: TikTok is not showing this account’s posts publicly right now. Asking again at once returns the same answer; nothing is charged. |
| store_unreachable | 503 | yes | Store routes (Shopify, WooCommerce): the store itself can’t be reached right now — it may be offline. Ask again later. Where a store route doesn’t say so yet, an offline store is temporarily_unavailable. |
| upstream_error | 502 | yes | The source answered in a way that could not be used; ask again later. |
| internal_error | 500 | yes | Something failed on our side; ask again later, and quote requestId if it persists. |
| tool_error | — | no | MCP only: a tool call failed in a way no other code describes; error says what. |
More codes may be added; treat one you do not recognise by its retryable flag. Over MCP, a tool error carries the same fields in structuredContent, and as a JSON text block beside the message.