Skip to main content
Use these endpoints when your ERP is the master for products, prices and customers. They all work the same way, so you learn the pattern once.
New to the API? Read Sync an ERP first for the order loop. This page is about sending data to BrandGate.

How it works

  • You choose the id. Every object carries your own external_id (the id in your ERP). BrandGate remembers it per object type, so sending the same external_id again updates the same record. Two integrations on one workspace never collide: ids are kept per API key label (integration).
  • Send state, not events. Repeating a request changes nothing ("result": "unchanged"). You can resend a whole batch after a crash.
  • Fields you leave out are not touched. Send null to clear a field that can be cleared.
  • Each item stands alone. A batch returns one result per item (created, updated, unchanged or error). A bad item never blocks the others, and business errors come back with HTTP 200 and an error.code on the item.
  • Money is a decimal string, excl. VAT, at most two decimals, never negative ("129.50").
  • Optional source_updated_at (ISO time of the change in your ERP): BrandGate refuses an older change with stale_write, so late retries cannot overwrite newer data.
You need the scopes products:write, pricing:write, customers:write and orders:write. A key created from your ERP’s tile under Settings → Integrations has them (plus inventory, invoices:read and webhook scopes).

Who owns what

Do not send fields a person edits in BrandGate; it is last write wins per field.

Products

Up to 200 products per request. The first time an external_id is seen, an existing product with the same sku is adopted; otherwise a product is created (name and unit_price are required then). Changing sku or name later updates the same product (sku_conflict if another product has that sku). Stock is set with the inventory endpoint.

Price lists and customer prices

A price list is a named set of prices that you assign to customers. For a per-customer price, create one list for that customer.
  • One list per request, up to 1000 prices. Name each product by product_external_id or sku.
  • By default listed products are added or updated. With "replace": true products you do not list are removed from the list (the response reports removed).
  • Products that cannot be found come back in unmatched_products; the rest is saved.
  • A customer pays the list price for a product when their list has it, otherwise the product’s base price. Volume prices still apply when lower. BrandGate never recalculates old orders.
  • status: "inactive" retires a list. Renaming a list keeps every customer assigned to it.

Customers

Up to 100 customers per request. price_list is the external_id of a price list you sent (send null to return to standard prices). A new customer is created as pending: they log in through BrandGate’s invitation, and you never handle passwords. A customer is never merged by email. If the email or customer_number already belongs to a BrandGate customer, that item answers customer_exists with existing_id. To link it, repeat the item with "id": "<existing_id>" once.

Resellers that already exist

Most brands already have resellers in BrandGate before an ERP is connected, so the first customer sync will mostly answer customer_exists. That is expected, not a failure. For each one, check that it is the same company, then send the item again with "id": "<existing_id>" once. From then on external_id finds it. Run this first sync with a small batch and review the answers before sending everything.

Resellers created in BrandGate

A reseller who registers in BrandGate has no ERP customer number yet. Their orders show customer.id and customer.name only; read GET /v1/customers/{id} for the contact and address details. Create the customer in your ERP, then link it back by sending {"external_id": "<your id>", "id": "<customer.id>", "customer_number": "<your number>"} to POST /v1/customers. Do this before you acknowledge the order, so later orders find the customer by number.

Delivery status

Orders move forward one step: processing → shipped → delivered. Repeating the same status is safe and may add tracking. Only shipped and delivered are accepted values (anything else is 400 invalid_request). Cancelled orders, going back or skipping a step answer 409 status_not_allowed. The whole order moves at once: partial shipments are not supported yet, so send shipped when the last line leaves. The customer is notified exactly as when the seller marks the order shipped in BrandGate.

Try it without touching real data

Ask the seller to create a test workspace in BrandGate and generate a key there, the same way as for production. Everything on this page works the same.

Checklist

  • Send a stable external_id per object and never reuse one.
  • Send changes often and the full set once a night (it is safe).
  • Use Idempotency-Key on writes you may retry (Idempotency).
  • Expect plan_limit_reached when the company’s BrandGate plan caps products or customers: the seller must upgrade (or remove records) before the rest of a large first sync goes through.
  • Read the results of every batch and log the items with error.