Ai knowledge and logicHelpers

shopify_graphql

Run any Shopify Admin GraphQL query or mutation from Python. Octocom attaches the store's token and calls Shopify from its fixed IP.

shopify_graphql(context, query, variables=None, *, api_version, shop=None) -> dict

The only way to call the Shopify Admin API from Python. Octocom sends the request from its own servers with the store's access token, so your code never holds a Shopify token, and every request comes from Octocom's fixed IP address, which Shopify's IP allowlist requires.

SHOPIFY_API_VERSION = "2026-10"

def execute_action(context):
    result = shopify_graphql(
        context,
        "query($q: String!) { orders(first: 5, query: $q) { nodes { id name displayFulfillmentStatus } } }",
        {"q": f"email:{context['args']['email']}"},
        api_version=SHOPIFY_API_VERSION,
    )
    if result.get("errors"):
        return {"success": False, "error": "Shopify could not search orders."}
    return {"success": True, "orders": result["data"]["orders"]["nodes"]}
NameTypeDescription
contextdictThe context object passed to your code
querystrThe GraphQL query or mutation
variablesdict | NoneGraphQL variables
api_versionstrRequired. The Admin API version, for example "2026-10"
shopstr | NoneThe store's myshopify.com domain. Any store connected to a business in your organization can be named; get_integration_credentials lists them. Omit it to use the current business's first connected store.

Returns Shopify's response body: {"data": ..., "errors": [...], "extensions": {...}}. GraphQL errors and a mutation's userErrors are returned, not raised, so check them. Throttled requests are retried for you. A mutation is never resent after a server error or lost connection, because Shopify may already have applied it; the helper raises instead.

Raises requests.HTTPError when Shopify answers with an HTTP error (for example a revoked token or a missing scope), when the store is not connected, or when the version is not accepted.

API versions

Octocom accepts only versions Shopify still supports: currently 2026-01, 2026-04, 2026-07 and 2026-10. Shopify supports each version for a year and then silently answers with a newer one, so pinning a retired version does not keep its behavior. When a version retires, Octocom moves stored automations to a newer one.

Newer versions also add rules a query validator cannot see. From 2026-04, refundCreate (and Shopify's inventory and location mutations) require an idempotency key:

REFUND = """
mutation Refund($input: RefundInput!, $idempotencyKey: String!) {
  refundCreate(input: $input) @idempotent(key: $idempotencyKey) {
    refund { id }
    userErrors { field message }
  }
}
"""

result = shopify_graphql(
    context,
    REFUND,
    {"input": refund_input, "idempotencyKey": str(uuid.uuid4())},
    api_version="2026-10",
)

Use a new key for each refund you mean to send. Reusing a key returns the first attempt's result instead of refunding again.

REST

The REST Admin API is not available from Python: Shopify made it legacy in October 2024, and every REST operation has a GraphQL equivalent. For order lookups by number or email, shopify_get_order and shopify_find_orders are built on this helper.

Product-sync parsers

Product-sync parsers get the same helper without context: shopify_graphql(query, variables=None, *, api_version, shop=None). It only reaches the stores of the business being synced.

See Shopify Custom Actions for a worked playbook.

On this page