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

Testing safely

Products you create while still learning the contract are real products, visible to real customers. Get the loop working on one test product before you point a whole catalog at it.

A half-finished mapping is worse than no integration
A wrong brand or a wrong price is live the moment it is accepted, and some of it is sellable. One product, checked by eye, before anything else.

One host, one credential

Everything runs through the portal. You never address the marketplace directly, so there is only one URL to point at and one credential to keep safe.

.env
# .env in your integration — one host, one credential
BG_PORTAL_URL=https://vendors.brandsgateway.com
BG_VENDOR_ID=71940
BG_USER=your-vendor-user
BG_APP_PASSWORD=xxxx xxxx xxxx xxxx xxxx xxxx

Ask us for a staging BG_PORTAL_URL if you want a sandbox that cannot touch the live catalog. The API is identical; only the host differs.

You are currently reading docs served by Which means
vendors.brandsgateway.com Every example on every page is already pointed at this environment. Copying one cannot send you somewhere unexpected.

Prove the connection before writing code

smoke test
# 1. Are you reaching the portal at all? No credential needed.
curl -s -o /dev/null -w '%{http_code}\n' -X POST \
  $BG_PORTAL_URL/api/v1/validate \
  -H 'Content-Type: application/json' -d '{"type":"simple"}'

#  200  the portal is up and the validator answered
#  429  you are checking faster than the limit; retry after Retry-After

# 2. Do your credentials work? Sign in once, in a browser:
#      $BG_PORTAL_URL/login
#    The portal verifies them upstream and keeps no account of its own,
#    so a successful sign-in is proof they work for the API too.

# 3. Does a value from your feed map? Send it and read `unresolved`.
curl -s -X POST $BG_PORTAL_URL/api/v1/validate \
  -H 'Content-Type: application/json' \
  -d '{"values":{"brand":"Gucci"},"product":{"type":"simple"}}' | jq '.unresolved'

# An empty array means it mapped. An entry means it did not — with the
# closest accepted values, and how many that field has.

Check a product without sending it

The validator runs the exact schema and business rules BrandsGateway enforces, and contacts nothing. It is the cheapest possible feedback loop, and it belongs in your pipeline rather than your browser.

validate
# Check without sending. No credential needed, no side effects,
# no rate limit — put this in CI.

curl -s -X POST $BG_PORTAL_URL/api/v1/validate \
  -H 'Content-Type: application/json' --data @product.json | jq

There is an interactive version too, for working through a payload by hand.

Your first real write

send it twice
curl -i -X PUT \
  $BG_PORTAL_URL/api/v1/products/TEST0001 \
  -u "$BG_USER:$BG_APP_PASSWORD" \
  -H "X-Vendor-Id: $BG_VENDOR_ID" \
  -H 'Content-Type: application/json' \
  --data @product.json

# Run it twice.
#   First call  -> 201 Created
#   Second call -> 200 OK
#
# If the second also returns 201, your external ID is not persisting and
# every sync you ever run will duplicate your catalog.

Sending twice and checking for 201 then 200 is the single most valuable test in this integration: it proves your external ID round-trips, which is what stops your catalog duplicating itself on every run.

Taxonomy IDs are per environment
The IDs a staging portal returns are not the IDs production returns. Never hardcode the integers you saw while testing: send your own words in a values block and let the portal resolve them against whichever environment it is pointed at.

Going live

  1. Confirm on staging: a create, an update, a rejection you recognise, and a reset that zeroes a departed product.
  2. Point BG_PORTAL_URL at production and re-resolve every taxonomy value. Nothing carries over.
  3. Send one product. Look at it in the shop.
  4. Send a slice — fifty products, one brand — and read your monitoring.
  5. Only then, the full catalog.