Docs menu

Reference

REST API

Price changes

List price changes and preview one, including what a customer will pay before and after.

List prices never change silently in TradeCatalog. New list prices go into a price change: a draft that staff review, date and publish, optionally emailing every customer their own new prices.

How price changes are madeLink to this section#

  • From the API: PUT /products with a new listPrice for an existing product adds it to a draft and returns the draft’s priceChangeId.
  • From the app: spreadsheet imports, and bulk changes like “+4% on the Bolts category”.

Publishing, scheduling and cancelling happen in the app, under Price changes. There’s no API for them: a person always checks a price change before customers see it.

StatusesLink to this section#

StatusMeaning
draftNot published. No prices have changed.
scheduledPublished with a future date. Prices change on that date.
liveIn effect.
cancelledCancelled before it took effect.

The price change objectLink to this section#

json
{
  "id": "c4d5e6f7-1234-4abc-9def-0123456789ab",
  "source": "import",
  "title": "API import (Sage stock sync)",
  "supplierNote": null,
  "status": "draft",
  "effectiveAt": null,
  "notifyCustomers": true,
  "raiseFixedPrices": false,
  "createdBy": "Fq3L0cZ7tN1pW9aYx2Rk",
  "publishedAt": null,
  "cancelledAt": null,
  "createdAt": "2026-09-27T02:00:14.000Z",
  "items": 38
}
FieldTypeDescription
sourcestringimport (spreadsheet or API) or bulk (a percentage change made in the app).
titlestringShown to staff. API drafts are titled “API import (key name)”.
supplierNotestring or nullMessage to customers in the price-change email.
statusstringSee statuses.
effectiveAtstring or nullWhen the new prices apply.
notifyCustomersbooleanWhether customers are emailed their new prices.
raiseFixedPricesbooleanWhether agreed prices rise by the same percentage.
createdBystring or nullId of the person who made it. For API drafts, the owner who made the key.
itemsintegerHow many products it changes. Only in the list.

List price changesLink to this section#

GET/api/v1/price-changes

Newest first. Covers the 100 most recent price changes.

NameTypeRequiredDescription
limitintegerno1 to 100. Default 100.
offsetintegernoRows to skip. Default 0.
bash
curl https://tradecatalog.app/api/v1/price-changes \
  -H "Authorization: Bearer $TRADECATALOG_API_KEY"
js
const res = await fetch('https://tradecatalog.app/api/v1/price-changes', {
  headers: { Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}` },
})
const { data: changes } = await res.json()
const drafts = changes.filter((change) => change.status === 'draft')

Preview a price changeLink to this section#

GET/api/v1/price-changes/{id}

Everything staff see before publishing: how many prices go up and down, the biggest moves, warnings, and how many agreed prices it touches. Pass customer to see that customer’s own prices before and after.

NameInTypeRequiredDescription
idpathstringyesPrice change id.
customerquerystringnoCustomer id or account code.
bash
curl "https://tradecatalog.app/api/v1/price-changes/c4d5e6f7-1234-4abc-9def-0123456789ab?customer=OAK01" \
  -H "Authorization: Bearer $TRADECATALOG_API_KEY"
js
const res = await fetch(
  `https://tradecatalog.app/api/v1/price-changes/${priceChangeId}?customer=OAK01`,
  { headers: { Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}` } },
)
const { data: preview } = await res.json()
if (preview.warnings.length)
  console.warn('Check these before publishing', preview.warnings)
json
{
  "data": {
    "change": {
      "id": "c4d5e6f7-1234-4abc-9def-0123456789ab",
      "source": "import",
      "title": "API import (Sage stock sync)",
      "supplierNote": null,
      "status": "draft",
      "effectiveAt": null,
      "notifyCustomers": true,
      "raiseFixedPrices": false,
      "createdBy": "Fq3L0cZ7tN1pW9aYx2Rk",
      "publishedAt": null,
      "cancelledAt": null,
      "createdAt": "2026-09-27T02:00:14.000Z"
    },
    "counts": { "total": 38, "up": 36, "down": 2 },
    "biggest": [
      {
        "productId": "3f8a2c1e-9b4d-4e6f-a7c8-1d2e3f4a5b6c",
        "oldPrice": 1850,
        "newPrice": 1950,
        "sku": "HX-8510",
        "name": "Hex bolt M10 x 50 zinc",
        "changeBp": 541
      }
    ],
    "warnings": [],
    "fixedAffected": 3,
    "customer": {
      "name": "Oakfield Joinery",
      "rows": [
        {
          "sku": "HX-8510",
          "name": "Hex bolt M10 x 50 zinc",
          "before": 1573,
          "after": 1658,
          "label": "Brand discount −15%"
        }
      ]
    }
  },
  "currency": "GBP"
}
FieldDescription
countsProducts in the change, and how many go up and down.
biggestUp to 20 items with the largest percentage move. changeBp is the change in basis points (541 = +5.41%).
warningsItems that move by more than 30% either way, or go to zero. Usually typos.
fixedAffectedAgreed prices on these products that are valid now. They only change if the change raises agreed prices.
customerWith customer: that customer’s unit prices before and after, for up to the first 50 items. null without it.

404 not_found if there’s no such price change in this workspace.