Build and stock BOMs from your catalog via the API
Once a Claude or ChatGPT connection (or an asmk_ key) is set up under Settings ▸ LLM / API
Access (see AI / Agent access), an assistant can take a shop from bare
catalog to fully modelled BOMs without any copy-pasting of IDs. This guide shows the canonical
flow and the snippets an assistant would run.
1. Find the variants in your Shopify catalog
Section titled “1. Find the variants in your Shopify catalog”shopify.searchVariants accepts Shopify’s own search filter syntax — the same queries you’d type
in the admin search box:
const page = await app.shopify.searchVariants({ query: 'sku:BOLT-* AND vendor:Acme', first: 50,});return page.variants.map((v) => ({ id: v.variantId, sku: v.sku, title: v.displayName }));Page through big result sets with after: page.pageInfo.endCursor. If you already know the ids,
shopify.getVariants({ variantIds: [...] }) hydrates up to 100 at once.
2. Register them as raw materials — in one call
Section titled “2. Register them as raw materials — in one call”return await app.rawMaterials.registerFromShopifyVariants({ variantIds: ['53680817373507', '53680817439043' /* …up to 100 */],});Each item reports created: true (newly registered) or false (already known — refreshed).
Purely internal components that don’t exist in Shopify are created as virtual materials in
bulk, with duplicate protection:
return await app.rawMaterials.createMany({ items: [ { productName: 'Packaging Foam', variantName: 'Default', unit: 'pcs', inventoryQuantity: 500 }, { productName: 'Assembly Glue', variantName: '50ml', sku: 'GLUE-50' }, ], skipExisting: true, // SKU first, (productName, variantName) fallback dryRun: true, // preview first — flip off to commit});3. Create the BOMs
Section titled “3. Create the BOMs”billOfMaterials.createMany takes up to 25 BOMs per call; unknown Shopify component references
are auto-registered along the way, and skipExisting: true skips variants that already have a BOM:
return await app.billOfMaterials.createMany({ items: [ { productId: '15330758263107', variantId: '53680816652611', productName: 'Gift Box Deluxe', variantName: 'Default', rawMaterialReferences: [ { nodeId: '53680817373507', quantity: 2 }, { nodeId: 'VMAT-VAR-…', quantity: 1 }, ], }, ], skipExisting: true,});Every batch method returns per-item results — check results[] / failedCount rather than
assuming the whole batch landed; failed items can be resent alone.
4. Ask what you can build
Section titled “4. Ask what you can build”billOfMaterials.buildable computes the same number the app’s Max Buildable column shows —
live Shopify component levels, virtual levels and nested pre-assembled stock included:
const { items } = await app.billOfMaterials.buildable({ ids: ['BOM-…'] });return items.map((i) => ({ bom: i.bomId, perLocation: i.perLocation, total: i.totals.maxBuildable }));Real per-location levels for any mix of materials come from inventory.levels, and
shopify.listLocations is the canonical way to resolve location ids and names.
5. Record what’s already on the shelf
Section titled “5. Record what’s already on the shelf”When finished goods are physically assembled (or counted during a stock-take), adjust the pre-assembled quantity directly — no work order needed:
// Stock-take: SET the level (retry-safe — prefer absolute over delta for counts)await app.billOfMaterials.adjustPreassembled({ id: 'BOM-…', locationId: '101176672579', absolute: 12,});
// Or record 3 freshly built unitsawait app.billOfMaterials.adjustPreassembled({ id: 'BOM-…', locationId: '101176672579', delta: 3 });adjustPreassembledMany batches up to 25 adjustments for a full stock-take, and
assemblyBills.adjustPreassembled does the same for sub-assemblies. A BOM with Only sell
pre-assembled enabled automatically re-anchors its Shopify availability to the new pre-assembled
quantity.