Gentic Shopify — Documentation

Connect any AI agent to a Shopify store for orders, products, customers, and bulk revenue exports — all through the Model Context Protocol. Read-only by design: list and inspect data, export CSVs for joins against your ad spend, and run free-form Admin GraphQL when the typed tools don't cover what you need.

1. Getting Started

Sign Up & Get Your API Key

Before you can use Gentic Shopify, you need an API key to authenticate your requests.

  1. Go to gentic.co/shopify and create an account.
  2. Create an organization from your dashboard. API keys and billing are scoped to the organization.
  3. Generate an API key and use it as a Bearer token in your MCP client.

2. Connecting to the MCP Server

The server is available at https://mcp.gentic.co/shopify. For Claude Code:

claude mcp add gentic-shopify \
  --transport http \
  https://mcp.gentic.co/shopify \
  --header "Authorization: Bearer YOUR_API_KEY"

For Claude Web and ChatGPT you can also connect via OAuth — no API key needed. See the connect section on the landing page for other MCP clients (n8n, OpenClaw).

3. Agent Skill

For the best results, pair the MCP server with the Gentic Shopify agent skill. The MCP server gives your agent tool access; the skill teaches it the optimal workflow order. Both the raw SKILL.md and a ready-to-upload .skill bundle are generated on demand from the live manifest, so they always reflect the current tools and pricing.

Add the skill directly via URL:

https://gentic.co/shopify/SKILL.md

Or upload a .skill bundle to Claude Managed Agents:

https://gentic.co/shopify/gentic-shopify.skill

Download this file and upload it wherever Claude Managed Agents asks for a .skill file. It's a zip bundle generated on demand from the latest SKILL.md.

4. When to Apply

  • User wants to inspect or analyze Shopify orders, products, or customers in plain English.
  • User wants to compute ROAS, attributed revenue, or CAC by joining Shopify orders against ad spend from Meta or Google Ads.
  • User wants a CSV export of orders filtered by date, financial status, or channel (source_name).
  • User wants the top customers by lifetime value, or to investigate a specific customer's order history.
  • User wants to look up a single order, product, or customer by ID, GID, or product handle.
  • User wants to run an arbitrary Admin GraphQL query against the Shopify store (read-only).
  • User wants to know which Shopify store is connected, or check the store's currency, timezone, or plan.

5. Workflow

  1. 1. Check connection with `shopify_connection_status`

    Free call — returns whether the org has connected a Shopify store, plus the `shop_domain` and `updated_at` timestamp when connected. If not connected, direct the user to the Gentic dashboard → Integrations → Shopify to paste a shop subdomain and Admin API access token. At least one of `read_orders` / `read_products` / `read_customers` must be granted on the token; individual tools that need a specific scope will surface their own error at call time if it's missing.

  2. 2. Grab store basics with `get_shop_info`

    Free call — returns name, email, primary domain, currency, IANA timezone, weight unit, and plan. Worth calling once per session: the currency drives how you format revenue numbers, and the timezone matters for any date-bucketed analysis (`processed_at` comes back in store-local time).

  3. 3. List orders with `list_orders` (5¢/call)

    Cursor-paginated. Sort defaults to `processed_at` descending — the right key for revenue attribution, since `processed_at` is when the order was actually placed (`created_at` can include draft-order timestamps that lag). Filter by date range (`processed_at_min`/`max` for ROAS, `created_at_min`/`max` for funnel analysis), `financial_status`, `fulfillment_status`, and `source_name` (the channel — workhorse for ROAS attribution). Watch for `line_items_truncated: true` on orders with >50 line items — follow up with `get_order` for the full breakdown.

  4. 4. Drill into a single record (free)

    `get_order`, `get_product`, and `get_customer` are all free. `get_order` returns full line items (up to 250), refunds, fulfillments + tracking, addresses, and customer summary. `get_product` accepts either `id` or `handle` and returns up to 20 images + 100 variants with prices, SKUs, and inventory quantities — set `include_html: true` to also pull `descriptionHtml`. `get_customer` returns the customer profile plus the 10 most recent orders inline (handy for LTV / churn / cohort analysis without a second roundtrip).

  5. 5. List products with `list_products` (5¢/call)

    Most recently updated first. Filter by `status` (ACTIVE / ARCHIVED / DRAFT), `vendor`, `product_type`, and `title` (substring match). Returns summary fields including price range and total inventory. For variants, SKUs, and full descriptions, follow up with `get_product`. Use `extra_query` for any Shopify search syntax the typed filters don't cover.

  6. 6. List customers with `list_customers` (5¢/call)

    Sorts by `total_spent` descending by default — top customers first, the right order for LTV analysis. Filter by `email` (exact), `tag` (exact), `total_spent_min`/`max`, `orders_count_min`, `created_at_min`/`max`. `extra_query` is the escape hatch for free-form Shopify search. Paginate via `next_cursor` — `resultCount` reflects the page only, not the total.

  7. 7. Export revenue for joins with `export_orders_report` ($1/call)

    The ROAS workhorse. Returns a CSV download URL that expires in **1 hour** AND persists the rows to MotherDuck `shopify_orders` with a schema that matches the row layout exactly. Pre-computes `net_revenue` (= `current_total_price` − `total_refunded`) and `processed_date` (DATE part of `processed_at`) so the join against `meta_ad_insights` is a single equality predicate, not a CASE-laden CTE. Filter by `processed_at_min`/`max` (preferred for ROAS attribution), `created_at_min`/`max`, `financial_status`, `source_name`, or `extra_query`. Caps at 10,000 orders per call — narrow the date window if you hit it. Tell the user the 1-hour expiry up front.

  8. 8. Use `shopify_graphql_query` as an escape hatch (10¢/call)

    When the typed tools don't cover a specific field, drop into raw Admin GraphQL (API version `2026-04`). Mutations and subscriptions are rejected server-side — Gentic's Shopify surface is analytics-only and won't modify the store. Returns the raw GraphQL response plus rate-limit cost info. Prefer the typed tools when they exist: they paginate, normalize money fields, and surface consistent error messages.

  9. 9. Present results clearly

    For orders: lead with the headline (period revenue, order count, AOV), show a ranked table by the metric the user cares about, and call out outliers (huge orders, refunds, unusual channels). For customers: surface lifetime value, order count, and the most recent order date prominently. For exports: show the download URL **and the 1-hour expiry** clearly so the user doesn't lose access to the file. For ROAS workflows: after running `export_orders_report`, hand the analysis to the Data MCP server to join `shopify_orders.processed_date` against `meta_ad_insights.date` and compute ROAS = `net_revenue / spend`.

