Prepare a JSONL file where each line is a JSON object representing one productVariantUpdate input: { "input": { "id": "gid://shopify/ProductVariant/...", "price": "19.99" } }
Call stagedUploadsCreate Admin GraphQL mutation with input specifying resource: BULK_MUTATION_VARIABLES, filename, mimeType: 'text/jsonl', and httpMethod: POST; the response returns a staged upload target with url and parameters
Upload the JSONL file to the staged upload URL using a multipart form POST with the parameters from the previous step; confirm a 200 response before proceeding
Call bulkOperationRunMutation with the mutation string (productVariantUpdate with $input variable) and the stagedUploadPath from the staged upload response to start the bulk operation
Poll currentBulkOperation for status; when COMPLETED retrieve the url (results JSONL) and optionally partialDataUrl for any partial results; parse the results to identify any lines that returned userErrors
Log and retry failed lines individually using standard single mutations; bulk mutations do not retry on partial failure — your app is responsible for handling line-level errors from the results JSONL
Known gotchas
The staged upload URL is short-lived; upload the JSONL file immediately after receiving the staged upload target and do not wait between getting the URL and uploading
Bulk mutations run asynchronously and take time proportional to the number of lines; do not set a short timeout on your polling loop — large catalogs may take many minutes
Each line in the JSONL must be a valid JSON object on a single line with no newlines within the object; pretty-printed JSON or multi-line strings in values will cause parsing failures for those lines
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp