production writes → app.brandsgateway.com Examples on this page target the live marketplace.
BG Vendor Integration
Menu
Start here

Authentication

One credential, one host. Everything you need runs through this portal — you never address the marketplace directly, and you never need to know how it is put together.

What you need

  • BG_VENDOR_ID — your vendor number, e.g. 71940. It scopes everything you can see or change.
  • BG_USER — your vendor account username.
  • BG_APP_PASSWORD — an application password, generated in your BrandsGateway profile. Not your login password.

The same three values sign you in at the portal if you would rather work in the browser. There is no separate account to create.

The scheme

an authenticated request
# HTTP Basic over TLS, plus your vendor ID.
# The password is an application password — a long generated string,
# not your login password.

curl -s -X PUT https://vendors.brandsgateway.com/api/v1/products/SKU12345 \
  -u "$BG_USER:$BG_APP_PASSWORD" \
  -H "X-Vendor-Id: $BG_VENDOR_ID" \
  -H 'Content-Type: application/json' \
  -d @product.json
building the headers
const auth =
  "Basic " +
  Buffer.from(
    `${process.env.BG_USER}:${process.env.BG_APP_PASSWORD}`
  ).toString("base64");

const headers = {
  Authorization: auth,
  "X-Vendor-Id": process.env.BG_VENDOR_ID,
  "Content-Type": "application/json",
};
Never ship the credential to a browser
The application password is a server-side secret. Any integration that puts it in front-end code, a mobile app, or a public repository must be rotated — tell us and we will revoke it.

Everything you can call

Two endpoints do the work. Every path is relative to https://vendors.brandsgateway.com, and every one is scoped to the vendor in your X-Vendor-Id header.

Method Path What it does
PUT /api/v1/products/{yourProductId} Add or update a product. Send your own words for brand, colour and the rest — we map them. Checked before anything is forwarded, so an invalid product never reaches the shop.
POST /api/v1/validate Check a payload without sending it. No credential needed, so it is safe to run in CI on every build.
That is the integration
One host, one credential, two calls — and only one of them needs the credential. There is no third, more powerful API to discover, and nothing you have to build a mapping layer for.

Coming later

Not available yet. Everything below is on the roadmap, and none of it is needed for a complete, correct integration today — sending your products and reading your dashboard is the whole of it. This page lists only calls that work; when one of these ships it is documented here and in the API reference.

Path What it will do
/api/v1/sync Reconcile a whole catalog in one call: every product ID you still sell, with anything missing zeroed — and a guard that refuses a run which would zero more than half of it. Until then, zero a product by re-sending it with stock_quantity: 0.
/api/v1/products Read back what BrandsGateway holds for you, with stock levels. Your dashboard already shows this per product.
/api/v1/resolve Map a batch of your values in one pass, before sending anything. Today the same mapping runs inside /api/v1/validate, which reports every value it could not map.

Rate limits

Product writes are limited to roughly two per second. This is not arbitrary: each write touches images, terms and variations, and a burst from one vendor degrades the shop for everyone.

pacing your submissions
// Two products per second. A token bucket beats a naive sleep,
// because it absorbs the variance in response time.

async function* paced(items, perSecond = 2) {
  const gap = 1000 / perSecond;
  let next = Date.now();
  for (const item of items) {
    const wait = next - Date.now();
    if (wait > 0) await new Promise((r) => setTimeout(r, wait));
    next = Math.max(next + gap, Date.now());
    yield item;
  }
}

POST /api/v1/validate needs no credential, so it is limited by where the call comes from rather than by who you are — generously enough for a payload editor that re-checks as you type, and for CI on every build. A batch of up to 500 products in one call is limited more tightly than a single payload, because it is 500 checks.

Both limits are per vendor and shared across every server, so they do not loosen under load. PUT /products/{externalId} and POST /submit draw on one bucket — alternating between them does not buy you extra throughput. A refusal is a 429 carrying Retry-After in seconds; honour it rather than retrying immediately.

Full-catalog syncs are long by design
Five thousand products at two per second is around forty minutes, and that is expected. Most of it is avoidable: send only what changed. See change detection.

Rotation and revocation

  • Application passwords do not expire on a schedule. Rotate yours when staff with access change, or immediately on suspected exposure.
  • Revoking one takes effect instantly; in-flight requests fail with 401.
  • Keep two active during a rotation so a running sync is not interrupted, then revoke the old one.