SDKs
Official client libraries for Node.js/TypeScript and Python, so you don't have to hand-roll HTTP calls and response types against the REST API yourself. Both wrap the same single-lookup, batch, and history endpoints documented elsewhere in these docs.
Node.js / TypeScript
npmA dependency-free client with full TypeScript types for every request and response shape - no manual header/auth wiring, no guessing field names. Ships ESM, CommonJS and bundled type declarations, and requires Node 18 or newer.
npm install @siktec-lab/productmapperimport { ProductMapper } from '@siktec-lab/productmapper';
const client = new ProductMapper({ apiKey: process.env.PRODUCTMAPPER_API_KEY });
const result = await client.lookup({ value: '753933140816', type: 'UPC' });
console.log(result.marketplaceId); // "B09Z2J1MP2" (the matched ASIN)
console.log(result.listingDetails?.title); // product title
console.log(result.listingDetails?.price); // 80.99// Up to 500 identifiers per background job.
const job = await client.lookupMany(['753933140816', 'B09Z2J1MP2']);
const finished = await client.waitForBatch(job.id, {
onProgress: (j) => console.log(`${j.processedItems}/${j.totalItems}`)
});
for (const item of finished.items ?? []) {
console.log(item.identifierValue, item.title, item.price);
}
// Or export the whole batch as CSV.
const csv = await client.getBatchCsv(job.id);import { NotFoundError, RateLimitError, CreditsExhaustedError } from '@siktec-lab/productmapper';
try {
const result = await client.lookup({ value: '753933140816' });
} catch (error) {
if (error instanceof NotFoundError) {
// No match in the Amazon catalog.
} else if (error instanceof CreditsExhaustedError) {
// Out of credits: upgrade the plan or buy a credit pack.
} else if (error instanceof RateLimitError) {
console.log(`Retry in ${error.retryAfter}s`);
} else {
throw error;
}
}Python
PyPIA fully type-hinted client with both synchronous and asyncio support, for scripts and
backend services that would rather import a package than manage HTTP calls directly.
Supports Python 3.9 through 3.13 and ships py.typed.
pip install productmapperimport os
from productmapper import ProductMapper
client = ProductMapper(api_key=os.environ["PRODUCTMAPPER_API_KEY"])
result = client.lookup(value="753933140816", type="UPC")
print(result.marketplace_id) # "B09Z2J1MP2" (the matched ASIN)
print(result.title) # product title
print(result.price) # 80.99# Up to 500 identifiers per background job.
job = client.lookup_many(["753933140816", "B09Z2J1MP2"])
finished = client.wait_for_batch(
job.id,
on_progress=lambda j: print(f"{j.processed_items}/{j.total_items}"),
)
for item in finished.items:
print(item.identifier_value, item.title, item.price)
# Or export the whole batch as CSV.
csv_text = client.get_batch_csv(job.id)import asyncio
from productmapper import AsyncProductMapper
async def main():
async with AsyncProductMapper(api_key=...) as client:
result = await client.lookup(value="753933140816", type="UPC")
print(result.title, result.price)
asyncio.run(main())Method reference
Every method maps to an endpoint documented in these docs. The polling helpers (waitForJob, waitForBatch) wrap the queue-based endpoints so a slow lookup or a batch
becomes a single call.
| Node.js | Python | Description |
|---|---|---|
| lookup | lookup | Resolve one identifier. Polls a queued lookup automatically. |
| lookupMany | lookup_many | Submit up to 500 identifiers as a batch job. |
| getJob | get_job | Poll one queued single lookup. |
| getJobs | get_jobs | Poll up to 100 queued lookups in one round trip. |
| getBatch | get_batch | Fetch a batch job and its items. |
| getBatchCsv | get_batch_csv | Export a batch job as CSV. |
| waitForJob | wait_for_job | Poll a queued lookup until it resolves. |
| waitForBatch | wait_for_batch | Poll a batch until every item is processed. |
| history | history | List lookup history, 25 rows per page. |
| historyAll | history_all | Iterate every history row across all pages. |
| deleteHistoryRow | delete_history_row | Delete one history row. |
| clearHistory | clear_history | Clear the entire lookup history. |
Errors and retries
Both SDKs raise a typed error per failure mode, all inheriting from a single ProductMapperError base so one catch can cover everything. Rate limits
(429), server errors (5xx) and network failures are retried automatically with
exponential backoff, honoring Retry-After. Validation and authentication
failures are never retried.
| Error | HTTP | Raised when |
|---|---|---|
| ValidationError | 400 | Bad arguments, rejected before or by the API. |
| AuthenticationError | 401 | API key missing, malformed or revoked. |
| PermissionError | 403 | No active organization selected. |
| CreditsExhaustedError | 403 | Credit balance is empty. |
| NotFoundError | 404 | No catalog match, or the resource is not yours. |
| RateLimitError | 429 | Plan requests-per-minute exceeded. |
| ServerError | 5xx | The API failed to handle the request. |
| TimeoutError | - | A request or polling loop ran out of time. |
| ConnectionError | - | The request never reached the API. |
| JobFailedError | - | A queued lookup or batch ended in a failed state. |
Both SDKs are open source under the MIT license. Issues and pull requests are welcome.