- Start here
- Getting Started
- Development Store
- Build an app
-
App Development
-
Webhooks
- Guides by use case
- Popular APIs
-
Logistic Apps
- Reference
- Authentication
- API access scopes
- API call limit
- Response status codes
- API 3.0 reference โ
- API 4.0 reference โ
- EasyStore App Store โ
Popular APIs ๐งฐ
Most EasyStore Apps are built on a handful of APIs. This page explains what each one is for and which endpoints to start with. Every endpoint links to its full reference in the EasyStore Postman documentation.
API versions
All endpoints use the same access token and the EasyStore-Access-Token header (see Calling the API). Only the version in
the path changes:
| Version | Base URL | Use it for | Reference |
|---|---|---|---|
| 3.0 | https://{shop}/api/3.0/ |
Most resources: products, orders, customers, locations, snippets, script tags, webhooks and more | API 3.0 reference |
| 4.0 | https://{shop}/api/4.0/ |
Newer resources, including inventory levels, fulfillment requests, returns and tags | API 4.0 reference |
๐ก Tip: you can mix versions in one app. For example, read products with 3.0 and update their stock with the 4.0 inventory levels API.
Pagination and syncing
List endpoints return one page at a time, with the paging details next to the results:
{
"products": [ ... ],
"total_count": 230,
"page_count": 5,
"page": 1,
"limit": 50
}
pageandlimit: page starts at 1; limit defaults to 50. Use a moderate limit (50โ100) to stay well within the API call limit.- Stop at the last page: loop until
pageequalspage_count. Asking for a page past the end returns the last page again, not an empty list. - Use a stable order for full syncs: pass
sort=id.asc(products, orders and customers). The default sorts can change while you page, so records may be skipped or repeated. since_idincludes that ID: results start atsince_id(id >= since_id), so skip the first record when you continue from the last ID you saw.- Dates: send ISO 8601 with an offset, for example
2026-10-01T00:00:00+08:00. A value that can't be parsed is ignored rather than rejected, so check your format.
Keeping data in sync
- Initial import: page through everything with
sort=id.asc. - Real-time changes: subscribe to webhook
topics such as
order/create,product/updateandinventory_level/inventory_quantity_update. - Reconcile regularly: webhooks can be delayed or arrive out of order, so periodically fetch
recent changes with
updated_at_minand an overlap window (for example, the last 2 hours).
โ ๏ธ Date filters use the store's time zone. On orders and products, updated_at_*
values are read in the store's local time, whatever offset you send. On orders, created_at_*
filters by the order's processed time. Allow an overlap window when you filter by time.
๐ฆ Products
Create and manage the products a merchant sells. A product can have up to 9 images and several variants. Variants are built from option types and option values; for example, the type "Size" with the values "S", "M" and "L". Each variant has its own price, SKU and stock, and can be linked to one of the product's images. Products are grouped into collections.
Common uses: importing a catalogue from a supplier or ERP, keeping prices in sync, and publishing products to marketplaces.
| Endpoint | What it does |
|---|---|
GET /products.json |
List products |
POST /products.json |
Create a product with its variants |
PUT /products/:product_id.json |
Update a product |
GET /products/:product_id/variants.json |
List a product's variants |
PUT /products/:product_id/variants.json |
Update variants, for example price or SKU |
POST /products/:product_id/options.json |
Add option values, which creates new variants |
Scopes: read_products, write_products. To change stock quantities,
use the Inventory levels API.
๐งพ Orders
Read and manage orders from every channel a merchant sells on: the online store, marketplaces, social channels and point of sale all arrive as orders in the same store. Each order has its line items, customer, addresses, discounts, transactions and fulfillments.
Common uses: sending orders to an ERP, accounting or warehouse system, building reports, and creating orders that come from an external channel.
| Endpoint | What it does |
|---|---|
GET /orders.json |
List orders, with filters (see below) |
GET /orders/:order_id.json |
Get one order with its items, fulfillments and sales attribution |
POST /orders.json |
Create an order, for example from an external channel |
POST /orders/:order_id/cancel.json |
Cancel an order |
POST /orders/:order_id/fulfillments.json |
Fulfill an order and add tracking details |
Useful filters on GET /orders.json:
updated_at_min/updated_at_max: only orders changed in a time window, for incremental syncfinancial_status,fulfillment_status: for example, only paid orders not yet fulfilledsort=id.ascwithsince_id: a stable order for paging through every order (see Pagination)
Scopes: read_orders, write_orders. Fulfillments also need
read_fulfillments / write_fulfillments. To react to new orders as they come in, subscribe
to order webhooks instead of polling.
๐ฌ Inventory API 4.0
Control stock quantities across all of a merchant's stocked locations, such as warehouses, retail outlets and fulfillment centres. Stock is stored as an inventory level: one for each variant at each location where it is stocked.
Product โโโบ Variant โโโฌโโโบ Inventory level @ Warehouse A quantity: 30
โโโโบ Inventory level @ Outlet B quantity: 12
โโโโบ Inventory level @ Outlet C quantity: 0
Common uses: syncing stock from a warehouse or ERP system, sharing stock with marketplaces, and moving stock between locations.
| Endpoint | What it does |
|---|---|
GET /api/4.0/inventory_levels.json |
List inventory levels. Pass variant_ids or location_ids (at least one is
required) |
PUT /api/4.0/inventory_levels/set.json |
Set the quantity of a variant at a location to an exact number |
PUT /api/4.0/inventory_levels/adjust.json |
Adjust the quantity up or down by an amount |
GET /api/3.0/locations.json |
List the store's locations, to get each location_id |
Set or adjust?
| Set | Adjust | |
|---|---|---|
| Body | variant_id, location_id, quantity |
variant_id, location_id, adjustment_quantity |
| Example | "quantity": 30 makes the stock exactly 30 |
"adjustment_quantity": -5 takes 5 off the current stock (10 becomes 5) |
| Use when | Your system is the source of truth, for example a full stock sync from a warehouse | Recording a change, for example stock received or sold elsewhere. Safer when other sales happen at the same time |
curl --request PUT 'https://{shop}/api/4.0/inventory_levels/adjust.json' \
--header 'EasyStore-Access-Token: {access_token}' \
--header 'Content-Type: application/json' \
--data '{
"variant_id": 11950685,
"location_id": 9083,
"adjustment_quantity": -5
}'
Inventory level fields
inventory_quantity |
Available stock at this location. This is what set and adjust change. |
committed_inventory_quantity |
Units on open orders that aren't fulfilled yet. On-hand stock is
inventory_quantity + committed_inventory_quantity. |
incoming_inventory_quantity |
Units on the way from purchase orders and transfers. |
reserved_inventory_quantity |
Units held back from online selling. Online available stock is
inventory_quantity โ reserved_inventory_quantity. |
Variant stock vs inventory levels
- A variant's
inventory_quantity(in the Products API) is the total across its inventory levels. - Setting
inventory_quantitythroughPUT /products/:product_id/variants.jsonchanges the primary location only, and the total is then recalculated. For example, sending 10 when another location holds 5 makes the variant total 15. - For stores with more than one location, always use the inventory levels API. Find the primary location with
is_primary: trueinGET /api/3.0/locations.json.
Detecting stock changes
Subscribe to the inventory_level/inventory_quantity_update webhook. It fires on every stock change with the
variant_id, location_id, new inventory_quantity, the adjustment
type (SET, INCREASE or DECREASE) and inventory_level_updated_at.
Use inventory_level_updated_at to ignore older events that arrive late.
Scopes: read_products to read inventory levels and write_products to
set or adjust them. An adjustment_quantity of 0 is rejected.
๐ฅ Customers
Manage the merchant's customer data: profiles, addresses, customer groups and marketing consent, plus loyalty balances such as store credit and points.
Common uses: syncing customers with a CRM or email marketing tool, running loyalty or referral programmes, and segmenting customers into groups.
| Endpoint | What it does |
|---|---|
GET /customers.json |
List customers |
GET /customers/search.json |
Search customers, for example by email or phone |
POST /customers.json |
Create a customer |
PUT /customers/:customer_id.json |
Update a customer |
PUT /customers/:customer_id/credits/adjust.json |
Add or deduct store credit |
PUT /customers/:customer_id/point/adjust.json |
Add or deduct loyalty points |
Scopes: read_customers, write_customers. Custom customer fields use
read_customer_attributes / write_customer_attributes. API 4.0 also has customer endpoints.
๐จ Online store customisation
Add features to the merchant's online store without them editing their theme. When your app is uninstalled, EasyStore removes the snippets and script tags it created, so the store goes back to how it was.
| API | What it does | Good for |
|---|---|---|
| Snippets | Inserts HTML into a specific place on store pages, chosen by its field |
Badges, banners, widgets, and tracking tags in <head> |
| Script tags | Loads a JavaScript file from your server (src) on storefront and checkout pages |
Interactive features such as chat widgets, pop-ups and analytics |
| Metafields | Stores extra data on store objects such as products | Product specs, size charts, or settings your app needs |
Where snippets can go
The field sets where a snippet appears. Common placements:
| Every page | global/head, global/body_start, global/body_end,
global/content_top, global/content_bottom |
| Product page | product/description_top, product/description_bottom, product/button,
product/content_bottom |
| Cart and checkout | cart/content_top, cart/content_bottom, checkout/content_top,
checkout/content_bottom |
| Collection page | collection/content_top, collection/product_bottom |
See the Snippets reference for the full list.
curl --request POST 'https://{shop}/api/3.0/script_tags.json' \
--header 'EasyStore-Access-Token: {access_token}' \
--header 'Content-Type: application/json' \
--data '{
"script_tag": {
"src": "https://apps.yourapps.com/widget.js"
}
}'
Scopes: read_snippets / write_snippets,
read_script_tags / write_script_tags.