Catalog
List every product of one Shopify store, or of one of its collections.
GET | POST /v1/shopify/catalogSend parameters as a query string with GET, or as a JSON body with POST. Both are equivalent.
Parameters
| Parameter | Type | Required | Notes |
|---|---|---|---|
id | string | yes | The store: its host (comfrt.com) or any URL on it — a product, collection or home page link. |
collection | string | Only this collection: its handle (best-sellers) or its URL. Omitted means the whole store — unless id is itself a collection page link, which lists that collection. | |
currency | string | Presentment currency, ISO 4217. | |
cursor | string | The previous page's cursor. Pass it for the next page; it also carries the store's total forward. | |
page | integer ≥ 1 | 1-based page number. | |
pageSize | integer 1–250 | Products per page, 1–250 (default 50). | |
region | string | Buyer country as ISO 3166-1 alpha-2; sets availability, shipping and price. |
Request
curl "https://gateway.apinoa.com/v1/shopify/catalog?id=thedoodlebot.com" \
-H "x-api-key: $APINOA_API_KEY"Response
Returns SearchResult in data. A real response, shortened: arrays keep their first entries and long text is cut.
{
"success": true,
"data": {
"marketplace": "shopify",
"page": {
"index": 1,
"size": 4,
"total": 4
},
"items": [
{
"marketplace": "shopify",
"id": "thedoodlebot.com/doodle-bot-1",
"url": "https://thedoodlebot.com/products/doodle-bot-1",
"title": "Doodle Bot",
"price": {
"currency": "USD",
"amount": 60
},
"listPrice": {
"currency": "USD",
"amount": 120
},
"brand": "Doodle Bot",
"listedAt": "2025-11-11T21:04:21.000Z",
"inStock": true,
"description": "<p><meta charset=\"utf-8\"><strong data-start=\"302\" data-end=\"392\">Doodle Bot is the fun, interactive robot that helps ki…",
"badges": [],
"promotions": [],
"features": [],
"media": {
"images": [
"https://cdn.shopify.com/s/files/1/0785/4070/1921/files/01803622-2C47-4C92-AB09-18AF6FB97168.jpg?v=1762895019",
"https://cdn.shopify.com/s/files/1/0785/4070/1921/files/530150FC-A189-4EE9-8A39-6775D4EE9A5D.jpg?v=1762895186"
],
"videos": []
},
"category": [],
"attributes": [],
"options": [
{
"id": "1",
"name": "Color",
"values": [
{
"id": "BLUE",
"name": "BLUE",
"imageUrl": "https://cdn.shopify.com/s/files/1/0785/4070/1921/files/530150FC-A189-4EE9-8A39-6775D4EE9A5D.jpg?v=1762895186"
},
{
"id": "PINK",
"name": "PINK",
"imageUrl": "https://cdn.shopify.com/s/files/1/0785/4070/1921/files/01803622-2C47-4C92-AB09-18AF6FB97168.jpg?v=1762895019"
}
]
}
],
"variants": [
{
"id": "47433841967329",
"price": {
"currency": "USD",
"amount": 60
},
"listPrice": {
"currency": "USD",
"amount": 120
},
"inStock": true,
"selections": [
{
"optionId": "1",
"valueId": "BLUE",
"optionName": "Color",
"valueName": "BLUE"
}
]
},
{
"id": "47433842000097",
"price": {
"currency": "USD",
"amount": 60
},
"listPrice": {
"currency": "USD",
"amount": 120
},
"inStock": true,
"selections": [
{
"optionId": "1",
"valueId": "PINK",
"optionName": "Color",
"valueName": "PINK"
}
]
}
],
"offers": [],
"reviewAspects": [],
"boxContents": [],
"reviews": [],
"seller": {
"id": "thedoodlebot.com",
"url": "https://thedoodlebot.com",
"name": "Doodle Bot",
"country": "US"
},
"imageUrl": "https://cdn.shopify.com/s/files/1/0785/4070/1921/files/01803622-2C47-4C92-AB09-18AF6FB97168.jpg?v=1762895019"
}
]
}
}Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_CURSOR | The cursor is not one this operation returned. Start again without it. |
| 400 | INVALID_PARAMS | A parameter is missing, unknown or out of range. The message names it. |
| 401 | UNAUTHORIZED | The x-api-key header is missing, or the key is revoked or unknown. |
| 402 | INSUFFICIENT_BALANCE | The balance does not cover this call. Top up in the dashboard. |
| 404 | NOT_FOUND | The store has no such collection. |
| 404 | NOT_SHOPIFY_STORE | The site is not a Shopify store. |
| 404 | STORE_CLOSED | The store is password-protected or closed. |
| 429 | MARKETPLACE_SATURATED | Too many concurrent calls. Retry after the Retry-After seconds. |
| 502 | UPSTREAM_ERROR | The platform answered with something unusable. Retry with backoff. |
Every code is listed in Errors. Failed calls are not billed.
Pricing
Price $0.001 per call. List price; the rate steps down above 1,000 calls a day.
Notes
idis the store's host or any link on it: a product page, a collection page or the home page. A collection page link lists that collection; addcollectionto narrow any other link to one.- Each item is the full product, the same object Product returns for that handle (every variant, option, image and the description), plus
imageUrl, the main image. page.totalis the store's product count, on every page, so the first page tells you whether a store is worth walking.- Follow the
cursor, not the item count. A page can hold fewer products thanpageSizeand still not be the last: Shopify leaves unlisted products out of a page rather than filling the gap. For the same reason a full walk can come to slightly fewer products thanpage.total.