Looking for the overview — what this API returns, what it costs, and a call you can run without a key? See the Shopify Store API page →
E-commerce & Marketplaces

Shopify Store API & Scraper

The Shopify Store API returns products, variants, prices and collections from any public Shopify store as clean JSON.

9 actionsLive JSON1,000 free credits$0.67–$1.50 / 1,000 creditsMCP-ready
Get a free keyOpen in playground

🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.

The primary products endpoint returns each product's id, title, handle, vendor, type, tags, description, options and variants (price, SKU, availability, compare-at price) — a store's full catalog. You can also pull a single product, collections and their products, run a search, get recommendations and read store_info. It is built for competitor-catalog monitoring, price tracking and dropshipping tools that need Shopify store data without a scraper. One ReefAPI key, one shared credit pool, the standard envelope.

Reference

Addressing a store, and the types you actually get back

Two things trip people up here. The first is which domain to send, because the obvious answer is the wrong one. The second is that Shopify's own public JSON returns prices as quoted strings and this API does not. Everything below was measured against allbirds.com in one session.

FieldType as returnedMeasured value
store (input)The public storefront domain or URLallbirds.com works; allbirds.myshopify.com returned TARGET_BLOCKED
product.id, variant.id, collection.idA string of digits, not a number"7218356060240", "41334293889104", "263506919504"
variant.price, price_min, price_maxJSON number, parsed from Shopify's string130.0, not the "130.00" the raw storefront JSON serves
product.currencyThe store's own currency, on the product and on every variantUSD on two US stores, AUD on an Australian one, GBP on a British one - filled from the storefront, never guessed from the domain
variant.compare_at_pricenull when the variant is not discountednull, alongside on_sale false and discount_percent 0.0
variant.inventoryObject of {quantity, management, policy, available}{0, "shopify", "deny", false} on a sold-out size
published_at, updated_atISO 8601 with the store's local offset, not Z"2026-06-16T11:02:10-07:00"
limitClamped at 250, never rejectedlimit=400 returned meta.limit 250 and 250 records

meta.pagination gives you {page, has_more} and no total, so page until has_more is false or set max_items and let it walk for you. The one place a total does exist is the collection action, which returned products_count 960 for the "mens" collection.

Live example

Real request and response JSON

Captured from the indexed primary action, products, on .

Captured request
{
  "method": "POST",
  "url": "https://api.reefapi.com/shopify/v1/products",
  "headers": {
    "x-api-key": "$REEF_KEY",
    "content-type": "application/json"
  },
  "body": {
    "store": "allbirds.com",
    "limit": 5
  }
}
Captured response
{
  "ok": true,
  "meta": {
    "api": "shopify",
    "endpoint": "products",
    "mode": "live",
    "latency_ms": 739.4,
    "record_count": 5,
    "bytes": 37799,
    "cache_hit": false,
    "stop_reason": "limit_reached",
    "store": "https://allbirds.com",
    "page": 1,
    "limit": 5,
    "has_more": true,
    "filters_applied": [],
    "pagination": {
      "page": 1,
      "has_more": true
    }
  },
  "data": {
    "__trimmed": "response capped for page display"
  }
}
Actions

What the Shopify Store API does

