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
# 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
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",
};
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. |
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.
// 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.
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.