6. Tool Reference

10 tools, rendered live from the Gentic MCP manifest. Parameter tables come directly from each tool's JSON Schema.

export_orders_report

100¢ / call

Export Shopify orders to a CSV (1-hour signed URL) AND persist to MotherDuck `shopify_orders` for SQL-level joins with `meta_ad_insights`. Filters: `processed_at_min`/`max` (preferred for ROAS attribution), `created_at_min`/`max`, `financial_status`, `source_name`, `extra_query`. Paginates up to 10000 orders per call — narrow the date window if you hit the cap. The row schema matches `SHOPIFY_ORDERS_SCHEMA` exactly so the CSV and the warehouse table stay aligned. Pre-computes `net_revenue` (= `current_total_price` − `total_refunded`) and `processed_date` (DATE part of `processed_at`) so the join query against `meta_ad_insights` is a single equality predicate. $1.00 per call.

ParameterTypeDescription
processed_at_minstring

ISO-8601 lower bound on `processed_at`. Strongly recommended for ROAS analytics — `processed_at` is when payment actually happened, which matches how ad-spend dates work.

processed_at_maxstring

created_at_minstring

ISO-8601 lower bound on `created_at`. Use when the analysis tracks order initiation including drafts.

created_at_maxstring

financial_statusstring

Filter to a financial status (e.g. 'paid'). Common practice for ROAS analysis is `paid` only.

source_namestring

Filter by Shopify channel/source name.

extra_querystring

Optional raw Shopify search-syntax clauses appended to the compiled query (parens-wrapped when combined with typed filters).

get_customer

Free

Fetch a single Shopify customer by ID. Accepts a numeric ID or full GID like 'gid://shopify/Customer/123456789'. Returns the customer profile plus the 10 most recent orders inline (useful for LTV / churn / cohort analysis without a second roundtrip). Free.

ParameterTypeDescription
id
required
string

Customer ID. Either a numeric string ('1234567890') or full GID ('gid://shopify/Customer/1234567890').

get_order

Free

Fetch a single Shopify order by ID. Accepts either a numeric ID (from a Shopify admin URL) or a full GID like 'gid://shopify/Order/123456789'. Returns the full order detail including all line items (up to 250), refunds, fulfillments + tracking, addresses, and customer summary. Free.

ParameterTypeDescription
id
required
string

Order ID. Either a numeric string ('1234567890') or a full GID ('gid://shopify/Order/1234567890').

get_product

Free

Fetch a single Shopify product by ID or handle. Provide exactly one of `id` (numeric or full GID) or `handle` (the url-safe slug). Returns full product detail including up to 20 images and 100 variants with prices, SKUs, and inventory quantities. By default the response carries the plain-text `description` only — set `include_html: true` to also pull `descriptionHtml` (roughly doubles the token cost on products with long marketing copy). Free.

ParameterTypeDescription
idstring

Product ID — numeric string ('1234567890') or full GID ('gid://shopify/Product/1234567890'). Mutually exclusive with `handle`.