ActionDescriptionConcrete use caseKey params
productsPaginated product catalog from any public Shopify store: title, vendor, variants, prices, inventory status, tags, and images.Pricing teams call products to get paginated product catalog from any public Shopify store.store, page, limit, max_items, vendor, ...
productFull detail for a single Shopify product by its handle (URL slug) or product page URL: title, vendor, variants, prices, images, and inventory.Marketplace operators call product to get full detail for a single Shopify product by its handle (URL slug) or product page URL.store, handle
collectionsPaginated list of public collections from a Shopify store: collection id, title, handle, description, and cover image.Catalog enrichment teams call collections to get paginated list of public collections from a Shopify store.store, page, limit, max_items
collection_productsPaginated products within a specific Shopify collection — same product shape as the products action, filterable and sortable.Retail analysts call collection_products to get paginated products within a specific Shopify collection.store, handle, page, limit, max_items, ...
searchPredictive search across a Shopify store: matching products (title, price, variants, image) plus optional collection, page, and autocomplete query suggestions.Pricing teams call search to get predictive search across a Shopify store.store, query, limit, page, max_items, ...
recommendationsRelated or complementary products that a Shopify store recommends for a given product — the store's own 'you may also like' / 'goes well with' set, same rich product shape.Marketplace operators call recommendations to get related or complementary products that a Shopify store recommends for a given product.store, handle, intent, limit
collectionMetadata for a single Shopify collection by handle: title, description, cover image, published/updated dates, and product count.Catalog enrichment teams call collection to get metadata for a single Shopify collection by handle.store, handle
pagesContent pages published on a Shopify store (About, FAQ, Shipping, size guides, etc.): title, handle, URL, and HTML/plain-text body.Retail analysts call pages to get content pages published on a Shopify store (About, FAQ, Shipping, size guides, etc.).store, page, limit, max_items
store_infoRich profile for a Shopify store: name, currency, country/city, product & collection counts, accepted card brands, social links, myshopify domain, and platform confirmation.Pricing teams call store_info to get rich profile for a Shopify store.store
Code samples

Call products from your stack

curl -X POST https://api.reefapi.com/shopify/v1/products \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"store":"allbirds.com","limit":5}'
MCP one-liner
Ask your MCP-connected assistant: call reefapi.shopify.products with {"store":"allbirds.com","limit":5}.
Use cases

Who uses this API and why

  • Price-monitoring tools call products to track a competitor Shopify store's prices and stock across variants.
  • Dropshipping and catalog tools use collection_products to mirror a store's product structure.
  • Market researchers pull store_info and products to profile a brand's full Shopify catalog.
FAQ

Questions developers ask before integrating

Should I pass the myshopify.com domain or the store's own domain?

The store's own domain. A live products call on allbirds.com succeeded and reported meta.store "https://allbirds.com", while the identical call on allbirds.myshopify.com failed with TARGET_BLOCKED. Shopify's admin-canonical myshopify hostname is not the surface the public JSON is served from once a custom domain is attached. Send the domain a customer would type, with or without the scheme.

Is price a string, the way Shopify's own products.json returns it?

No. Shopify's public endpoint serializes prices as quoted decimal strings, and this API parses them into JSON numbers before returning them. A measured Allbirds variant came back as "price": 130.0, and price_min and price_max on the parent product are numbers too. You can do arithmetic on them directly, and the currency travels beside them on the same row.

What currency are the prices in, and can I trust it across stores?

Each row states it. currency is filled on the product and on every variant, taken from what the storefront itself declares rather than inferred from the domain, so it is the store's real trading currency: two US stores returned USD on 40 of 40 products and all 322 variants between them, an Australian store returned AUD and a British one GBP. It is filled on the store's own predictive search too. If the storefront cannot be asked, the field stays null rather than being guessed - so a null means unknown, never a default.

Why do search results come back with an empty variants array?

Because search runs against Shopify's predictive-search endpoint, which returns a summary row rather than the full product record. A measured search for "wool runner" on allbirds.com returned the product with price_min, price_max, available, featured_image and url populated but variants length 0, while the product action on the identical handle returned all seven variants. products, collection_products and recommendations all carry full variants; only search does not. Use search to find handles, then fetch by handle.

Why is inventory_quantity null in a product listing but a real number for the same variant elsewhere?

The listing endpoint and the single-product endpoint expose different amounts of detail, and that shows through. Variant 41334293889104 was fetched both ways at the same moment: through the product action it returned inventory_quantity 0, inventory_management "shopify", inventory_policy "deny", weight 2.0264 and a barcode; through the products listing the same variant returned null for all five. price, sku, grams and available were identical on both paths. If you need stock numbers, weights or barcodes, fetch the product by handle.

I set only_on_sale and got zero products from a store that runs promotions. Why?

