Tutorial: Build a Product Sync App
Sync products from your own system into a Prebit store, safely retryable.
This builds on prebit-examples/product-sync —
here we walk through why it's built the way it is, not just what it does.
The goal
You have products in your own system (a warehouse tool, a legacy catalog, whatever) and want them mirrored into a merchant's Prebit store, safely — meaning a network blip or a crashed process retrying the same sync doesn't create duplicates.
Step 1: get an access token
Assume you already completed OAuth
and have an access_token with write_products granted.
import { PrebitPartnerClient } from "@prebit/sdk";
const client = new PrebitPartnerClient({ baseUrl: "https://admin.prebit.in", accessToken });Step 2: pick a stable idempotency key per product
The key must be the same across retries of the same logical write, and different for a genuinely different write. A hash of your own system's stable identifier for that product (a SKU, an internal id) works well:
import crypto from "crypto";
function idempotencyKeyFor(sku: string): string {
return crypto.createHash("sha256").update(`product-sync:${sku}`).digest("hex");
}Don't use crypto.randomUUID() here. A fresh random key on every call
means every retry is treated as a brand-new write — the exact thing
idempotency exists to prevent. Derive it from something stable.
Step 3: create (or, on a real second run, decide create vs. update)
for (const product of myProducts) {
const key = idempotencyKeyFor(product.sku);
try {
const { data } = await client.createProduct(
{ name: product.name, price: product.price, sku: product.sku, stock: product.stock },
key,
);
console.log(`✓ ${product.name} → ${data.id}`);
} catch (err) {
console.error(`✗ ${product.name}:`, err);
}
}This tutorial's example always calls createProduct for simplicity. A
real sync needs to track which of your products already have a Prebit
id (store that mapping in your own database after the first successful
create) so a second run calls updateProduct(id, ...) instead of trying
to create the same product twice — the idempotency key protects against
retrying the exact same request, not against sending a different
request for a product you already created last week.
Step 4: handle partial failure
The loop above catches per-product errors so one bad product (e.g. a negative price, caught by validation) doesn't abort the whole sync. Log failures somewhere you'll actually see them — a sync that silently drops failed rows is worse than one that's slow.
Step 5 (optional): react to the merchant's own edits
If a merchant edits a product Prebit-side, you'll want to know — subscribe
to product.updated in your manifest and see Webhooks.
Note the loop-prevention behavior: your own writes never echo back to
you, but the merchant's edits do.
Where to go from here
- Inventory for keeping stock levels in sync separately (a different endpoint, different idempotency-key shape).
- Collections if you also need to sync category/ collection membership.
- Errors, Pagination & Idempotency for the full contract this tutorial builds on.