Skip to content

Get a product

GET
/products/{id}
curl --request GET \
--url https://example.com/products/019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f \
--cookie __Host-bottle.session_token=<__Host-bottle.session_token>
id
required

UUID v7

string format: uuid

Example

019205d1-6e7a-7c3b-9f6e-3a2b1c0d9e8f

UUID v7

Product

Media typeapplication/json
object
id
required

UUID v7

string format: uuid
name
required
string
shortCode
required
string | null
sku
required
string | null
unitPrice
required

Pence, exactly as entered. Whether VAT is in this figure is what priceIncludesVat says; the other reading is given beside it for display.

integer
<= 100000000
priceIncludesVat
required

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.

boolean
unitPriceExVat
required

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.

integer
unitPriceIncVat
required

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.

integer
vatRate
required

VAT in basis points: 2000 is 20%, 500 is 5%, 0 is zero rated.

integer
<= 10000
charge
required
string | null
Allowed values: deposit hire
chargePeriod
required
string | null
Allowed values: once daily weekly monthly
chargeForProductId
required

UUID v7

string | null format: uuid
chargeForProductIds
required
Array<string>
chargeAudience
required

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.

string
Allowed values: both consumer trade
gasTypeId
required

UUID v7

string | null format: uuid
dangerousGoods
required

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
unNumber
required

The UN number, four digits without “UN”.

string
/^\d{4}$/
shippingName
required

The proper shipping name from the ADR list, as on the cylinder label.

string
>= 1 characters <= 200 characters
hazardClass
required

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.

string
Allowed values: 2.1 2.2 2.2 (5.1) 2.3
weightKg
required
number | null
volumeLitres
required
integer | null
notes
required
string | null
kind
required

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.

string
Allowed values: cylinder deposit hire accessory appliance fuel consumable delivery other
kindSet
required

Whether kind was set rather than read from the product.

boolean
brand
required
string | null
description
required

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.

string | null
descriptionHtml
required

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.

string | null
relatedProductIds
required

Products picked to show under this one on the shop, in order, up to 8. Empty: the shop shows others from the same category.

Array<string>
published
required

On the business’s own shop. Shown there only once the shop is switched on. Never true on an archived product.

boolean
shopAudience
required

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.

string
Allowed values: both consumer trade
refundRule
required

On a deposit: what comes back when a cylinder is returned. Null follows the business’s own setting (invoice settings).

string | null
Allowed values: full percent scale none
refundPercent
required
integer | null
<= 100
refundDeductionPence
required
integer | null
refundScale
required
Array<object> | null
>= 1 items <= 10 items
object
upToMonths
required
integer | null
>= 1 <= 1200
percent
integer
<= 100
fixedPence
integer
<= 10000000
refundCountsFrom
required

Which hire a returned cylinder is measured from. Null is latest.

string | null
Allowed values: latest first
tradeUnitPrice
required

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.

integer | null
<= 100000000
tradePriceIncludesVat
required
boolean
tradePriceExVat
required
integer | null
tradePriceIncVat
required
integer | null
costPrice
required

What one costs the business, pence without VAT. Optional; read by cost-plus price rules. Never shown to customers.

integer | null
<= 100000000
stockOnHand
required

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.

integer | null
stockLowAt
required

At or under this count the office is told, and the shop may say low stock. Null is never.

integer | null
stockCounted
required

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.

boolean
tracking
required

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.

string
Allowed values: quantity individual
shelfLifeMonths
required

How many months a fill lasts, for a tracked cylinder. Used to suggest the expiry date when stock comes in. Null: no suggestion.

integer | null
homeLocationId
required

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.

string | null format: uuid
whenOut
required

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.

string | null
Allowed values: stop continue
images
required
Array<object>
object
id
required

UUID v7

string format: uuid
alt
required

What the picture shows, for screen readers and search.

string | null
sortOrder
required
integer
width
required

Of the original, in pixels.

integer
height
required
integer
thumb
required

Fits inside 200 pixels. WebP.

string
card
required

Fits inside 600 pixels. WebP.

string
large
required

Fits inside 1600 pixels. WebP.

string
categoryIds
required
Array<string>
links
required
Array<object>
object
source
required
string
Allowed values: woocommerce shopify
externalId
required
string
externalVariantId
required
string | null
externalSku
required
string | null
lastSyncedAt
required
string | null format: date-time
details
required

The product details it has, in the order the details are listed (GET /product-details). Archived details are left out; their values are kept.

Array<object>
object
detailId
required

UUID v7

string format: uuid
value
required
Any of:
Array<string>
<= 100 items
archivedAt
required
string | null format: date-time
createdAt
required
string format: date-time
updatedAt
required
string format: date-time

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"
]
}
]
}

Not signed in

Media typeapplication/json
object
error
required
string
message
required
string

Example

{
"error": "not_found",
"message": "Customer not found"
}

Not a member, or without the permission this needs

Media typeapplication/json
object
error
required
string
message
required
string

Example

{
"error": "not_found",
"message": "Customer not found"
}

Not found

Media typeapplication/json
object
error
required
string
message
required
string

Example

{
"error": "not_found",
"message": "Customer not found"
}

Validation failed

Media typeapplication/json
object
error
required
string
Allowed values: validation
message
required
string
issues
required
Array<object>
object
path
required
string
message
required
string

Example

{
"error": "validation",
"issues": [
{
"path": "email",
"message": "Invalid email"
}
]
}