GlamBug Partner API — Connect Your Systems to Our Silver Jewellery Catalogue

Partner Management has been part of GlamBug for a while. It is how we work with resellers and online sellers who sell our jewellery under their own business. The GlamBug Partner API is the next step: it lets your own software read our 925 silver catalogue, place orders and follow them through to delivery, with no manual messages in between.
Updated October 2026 with incremental catalogue sync, wallet checks on every order and webhooks.
This guide explains how the API works, what you can build with it and how to stay well inside its limits. The full reference is public at apidocs.glambug.in, so you can read everything before you speak to us.
Who the API is for
The API suits partners whose orders should flow from their own systems:
- An online store that wants GlamBug products listed, with stock and prices kept current.
- A marketplace seller or reseller with their own order software.
- A developer building an integration for a business that dropships GlamBug jewellery.
If you simply want to browse and order, you do not need the API. The B2B app and WhatsApp ordering work for that. If you run a Shopify store, our Shopify app does the connecting for you. And if you are new to selling without stock, start with how dropshipping with GlamBug works.
How you get access
There is no self-service signup. You speak to your GlamBug contact, we set up your partner account and we issue your keys. You receive two kinds:
| Key | Starts with | What an order does |
|---|---|---|
| Live | gb_live_ |
Creates a real order that is reviewed and fulfilled. |
| Test | gb_test_ |
Creates an order flagged as a test. It never enters fulfilment. |
Both keys see the same live catalogue, so you can build and check your integration against real products. Switch to the live key only when you are ready to send real orders.
Every request is a POST to one GraphQL address, https://api.gemzy.in/graphql, with your key in an X-Api-Key header. There is no separate login or token step.
Two habits keep a key safe. Call the API from your own backend, never from browser code, because anyone can read what a browser sends. And remember that we show a key's full value only once, when it is created. If you lose it, or think it has been exposed, tell us and we revoke it and issue a new one.
Your first request
Ask for the categories:
curl https://api.gemzy.in/graphql \
-H "Content-Type: application/json" \
-H "X-Api-Key: gb_test_your_key_here" \
-d '{"query": "{ partnerCategories { id name catId children { id name catId } } }"}'
Our catalogue has two levels. A top-level category such as Rings contains subcategories such as CZ Solitaire Rings, and the subcategories are what actually hold products. Each subcategory has a catId, our own code for it.
GraphQL always answers with HTTP status 200, even when something is wrong. The problem appears in an errors list in the response body, so check errors[].extensions.code and not the HTTP status.
Reading the catalogue
partnerProducts returns the products of a subcategory, a page at a time. Each product includes:
sku, which is what you use when you order. Notid.name,description,images(ready-to-use image links) andweight.stock, a live count.pprice, your price for that product.available, true when the product can be ordered right now.updatedAt, the time the product last changed.
Pages hold 20 products by default and at most 500. Prices are specific to your account, which is why they are called pprice. Silver jewellery is priced by weight, and the API computes the price for you.
Keep your copy up to date without re-reading everything
Reading the whole catalogue every time wastes your request budget. Instead:
- First run: read everything once, with
includeUnavailable: trueso you also learn which products to hide. Page through withoffsetuntilhasMoreis false. Save the largestupdatedAtyou saw. That is your cursor. - Every later run: ask only for what changed, with
updatedSinceset to your cursor minus a minute or two. That margin covers a change that landed while you were reading. - Treat every item as an upsert keyed by
sku. A product can show up in two runs in a row, and that is expected.
Items with available: false cannot be ordered now, because they are inactive, archived or out of stock. Hide them in your store. They come back with available: true when they can be ordered again. updatedAt moves whenever a product's price, stock or content changes.
Placing an order
An order is a single partnerSubmitOrder request. You send the SKUs and quantities, your customer's delivery address and a partnerReference, which is your own id for the order. You never send a price: we calculate it on our side from the current rate and the weight.
A few rules make orders safe to automate:
- Prices and stock are checked by us. Each SKU must exist and be active, and the quantity cannot exceed current stock. A product can sell out between the moment you read it and the moment you order it, so handle that error.
- Retries cannot create duplicates. If a request times out and you are unsure it arrived, send it again with the same
partnerReference. You get the original order back, not a second one. - Your wallet funds the order. There is no separate checkout. The order is refused up front, and nothing is created, if your wallet balance does not cover the total. The check counts your other orders that are still waiting for review, so submitting several in a row cannot overdraw the wallet.
- The line total follows the weight.
priceAtOrderis a per-gram rate, not a price per piece. ThelineTotalis the quantity multiplied by the weight multiplied by that rate. The documentation's own example: 2 pieces of 3.2 g at a rate of 440 gives 2,816.
What happens after you submit
A new order arrives as PENDING, and our team reviews and accepts it before it moves into packing. We built it this way on purpose while integrations are still new. After that, an order moves through these statuses:
| Status | Meaning |
|---|---|
PENDING |
Submitted, waiting for our review. |
ACCEPTED |
Reviewed and accepted, moving into fulfilment. |
REJECTED |
Not accepted. Your contact can explain why. |
PAID |
Payment received. |
PROCESSED |
Ready to ship or in transit. |
DISPATCHED |
Shipped, waiting for delivery confirmation. |
COMPLETED |
Delivered. |
CANCELLED |
Cancelled. |
You can read your own orders, the amounts due and paid, each order's shipments with courier, tracking number and expected delivery date, and the GST invoice once one has been raised. You only ever see your own orders.
Whose name is on the parcel
The sender printed on the parcel and its label comes from your account, not from your request. If your account is set up as white label, parcels show your own business name and phone number. Otherwise they carry ours. A white-label account with no phone number on its profile cannot submit orders yet and gets the error PARTNER_PHONE_MISSING. Ask us to add the number and send the request again. If you want to know what white label involves, read about White Label and Private Branding.
Staying in sync: polling and webhooks
You have two ways to learn that something changed.
Polling always works. Read your latest orders every few minutes and compare them with what you stored. One request for the newest page usually covers every order that can still change. Only keep checking orders that are still open. Once an order is COMPLETED, CANCELLED or REJECTED, you can stop.
Webhooks push the change to you. We can send order.status_changed, shipment.updated and invoice.created to an https address you give us. Webhooks are off until you ask your contact. When we turn them on, we send you a signing secret and can send a test message to check your address.
Each message is a POST with a JSON body and a signature. To trust a message:
- Read the raw body before any JSON parsing.
- Reject it if its timestamp is more than 5 minutes old or in the future. That stops replays.
- Compute an HMAC-SHA256 of the timestamp, a dot and the raw body, using your secret, and compare it with the signature header using a constant-time comparison. The headers start with
X-Ornato-, because Ornato is the platform that runs GlamBug.
Your side has three jobs: answer with any 2xx status within 5 seconds, do the real work afterwards, and expect repeats. If an address fails, we retry after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 24 hours, which makes seven attempts in all. Delivery is at least once, so the same event can arrive twice, and events can arrive out of order, so use previousStatus and occurredAt or simply re-read the order. Keep the ids you have handled and ignore repeats.
Planning your request budget
The limit is 60 requests per minute per account, shared across your live and test keys. It is generous for a sensible integration. This is the schedule the documentation suggests:
| What | How often | Requests |
|---|---|---|
Catalogue changes with updatedSince |
Every 15 minutes | 4 an hour, plus extra pages when many products changed |
| Latest orders | Every 5 minutes | 12 an hour for one page of 50 |
| Tracking for open shipments | A few times a day | One per open order per check |
That is a few dozen requests an hour. If you go over the limit, you get RATE_LIMITED. Wait for the next minute and try again. If you truly need more, talk to your contact. Please do not work around the limit with several keys.
Errors you should handle
| Code | What it means |
|---|---|
UNAUTHENTICATED |
The key is missing or invalid. |
FORBIDDEN |
Your key is valid but not allowed to do this. |
BAD_USER_INPUT |
The request is wrong, for example an unknown SKU or too many pieces. The message says exactly what. |
INSUFFICIENT_BALANCE |
Your wallet, net of other pending orders, does not cover the order. Nothing was created. |
PARTNER_PHONE_MISSING |
A white-label account has no phone number yet. |
RATE_LIMITED |
Too many requests in a minute. |
A short checklist before you go live
- Build everything with the test key, and confirm orders are flagged as tests.
- Read the catalogue once in full, then switch to
updatedSince. - Use a unique
partnerReferencefor every order, such as your own order id. - Keep enough balance in your wallet for the orders you expect.
- Decide between polling and webhooks, and handle repeats and out-of-order events if you choose webhooks.
- Switch to the live key, and place one small real order first.
Frequently asked questions
Can I sign up for a key myself?
No. Keys are issued by your GlamBug contact once your partner account exists.
Do I need to be a developer?
Only if you want to use the API yourself. You can also order through the B2B app or WhatsApp, and a developer can connect your store later.
Do test orders ship?
No. A test key creates an order that is flagged and never enters fulfilment, but it sees the same live catalogue and prices.
Is there a limit on how many products I can read?
Pages hold up to 500 products. The request limit, 60 a minute, is what matters, which is why the updatedSince approach is worth using.
Where is the full reference?
At apidocs.glambug.in, with a changelog that lists every change.
Get started
To become a partner, message us on WhatsApp or write through the contact page. If you would rather start without code, the B2B Catalogue App lets you browse and order from your phone, and the dropshipping page explains how we pack and ship for you.
