API docs

Guide: inventory sync for a channel manager

This guide is for systems like Flxpoint that publish stock to sales channels and route orders. It shows how to keep an accurate picture of a shop's on-hand inventory, with Iron Register as the source of truth for what's on the shelf.

Permissions to ask the owner for:

  • products: read
  • inventory: read
  • locations: read
  • inventory: write, only if you'll push adjustments back
  • orders: write, if you'll create orders (see Marketplace orders)

Ask for a webhook endpoint subscribed to inventory.changed, product.created, product.updated and product.deleted.

1. Map the locations

curl https://app.ironregister.com/api/v1/locations -H "Authorization: Bearer $KEY"

Each location is one warehouse or source on your side. bigcommerce_location_id tells you which BigCommerce inventory location it feeds, if any.

2. Initial load

Page through products with their inventory, 200 at a time:

curl "https://app.ironregister.com/api/v1/products?limit=200&include=inventory" -H "Authorization: Bearer $KEY"
# then repeat with &cursor=<meta.next_cursor> while meta.has_more is true

Match products on sku, upc, vendor_sku, or the bigcommerce.product_id and bigcommerce.variant_id pair. Publish qty_available per location.

Firearms (is_firearm: true) and other serialized items are counted per unit: qty_on_hand is the number of units in stock. GET /v1/inventory/serialized?product_id=…&status=in_stock lists the actual serial numbers if you need them.

Record the time before you started the load. That's your first updated_since.

3. Stay current with webhooks

Every stock change fires inventory.changed with the new level:

{ "type": "inventory.changed", "data": { "object": { "product_id": 2062, "location_id": 93, "qty_on_hand": 38, "qty_available": 38, "qty_delta": -2, "reason": "sale", "sku": "AMM-9-115-50", "updated_at": "2026-09-25T01:48:03Z" } } }

Set your number to qty_available; don't add qty_delta to it. Deliveries can repeat or arrive out of order, and an absolute value is always safe to apply. Skip an event if its updated_at is older than what you already have.

4. Reconcile on a schedule

Webhooks can be missed, for example while your receiver is down. Every 15–60 minutes, pull what changed:

curl "https://app.ironregister.com/api/v1/inventory?updated_since=2026-09-25T01:00:00Z&limit=200" -H "Authorization: Bearer $KEY"
curl "https://app.ironregister.com/api/v1/products?updated_since=2026-09-25T01:00:00Z&limit=200" -H "Authorization: Bearer $KEY"

On Established, this takes a few requests an hour out of 10,000 a day.

5. Writing stock back (optional)

When stock arrives through your flow (a dropship return landing in the store, a distributor delivery you received), adjust by the difference and always send an Idempotency-Key:

curl -X POST https://app.ironregister.com/api/v1/inventory/adjust \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: flx-receipt-55120-line-3" \
  -d '{ "sku": "AMM-9-115-50", "location_id": 93, "qty_delta": 24, "reason": "receive", "note": "Flxpoint receipt 55120" }'

Or set an absolute count with POST /v1/inventory/set.

Two limits:

  • Serialized products (every firearm) can't be adjusted through the API (409 SERIALIZED). They're received in Iron Register, where each unit is entered in the bound book.
  • Mind the rate limit. Throttle bulk writes to stay under 60 per minute on Established. Watch X-RateLimit-Remaining and honor Retry-After.

6. Purchase orders to distributors

When your platform places a replenishment order with a distributor for the store, create it as a purchase order so the store sees what's on the way. Put your own id in flxpoint_order_id (it's unique per shop, so a retry can't create a second one) and send an Idempotency-Key. The key needs purchase_orders:write.

curl -X POST https://app.ironregister.com/api/v1/purchase-orders \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: po-FXP-448120" \
  -d '{ "vendor_id": 155, "location_id": 93, "flxpoint_order_id": "FXP-448120", "submit": true,
        "lines": [ { "sku": "AMM-9-115-50", "qty": 40, "unit_cost_cents": 1100 } ] }'

When the distributor's shipment is delivered, receive against it. Stock goes up and receiving.posted and inventory.changed fire:

curl -X POST https://app.ironregister.com/api/v1/purchase-orders/77/receive \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: rcv-FXP-448120-1" \
  -d '{ "all_outstanding": true, "reference": "UPS 1Z999AA10123456784" }'

Firearms and other serialized items on a purchase order are left for the store to receive in Iron Register, where each serial is entered in the bound book. all_outstanding lists them in skipped. Receive through the purchase order rather than inventory/adjust, so the store's purchase orders stay in step with its stock. See Purchase orders for every rule.

7. Prices and product data

product.updated covers price, sale-price and detail changes. effective_price_cents is what the counter charges right now. map_price_cents is the manufacturer's advertised minimum.

If your system is the pricing authority, send PATCH /v1/products/{id} with price_cents or a sale window (products: write).