handlestring

Product handle (url slug, e.g. 'cool-tshirt'). Mutually exclusive with `id`.

include_htmlboolean

Include `descriptionHtml` (the rich-text form) in the response. Defaults to false.

get_shop_info

Free

Get basic information about the connected Shopify store: name, email, primary domain, currency, IANA timezone, weight unit, and plan. Free. Useful as a connection sanity check and to discover the currency/timezone needed for downstream order/revenue analysis.

This tool takes no parameters.

list_customers

5¢ / call

List Shopify customers. Cursor-paginated. Typed filters: `email` (exact match), `tag` (exact tag match), `total_spent_min`/`max`, `orders_count_min`, `created_at_min`/`max`. Free-form Shopify search via `extra_query` (auto-wrapped in parens when combined with typed filters). Sort by `total_spent` (default, descending — top customers first, ideal for LTV analysis), `created_at`, `updated_at`, or `name`. $0.05 per call. `resultCount` reflects the page size only — paginate via `next_cursor`.

ParameterTypeDescription
emailstring

Exact-match email filter (Shopify also supports wildcards like 'foo@*.com' via `extra_query`).

tagstring

Exact-match customer tag filter.

total_spent_minnumber

Lower bound on lifetime total_spent (in shop currency). Use to filter to whale / VIP cohorts.

min 0

total_spent_maxnumber

Upper bound on lifetime total_spent.

min 0

orders_count_mininteger

Lower bound on lifetime order count. Use to filter to repeat-buyer cohorts.

0 – 9007199254740991

created_at_minstring

ISO-8601 lower bound on customer `created_at` (signup date). Use for cohort analysis.

created_at_maxstring

extra_querystring

Optional raw Shopify customer search-syntax clauses appended to the compiled query. Examples: 'email:*@gmail.com', 'last_order_id:>0'. Auto-wrapped in parens when combined with typed filters.

sort_bystring

Sort key. Defaults to 'total_spent' (descending) — most valuable customers first.

enum: total_spent, created_at, updated_at, name

reverseboolean

Reverse the sort direction. Default true when sorting by spend or recency (descending); false for name (alphabetical).

limit
required
integer

Max results per page (1–250). Default 50. Shopify caps this at 250 even if a higher value is requested.

1 – 250 · default: 50

cursorstring

Opaque cursor from a prior call's `next_cursor`. Omit to start at the beginning.

list_orders

5¢ / call

List Shopify orders. Cursor-paginated. Filter by date range (`created_at_min/max`, `processed_at_min/max`, `updated_at_min/max`), `financial_status`, `fulfillment_status`, and `source_name` (channel — workhorse for ROAS attribution). Sort defaults to `processed_at` descending — that's the right key for revenue attribution because `processed_at` reflects when the order was actually placed; `created_at` can include the draft-order timestamp which lags. Returns flattened orders with shopMoney totals for analytics consistency. Each order carries `line_items_truncated: true` when more than 50 line items exist on it — follow up with `get_order` (250-item cap) for the full breakdown. $0.05 per call. `resultCount` reflects the page size only — paginate via `next_cursor`. For very large pull-downs (>1k orders) prefer `export_orders_report` (shipping in PR 3) which bulk-exports to CSV + MotherDuck.

ParameterTypeDescription
created_at_minstring

ISO-8601 lower bound on `created_at`, inclusive. Use this when the agent's clock tracks when orders were started (drafts included).

created_at_maxstring

ISO-8601 upper bound on `created_at`, inclusive.

processed_at_minstring

ISO-8601 lower bound on `processed_at`, inclusive. Prefer this for ROAS / revenue-attribution polling — `processed_at` is when payment actually happened.

processed_at_maxstring

ISO-8601 upper bound on `processed_at`, inclusive.

updated_at_minstring

ISO-8601 lower bound on `updated_at`. Use for change-data-capture flows that need to catch refunds and edits.

updated_at_maxstring

financial_statusstring

Filter by Shopify financial status. Common values: 'paid', 'pending', 'authorized', 'partially_paid', 'refunded', 'partially_refunded', 'voided'.

fulfillment_statusstring

Filter by fulfillment status. Common values: 'fulfilled', 'unfulfilled', 'partial', 'restocked'.

source_namestring

Filter by Shopify channel/source name (e.g. 'web', 'pos', 'shopify_draft_order', or a specific connected-app source name).

extra_querystring

Optional raw Shopify search-syntax clauses appended to the compiled query. Auto-wrapped in parens when combined with typed filters so OR clauses scope correctly. See https://shopify.dev/docs/api/usage/search-syntax.

sort_bystring

Sort key. Defaults to 'processed_at' (descending) which matches revenue-attribution expectations. Set 'created_at' if the polling pattern tracks order-start timestamps including drafts.

enum: processed_at, created_at, updated_at

