Create a product
const url = 'https://example.com/products';const options = { method: 'POST', headers: { cookie: '__Host-bottle.session_token=<__Host-bottle.session_token>', 'Content-Type': 'application/json' }, body: '{"name":"example","shortCode":"example","sku":"example","unitPrice":1,"priceIncludesVat":true,"vatRate":1,"charge":"deposit","chargePeriod":"once","chargeForProductId":"019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f","chargeForProductIds":["019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f"],"chargeAudience":"both","gasTypeId":"019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f","dangerousGoods":{"unNumber":"1978","shippingName":"PROPANE","hazardClass":"2.1"},"weightKg":1,"volumeLitres":1,"notes":"example","kind":"cylinder","brand":"example","description":"example","descriptionHtml":"example","relatedProductIds":["019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f"],"published":true,"shopAudience":"both","categoryIds":["019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f"],"refundRule":"full","refundPercent":1,"refundDeductionPence":1,"refundScale":[{"upToMonths":1,"percent":1,"fixedPence":1}],"refundCountsFrom":"latest","tradeUnitPrice":1,"tradePriceIncludesVat":true,"costPrice":1,"stockLowAt":1,"stockCounted":true,"tracking":"quantity","shelfLifeMonths":1,"homeLocationId":"019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f","whenOut":"stop","details":[{"detailId":"019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f","value":["019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f"]}]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/products \ --header 'Content-Type: application/json' \ --cookie __Host-bottle.session_token=<__Host-bottle.session_token> \ --data '{ "name": "example", "shortCode": "example", "sku": "example", "unitPrice": 1, "priceIncludesVat": true, "vatRate": 1, "charge": "deposit", "chargePeriod": "once", "chargeForProductId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "chargeForProductIds": [ "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" ], "chargeAudience": "both", "gasTypeId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "dangerousGoods": { "unNumber": "1978", "shippingName": "PROPANE", "hazardClass": "2.1" }, "weightKg": 1, "volumeLitres": 1, "notes": "example", "kind": "cylinder", "brand": "example", "description": "example", "descriptionHtml": "example", "relatedProductIds": [ "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" ], "published": true, "shopAudience": "both", "categoryIds": [ "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" ], "refundRule": "full", "refundPercent": 1, "refundDeductionPence": 1, "refundScale": [ { "upToMonths": 1, "percent": 1, "fixedPence": 1 } ], "refundCountsFrom": "latest", "tradeUnitPrice": 1, "tradePriceIncludesVat": true, "costPrice": 1, "stockLowAt": 1, "stockCounted": true, "tracking": "quantity", "shelfLifeMonths": 1, "homeLocationId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "whenOut": "stop", "details": [ { "detailId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "value": [ "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" ] } ] }'Not on the business’s own shop unless published is true. kind is read from the charge and gas type unless set.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”object
Pence, as typed. Say whether VAT is in it with priceIncludesVat.
Whether unitPrice includes VAT. Left out, the business’s own setting (pricesIncludeVat on /tax) applies.
VAT in basis points. Defaults to 2000, the standard 20%.
UUID v7
Example
019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8fExact cylinder products this charge applies to, replacing the previous selection. May span gas types. Empty uses gasTypeId instead.
Who pays a deposit or rent where no price list or agreed amount says otherwise. both: Consumer and Trade customers (the default). consumer: everybody who is not a trade customer, signed in or not. trade: trade customers only. Meaningless on anything that is not a charge.
UUID v7
Example
019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8fOverride the gas type’s UN number, proper shipping name and hazard class for this product. Null follows the gas type.
object
The UN number, four digits without “UN”.
Example
1978The proper shipping name from the ADR list, as on the cylinder label.
Example
PROPANEThe ADR hazard class: 2.1 flammable gas, 2.2 non-flammable non-toxic gas, 2.2 (5.1) non-flammable gas that is also oxidising, 2.3 toxic gas.
Example
2.1What the product is. Null or left out: read from its charge and gas type.
Plain text, line breaks kept: a blank line starts a paragraph. Ignored when descriptionHtml is given.
The description with formatting, as HTML, up to 50,000 characters as sent and 20,000 once sanitised (over either is refused with 400, description_too_long). Sanitised on the server: anything outside p, h2, h3, strong, em, ul, ol, li, br and a (http, https or mailto) is removed, keeping its words; scripts, styles, frames, forms, pictures, svg and math go with their contents; every attribute but a link address goes. Wins over description. Null clears it.
Products to show under this one on the shop, in order, replacing any picked before. Up to 8. An empty list goes back to others from the same category.
Put it on the business’s own shop. Off unless asked for. Ignored on an archived product.
Who may buy it on the shop once published. both: everybody (the default). consumer: anybody not signed in for a trade account, so trade customers do not see it. trade: signed-in trade customers only.
The shop categories it sits in, replacing any it was in.
On a deposit only. full, percent (refundPercent less refundDeductionPence), scale (refundScale), none. Null follows the business’s setting.
object
Which hire a returned cylinder is measured from when a customer holds several: latest (the most recent, kinder to the customer) or first (the oldest).
The trade price, pence as typed. Null for none (trade pays the list price).
Whether tradeUnitPrice includes VAT. Left out, the business’s own setting.
What one costs the business, pence without VAT. Null for not known.
Tell the office at or under this count. Null for never. The count itself is set with POST /products/{id}/stock.
Whether to keep a yard stock figure for this cylinder. Left out, true. False marks it as not counted on the stock list, plans rounds as though there are always enough, and turns off its low-stock and no-figure warnings.
Quantity or individual. Left out, quantity. individual is refused unless Assets is open and switched on for the business, and only a cylinder can be tracked.
How many months a fill lasts, 1 to 600, for suggesting the expiry date when stock comes in. Null for no suggestion.
The yard this cylinder is kept at, when it is not wherever a round loads. Left out or null, every yard keeps it and it goes on with the morning load. Must be one of your yards.
Example
019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8fWhen none are left: stop or continue. Null follows the shop’s own rule.
Product details to set, by detail id. Only the details sent change; null clears one. A detail has to be one of the business’s own, not archived, and apply to the kind of product (error: detail_not_for_kind).
object
UUID v7
Example
019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8fResponses
Section titled “Responses”Created
object
UUID v7
Pence, exactly as entered. Whether VAT is in this figure is what priceIncludesVat says; the other reading is given beside it for display.
Whether unitPrice includes VAT. False: VAT goes on top when the product is sold. True: unitPrice is the shelf price, and the VAT is worked back out of it on each line.
UnitPrice without VAT, in pence, for display. The same as unitPrice when it excludes VAT or the business is not registered; otherwise derived and rounded. Do not multiply it: amounts are worked out from unitPrice.
UnitPrice with VAT, in pence, for display. The same as unitPrice when it includes VAT or the business is not registered; otherwise derived and rounded.
VAT in basis points: 2000 is 20%, 500 is 5%, 0 is zero rated.
UUID v7
Who pays a deposit or rent where no price list or agreed amount says otherwise. both: Consumer and Trade customers (the default). consumer: everybody who is not a trade customer, signed in or not. trade: trade customers only. Meaningless on anything that is not a charge.
UUID v7
This product’s own UN number, proper shipping name and hazard class, where they differ from its gas type’s. Null follows the gas type.
object
The UN number, four digits without “UN”.
The proper shipping name from the ADR list, as on the cylinder label.
The ADR hazard class: 2.1 flammable gas, 2.2 non-flammable non-toxic gas, 2.2 (5.1) non-flammable gas that is also oxidising, 2.3 toxic gas.
What the product is. The one set on it, or when none has been, read from it: a charge makes it a deposit or hire, a gas type a cylinder, anything else other.
Whether kind was set rather than read from the product.
The description as plain text, with a blank line between paragraphs and a line per list item. Made from descriptionHtml, for search, previews and anywhere HTML cannot go.
The description with its formatting, as sanitised HTML: only p, h2, h3, strong, em, ul, ol, li, br and a. A link has only an http, https or mailto href, rel=“noopener noreferrer nofollow”, and target=“_blank” for a web address. Sanitised again on every read; still treat it as HTML from a third party.
Products picked to show under this one on the shop, in order, up to 8. Empty: the shop shows others from the same category.
On the business’s own shop. Shown there only once the shop is switched on. Never true on an archived product.
Who may buy it on the shop once published. both: everybody (the default). consumer: anybody not signed in for a trade account, so trade customers do not see it. trade: signed-in trade customers only.
On a deposit: what comes back when a cylinder is returned. Null follows the business’s own setting (invoice settings).
object
Which hire a returned cylinder is measured from. Null is latest.
What a trade customer pays, on the shop and on office orders, when no rate has been agreed with them, pence as typed. Null: the list price. A customer’s agreed rate still comes first, and price rules for trade work off this.
What one costs the business, pence without VAT. Optional; read by cost-plus price rules. Never shown to customers.
How many are on the shelf, for things sold on the shop that are not cylinders. Null is not counted: always available. Set and moved with POST /products/{id}/stock, never here. May be below nought when the product keeps selling once none are left.
At or under this count the office is told, and the shop may say low stock. Null is never.
Whether the yard’s cylinder stock keeps a figure for this product. False: the stock list marks it as not counted, rounds plan as though there are always enough, and nothing warns that it is low or has no figure. Only read on a cylinder.
How this product’s stock is recorded. quantity: as a count. individual: each cylinder by its own serial number, once Assets is open and switched on for the business. Only read on a cylinder.
How many months a fill lasts, for a tracked cylinder. Used to suggest the expiry date when stock comes in. Null: no suggestion.
The yard this cylinder is kept at, when it is not wherever a round loads. A round loading at another yard gets a stop at this one to collect what its orders need, before the doors that need it. Null for a cylinder every yard keeps. Only read on a cylinder.
What the shop does when none are left, for this product. Null follows the shop’s own rule (Settings, Shop). stop: off sale. continue: keeps selling, shown as ships when back in stock.
object
UUID v7
What the picture shows, for screen readers and search.
Of the original, in pixels.
Fits inside 200 pixels. WebP.
Fits inside 600 pixels. WebP.
Fits inside 1600 pixels. WebP.
object
The product details it has, in the order the details are listed (GET /product-details). Archived details are left out; their values are kept.
object
UUID v7
Example
{ "id": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "name": "19kg propane", "shortCode": "19", "sku": "PROP-19", "unitPrice": 5400, "unitPriceExVat": 5400, "unitPriceIncVat": 6480, "vatRate": 2000, "charge": "deposit", "chargePeriod": "once", "chargeForProductId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "chargeForProductIds": [ "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" ], "chargeAudience": "both", "gasTypeId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "dangerousGoods": { "unNumber": "1978", "shippingName": "PROPANE", "hazardClass": "2.1" }, "weightKg": 38.5, "volumeLitres": 60, "kind": "cylinder", "brand": "Flogas", "descriptionHtml": "<p>A <strong>13kg</strong> propane refill.</p><ul><li>Same day delivery</li></ul>", "relatedProductIds": [ "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" ], "shopAudience": "both", "refundRule": "full", "refundCountsFrom": "latest", "stockOnHand": 12, "stockLowAt": 3, "tracking": "quantity", "homeLocationId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "whenOut": "stop", "images": [ { "id": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" } ], "categoryIds": [ "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" ], "links": [ { "source": "woocommerce", "externalId": "1043" } ], "details": [ { "detailId": "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f", "value": [ "019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f" ] } ]}The description is over 50,000 characters as sent or 20,000 once sanitised (error: description_too_long). Nothing was changed.
object
Example
{ "error": "not_found", "message": "Customer not found"}Not signed in
object
Example
{ "error": "not_found", "message": "Customer not found"}Not a member, or without the permission this needs
object
Example
{ "error": "not_found", "message": "Customer not found"}Validation failed
object
object
Example
{ "error": "validation", "issues": [ { "path": "email", "message": "Invalid email" } ]}