Products & Prices
Products are the catalog items you sell in your SMBcrm account. Each product can have one or more prices, which set how much it costs and how it’s billed, one-time or recurring.
Base URL: https://services.smbcrm.com · Version header: v3 ·
Scopes: products.readonly / products.write for products, bulk updates, reviews, and
online store visibility; products/prices.readonly / products/prices.write for prices and
inventory; products/collection.readonly / products/collection.write for collections. See
Scopes.
List products
Section titled “List products”locationId is required. Use limit and offset to page through results, or search to
filter by name. total in the response is an array with one object, [{ "total": n }].
curl "https://services.smbcrm.com/products/?locationId=<location_id>&limit=20&offset=0" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "products": [ { "_id": "<product_id>", "locationId": "<location_id>", "name": "1-Hour Consultation", "productType": "SERVICE", "description": "A single 60-minute strategy session.", "availableInStore": true, "createdAt": "2026-06-01T12:00:00.000Z", "updatedAt": "2026-06-01T12:00:00.000Z" } ], "total": [{ "total": 1 }]}| Query param | Type | Required | Description |
|---|---|---|---|
locationId |
string | Yes | Your <location_id>. |
limit |
number | No | Maximum number of products to return per page. |
offset |
number | No | Number of products to skip, for pagination. |
search |
string | No | Filter by product name. |
collectionIds |
string | No | Comma-separated collection IDs to filter by. |
collectionSlug |
string | No | Slug of a collection to filter by. |
productIds |
array of strings | No | Return only these products. |
availableInStore |
boolean | No | Filter by whether the product is available in your online store. |
storeId |
string | No | Return products for this online store. |
includedInStore |
boolean | No | Separate the products that are included in the store from those that aren’t. |
sortOrder |
string | No | asc or desc. Sorts by date. |
expand |
array of strings | No | Entities to return in full: tax, stripe, or paypal. Without tax, taxes holds IDs only. |
Product objects can also include variants, image, statementDescriptor, collectionIds,
isTaxesEnabled, taxes, automaticTaxCategoryId, label, and slug. These fields appear
when they’re set. See Product collections for collectionIds.
Retrieve a product
Section titled “Retrieve a product”productId accepts the product’s ID or its slug. locationId is required. Add
sendWishlistStatus=true to the query to include the product’s wishlist status.
curl "https://services.smbcrm.com/products/<product_id>?locationId=<location_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "_id": "<product_id>", "locationId": "<location_id>", "name": "1-Hour Consultation", "productType": "SERVICE", "description": "A single 60-minute strategy session.", "availableInStore": true, "createdAt": "2026-06-01T12:00:00.000Z", "updatedAt": "2026-06-01T12:00:00.000Z"}Create a product
Section titled “Create a product”locationId, name, and productType (DIGITAL, PHYSICAL, SERVICE, or
PHYSICAL/DIGITAL) are required.
curl -X POST https://services.smbcrm.com/products/ \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "locationId": "<location_id>", "name": "1-Hour Consultation", "productType": "SERVICE", "description": "A single 60-minute strategy session." }'{ "_id": "<product_id>", "locationId": "<location_id>", "name": "1-Hour Consultation", "productType": "SERVICE", "description": "A single 60-minute strategy session.", "availableInStore": false, "createdAt": "2026-07-08T15:04:00.000Z", "updatedAt": "2026-07-08T15:04:00.000Z"}Optional body fields:
| Field | Type | Description |
|---|---|---|
description |
string | A short description of the product. |
image |
string | URL of the product image. |
statementDescriptor |
string | The statement descriptor for the product. |
availableInStore |
boolean | Whether the product is available in your online store. |
medias |
array | Media for the product. Each item needs id, url, and type (image or video). title, isFeatured, and priceIds are optional. |
variants |
array | Product variants. Each item has an id, a name, and options, an array of { id, name } objects. |
collectionIds |
array of strings | IDs of the collections the product belongs to. |
slug |
string | The slug used to navigate to the product. |
seo |
object | SEO preview data: title and description. |
isTaxesEnabled |
boolean | Defaults to false. When true, taxes can’t be empty. |
taxes |
array of strings | IDs of the taxes attached to the product. If you send taxes, set isTaxesEnabled to true. |
taxInclusive |
boolean | Defaults to false. Whether taxes are included in the purchase price. |
automaticTaxCategoryId |
string | Tax category ID for automatic tax calculation. |
isLabelEnabled |
boolean | Defaults to false. When true, label can’t be empty. |
label |
object | A product label with title (required), startDate, and endDate. |
Update & delete a product
Section titled “Update & delete a product”PUT replaces the product, so name, locationId, and productType are required even if
you’re only changing one field. It accepts the same optional fields as
Create a product, plus prices (an array of strings). productId can be
the product’s ID or its slug.
curl -X PUT https://services.smbcrm.com/products/<product_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "name": "60-Minute Consultation", "locationId": "<location_id>", "productType": "SERVICE", "description": "Updated description." }'{ "_id": "<product_id>", "locationId": "<location_id>", "name": "60-Minute Consultation", "productType": "SERVICE", "description": "Updated description.", "availableInStore": false, "createdAt": "2026-07-08T15:04:00.000Z", "updatedAt": "2026-07-09T10:30:00.000Z"}productId can be the product’s ID or its slug. locationId is required.
curl -X DELETE "https://services.smbcrm.com/products/<product_id>?locationId=<location_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "status": true }Bulk update products
Section titled “Bulk update products”Send altId (your location ID), altType (location), a type, and the productIds to
change. The type decides what the request does and which other field it uses:
type |
What it does | Field to send |
|---|---|---|
bulk-update-price |
Updates the prices of the products. | price, and optionally compareAtPrice |
bulk-update-availability |
Updates whether the products are available. | availability (boolean) |
bulk-update-product-collection |
Updates the collections the products belong to. | collectionIds (array of strings) |
bulk-delete-products |
Deletes the products. | None |
bulk-update-currency |
Updates the currency of the products. | currency (for example, USD) |
price and compareAtPrice are objects with the same shape. type and value are
required; roundToWhole is an optional boolean that rounds the result to a whole number.
type is one of INCREASE_BY_AMOUNT, REDUCE_BY_AMOUNT, SET_NEW_PRICE,
INCREASE_BY_PERCENTAGE, or REDUCE_BY_PERCENTAGE, and value is the amount or the
percentage, depending on type. You can also send a filters object with collectionIds,
productType, availableInStore, and search.
curl -X POST https://services.smbcrm.com/products/bulk-update \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "type": "bulk-update-price", "productIds": ["<product_id>", "<product_id>"], "price": { "type": "INCREASE_BY_PERCENTAGE", "value": 10, "roundToWhole": true } }'{ "status": true }List prices
Section titled “List prices”locationId is required. Optional: limit and offset to page through results, and ids
(comma-separated price IDs) to return only specific prices.
curl "https://services.smbcrm.com/products/<product_id>/price?locationId=<location_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "prices": [ { "_id": "<price_id>", "product": "<product_id>", "name": "Standard rate", "type": "one_time", "amount": 149, "currency": "USD" } ], "total": 1}Retrieve a price
Section titled “Retrieve a price”curl "https://services.smbcrm.com/products/<product_id>/price/<price_id>?locationId=<location_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "_id": "<price_id>", "product": "<product_id>", "name": "Standard rate", "type": "one_time", "amount": 149, "currency": "USD"}Price responses can also include recurring, compareAtPrice, trackInventory,
availableQuantity, allowOutOfStockPurchases, membershipOffers, variantOptionIds,
userId, and updatedAt. These fields appear when they’re set.
Create a price
Section titled “Create a price”name, type (one_time or recurring), amount, currency, and locationId are
required. amount can’t be negative. For a recurring price, also include a recurring
object with interval (day, week, month, or year) and intervalCount.
curl -X POST https://services.smbcrm.com/products/<product_id>/price \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "name": "Standard rate", "type": "one_time", "amount": 149, "currency": "USD", "locationId": "<location_id>" }'{ "_id": "<price_id>", "product": "<product_id>", "locationId": "<location_id>", "name": "Standard rate", "type": "one_time", "amount": 149, "currency": "USD", "createdAt": "2026-07-08T15:04:00.000Z"}Optional body fields:
| Field | Type | Description |
|---|---|---|
description |
string | A short description of the price. |
trialPeriod |
number | Length of the trial period, in days. |
totalCycles |
number | Total number of billing cycles. Minimum 1. |
setupFee |
number | A one-time setup fee. |
compareAtPrice |
number | The original price to show next to the current one. |
trackInventory |
boolean | Track the stock quantity of this price. See Inventory. |
availableQuantity |
number | Stock quantity available. |
allowOutOfStockPurchases |
boolean | Keep selling when the quantity reaches zero. |
sku |
string | The SKU for the price. |
shippingOptions |
object | Shipping details: weight (value and unit: kg, lb, g, or oz) and dimensions (height, width, length, and unit: cm, in, or m). |
variantOptionIds |
array of strings | IDs of the variant options this price applies to. |
isDigitalProduct |
boolean | Whether the price is for a digital product. |
digitalDelivery |
array of strings | Digital delivery options. |
Update & delete a price
Section titled “Update & delete a price”PUT replaces the price, so name, type, currency, amount, and locationId are required
even if you’re only changing one field. It accepts the same optional fields as
Create a price.
curl -X PUT https://services.smbcrm.com/products/<product_id>/price/<price_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "name": "Promo rate", "type": "one_time", "amount": 99, "currency": "USD", "locationId": "<location_id>" }'{ "_id": "<price_id>", "product": "<product_id>", "locationId": "<location_id>", "name": "Promo rate", "type": "one_time", "amount": 99, "currency": "USD", "updatedAt": "2026-07-09T10:30:00.000Z"}locationId is required.
curl -X DELETE "https://services.smbcrm.com/products/<product_id>/price/<price_id>?locationId=<location_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "status": true }Inventory
Section titled “Inventory”Stock is tracked per price. Turn tracking on with trackInventory when you
create or update a price, then use these endpoints to read and change the
stock of many prices at once.
Each item in inventory is a price. Its _id is the price ID and product is the ID of the
product it belongs to. total is an object, { "total": n }.
curl "https://services.smbcrm.com/products/inventory?altId=<location_id>&altType=location&limit=20&offset=0" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "inventory": [ { "_id": "<price_id>", "name": "Medium", "availableQuantity": 50, "sku": "TSHIRT-MED-001", "allowOutOfStockPurchases": false, "product": "<product_id>", "productName": "T-shirt", "updatedAt": "2026-10-01T09:27:42.355Z" } ], "total": { "total": 1 }}| Query param | Type | Required | Description |
|---|---|---|---|
altId |
string | Yes | Your <location_id>. |
altType |
string | Yes | Always location. |
limit |
number | No | Maximum number of items to return per page. |
offset |
number | No | Number of items to skip, for pagination. |
search |
string | No | Search term for finding a variant. |
Send altId, altType, and an items array. Each item needs a priceId; add
availableQuantity and allowOutOfStockPurchases for the values you want to change.
curl -X POST https://services.smbcrm.com/products/inventory \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "items": [ { "priceId": "<price_id>", "availableQuantity": 25, "allowOutOfStockPurchases": false } ] }'{ "status": true }Product collections
Section titled “Product collections”Collections group products, for example a “Best Sellers” collection. Add a product to a
collection with collectionIds when you create or update it. These endpoints take altId
and altType instead of locationId.
The response has data, the array of collections, and total, the number of collections.
curl "https://services.smbcrm.com/products/collections?altId=<location_id>&altType=location&limit=10&offset=0" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "data": [ { "_id": "<collection_id>", "altId": "<location_id>", "name": "Best Sellers", "slug": "best-sellers", "image": "https://example.com/best-sellers.png", "createdAt": "2026-10-01T09:27:19.728Z" } ], "total": 1}| Query param | Type | Required | Description |
|---|---|---|---|
altId |
string | Yes | Your <location_id>. |
altType |
string | Yes | Always location. |
limit |
number | No | Maximum number of collections to return per page. Defaults to 10. |
offset |
number | No | Number of collections to skip, for pagination. Defaults to 0. |
collectionIds |
string | No | Comma-separated collection IDs to return. |
name |
string | No | Search collections by name. |
altId, altType, name, and slug are required. The slug must be unique and can’t
contain spaces or special characters. Optional fields are image (a thumbnail URL), seo
(an object with title and description), and collectionId.
curl -X POST https://services.smbcrm.com/products/collections \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "name": "Best Sellers", "slug": "best-sellers", "image": "https://example.com/best-sellers.png", "seo": { "title": "Best Sellers", "description": "Our most popular products." } }'{ "data": { "_id": "<collection_id>", "altId": "<location_id>", "name": "Best Sellers", "slug": "best-sellers", "image": "https://example.com/best-sellers.png", "seo": { "title": "Best Sellers", "description": "Our most popular products." }, "createdAt": "2026-10-08T15:04:00.000Z" }}altId is required. This request doesn’t take altType. The response has data, the
collection, and a status boolean.
curl "https://services.smbcrm.com/products/collections/<collection_id>?altId=<location_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"altId and altType are required. Send any of name, slug, image, and seo to change
them.
curl -X PUT https://services.smbcrm.com/products/collections/<collection_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "name": "Top Sellers" }'{ "status": true }altId and altType are required.
curl -X DELETE "https://services.smbcrm.com/products/collections/<collection_id>?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "status": true }Product reviews
Section titled “Product reviews”Read and moderate customer reviews of your products. These endpoints take altId and
altType instead of locationId.
The response has data, the array of reviews, and total.
curl "https://services.smbcrm.com/products/reviews?altId=<location_id>&altType=location&sortField=createdAt&sortOrder=desc&limit=20" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"| Query param | Type | Required | Description |
|---|---|---|---|
altId |
string | Yes | Your <location_id>. |
altType |
string | Yes | Always location. |
limit |
number | No | Maximum number of reviews to return per page. |
offset |
number | No | Number of reviews to skip, for pagination. |
sortField |
string | No | createdAt or rating. |
sortOrder |
string | No | asc or desc. |
rating |
number | No | Return reviews with this rating. |
startDate |
string | No | Return reviews from this date. |
endDate |
string | No | Return reviews up to this date. |
productId |
string | No | Comma-separated product IDs. |
storeId |
string | No | Comma-separated store IDs. |
altId and altType are required. The optional rating, startDate, endDate,
productId, and storeId filters work the same as on the review list. The response has a
data array of review counts by status.
curl "https://services.smbcrm.com/products/reviews/count?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"altId, altType, productId, and status are required in the body. status sets the
review’s status, for example approved. You can also send rating, headline, detail,
and reply. Each reply item needs a headline (up to 200 characters), a comment (up to
5,000 characters), and a user object with a name and email; phone and isCustomer
are optional.
curl -X PUT https://services.smbcrm.com/products/reviews/<review_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "productId": "<product_id>", "status": "approved", "reply": [ { "headline": "Thanks for your review", "comment": "We are glad it worked out for you.", "user": { "name": "Support Team", "email": "support@example.com", "isCustomer": false } } ] }'{ "status": true }altId, altType, and productId are required query parameters.
curl -X DELETE "https://services.smbcrm.com/products/reviews/<review_id>?altId=<location_id>&altType=location&productId=<product_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "status": true }altId, altType, reviews, and status are required. Each item in reviews needs a
reviewId, a productId, and a storeId.
curl -X POST https://services.smbcrm.com/products/reviews/bulk-update \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "reviews": [ { "reviewId": "<review_id>", "productId": "<product_id>", "storeId": "<store_id>" } ], "status": "approved" }'{ "status": true }Online store visibility
Section titled “Online store visibility”Choose which products appear in your online store. storeId is the ID of your online store.
These endpoints take altId and altType instead of locationId.
altId and altType are required. Add search to filter by product name and
collectionIds (comma-separated) to filter by collection.
curl "https://services.smbcrm.com/products/store/<store_id>/stats?altId=<location_id>&altType=location" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "totalProducts": 100, "includedInStore": 80, "excludedFromStore": 20}altId, altType, action (include or exclude), and productIds are all required.
curl -X POST https://services.smbcrm.com/products/store/<store_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "altId": "<location_id>", "altType": "location", "action": "include", "productIds": ["<product_id>"] }'{ "status": true }Related
Section titled “Related”- Payments: orders, transactions, subscriptions, and invoices built on top of your product catalog.
- Subscriptions: recurring billing tied to a price.
- Invoices & Estimates: add a price as a line item on an invoice or estimate.
- Scopes: request only the product/price scopes your integration needs.