reverseboolean

Reverse the sort order. Defaults to `true` (descending — newest first).

limit
required
integer

Max results per page (1–250). Default 50. Shopify caps this at 250 even if a higher value is requested.

1 – 250 · default: 50

cursorstring

Opaque cursor from a prior call's `next_cursor`. Omit to start at the beginning.

list_products

5¢ / call

List Shopify products, most recently updated first. Cursor-paginated. Filter by `status` (ACTIVE / ARCHIVED / DRAFT), `vendor`, `product_type`, and `title` (substring match). Free-form Shopify search via `extra_query` (auto-wrapped in parens when combined with typed filters). Returns summary fields including price range and total inventory — for variants and full descriptions, follow up with `get_product`. $0.05 per call. `resultCount` reflects the page size only — paginate via `next_cursor`.

ParameterTypeDescription
statusstring

Product status filter.

enum: ACTIVE, ARCHIVED, DRAFT

vendorstring

Vendor name filter (exact match).

product_typestring

Product type filter (exact match).

titlestring

Substring match on product title.

extra_querystring

Optional raw Shopify search-syntax clauses appended to the compiled query. Auto-wrapped in parens when combined with typed filters so OR clauses scope correctly.

limit
required
integer

Max results per page (1–250). Default 50. Shopify caps this at 250 even if a higher value is requested.

1 – 250 · default: 50

cursorstring

Opaque cursor from a prior call's `next_cursor`. Omit to start at the beginning.

shopify_connection_status

Free

Check whether the calling organization has connected a Shopify store. Returns `{ connected, shop_domain, updated_at }` when connected, or `{ connected: false }` otherwise. Free. Call this before any other Shopify tool to give the user actionable guidance when the integration is missing.

This tool takes no parameters.

shopify_graphql_query

10¢ / call

Execute a read-only GraphQL query against the Shopify Admin API (version 2026-04). Use this as an escape hatch when the typed Shopify tools don't cover what you need. Mutations and subscriptions are rejected — Gentic's v1 Shopify surface is analytics-only and will not modify the store. Prefer the typed tools (list_orders, list_products, etc.) when they exist — they handle pagination, field selection, and error formatting consistently. Returns the raw GraphQL response plus rate-limit cost info. $0.10 per call.

ParameterTypeDescription
query
required
string

A complete GraphQL query string (read-only — mutations/subscriptions are rejected). Must end with a closing brace. Example: '{ shop { name } }'. Reference: https://shopify.dev/docs/api/admin-graphql/2026-04

variablesobject

Optional GraphQL variables object for parameterized queries, e.g. { id: 'gid://shopify/Product/123' }.

7. Pricing

Pricing is pulled live from the Gentic MCP manifest. All prices are per call and deducted from your Gentic credits.

ToolCost
export_orders_report100¢ / call
get_customerFree
get_orderFree
get_productFree
get_shop_infoFree
list_customers5¢ / call
list_orders5¢ / call
list_products5¢ / call
shopify_connection_statusFree
shopify_graphql_query10¢ / call

8. Notes

  • **Read-only by design.** Every tool in v1 is read-only; `shopify_graphql_query` rejects mutations and subscriptions server-side.
  • **Scopes are not all-or-nothing.** Connection succeeds as long as at least one of `read_orders` / `read_products` / `read_customers` is granted. A ROAS-focused user can connect with `read_orders` alone; tools that need a different scope error at call time with a clear message naming the scope to add.
  • **`processed_at` vs `created_at`:** `processed_at` is when the order was actually placed and is the right key for revenue attribution. `created_at` can include draft-order timestamps that lag. Default sort and the export's pre-computed `processed_date` both use `processed_at`.
  • `shop_domain` is the subdomain only (e.g. `my-shop` for `my-shop.myshopify.com`) and is stored as plaintext — it's a tenant identifier, not a secret. The Admin API access token is encrypted at rest.
  • `list_*` tools cap each page at 50 records and paginate via `next_cursor`. `resultCount` is the page size, not the total — there's no cheap total count on Shopify, by design.
  • `get_order` returns up to 250 line items; if an order has more (rare), use `shopify_graphql_query` for the rest.
  • `get_product` accepts either `id` (numeric or full GID) or `handle` (the url-safe slug) — exactly one, not both.
  • **`export_orders_report` CSV links expire in 1 hour.** The MotherDuck `shopify_orders` table persists, so you don't lose the data — re-export only if you need a fresh CSV file.
  • `export_orders_report` caps at 10,000 orders per call. Narrow the date window if you hit it; the warehouse table is appended/upserted in chunks so multiple calls compose cleanly.
  • Shopify Admin API version pinned to `2026-04`. Bumps are coordinated with the gentic-web validator's `SHOPIFY_API_VERSION` constant.
  • All tools are organization-scoped — users only see their own Shopify store.