Skip to main content

Shopify ExecModule

Overview

ShopifyModule connects ValkyrAI workflows to Shopify's versioned Admin GraphQL API through the native map I/O ExecModule ABI. Workflow Studio discovers it as ShopifyModule; the shop domain and Admin API access token come only from an encrypted IntegrationAccount.

The initial release provides twelve commerce operations:

  • get_shop
  • list_products, get_product, create_product, update_product, delete_product
  • list_orders, get_order
  • list_customers, get_customer
  • list_locations, list_inventory_items

Connection reads use opaque cursor pagination with bounded responses. Only read operations are eligible for automatic retry. Product creates, updates, and deletion run once so an ambiguous timeout cannot repeat a mutation.

Usage

  1. Create a Shopify custom app or organization-managed app for the target store.
  2. Grant only the Admin API scopes needed by the selected workflow operations.
  3. Install the app on the store and store its Admin API access token in the encrypted apiKey field of an IntegrationAccount.
  4. Put the store's <shop>.myshopify.com domain in IntegrationAccount.accountId.
  5. Bind that account through ExecModuleConfig.authConfig.integrationAccount.
  6. Add ShopifyModule to a workflow, select an operation, and reuse GraphQL global IDs returned by discovery operations.

Workflow inputs can supply resource IDs, an allowlisted product object, search expressions, pagination controls, and explicit destructive confirmation. They cannot supply credentials or redirect requests away from the trusted *.myshopify.com Admin API endpoint.

Inputs

NameTypeRequirementDefaultDescriptionConstraints
operationstringRequiredNoneOperation to execute.One of the twelve operations above.
resourceIdstringOperation-specificNoneProduct, order, customer, or other resource ID.Full gid://shopify/.../... global ID.
productobject or JSON stringCreate/updateNoneProduct create or update input.256 KiB; allowlisted fields only.
querystringOptional for listsNoneShopify search syntax.Maximum 4,096 characters.
afterstringOptionalNoneOpaque continuation cursor.Maximum 4,096 characters.
limitintegerOptional50Maximum returned items.1–10,000; pages contain at most 100.
returnAllbooleanOptionalfalseContinue until provider exhaustion.Safety-capped at 10,000 items.
confirmDeletebooleanRequired for deletionfalsePermanent-delete acknowledgement.Must be true for delete_product.
apiVersionstringOptional2026-07Stable Admin GraphQL API version.YYYY-01, YYYY-04, YYYY-07, or YYYY-10.

The product object accepts title, descriptionHtml, handle, productType, vendor, status, tags, templateSuffix, seo, metafields, and redirectNewHandle. status is normalized to ACTIVE, ARCHIVED, or DRAFT; tags are capped at 250 strings and metafields at 100 entries. Unknown fields fail validation before any request is sent.

Outputs

NameTypeWhen presentDescription
statusstringAlwayssuccess or error.
operationstringAlwaysNormalized operation name.
attemptsintegerAlwaysTotal Shopify HTTP attempts across all pages.
httpStatusintegerProvider response receivedLast HTTP status.
dataobjectSingle-resource/mutation successNormalized GraphQL resource or mutation payload.
id, name, handle, deletedProductIdstringProvider response includes itConvenience fields.
items, countarray, integerList successReturned resources and count.
hasMore, nextCursorboolean, stringList successContinuation state and opaque cursor.
requestIdstringProvider supplies oneShopify request correlation ID.
errorobjectFailureSafe {code, message, httpStatus?, retryable} details.

Access tokens and request headers never enter outputs. Provider messages pass through the shared workflow sensitive-data policy and explicit token redaction.

IntegrationAccount Requirements

SettingShopify requirement
ProviderShopify Admin API custom or organization-managed app
AuthenticationX-Shopify-Access-Token
accountNameHuman-readable store or automation identity label
accountIdStore subdomain or full <shop>.myshopify.com domain
apiKeyPreferred encrypted SecureField containing the Admin API token
passwordLegacy token fallback only; prefer apiKey
statusready or unset legacy status; closed and error fail closed

Use read_products for catalog reads and write_products for product mutations. Add read_orders, read_customers, read_locations, and read_inventory only when their operations are needed. Orders older than Shopify's default order-access window require approved read_all_orders access. Token rotation or OAuth refresh happens before execution; workflow payloads cannot replace credentials.

Configuration

{
"version": "1.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:shopify-release-store"
},
"retryPolicy": {
"maxAttempts": 3,
"backoffStrategy": "EXPONENTIAL",
"initialDelayMs": 1000,
"maxDelayMs": 60000,
"jitter": false
},
"executionConfig": {"timeoutMs": 30000},
"payloadConfig": {
"parameters": "{\"operation\":\"list_orders\",\"query\":\"status:open financial_status:paid\",\"limit\":50,\"apiVersion\":\"2026-07\"}"
}
}

The integration account value is symbolic. Persisted workflows use the generated relationship, never a plaintext token.

Operations

