Commerce & blogs
Connect Shopify, WooCommerce, WordPress, Wix and Webflow to manage catalogs, read orders, publish blog articles and install ad pixels with one API.
Stores and websites are accounts too. Connect a Shopify store, a WooCommerce shop or a WordPress, Wix or Webflow site to a profile, and you can manage its catalog, read its orders, publish its blog and put ad pixels on it, with the same API key and request shapes you use for social posting. Write the integration once and it works on every platform that supports the job.
#What each platform supports
| Job | Shopify | WooCommerce | WordPress | Wix | Webflow |
|---|---|---|---|---|---|
| Products, variants, images, stock | Yes | Yes | Through WooCommerce | No | No |
| Collections and discounts | Yes | Categories and coupons | Through WooCommerce | No | No |
| Orders (read-only) | Yes | Yes | Through WooCommerce | No | No |
| Store pages | Yes | Yes | Yes | No | No |
| Menus, redirects, markets, metaobjects, sales channels | Yes | No | No | No | No |
| Meta catalog sync | Yes | Yes | Through WooCommerce | No | No |
| Blog articles | Yes | Via WordPress | Yes | Yes | Yes (CMS items) |
| Native scheduling of articles | Yes | Via WordPress | Yes | Yes | No |
| Ad pixels on the site | Yes, with storefront events | Via WordPress | Yes, page views | Yes, page views | Yes, page views |
WooCommerce is not a separate connection: it is a self-hosted WordPress site with WooCommerce installed, connected with an Application Password. Store objects from it report platform: "woocommerce".
#Two APIs, one account
- Commerce API at
/v1/commerce/...covers the catalog, stock, orders, discounts and store content. Every call names the store withaccountId: in the query on reads, in the body on writes. See Products and Orders. - Blogs API at
/v1/accounts/{accountId}/blogs/...publishes articles. The same five calls work on Shopify, WordPress, Wix and Webflow. See Blogs.
Ad pixels use the tracking tag endpoints of your ads account and name the site as storeAccountId. See Site pixels.
#Start with the store's capabilities
Call GET /v1/commerce/store before anything else. It tells you the currency and country, what the store can do now, and what it could do once the owner grants more permissions.
curl "https://api.pozy.ai/v1/commerce/store?accountId=6710c4b2e4b0d2f1a8c95e3a" \
-H "Authorization: Bearer $POZY_API_KEY"const res = await fetch("https://api.pozy.ai/v1/commerce/store?accountId=6710c4b2e4b0d2f1a8c95e3a", {
headers: { Authorization: `Bearer ${process.env.POZY_API_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
if (data.store.missingCapabilities.includes("orders.read")) {
console.log("Ask the owner to approve:", data.store.grantPermissionsUrl);
}import os, requests
store = requests.get(
"https://api.pozy.ai/v1/commerce/store",
headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
params={"accountId": "6710c4b2e4b0d2f1a8c95e3a"},
).json()["store"]
print(store["capabilities"], store["grantPermissionsUrl"]){
"store": {
"accountId": "6710c4b2e4b0d2f1a8c95e3a",
"platform": "shopify",
"name": "Acme",
"domain": "acme.myshopify.com",
"url": "https://acme.com",
"currency": "USD",
"country": "US",
"capabilities": ["products.read", "products.create", "products.update", "collections.read", "pages.read", "pages.write"],
"missingCapabilities": ["inventory.read", "inventory.write", "discounts.read", "orders.read"],
"grantPermissionsUrl": "https://admin.shopify.com/store/acme/oauth/install?..."
}
}On Shopify, send the owner to grantPermissionsUrl to approve the missing capabilities on the existing install, then read the store again. grantPermissionsUrl is null when nothing is missing, on stores connected with a custom-app token, and always on WooCommerce. The capability-to-scope table is on the Shopify page.
#Shared conventions
| Topic | Rule |
|---|---|
| Ids | The platform's own ids, as strings. Read them from responses, never build them |
| Money | Responses return { "amount": "24.00", "currency": "USD" }. Write bodies take a plain decimal in the store currency, as a number or string |
| Product status | active, draft, pending_review, rejected, inactive, archived or deleted. The platform's raw value is in platformStatus |
| Timestamps | ISO 8601, UTC |
| Pagination | Lists return { <resource>, nextCursor }. Pass limit and the previous nextCursor as cursor. nextCursor is null on the last page |
| Storage | Pozy keeps no copy of store data. Each call goes to the store live, so results are always current |
| Unsupported operations | 400 platform_not_supported. Check capabilities first |
#Errors
| Error | Cause | Fix |
|---|---|---|
400 platform_not_supported |
The account is not a store, or its platform lacks the operation | Check capabilities on GET /v1/commerce/store |
400 invalid_field_value |
The platform rejected a field, or it does not exist there | Read the message; see the WooCommerce differences on WordPress |
403 insufficient_permissions |
The store has not granted the scope | Send the owner to grantPermissionsUrl, or reconnect |
404 product_not_found, 404 resource_not_found |
Deleted, or another store's id | List the resource for a current id |
409 catalog_sync_conflict |
A sync for that store and catalog exists, or a run is in progress | Run the existing sync, or wait |
429 |
Your rate limit or the platform's | Wait for Retry-After |
502 |
The platform failed or was unavailable | Check the result of the earlier write before retrying |
#In this section
#Endpoints
#Webhook events
| Event | When it fires |
|---|---|
commerce.product.created |
Commerce product created. |
commerce.product.updated |
Commerce product updated. |
commerce.product.deleted |
Commerce product deleted. |
commerce.order.created |
Commerce order created. |
commerce.order.updated |
Commerce order updated. |
commerce.order.refunded |
Commerce order refunded. |