Because vendor, tag, price, sale and stock filters are applied after the fetch, over whatever pages were actually pulled. A measured only_on_sale call on allbirds.com returned 0 products with meta.filters_applied ["only_on_sale"] and stop_reason "cap_reached", meaning nothing on the pages it walked had a discounted variant. Set max_items high enough for the walk to reach the discounted products before concluding the store has no sales.

What happens on a store that is not Shopify, or that turned the public JSON off?

You get a clear NOT_FOUND rather than an empty list. A measured products call on nike.com returned ok:false with the message "https://nike.com has disabled Shopify public JSON for products". That distinction is worth handling: ok:true with zero products means the store is reachable and genuinely has nothing matching, while NOT_FOUND means the endpoint is closed to you.

How do the collections and recommendations actions relate to products?

collections lists every public collection with its handle, which is what collection_products and collection take. Be ready for internal ones: the first page on Allbirds included a collection titled "$109 Tree Dashers for Outlet Discount Code" and one titled just "98". recommendations takes a product handle, resolves it to a product_id reported in meta, and returns the store's own related set - for a men's Wool Runner it came back with three women's Wool Runners, because that is what the store recommends, not something the API chose.

What is the Shopify Store API?

Shopify Store API is a ReefAPI endpoint group for shopify store It returns live JSON through POST requests under /shopify/v1.

Is the Shopify Store API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. Shopify Store calls use the same shared credit balance as every other ReefAPI engine.

Do I need a Shopify Store login or account?

No login to Shopify Store is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the Shopify Store data?

The page example is captured from a live products call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the Shopify Store API use?

Shopify Store actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call Shopify Store from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call shopify actions with the same key, credit pool and JSON envelope used by normal REST requests.

docs / shopify

Shopify Store

Shopify Store

base /shopify/v19 endpoints
post/shopify/v1/products1 credit

Paginated product catalog from any public Shopify store: title, vendor, variants, prices, inventory status, tags, and images.

