# Alibaba.com B2B Wholesale API — supplier product search, full wholesale product detail with quantity price tiers, MOQ, lead time and shipping weight, plus live buyer RFQs (what buyers are asking to purchase) from alibaba.com

> Search alibaba.com wholesale listings by keyword — 48 supplier offers per page, each with its unit price (or price range), minimum order quantity, units sold, supplier company and country, review scores and certifications. Filter by price, MOQ, supplier country, category, review score and supplier credentials; sort by relevance, sales volume, response rate or price
> ReefAPI engine `alibaba` · 3 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/alibaba/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed or blocked calls are free.
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http, `Authorization: Bearer <key>`) and your assistant can call these actions directly.

## Endpoints

### POST /alibaba/v1/search — 1 credit
Search alibaba.com wholesale listings by keyword — 48 supplier offers per page, each with its unit price (or price range), minimum order quantity, units sold, supplier company and country, review scores and certifications. Filter by price, MOQ, supplier country, category, review score and supplier credentials; sort by relevance, sales volume, response rate or price

**Parameters:**
- `query` (string, required) — What to search for on alibaba.com — a product keyword the way a buyer would type it ('led strip', 'corrugated carton box', 'nitrile gloves').
- `page` (integer, optional, default 1) — Result page, 1-based, 48 offers per page (max 100). Page forward with next_page from the response.
- `sort` (enum, optional, default "relevance") — Result order. 'relevance' is Alibaba's own default mix; 'sales' ranks by units sold in the last 180 days; 'response_rate' ranks suppliers by how fast they reply. Alibaba's search has no price sort — use min_price / max_price to bound the range instead. [one of: relevance, sales, response_rate]
- `min_price` (number, optional) — Lowest unit price to include, in the listing currency (USD from our exits).
- `max_price` (number, optional) — Highest unit price to include, in the listing currency.
- `min_order` (integer, optional) — Only listings whose minimum order quantity is at least this. Units differ per listing (pieces, meters, sets, kilograms), so this filters the number, not a normalised quantity.
- `max_order` (integer, optional) — Only listings whose minimum order quantity is at most this — the practical filter for buyers who cannot commit to a container load.
- `supplier_country` (string, optional) — Two-letter country code of the supplier (CN, IN, VN, TR, US, DE …). Alibaba is overwhelmingly Chinese suppliers; this is how you find the others.
- `category_id` (string, optional) — Alibaba category id to restrict the search to. Category ids come back on every product_detail response, in category_id and in the categories breadcrumb.
- `verified_supplier` (boolean, optional) — Only suppliers Alibaba has inspected and verified on site (its 'Verified Supplier' programme).
- `trade_assurance` (boolean, optional) — Only listings covered by Alibaba Trade Assurance (order protection on payments made through Alibaba).
- `min_review_score` (enum, optional) — Only suppliers at or above this review score (4, 4.5 or 5). [one of: 4, 4.5, 5]

