Temu is PDD Holdings' cross border marketplace, launched in 2022 and now selling into North America, Europe, Latin America and Asia. Its seller base splits into two populations that behave almost like separate platforms: cross border sellers, who ship into Temu's warehouses and whose merchandising Temu largely controls, and local sellers on the semi managed and local models, who hold stock in market and fulfil themselves. The Open Platform exists for the second group, and much of the order and fulfilment API explicitly refuses a cross border token. The API itself is in the Chinese ecommerce tradition rather than the REST tradition: a single POST router per region, a type parameter that names the method, an MD5 signature over every parameter, and method names like bg.order.list.v2.get.
At a glance
What it is
Temu is a marketplace where the platform is unusually involved in pricing and merchandising. Three seller models matter:
- Cross border (fully managed). The seller ships into Temu, Temu sets the retail price and handles everything downstream. The fulfilment and order APIs are largely closed to these tokens.
- Semi managed (SEMI). The seller holds stock in the destination market and fulfils, Temu handles the storefront.
- Local (LOCAL). A local entity selling in its own market.
This distinction is not theoretical, it is an error code. bg.order.list.v2.get returns error 140020001 with the message "This interface does not support cross-border sellers. Please check whether the store bound to the token is a SEMI or LOCAL store!" The first question to ask about any Temu integration is which model the seller is on, because it determines whether the API can do anything useful at all.
The identifiers: a parentOrderSn is the customer's order, formatted like PO-211-21905452099192792, and an orderSn is a line within it, formatted like 211-21905473070712792. A goodsId is the product, a skuId is the variant. A mallId is the store, and a token is bound to one mall, though the token response can carry an associatedMallTokenList for linked malls.
API access
- Create an application on the Partner Platform and complete the partner profile.
- Pass the compliance and security questionnaires. The documentation treats this as a gate: only approved applications can subscribe to webhook events.
- Receive an
app_keyand anapp_secretfor each application. Temu's partner terms describe these as "authentication credentials issued by us corresponding to each new Application, including but not limited to App_key and App_secret". - Publish the app so sellers can authorise it, then have each seller grant it access.
The seller side differs by seller type and region:
The API hosts are regional and you must pick the one matching the store:
Only POST is supported. Temu's own guide is blunt about it: "We have removed many calling methods for the convenience and security of overall calls."
Versioning is per method rather than global. A version common parameter exists and defaults to V1, and newer methods carry the version in the name instead, as with bg.order.list.v2.get and bg.logistics.shipment.v2.confirm. There is no published deprecation calendar and no official SDK, though the documentation ships Python and Java examples.
The official documentation at partner-us.temu.com/documentation and partner-eu.temu.com/documentation is a client rendered JavaScript application: fetching it without a browser returns only "You need to enable JavaScript to run this app." The endpoint names, parameters, signature algorithm, rate limit and webhook details on this page were read from github.com/opastorello/temu-api-docs, a public mirror that a scheduled job syncs from Temu's portal daily, with page level "Last update" timestamps preserved. Treat it as accurate in structure and verify exact field semantics against the portal in a browser before implementing.
Authentication
Two layers: the application signs, the seller authorises.
Common parameters
Every call carries these alongside the method's own parameters.
The 300 second window on both sides means clock skew is a real failure mode. Sync the clock on whatever runs the connector.
The signature
The signing method is MD5. The procedure, as published:
- Take every request parameter, common and method specific, and sort by key in ascending ASCII order.
- Concatenate as parameter name followed by parameter value, with no separator at all.
- Prepend and append
app_secretto that string. - MD5 the result and uppercase the hex digest. That is
sign.
Two details bite. Nested structures are serialised as their JSON string before concatenation, so array and object parameters have to be stringified exactly as they will be sent, including key order inside the JSON. And the secret wraps the string on both sides, not just the front. Error 3000001 is "sign is invalid, please check your sign calculation", and it has its own troubleshooting page in the documentation, which tells you how often people get this wrong.
Getting a seller token
There are two flows.
Manual authorisation. The seller authorises the app in the Seller Center, picks the permissions, and the system displays the access_token directly. The seller copies it into your application. This is the only flow available to cross border sellers.
Callback authorisation. The seller authorises in the Seller Center, Temu redirects to your pre-configured redirect_url with a code, and you exchange it. Temu marks this as the recommended approach and it is available to local sellers.
curl -X POST 'https://openapi-b-global.temu.com/openapi/router' \
-H 'content-type: application/json' \
-d '{
"type": "bg.open.accesstoken.create",
"app_key": "<app-key>",
"timestamp": "1758412800",
"data_type": "JSON",
"code": "<code-from-redirect>",
"sign": "<uppercase-md5>"
}'
{
"success": true,
"errorCode": 0,
"errorMsg": null,
"result": {
"accessToken": "...",
"expiredTime": 1790000000,
"mallId": 634418212345678,
"regionId": 211,
"mallType": 1,
"apiScopeList": ["bg.order.list.v2.get", "bg.local.goods.stock.edit"],
"associatedMallTokenList": [{ "mallId": 634418212345679, "accessToken": "..." }],
"appSubscribeStatus": 1,
"appSubscribeEventCodeList": ["..."],
"authEventCodeList": [{ "eventCode": "...", "permitsStatus": 1 }]
}
}
The response is richer than a plain token and worth storing whole. apiScopeList tells you exactly which methods this seller granted, so a connector can degrade gracefully instead of discovering a permission failure at runtime. expiredTime drives refresh. mallType distinguishes the seller model. authEventCodeList tells you which webhook events the seller has permitted, which you need before the per seller event subscription call will work. bg.open.accesstoken.info.get re-reads the same information later.
Multi account handling is one access_token per mall, with associatedMallTokenList covering linked malls under one authorisation. The app_key and app_secret are shared across all of them.
Error codes 110020001 through 110020003 cover token creation failures, with 110020002 being an invalid or already used code.
Objects we can read
Orders
type=bg.order.list.v2.get
The filter set is unusually rich. Paging is pageNumber and pageSize. Time windows come in four flavours, all second level timestamps: createAfter and createBefore, updateAtStart and updateAtEnd, parentConfirmTimeStart and parentConfirmTimeEnd, and expectShipLatestTimeStart and expectShipLatestTimeEnd. That last pair is the ship by deadline, which is the right axis for a fulfilment queue rather than a data sync. Other filters are parentOrderStatus, parentOrderSnList, regionId, fulfillmentTypeList, parentOrderLabel, packageAbnormalTypeList, skuId, sortby, hasPreSaleOrder and hasQualificationRequiredOrder.
Every response follows the same envelope: success, errorCode, errorMsg and a result object. The mirror publishes the parameter list and an example request for each method but not a populated response example for the order list, so the response field detail is not reproduced here. Sample response not published.
Companion reads:
The address decryption being its own method is the notable design point: order reads return the address encrypted, and reading it in the clear is a deliberate, auditable call. Build the connector to fetch and store plaintext addresses only where they are actually needed for a label.
Order items
Lines are orderSn values under a parentOrderSn, each carrying a goodsId and a skuId. The signature example in Temu's own documentation shows the shape clearly, with an orderSendInfoList of goodsId, orderSn, parentOrderSn, quantity and skuId.
Products and listings
The product domain is the largest, with roughly 57 methods. The useful reads:
bg.local.goods.cats.getfor the category tree, withbg.local.goods.category.checkandbg.local.goods.category.recommendto validate or suggest a categorybg.local.goods.list.queryandtemu.local.goods.list.retrievefor productsbg.local.goods.sku.list.queryandtemu.local.sku.list.retrievefor SKUsbg.local.goods.sku.list.price.queryfor current pricestemu.local.goods.sku.stock.queryfor current stockbg.local.goods.publish.status.getfor where a submitted product is in reviewtemu.local.goods.baseprice.recommendandtemu.local.goods.recommendedprice.queryfor Temu's own price guidance, which matters because Temu actively pushes sellers on price
There is a whole compliance sub-domain for certificates and regulatory attributes: bg.compliance.metadata.get, bg.compliance.edit, bg.arbok.open.cert.queryNeedUploadItems, bg.arbok.open.cert.uploadProductCert and bg.arbok.open.product.cert.query. On EU sites this is not optional.
Inventory
temu.local.goods.sku.stock.query reads, bg.local.goods.stock.edit writes, covered below.
Shipments and tracking
A full logistics domain of around 19 methods:
bg.logistics.companies.getandbg.logistics.shippingservices.getfor carriers and servicesbg.logistics.warehouse.list.getfor warehouses,bg.freight.template.list.queryfor freight templatesbg.logistics.shipment.create,bg.logistics.shipment.update,bg.logistics.shipment.v2.confirm,bg.logistics.shipment.sub.confirmandbg.logistics.shipped.package.confirmfor the shipping flowbg.logistics.shipment.v2.getandbg.logistics.shipment.result.getto read backbg.logistics.shipment.document.getandtemu.logistics.label.list.getfor labels and documentstemu.track.trackinginfo.getfor tracking eventstemu.logistics.shipment.pickup.reservation.create,.canceland.result.getfor booking a collection
The separation of create, confirm and sub confirm means shipping is a multi step state machine, not a single call. Splitting a package across shipments has its own guide in the documentation.
Returns and cancellations
An after sales domain of around 12 methods, with the list entry point named bg.aftersales.parentaftersales.list.get. Cancellation has its own dedicated flows: temu.order.cancel.outofstock.apply with temu.order.cancel.outofstock.result.get for cancelling because you cannot supply, and temu.order.cancel.appeal.apply with temu.order.cancel.appeal.result.get for contesting a cancellation. Both are apply and then poll for a result, so neither is synchronous.
Payments and settlements
No settlement, payout or fee domain appears in the published method list. bg.order.amount.query and temu.order.amount.v2.query give per order amounts, which is the closest available substitute. Reconciling actual payouts will need Seller Center reports.
Customers
There is no customer object. Customer address data arrives encrypted on the order and is read through bg.order.decryptshippinginfo.get.
Locations
bg.logistics.warehouse.list.get lists warehouses. There is also a cooperative warehouse domain, bg.cooperativewarehouse.provider.list, .token.authorization, .fulfill.submit, .fulfill.query and .fulfill.cancel, for sellers using a third party fulfilment provider through Temu.
Writing back: listings, price and stock
Stock. bg.local.goods.stock.edit supports both absolute and delta updates, and refuses to mix them.
{
"type": "bg.local.goods.stock.edit",
"goodsId": 601099548666279,
"stockType": 1,
"skuStockTargetList": [ { "skuId": 17592352673534, "stockTarget": 42 } ],
"requestUniqueKey": "2026-09-21T10:00:00Z/SKU-1001"
}
Use skuStockTargetList with stockTarget for absolute quantities, or skuStockChangeList with stockDiff for deltas, never both: error 150013003 is "Only one stock adjustment method can be active at a time." Quantities must be between 0 and 1,000,000, per error 150013002, and duplicate SKUs in one call are rejected with 150013001. The requestUniqueKey is an idempotency key, so use it.
The response reports per SKU:
{
"success": true,
"result": {
"goodsId": 601099548666279,
"operateResult": true,
"skuStockEditStatusInfoList": [
{ "skuId": 17592352673534, "stockEditStatus": true, "errorCode": 0, "errorMsg": null }
]
}
}
Always read skuStockEditStatusInfoList, not just success.
Price. Price is not a simple update on Temu. bg.local.goods.priceorder.change.sku.price raises a price change order, and bg.local.goods.priceorder.query reads its state. Treat a price change as a submitted request that may be reviewed rather than as a write that takes effect, and never assume the new price is live until the price order says so. temu.local.goods.baseprice.recommend and temu.local.goods.recommendedprice.query exist because Temu has an opinion about what your price should be.
Listings. bg.local.goods.add creates products, with separate guides in the documentation for the original and the v2 flow, for parent and child attributes, and for material and image upload. bg.local.goods.sale.status.set lists and delists, and temu.local.goods.pre.sale.status.edit handles pre sale. bg.local.goods.publish.status.get tracks review progress. Product publishing has enough documented failure modes to have its own error catalogue: inconsistent SKU specifications, duplicated SKUs, too similar variation information, more than 25 SKCs, non leaf category ids, missing shipping templates and image aspect ratio rejections all have dedicated pages.
Fulfilment. Shipment creation and confirmation, pickup reservations, and document retrieval, as listed above.
Webhooks and notifications
Temu's webhook design is notification only: the push tells you something happened and you then call the query API for detail. That is deliberate, and it keeps event bodies small.
Enabling one is a four gate process:
- The application is registered and has passed the compliance and security assessment.
- The application has subscribed to the topics in the Partner Platform with a valid HTTPS push URL. Any change to the callback URL needs approval, and the documentation says approval may take up to one week.
- The seller has granted authorisation for those topics in the Seller Center.
- The application has subscribed to the topics on behalf of that seller through an API call.
Only when all four hold does Temu call your URL.
The callback is a POST with these headers:
The body is a single field, eventData, holding an encrypted string. You decrypt it to get camel case JSON such as {"orderSn":"XXYYZZ","status":1}.
Verification is over the decrypted content, which means you must decrypt before you can authenticate. The signing string sorts x-tm-app-key, x-tm-event-code, x-tm-timestamp, x-tm-ext-param and the decrypted eventData by name in ascending order and concatenates them, then applies HMAC-SHA256 keyed with app_secret and hex encodes. Temu publishes a worked example and a Java reference implementation.
No retry policy or ordering guarantee is published. Because the event carries only an identifier and a status, the receiver should enqueue a detail fetch rather than trying to act on the event alone.
Rate limits and pagination
The default is 20 requests per second per app_key, and the limit is shared across all the sellers that app serves, not per seller. Exceeding it returns error code 4000004 with the message RATE_LIMIT_EXCEED_EXCEPTION.
Temu states that the rules are dynamically adjustable and that an increase can be requested by emailing partner@temu.com, which is evaluated case by case. For an aggregator serving many sellers on one app key, plan that conversation before onboarding, not after.
Pagination is pageNumber and pageSize, not a cursor, so a scan over a changing result set can skip or repeat. Prefer the updateAtStart and updateAtEnd window for incremental syncs and treat page numbers as a within-window device only.
A cadence that fits 20 qps shared: rely on webhooks for order arrival, run an updateAtStart window sweep every ten minutes, push stock edits as they happen with a requestUniqueKey, and submit price orders in small batches since each one needs a follow up query.
Mapping to the unified model
Gaps and open questions
- The official portal could not be rendered by this research. Every endpoint name, parameter and limit here comes from a daily synced mirror. Verify in a browser before implementation.
- The mirror publishes parameter names but its type column is numeric codes rather than type names, and most descriptions are empty, so field semantics for order and product responses remain thin. Populated response examples exist for some methods, including the token and stock edit calls quoted here, but not for the order list.
- The cross border restriction is the biggest commercial unknown. Confirm the seller's
mallTypebefore quoting any integration work, because140020001closes much of the API to fully managed cross border tokens. - No settlement or payout API exists in the published domain list.
- No sandbox is published, so first contact with the signature algorithm and the webhook decryption happens against production.
- Webhook encryption is described with a Java reference implementation but the cipher and key derivation are not spelled out in the text read here. Get that detail from the portal.
- Access token lifetime is returned as
expiredTimebut no refresh endpoint appears in the authorisation domain, which has only token create and token info methods. How renewal works, and whether the seller must re-authorise, is unresolved. - The 20 qps default is per app key and shared across sellers, which is the main scaling constraint for an aggregator.
Sources
- Temu Partner Platform documentation, official, a JavaScript application that did not render for this research
- Authorize and authorization callback, official, the EU portal page on the authorisation code flow
- Temu Partner Platform Terms, 23 May 2025, official, source of the App_key and App_secret issuance language
- opastorello/temu-api-docs, public mirror of Temu's portal, synced daily by a scheduled job, with per page "Last update" timestamps. Specific pages used: endpoints and request method, common parameters, signature method, rate limiting rules, seller authorization guide, webhook integration guide,
bg.open.accesstoken.create,bg.order.list.v2.getandbg.local.goods.stock.edit, plus the api-reference listings for the order, shipping, product, after sales, compliance, warehouse and ads domains - Temu Open Platform on the Postman API Network, official workspace, listed but not readable without a browser