ParameterAllowed / rangeDescription
storerequiredShopify store domain or URL (e.g. allbirds.com or https://shop.example.com) — works for ANY Shopify-powered store.
page = 1optional1–Page number (1, 2, 3…).
limit = 50optional1–250Items per page (1–250; larger values are capped at 250).
max_itemsoptional1–Auto-walk pages until this many items are collected (overrides single-page mode; recommended when using filters).
vendoroptionalOnly products whose vendor/brand contains this text (filter, post-fetch).
product_typeoptionalOnly products whose type contains this text (filter, post-fetch).
tagsoptionalOnly products carrying at least one of these tags (comma-separated or a list; filter, post-fetch).
title_containsoptionalOnly products whose title contains this text (filter, post-fetch).
sku_containsoptionalOnly products with a variant SKU containing this text (filter, post-fetch).
min_priceoptional0–Only products priced at or above this (store currency; post-fetch).
max_priceoptional0–Only products priced at or below this (store currency; post-fetch).
only_on_sale = falseoptionalOnly products with at least one discounted variant.
only_in_stock = falseoptionalOnly products with at least one available variant.
new_arrivals_daysoptional1–Only products published within the last N days.
Try in playground →
post/shopify/v1/product1 credit

Full detail for a single Shopify product by its handle (URL slug) or product page URL: title, vendor, variants, prices, images, and inventory.

ParameterAllowed / rangeDescription
storerequiredShopify store domain or URL (e.g. allbirds.com or https://shop.example.com) — works for ANY Shopify-powered store.
handlerequiredProduct handle — the slug in the product URL (…/products/<handle>); a full product URL also works.
Try in playground →
post/shopify/v1/collections1 credit

Paginated list of public collections from a Shopify store: collection id, title, handle, description, and cover image.

ParameterAllowed / rangeDescription
storerequiredShopify store domain or URL (e.g. allbirds.com or https://shop.example.com) — works for ANY Shopify-powered store.
page = 1optional1–Page number (1, 2, 3…).
limit = 50optional1–250Items per page (1–250; larger values are capped at 250).
max_itemsoptional1–Auto-walk pages until this many items are collected (overrides single-page mode; recommended when using filters).
Try in playground →
post/shopify/v1/collection_products1 credit

Paginated products within a specific Shopify collection — same product shape as the products action, filterable and sortable.

ParameterAllowed / rangeDescription
storerequiredShopify store domain or URL (e.g. allbirds.com or https://shop.example.com) — works for ANY Shopify-powered store.
handlerequiredCollection handle — the slug in the collection URL (…/collections/<handle>); take it from the collections action. A full collection URL also works.
sort_byoptionalrelevance · price-ascending · price-descending · created-descending · best-selling · title-ascendingRequested ordering — passed to the store's collection endpoint, but MANY stores ignore it (theme-dependent); ordering is not guaranteed. Aliases like priceAsc/newest are also accepted.
page = 1optional1–Page number (1, 2, 3…).
limit = 50optional1–250Items per page (1–250; larger values are capped at 250).
max_itemsoptional1–Auto-walk pages until this many items are collected (overrides single-page mode; recommended when using filters).
vendoroptionalOnly products whose vendor/brand contains this text (filter, post-fetch).
product_typeoptionalOnly products whose type contains this text (filter, post-fetch).
tagsoptionalOnly products carrying at least one of these tags (comma-separated or a list; filter, post-fetch).
title_containsoptionalOnly products whose title contains this text (filter, post-fetch).
sku_containsoptionalOnly products with a variant SKU containing this text (filter, post-fetch).
min_priceoptional0–Only products priced at or above this (store currency; post-fetch).
max_priceoptional0–Only products priced at or below this (store currency; post-fetch).
only_on_sale = falseoptionalOnly products with at least one discounted variant.
only_in_stock = falseoptionalOnly products with at least one available variant.
new_arrivals_daysoptional1–Only products published within the last N days.
Try in playground →
post/shopify/v1/recommendations1 credit

Related or complementary products that a Shopify store recommends for a given product — the store's own 'you may also like' / 'goes well with' set, same rich product shape.

ParameterAllowed / rangeDescription
storerequiredShopify store domain or URL (e.g. allbirds.com or https://shop.example.com) — works for ANY Shopify-powered store.
handlerequiredProduct handle — the slug in the product URL (…/products/<handle>); a full product URL also works.
intent = relatedoptionalrelated · complementaryWhich Shopify recommendation set to return. 'related' = similar products (works on every store); 'complementary' = goes-well-with picks (only on stores that configured Search & Discovery — falls back to related).
limit = 10optional1–250How many recommended products to return (1–250).
Try in playground →
post/shopify/v1/collection1 credit

Metadata for a single Shopify collection by handle: title, description, cover image, published/updated dates, and product count.

ParameterAllowed / rangeDescription
storerequiredShopify store domain or URL (e.g. allbirds.com or https://shop.example.com) — works for ANY Shopify-powered store.
handlerequiredCollection handle — the slug in the collection URL (…/collections/<handle>). A full collection URL also works.
Try in playground →
post/shopify/v1/pages1 credit

Content pages published on a Shopify store (About, FAQ, Shipping, size guides, etc.): title, handle, URL, and HTML/plain-text body.

ParameterAllowed / rangeDescription
storerequiredShopify store domain or URL (e.g. allbirds.com or https://shop.example.com) — works for ANY Shopify-powered store.
page = 1optional1–Page number (1, 2, 3…).
limit = 50optional1–250Items per page (1–250; larger values are capped at 250).
max_itemsoptional1–Auto-walk pages until this many items are collected (overrides single-page mode; recommended when using filters).
Try in playground →
post/shopify/v1/store_info1 credit

Rich profile for a Shopify store: name, currency, country/city, product & collection counts, accepted card brands, social links, myshopify domain, and platform confirmation.

ParameterAllowed / rangeDescription
storerequiredShopify store domain or URL (e.g. allbirds.com or https://shop.example.com) — works for ANY Shopify-powered store.
Try in playground →