**Returns:** results[] — one supplier offer per row: product_id (Alibaba's own numeric id as a string; pass it straight to product_detail), title, url, image, images[], price{text, currency, min, max}, promotion_price, currency, moq{text, quantity, unit}, sold_count, rating, review_count, supplier_service_score, shipping_score, supplier{company_id, name, country, years_on_alibaba, verified, logo, url, profile_url}, certifications[], is_ad — plus page, page_size, total_estimate, has_more, next_page.
price is the card price: a tiered listing shows its cheapest and dearest tier here (min differs from max), and the complete tier-by-tier ladder is one product_detail call away. min equals max on a flat-priced listing. price is null on the minority of listings the supplier publishes as 'Contact for price'.
moq.quantity is the number and moq.unit is the unit it is counted in — pieces, meters, sets, kilograms, tons — and the two must be read together: '1 set' and '1000 pieces' are both moq.quantity values. Present on every row measured.
is_ad is Alibaba's own paid-placement flag; roughly half of a page is sponsored and those rows are returned rather than silently dropped. sold_count is populated only on listings with recorded sales. rating/review_count are null on listings with no reviews yet.
total_estimate is Alibaba's own result count and it is an estimate — the same query reports noticeably different totals between calls, so paginate on has_more, not on arithmetic over the total.

**Example request body:**
```json
{
  "query": "led strip"
}
```

### POST /alibaba/v1/product_detail — 1 credit
Full wholesale detail for one alibaba.com listing — the complete quantity price ladder, minimum order quantity, production lead time, gross weight and package dimensions, the full specification table, image gallery, variant matrix with native SKU ids and per-variant stock, certifications, and the supplier scorecard

**Parameters:**
- `product_id` (string, optional) — Alibaba's own numeric product id — the digits before '.html' in a /product-detail/ URL, and the same value this API returns as product_id. Pass either this or url.
- `url` (string, optional) — Full alibaba.com product URL, used instead of product_id. Only alibaba.com hosts are accepted; the id is read out of the URL.

**Returns:** product{} — identity: product_id (Alibaba's own numeric id, returned as a string, identical to the id search returns), url, title, category_id, categories[] breadcrumb, brand, model_number, place_of_origin, ships_from.
Wholesale commercials: price_ladder[] {min_quantity, max_quantity, price, price_usd, formatted} — the quantity tiers, cheapest tier last; max_quantity is null on the open-ended top tier ('1000 and above'). price_usd is Alibaba's own USD conversion of that tier, so it stays comparable whatever currency the page was priced in. About one listing in six publishes no tiers at all — those return an empty price_ladder with price_range{min, max, min_usd, max_usd, text} instead, and price_on_request true when the supplier only invites an enquiry. currency is the currency the other price fields are quoted in.
moq{quantity, unit, text, customs_quantity, box_quantity} — the minimum order quantity and the unit it is counted in. Present on every product measured.
lead_time[] {min_quantity, max_quantity, days} — the supplier's own production time in days, laddered by order size.
shipping{gross_weight, weight_unit, package_dimensions{length, width, height, unit}, package_volume, packaging_details, port, selling_units, supply_ability, logistics_modes[], trade_price_type} — everything published that feeds a freight quote. gross_weight is per selling unit in kilograms and package_dimensions are centimetres. Both are null when the supplier left them blank, which happens on roughly a quarter of listings — a null here means 'not published', never zero. trade_price_type is the Incoterm the ladder is quoted on (FOB, EXW, CIF …). package_volume is a field Alibaba defines but suppliers do not fill; expect null.
Content: images[] full gallery at the largest rendition, videos[], specifications[] {group, name, value, attribute_id} — the whole attribute table with Alibaba's own grouping, including the 'Packaging and delivery' group — certifications[] {certificate_id, name, number, type, validity, issuing_authority, images[]}, customizable.
Variants: axes[] {attribute_id, name, type, values[{value_id, name, image, color}]} and variants[] {sku_id, attributes[], price, stock, unlimited_stock, in_stock}. sku_id is Alibaba's own SKU id as a string. price is ALWAYS null on a variant: Alibaba does not publish per-SKU prices on this marketplace — wholesale price is tiered by quantity at the product level, so price_ladder is the price for every variant. stock is null and unlimited_stock true on the many listings where the supplier declares unlimited capacity.
Trust: sold_count, rating{product_rating, product_review_count, store_rating, store_review_count} — aggregates only, Alibaba publishes no review text on the product page — and supplier{company_id, name, country, city, years_on_alibaba, business_type, verified, gold_supplier, url, logo, response_time, on_time_delivery_rate, reorder_rate, store_rating, store_review_count, main_markets[], customization_abilities[]}.
Either product_id or url is required.

**Example request body:**
```json
{
  "product_id": "1600104532932"
}
```

### POST /alibaba/v1/rfq_search — 1 credit
Search live buying requests (RFQs) posted by Alibaba buyers — the demand side of the marketplace. Each row is a purchase a real buyer is asking for right now, in their own words: what they want, how many, which country they are buying from and how long ago they posted it. Filter by keyword, buyer country, category and how recently it was posted; sort newest-first to work the board as a live feed

**Parameters:**
- `query` (string, optional) — What the buyer is asking for, in the buyer's own words — 'led strip', 'nitrile gloves', 'cnc machining'. Leave it out to browse every open request on the board (183,000+ live requests), which is what sort='recent' with a buyer_country filter is for.
- `page` (integer, optional, default 1) — Result page, 1-based, 20 requests per page (max 500). Page forward with next_page from the response.
- `sort` (enum, optional, default "relevance") — Result order. 'relevance' is Alibaba's own Best Match mix; 'recent' puts the newest requests first and is the one to poll — its first page is typically minutes old. [one of: relevance, recent]
- `buyer_country` (string, optional) — Two-letter country code of the BUYER (US, IN, BR, DE, TR, AE …). Must be upper-case, and Alibaba spells the United Kingdom 'UK', not 'GB'. A code Alibaba does not recognise is rejected rather than silently ignored.
- `category_id` (string, optional) — Alibaba sourcing category id to restrict the board to (1 Agriculture, 3 Apparel & Accessories, 66 Beauty, 8 Chemicals, 2829 Commercial Equipment & Machinery …). The ids are the same ones product_detail returns.
- `posted_within` (enum, optional) — Only requests posted inside this window. 'older_than_7d' is Alibaba's own inverse facet — it returns requests OLDER than a week, not newer. [one of: 1h, 3h, 12h, 24h, 2d, 3d, 7d, older_than_7d]
- `with_attachments` (boolean, optional) — Only requests where the buyer attached a file — a drawing, a spec sheet or a reference photo.
- `open_only` (boolean, optional) — Only requests Alibaba still lists as open for quoting (its own 'Open RFQs' filter).

**Returns:** results[] — one buying request per row: rfq_id (Alibaba's own numeric id as a string), title, description, description_truncated, url, image, quantity, quantity_unit, buyer{name, country, country_code, level}, posted_ago_text, posted_hours_ago, posted_at_estimate, quote_slots_total, quote_slots_left, has_attachments, rfq_level, rfq_star_level, rfq_star_max, tags[], expires_at, budget, budget_currency — plus query, page, page_size, total_estimate, has_more, next_page.
description is the buyer's OWN text and it is what makes this surface worth reading — but Alibaba truncates it on the listing page at roughly 210 characters. description_truncated is true when it did (44 of 60 rows measured), and the full text is not published anywhere we can read without an account.
quantity and quantity_unit must be read together and neither is normalised: the unit is whatever the buyer picked in their own language, so 'Piece/Pieces' and 'Meter/Meters' sit next to 'Caixa/Caixas' and 'Morgen/Morgen'. Both are present on every row measured across 10 categories.
Alibaba publishes the posting time ONLY as a relative phrase. posted_ago_text is that phrase verbatim ('Just now', '22 minutes before', '4 days ago'); posted_hours_ago is it as a number; posted_at_estimate is a UTC timestamp derived from it and is an ESTIMATE — no more precise than the phrase, so a '1 days ago' row is accurate to the day, not the minute.
expires_at, budget and budget_currency are fields Alibaba defines but does not fill on this surface: null on 200 of 200 rows measured. A null here means 'not published', never zero and never 'no deadline'.
buyer.name is the contact name the buyer chose to publish publicly on the sourcing board; no email, phone or address is published there and none is returned. buyer.country is always present; buyer.country_code is Alibaba's own two-letter code and is null on the handful of rows where Alibaba writes a full country name in that slot instead. image is present on roughly a third to two-thirds of rows depending on the category — buyers often post no photo at all.
total_estimate is Alibaba's own count for the filtered board. A query with no matches returns NOT_FOUND rather than an empty 200, and so does a page past the end of the result set — asked for a page it does not have, alibaba.com re-serves page 1, which this action detects rather than passing on.

**Example request body:**
```json
{
  "query": "packaging box"
}
```

## More
- Try it live, no code: https://reefapi.com/playground?engine=alibaba
- Human docs page: https://reefapi.com/docs/alibaba
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
