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_shoplist_products,get_product,create_product,update_product,delete_productlist_orders,get_orderlist_customers,get_customerlist_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
- Create a Shopify custom app or organization-managed app for the target store.
- Grant only the Admin API scopes needed by the selected workflow operations.
- Install the app on the store and store its Admin API access token in the encrypted
apiKeyfield of anIntegrationAccount. - Put the store's
<shop>.myshopify.comdomain inIntegrationAccount.accountId. - Bind that account through
ExecModuleConfig.authConfig.integrationAccount. - Add
ShopifyModuleto 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
| Name | Type | Requirement | Default | Description | Constraints |
|---|---|---|---|---|---|
operation | string | Required | None | Operation to execute. | One of the twelve operations above. |
resourceId | string | Operation-specific | None | Product, order, customer, or other resource ID. | Full gid://shopify/.../... global ID. |
product | object or JSON string | Create/update | None | Product create or update input. | 256 KiB; allowlisted fields only. |
query | string | Optional for lists | None | Shopify search syntax. | Maximum 4,096 characters. |
after | string | Optional | None | Opaque continuation cursor. | Maximum 4,096 characters. |
limit | integer | Optional | 50 | Maximum returned items. | 1–10,000; pages contain at most 100. |
returnAll | boolean | Optional | false | Continue until provider exhaustion. | Safety-capped at 10,000 items. |
confirmDelete | boolean | Required for deletion | false | Permanent-delete acknowledgement. | Must be true for delete_product. |
apiVersion | string | Optional | 2026-07 | Stable 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
| Name | Type | When present | Description |
|---|---|---|---|
status | string | Always | success or error. |
operation | string | Always | Normalized operation name. |
attempts | integer | Always | Total Shopify HTTP attempts across all pages. |
httpStatus | integer | Provider response received | Last HTTP status. |
data | object | Single-resource/mutation success | Normalized GraphQL resource or mutation payload. |
id, name, handle, deletedProductId | string | Provider response includes it | Convenience fields. |
items, count | array, integer | List success | Returned resources and count. |
hasMore, nextCursor | boolean, string | List success | Continuation state and opaque cursor. |
requestId | string | Provider supplies one | Shopify request correlation ID. |
error | object | Failure | Safe {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
| Setting | Shopify requirement |
|---|---|
| Provider | Shopify Admin API custom or organization-managed app |
| Authentication | X-Shopify-Access-Token |
accountName | Human-readable store or automation identity label |
accountId | Store subdomain or full <shop>.myshopify.com domain |
apiKey | Preferred encrypted SecureField containing the Admin API token |
password | Legacy token fallback only; prefer apiKey |
status | ready 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
| Operation | Shopify behavior | Side effect |
|---|---|---|
get_shop | Reads store identity, domain, currency, and plan details. | Read-only; safe retries. |
list_products, get_product | Searches or reads products with bounded catalog fields. | Read-only; safe retries. |
create_product | Creates one allowlisted product record. | New product; single attempt. |
update_product | Updates explicitly supplied allowlisted fields. | Mutation; single attempt. |
delete_product | Permanently deletes one product. | Irreversible; confirmation required. |
list_orders, get_order | Reads bounded order, customer, payment, and fulfillment status. | Read-only; safe retries. |
list_customers, get_customer | Reads bounded customer identity and aggregate order value. | Read-only; safe retries. |
list_locations | Lists fulfillment and inventory locations. | Read-only; safe retries. |
list_inventory_items | Lists inventory items with SKU, cost, and variant/product linkage. | Read-only; safe retries. |
Errors and Failure Modes
| Code | Typical cause | Retryable | Resolution |
|---|---|---|---|
VALIDATION_ERROR | Missing/invalid ID, domain, version, product field, query, or delete confirmation. | No | Correct the input; no unsafe request was sent. |
UNSUPPORTED_OPERATION | Unknown operation. | No | Select a documented operation. |
INTEGRATION_ACCOUNT_REQUIRED | No account bound. | No | Bind a Shopify IntegrationAccount. |
INTEGRATION_ACCOUNT_NOT_READY | Account status is closed/error. | No | Repair or reconnect the account. |
SHOPIFY_GRAPHQL_ACCESS_DENIED | Token or scope is insufficient. | No | Reinstall/rotate the app or grant the minimum missing scope. |
SHOPIFY_GRAPHQL_THROTTLED | GraphQL cost budget is exhausted. | Yes for reads | Honor backoff; reduce page size or query frequency. |
SHOPIFY_HTTP_401, 403 | Invalid token, installation, or store access. | No | Verify the bound store and token. |
SHOPIFY_HTTP_429, 5xx | Rate limit or transient failure. | Yes for reads | Honor Retry-After; reconcile writes before retry. |
SHOPIFY_* user error | Product validation rejected by Shopify. | No | Correct the field named in the bounded provider error. |
NETWORK_ERROR | Timeout, DNS, TLS, or connectivity failure. | Yes for reads | Verify connectivity and inspect writes before retry. |
RESPONSE_TOO_LARGE | Response exceeded 5 MiB. | No | Narrow the search or lower limit. |
INVALID_PROVIDER_RESPONSE | GraphQL payload lacked the expected connection/resource. | No | Use 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. ReusenextCursoronly with the same operation and search query. - Rate limits: reads retry HTTP 408, 429, 500, 502, 503, 504 and GraphQL
THROTTLED,INTERNAL_SERVER_ERROR, orSERVICE_UNAVAILABLEresponses 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_productis permanent and requiresconfirmDelete=true. Preferupdate_productwithstatus: ARCHIVEDwhen 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.