Imports
Import a Shopify product, with its variants and images, from its product URL.
POST /v1/imports brings one product into a brand from its Shopify product page: name, description, every variant and its images. It is the fastest way to get a new product ready to build ads for. ID prefix: brx_. Scopes: products:write to start, products:read to poll. Free.
Start an import
const { data: started } = await sal("/v1/imports", {
method: "POST",
idempotencyKey: crypto.randomUUID(),
body: {
brand_id: "brand_a1b2c3d4e5f67890",
url: "https://acme-apparel.com/products/heavyweight-tee",
},
});
// 202, started.status === "processing"The store and product are checked first, so a bad URL fails right away with a 400 that says why: INVALID_PRODUCT_URL, NOT_A_PRODUCT_URL or NOT_SHOPIFY_STORE. For a product that isn't on Shopify, create it from its image URLs instead. 503 SHOPIFY_UNAVAILABLE means the store didn't answer; try again in a minute. The import itself runs in the background, usually for one to three minutes.
Poll it
async function waitForImport(id, { intervalMs = 5_000, timeoutMs = 10 * 60_000 } = {}) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const { data } = await sal(`/v1/imports/${id}`);
if (data.status !== "processing") return data;
await new Promise((r) => setTimeout(r, intervalMs));
}
throw new Error(`Import ${id} still running after ${timeoutMs / 60_000} minutes`);
}
const done = await waitForImport(started.id);
if (done.status === "completed") {
console.log(done.product.id, done.product.name, done.product.variant_count);
} else {
console.error(done.failure.code, done.failure.message);
}| Field | Notes |
|---|---|
status | processing, completed or failed |
progress_message | What it's doing now |
product | Once completed: { id, name, variant_count, image_urls, variants } |
failure | { code, message } when failed |
The imported product has no audiences. Create one before building ads.