@lazada-sdk/sdk
v0.1.0-alpha.0
Published
Unofficial TypeScript SDK for the Lazada Open Platform API. Not affiliated with Lazada.
Maintainers
Readme
@lazada-sdk/sdk
Unofficial TypeScript SDK for the Lazada Open Platform API.
Not affiliated with Lazada. Derived from public documentation. Use at your own risk. See Lazada's terms.
Install
npm install @lazada-sdk/sdk
# or
pnpm add @lazada-sdk/sdkRuns on Node ≥ 20, Cloudflare Workers, Vercel Edge, Deno, and modern browsers. Signing uses WebCrypto — no node:crypto dependency.
Quick start
import { LazadaSDK } from "@lazada-sdk/sdk";
const sdk = new LazadaSDK({
appKey: process.env.LAZADA_APP_KEY!,
appSecret: process.env.LAZADA_APP_SECRET!,
region: "SG", // SG | VN | PH | MY | TH | ID
accessToken: process.env.LAZADA_ACCESS_TOKEN!,
});
const { data, error } = await sdk.seller.getSeller();
if (error) throw error;
console.log(data);Features
- 367 endpoints across 33 API groups, typed end-to-end from an OpenAPI 3.1 spec.
- HMAC-SHA256 request signing handled transparently — you never construct the
signparameter yourself. - Multi-region base URLs — automatically routes to
api.lazada.sg,api.lazada.vn, etc., and toauth.lazada.comfor OAuth endpoints. - Typed errors — non-zero
coderesponses throwLazadaApiErrorwith subclasses for auth / rate limit / validation families. - ESM + CJS dual output, source maps, full
.d.ts.
Auth
You bring your own access token. To exchange an OAuth code for a token:
const { data } = await sdk.system.createAuthToken({ code: oauthCode });
// data.access_token, data.refresh_token, data.expires_in, ...Refresh is automatic: pass a refreshToken at construction time and the SDK
refreshes before every request where the access token is within
refreshBufferSec of expiry (default 60s). Concurrent requests during a
refresh coalesce into a single network call.
Managers
One manager per Lazada API group:
sdk.order, sdk.product, sdk.seller, sdk.logistics, sdk.lazadaLogistics,
sdk.finance, sdk.fulfillment, sdk.returnAndRefund, sdk.sellerVoucher,
sdk.freeShipping, sdk.flexicombo, sdk.redmart, sdk.lazpay, sdk.membership,
sdk.content, sdk.productReview, sdk.storeDecoration, sdk.mediaCenter,
sdk.instantMessaging, sdk.sponsoredSolutions, sdk.lazlike, sdk.lazlive,
sdk.eTickets, sdk.earlyBirdPrice, sdk.crossBoarderProduct, sdk.fbl,
sdk.choiceCustomized, sdk.firstmileBigbagOnlyForCn, sdk.logisticsStation,
sdk.serviceMarket, sdk.lazadaDg, sdk.lazadaWalletCorporateTopUp, sdk.systemAll method names are generated from the OpenAPI spec using a <verb><PathSegments> heuristic — e.g. /orders/get becomes getOrders, /image/upload becomes uploadImage. Spec refreshes regenerate cleanly; no hand-maintained wrapper code drifts out of sync.
GET/POST duality
Many Lazada endpoints are registered twice — once as GET /foo/get (query
params) and once as POST /foo/get (form-encoded body). The two variants have
identical semantics; POST exists to handle payloads that exceed URL length
limits. The SDK emits one method per path, preferring POST when both
exist. If a code sample you're following specifically calls the GET variant
and you need to match that transport, reach for the raw client:
await sdk.client.GET("/choice/products/get", { params: { query: { ... } } });Pagination
Lazada list endpoints come in two flavors — offset-based ({ offset, limit, total }) and cursor-based ({ cursor, next_cursor }). The exported paginate() helper auto-detects which one a response is using and yields items as an async iterator:
import { LazadaSDK, paginate } from "@lazada-sdk/sdk";
for await (const order of paginate(
(p) => sdk.order.getOrders(p),
{ created_after: "2025-01-01", status: "pending" },
{ itemsKey: "orders", pageSize: 50, maxItems: 1000 },
)) {
console.log(order);
}itemsKey tells the helper which array inside data to iterate (e.g. "orders", "products", "items"). maxItems caps the total yielded as a runaway-loop guard.
Error handling
import { LazadaApiError, LazadaAuthError, LazadaRateLimitError } from "@lazada-sdk/sdk";
try {
await sdk.order.getOrders({ created_after: "2024-01-01" });
} catch (err) {
if (err instanceof LazadaAuthError) {
// Refresh your access token and retry
} else if (err instanceof LazadaRateLimitError) {
// Back off
} else if (err instanceof LazadaApiError) {
// err.code, err.type, err.message, err.requestId
}
}Status
v0.1.0-alpha. Plumbing validated against the live Lazada SG production API on 2026-04-21: GET /seller/get (manager dispatch + query signing) and POST /images/migrate (form-body signing pool) both returned code: 0. Unit tests cover signing, token refresh with concurrency coalescing, URL routing, form encoding, and error classification.
Not yet live-validated: the other 5 regions (VN, PH, MY, TH, ID), real-world error codes from the wire, unicode payloads, token-refresh round-trips against the auth host, multi-page pagination, and 31 of 33 managers. The first production user of any specific endpoint should expect to file 1–2 edge-case issues. Breaking changes are possible until v1.0.
License
MIT. See LICENSE.