OperationShopify behaviorSide effect
get_shopReads store identity, domain, currency, and plan details.Read-only; safe retries.
list_products, get_productSearches or reads products with bounded catalog fields.Read-only; safe retries.
create_productCreates one allowlisted product record.New product; single attempt.
update_productUpdates explicitly supplied allowlisted fields.Mutation; single attempt.
delete_productPermanently deletes one product.Irreversible; confirmation required.
list_orders, get_orderReads bounded order, customer, payment, and fulfillment status.Read-only; safe retries.
list_customers, get_customerReads bounded customer identity and aggregate order value.Read-only; safe retries.
list_locationsLists fulfillment and inventory locations.Read-only; safe retries.
list_inventory_itemsLists inventory items with SKU, cost, and variant/product linkage.Read-only; safe retries.

Errors and Failure Modes

CodeTypical causeRetryableResolution
VALIDATION_ERRORMissing/invalid ID, domain, version, product field, query, or delete confirmation.NoCorrect the input; no unsafe request was sent.
UNSUPPORTED_OPERATIONUnknown operation.NoSelect a documented operation.
INTEGRATION_ACCOUNT_REQUIREDNo account bound.NoBind a Shopify IntegrationAccount.
INTEGRATION_ACCOUNT_NOT_READYAccount status is closed/error.NoRepair or reconnect the account.
SHOPIFY_GRAPHQL_ACCESS_DENIEDToken or scope is insufficient.NoReinstall/rotate the app or grant the minimum missing scope.
SHOPIFY_GRAPHQL_THROTTLEDGraphQL cost budget is exhausted.Yes for readsHonor backoff; reduce page size or query frequency.
SHOPIFY_HTTP_401, 403Invalid token, installation, or store access.NoVerify the bound store and token.
SHOPIFY_HTTP_429, 5xxRate limit or transient failure.Yes for readsHonor Retry-After; reconcile writes before retry.
SHOPIFY_* user errorProduct validation rejected by Shopify.NoCorrect the field named in the bounded provider error.
NETWORK_ERRORTimeout, DNS, TLS, or connectivity failure.Yes for readsVerify connectivity and inspect writes before retry.
RESPONSE_TOO_LARGEResponse exceeded 5 MiB.NoNarrow the search or lower limit.
INVALID_PROVIDER_RESPONSEGraphQL payload lacked the expected connection/resource.NoUse requestId and verify API-version compatibility.

Example

{
"operation": "create_product",
"product": {
"title": "Enterprise Agent Operations Kit",
"descriptionHtml": "<p>Governed automation resources for production AI teams.</p>",
"vendor": "Valkyr Labs",
"productType": "Digital toolkit",
"status": "DRAFT",
"tags": ["enterprise-ai", "agentic-automation", "workflow"]
}
}

Expected result:

{
"status": "success",
"operation": "create_product",
"attempts": 1,
"httpStatus": 200,
"id": "gid://shopify/Product/101",
"data": {
"id": "gid://shopify/Product/101",
"title": "Enterprise Agent Operations Kit",
"status": "DRAFT"
}
}

Notes

  • Pagination: list operations request at most 100 nodes per page and stop at limit, provider exhaustion, or 10,000 items. Reuse nextCursor only with the same operation and search query.
  • Rate limits: reads retry HTTP 408, 429, 500, 502, 503, 504 and GraphQL THROTTLED, INTERNAL_SERVER_ERROR, or SERVICE_UNAVAILABLE responses per policy. Mutations never retry automatically.
  • API limits: Shopify GraphQL uses calculated query-cost budgets and versioned schemas. The module bounds product inputs to 256 KiB and responses to 5 MiB.
  • Idempotency: writes are single-attempt. Reconcile by product handle, returned ID, or a durable workflow business key before repeating an ambiguous create/update.
  • API versioning: the default is 2026-07. Pin and deliberately test a newer stable quarterly version before changing persisted workflows.
  • Destructive behavior: delete_product is permanent and requires confirmDelete=true. Prefer update_product with status: ARCHIVED when reversible retirement is appropriate.
  • Privacy: order and customer responses can contain personal data. Apply downstream minimization, retention, ACL, and audit rules.
  • Authentication: Admin API tokens remain in IntegrationAccount SecureFields and are redacted from errors and outputs.
  • External verification: request construction, cursor pagination, validation, redaction, retry safety, mutation safety, and metadata discovery are tested locally. Live store permissions require real Shopify credentials and are deferred.
  • Deferred operations: variants/options, bulk operations, collections, draft orders, refunds, fulfillments, inventory adjustments, subscriptions, files/media upload, metafield lifecycle, webhooks/triggers, and arbitrary raw GraphQL.
  • Functional reference: n8n's Shopify node models product and order create/get/list/update/delete workflows, multiple Shopify authentication modes, and cursor-aware pagination. This module carries its highest-value commerce semantics into ValkyrAI's secure native ABI while using Shopify's current Admin GraphQL surface.