API docs

Products, categories, vendors

Permission: products (read / write).

The product object

{
  "object": "product",
  "id": 2053,
  "sku": "GLK-G19G5",
  "upc": "764503037269",
  "name": "Glock 19 Gen 5 9mm",
  "brand": "Glock",
  "manufacturer": "Glock Inc.",
  "model": "19 Gen5",
  "description": null,
  "product_type": "firearm",
  "category_id": 511,
  "vendor_id": 155,
  "vendor_sku": "GLPA195S203",
  "is_active": true,
  "is_serialized": true,
  "is_firearm": true,
  "is_nfa": false,
  "track_inventory": true,
  "min_age": 21,
  "tax_class": "standard",
  "price_cents": 57900,
  "cost_cents": 43900,
  "map_price_cents": 54900,
  "compare_at_cents": null,
  "sale_price_cents": null,
  "sale_starts_at": null,
  "sale_ends_at": null,
  "sale_scope": "store",
  "effective_price_cents": 57900,
  "firearm": { "type": "pistol", "caliber": "9mm", "action": "striker", "barrel_length": "4.02\"", "capacity": "15", "finish": "Black", "importer": null, "country_of_origin": "Austria" },
  "weight_grams": 850,
  "image_url": "https://cdn11.bigcommerce.com/…/g19.jpg",
  "reorder_point": 2,
  "reorder_qty": 3,
  "sell_online": true,
  "bigcommerce": { "product_id": 141, "variant_id": 188 },
  "flxpoint_product_id": null,
  "inventory": [ { "object": "inventory_level", "product_id": 2053, "location_id": 93, "qty_on_hand": 3, "qty_reserved": 0, "qty_available": 3, "reorder_point": null, "bin_location": "Case 2", "updated_at": "2026-09-24T06:22:22Z" } ],
  "created_at": "2026-09-03T15:10:00Z",
  "updated_at": "2026-09-24T06:22:22Z"
}
Field Notes
product_type firearm, ammunition, accessory, service, fee, gift_card
is_firearm Sale needs a Form 4473 at the counter
is_serialized Stocked as individual units with serial numbers (see Inventory)
tax_class standard, exempt, ammunition, service
effective_price_cents sale_price_cents while a sale window is open, otherwise price_cents
sale_scope store (counter only) or store_online (also pushed to BigCommerce)
firearm Present for firearms, otherwise null. type is one of pistol, revolver, rifle, shotgun, receiver, frame, silencer, sbr, sbs, machine_gun, aow, other
inventory Levels at the locations the key can see. Always on single-product responses; on lists with include=inventory

List products

GET /v1/products

Filter
sku, upc, vendor_sku Exact match
product_type, category_id, vendor_id, bigcommerce_product_id Exact match
is_active true / false
q Name, SKU prefix, model, or exact UPC
include=inventory Embed levels
updated_since, limit, cursor See Conventions
curl "https://app.ironregister.com/api/v1/products?product_type=ammunition&include=inventory&limit=100" \
  -H "Authorization: Bearer $KEY"

Get a product

GET /v1/products/{id}: the product with its inventory levels.

Create a product

POST /v1/products (write). Requires name and price_cents. Everything else is optional:

  • sku is generated if you leave it out.
  • Send the read shape: is_firearm, reorder_point, reorder_qty and a nested firearm{}. The internal flat names (requires_4473, default_reorder_point, default_reorder_qty, firearm_type, caliber, action_type, …) are accepted too.
  • reorder_point and reorder_qty are the product's defaults. A product needs reordering at a location when what's available there (on hand less held) plus what's on order is at or below its reorder point; Reorder then orders reorder_qty (a location's own reorder point and quantity win when set).
  • vendor_id / vendor_sku are the product's preferred vendor. Setting them makes that vendor the preferred one on the product's vendor list in Iron Register (other vendors stay listed).
  • A product_type of firearm always makes the product is_firearm: true and is_serialized: true.
curl -X POST https://app.ironregister.com/api/v1/products \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7d3f0c1e-2b8a-4c55-9d1e-0f6a2c1b9e44" \
  -d '{
    "sku": "HRN-9-124-XTP-25",
    "name": "Hornady Critical Defense 9mm 115gr (25)",
    "brand": "Hornady",
    "product_type": "ammunition",
    "tax_class": "ammunition",
    "price_cents": 2899,
    "cost_cents": 1950,
    "upc": "090255900905",
    "vendor_id": 155,
    "vendor_sku": "90250",
    "reorder_point": 6
  }'

Returns 201 with the product.

Possible errors:

  • 409 SKU_TAKEN
  • 400 VALIDATION_ERROR for an unknown category_id or vendor_id, or a bad firearm.type

Update a product

PATCH /v1/products/{id} (write). Send only the fields you're changing.

  • Prices, descriptions and the rest are ordinary edits.
  • Compliance fields are fixed. is_firearm, is_serialized, is_nfa, and changing product_type to or from firearm, can't be changed after creation: 409 COMPLIANCE_FIELD with details.field. They decide whether a sale needs a 4473 and a bound-book entry, so they're changed only in Iron Register. Sending the current value is fine.
  • Sale prices online. Changing sale_price_cents, sale_starts_at or sale_ends_at on a product with sale_scope: "store_online" also queues the sale price to BigCommerce.
curl -X PATCH https://app.ironregister.com/api/v1/products/2062 \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{ "price_cents": 1799, "sale_price_cents": 1599, "sale_starts_at": "2026-10-01T04:00:00Z", "sale_ends_at": "2026-10-08T04:00:00Z" }'

Delete a product

DELETE /v1/products/{id} (write). Refused with 409 HAS_STOCK while any location has stock on hand. To take a product out of use, set is_active: false instead.

{ "status": "ok", "data": { "object": "product", "id": 2062, "deleted": true } }

Categories

GET /v1/categories (products:read). Paginated, with updated_since.

{ "object": "category", "id": 511, "name": "Handguns", "parent_id": 510, "sort_order": 1, "bigcommerce_category_id": 24, "updated_at": "2026-09-03T15:10:00Z" }

Vendors

GET /v1/vendors (products:read). Paginated, with updated_since.

{ "object": "vendor", "id": 155, "name": "Lipsey's", "code": "LIP", "contact_name": "Rep Desk", "email": "orders@example.com", "phone": "800-555-0100", "website": "https://www.lipseys.com", "is_distributor": true, "flxpoint_source_id": "src_8812", "status": "active", "updated_at": "2026-09-03T15:10:00Z" }