Products
Called with brand account keys. A key only sees its own account's data. Every example uses the same sample brand, order and item, so you can follow one item from call to call.
http://62.169.23.239:8001/api/v1Auth Bearer token7 endpointsEndpoints
- GET/brands/categoriesList categories
- POST/brands/create-productCreate a product
- GET/brands/products/{product_id}Retrieve a product
- PUT/brands/products/{product_id}Update a product
- GET/productsList products
- PUT/brands/products/{product_id}/protectionSet protection tier
- DELETE/brands/products/{product_id}Delete a product
List categories#
Requires scope products:read
Return the full category → product_types taxonomy.
Returns
HTTP 200A application/json file.
curl http://62.169.23.239:8001/api/v1/brands/categories \
-H "Authorization: Bearer $SKANNIT_TOKEN"// 200 — body is application/jsonCreate a product#
Requires scope products:write
Request body
multipart/form-data- productstringRequired
JSON BrandProductCreatePayload
- image_frontstring | null
- image_backstring | null
- image_sidestring | null
- image_detailstring | null
- image_lifestylestring | null
- tech_packstring | null
- spec_sheetstring | null
- certificatesarray of strings
Returns
HTTP 201- product_idstringRequired
Skannit's id for the product.
- brand_idstringRequired
The brand that owns the product.
- product_namestringRequired
- statusstringRequired
Current state of the object. See the allowed values.
- base_skustringRequired
SKU of the product. Variant SKUs are built from it.
- media_urlsobjectRequired
- spec_sheet_urlstring | nullRequired
- certificate_urlsarray of stringsRequired
- variants_countintegerRequired
- created_atstringRequired
When the object was created (ISO 8601, UTC).
- updated_atstring | null
When the object last changed (ISO 8601, UTC).
curl -X POST http://62.169.23.239:8001/api/v1/brands/create-product \
-H "Authorization: Bearer $SKANNIT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-F 'product={"product_name": "Trail Tee", "status": "active", "base_sku": "TT-100", "category": "Tops", "price": 19.0, "sizes": ["S", "M"], "colors": ["White"], "variants": [{"color": "White", "size": "S", "volume_l": 0.5}, {"color": "White", "size": "M", "volume_l": 0.5}]}' \
-F image_front=@front.jpg{
"product_id": "f6abe715-90aa-5908-a0a6-12951a3a21cc",
"brand_id": "8ea3462c-426c-5cc1-84d7-db99868bca1c",
"product_name": "Trail Tee",
"status": "active",
"base_sku": "TT-100",
"media_urls": {},
"spec_sheet_url": "https://files.skannit.example/spec_sheet.png",
"certificate_urls": [
"https://files.skannit.example/certificate.png"
],
"variants_count": 24,
"created_at": "2026-10-09T09:30:00Z",
"updated_at": "2026-10-09T09:30:00Z"
}Retrieve a product#
Requires scope products:read
Full product detail — same shape as PUT response (create-product + catalogue fields).
Parameters
- product_idstringpathRequired
Skannit's id for the product.
Returns
HTTP 200- product_namestringRequired
- statusstring
Current state of the object. See the allowed values.
One ofdraftactiveDefaults to
draft - base_skustring | null
SKU of the product. Variant SKUs are built from it.
- categorystring | null
- genderstring | null
- pricestring | null
- msrpstring | null
- descriptionstring | null
- seasonstring | null
- gtin_statusstring | nullOne of
has_ownreseller_partnerskannit_native - gtin_or_uuidstring | null
- organicboolean
Defaults to
false - recycled_contentboolean
Defaults to
false - fabric_weight_gsminteger | null
- texture_finishstring | null
- sizesarray of strings
- colorsarray of strings
- variantsarray of objects
+Show 6 child attributesHide child attributes
- colorstringRequired
Colour name, exactly as on the product's variants.
- sizestringRequired
Size name, exactly as on the product's variants.
- variant_skustring | null
SKU of one colour/size variant. Generated as <base SKU>-<colour>-<size> when you don't send one.
- upc_eanstring | null
- volume_lstring | null
Packaged volume per unit, in liters
- stockinteger
Defaults to
0
- id_assignmentstring
Defaults to
unique - authentication_hardwareobject
+Show 2 child attributesHide child attributes
- nfc_chipboolean
Defaults to
false - anti_counterfeit_threadboolean
Defaults to
false
- internal_tagsarray of strings
- approval_statusstring
Defaults to
pending_design_lead - private_notesstring | null
- media_urlsobject | null
- spec_sheet_urlstring | null
- certificate_urlsarray of strings
- product_idstringRequired
Skannit's id for the product.
- brand_idstringRequired
The brand that owns the product.
- updated_atstringRequired
When the object last changed (ISO 8601, UTC).
- created_atstringRequired
When the object was created (ISO 8601, UTC).
- carbon_co2string | null
- water_used_lstring | null
- circular_scoreinteger | null
- end_of_life_instructionsstring | null
- repair_difficultystring | null
- spare_parts_includedarray of strings
- repair_instructions_urlstring | null
- country_of_originstring | null
- main_supplierstring | null
- compliance_standardsobject
+Show 3 child attributesHide child attributes
- eu_dpp_readyboolean
Defaults to
false - esg_certifiedboolean
Defaults to
false - reach_compliantboolean
Defaults to
false
- stock_statusstringOne of
IN STOCKLOW STOCKOUT OF STOCKDefaults to
OUT OF STOCK - category_pathstring
Defaults to
- specificationsobject
+Show 5 child attributesHide child attributes
- primary_materialstring | null
- membrane_typestring | null
- weightstring | null
- sustainabilitystring | null
- warrantystring | null
- imagesarray of strings
- stock_distributionarray of objects
+Show 2 child attributesHide child attributes
- location_namestringRequired
- unitsintegerRequired
- material_specifications_compliancestring | null
- active_catalogboolean
Defaults to
true - lifecycle_stagestring | null
- inventory_on_handinteger
Defaults to
0 - inventory_reservedinteger
Defaults to
0 - low_stock_thresholdinteger
Defaults to
0 - last_modified_atstring | null
- last_modified_bystring | null
- tech_pack_urlstring | null
- protection_tierstring
Anti-counterfeit scanToken rotation tier (see ProductProtectionPayload). Read-only here — set via PUT /brands/products/{id}/protection, not via the product update payload, so a full product save can never silently reset a brand's protection level.
One ofstandardpremiumeliteDefaults to
standard - geo_lock_rulesobject | null
Elite-tier geographic restrictions, checked at scan time (Layer 2). Both forms are optional and independent — a brand can allow-list countries, fence a radius around a point, or do both.
+Show 4 child attributesHide child attributes
- allowed_countriesarray of strings | null
ISO country codes this item may legitimately be scanned in
- radius_kmnumber | null
Allowed distance from the anchor point
- anchor_latnumber | null
- anchor_lonnumber | null
curl http://62.169.23.239:8001/api/v1/brands/products/f6abe715-90aa-5908-a0a6-12951a3a21cc \
-H "Authorization: Bearer $SKANNIT_TOKEN"{
"product_name": "Trail Tee",
"status": "draft",
"base_sku": "TT-100",
"category": "Tops",
"gender": "unisex",
"price": 19,
"msrp": 29,
"description": "Organic cotton tee",
"season": "AW26",
"gtin_status": "has_own",
"gtin_or_uuid": "08712345678906",
"organic": false,
"recycled_content": false,
"fabric_weight_gsm": 1,
"texture_finish": "brushed",
"sizes": [
"S",
"M",
"L"
],
"colors": [
"White",
"Black"
],
"variants": [
"White / M"
],
"id_assignment": "unique",
"authentication_hardware": {
"nfc_chip": false,
"anti_counterfeit_thread": false
},
"internal_tags": [
"internal tag"
],
"approval_status": "pending_design_lead",
"private_notes": null,
"media_urls": {},
"spec_sheet_url": "https://files.skannit.example/spec_sheet.png",
"certificate_urls": [
"https://files.skannit.example/certificate.png"
],
"product_id": "f6abe715-90aa-5908-a0a6-12951a3a21cc",
"brand_id": "8ea3462c-426c-5cc1-84d7-db99868bca1c",
"updated_at": "2026-10-09T09:30:00Z",
"created_at": "2026-10-09T09:30:00Z",
"carbon_co2": 3.2,
"water_used_l": 2700,
"circular_score": 72,
"end_of_life_instructions": "Return to any Northwind store for recycling",
"repair_difficulty": "easy",
"spare_parts_included": [
"buttons"
],
"repair_instructions_url": "https://files.skannit.example/repair_instructions.png",
"country_of_origin": "PT",
"main_supplier": "Tecidos do Norte",
"compliance_standards": {
"eu_dpp_ready": true,
"esg_certified": true,
"reach_compliant": true
},
"stock_status": "IN STOCK",
"category_path": "Apparel / Tops",
"specifications": {
"primary_material": "Organic cotton",
"membrane_type": "none",
"weight": "180 g",
"sustainability": "GOTS certified",
"warranty": "2 years"
},
"images": [
"image"
],
"stock_distribution": [
{
"location_name": "Rotterdam DC",
"units": 24
}
],
"material_specifications_compliance": "REACH compliant",
"active_catalog": true,
"lifecycle_stage": "in_production",
"inventory_on_hand": 1,
"inventory_reserved": 1,
"low_stock_threshold": 1,
"last_modified_at": null,
"last_modified_by": "ops@northwind.example",
"tech_pack_url": "https://files.skannit.example/tech_pack.png",
"protection_tier": "standard",
"geo_lock_rules": {
"allowed_countries": [
"allowed country"
],
"radius_km": 1,
"anchor_lat": 51.9244,
"anchor_lon": 4.4777
}
}Update a product#
Requires scope products:write
Parameters
- product_idstringpathRequired
Skannit's id for the product.
Request body
multipart/form-data- productstringRequired
JSON BrandProductUpdatePayload
- image_frontstring | null
- image_backstring | null
- image_sidestring | null
- image_detailstring | null
- image_lifestylestring | null
- tech_packstring | null
- spec_sheetstring | null
- certificatesarray of strings
Returns
HTTP 200- product_namestringRequired
- statusstring
Current state of the object. See the allowed values.
One ofdraftactiveDefaults to
draft - base_skustring | null
SKU of the product. Variant SKUs are built from it.
- categorystring | null
- genderstring | null
- pricestring | null
- msrpstring | null
- descriptionstring | null
- seasonstring | null
- gtin_statusstring | nullOne of
has_ownreseller_partnerskannit_native - gtin_or_uuidstring | null
- organicboolean
Defaults to
false - recycled_contentboolean
Defaults to
false - fabric_weight_gsminteger | null
- texture_finishstring | null
- sizesarray of strings
- colorsarray of strings
- variantsarray of objects
+Show 6 child attributesHide child attributes
- colorstringRequired
Colour name, exactly as on the product's variants.
- sizestringRequired
Size name, exactly as on the product's variants.
- variant_skustring | null
SKU of one colour/size variant. Generated as <base SKU>-<colour>-<size> when you don't send one.
- upc_eanstring | null
- volume_lstring | null
Packaged volume per unit, in liters
- stockinteger
Defaults to
0
- id_assignmentstring
Defaults to
unique - authentication_hardwareobject
+Show 2 child attributesHide child attributes
- nfc_chipboolean
Defaults to
false - anti_counterfeit_threadboolean
Defaults to
false
- internal_tagsarray of strings
- approval_statusstring
Defaults to
pending_design_lead - private_notesstring | null
- media_urlsobject | null
- spec_sheet_urlstring | null
- certificate_urlsarray of strings
- product_idstringRequired
Skannit's id for the product.
- brand_idstringRequired
The brand that owns the product.
- updated_atstringRequired
When the object last changed (ISO 8601, UTC).
- created_atstringRequired
When the object was created (ISO 8601, UTC).
- carbon_co2string | null
- water_used_lstring | null
- circular_scoreinteger | null
- end_of_life_instructionsstring | null
- repair_difficultystring | null
- spare_parts_includedarray of strings
- repair_instructions_urlstring | null
- country_of_originstring | null
- main_supplierstring | null
- compliance_standardsobject
+Show 3 child attributesHide child attributes
- eu_dpp_readyboolean
Defaults to
false - esg_certifiedboolean
Defaults to
false - reach_compliantboolean
Defaults to
false
- stock_statusstringOne of
IN STOCKLOW STOCKOUT OF STOCKDefaults to
OUT OF STOCK - category_pathstring
Defaults to
- specificationsobject
+Show 5 child attributesHide child attributes
- primary_materialstring | null
- membrane_typestring | null
- weightstring | null
- sustainabilitystring | null
- warrantystring | null
- imagesarray of strings
- stock_distributionarray of objects
+Show 2 child attributesHide child attributes
- location_namestringRequired
- unitsintegerRequired
- material_specifications_compliancestring | null
- active_catalogboolean
Defaults to
true - lifecycle_stagestring | null
- inventory_on_handinteger
Defaults to
0 - inventory_reservedinteger
Defaults to
0 - low_stock_thresholdinteger
Defaults to
0 - last_modified_atstring | null
- last_modified_bystring | null
- tech_pack_urlstring | null
- protection_tierstring
Anti-counterfeit scanToken rotation tier (see ProductProtectionPayload). Read-only here — set via PUT /brands/products/{id}/protection, not via the product update payload, so a full product save can never silently reset a brand's protection level.
One ofstandardpremiumeliteDefaults to
standard - geo_lock_rulesobject | null
Elite-tier geographic restrictions, checked at scan time (Layer 2). Both forms are optional and independent — a brand can allow-list countries, fence a radius around a point, or do both.
+Show 4 child attributesHide child attributes
- allowed_countriesarray of strings | null
ISO country codes this item may legitimately be scanned in
- radius_kmnumber | null
Allowed distance from the anchor point
- anchor_latnumber | null
- anchor_lonnumber | null
curl -X PUT http://62.169.23.239:8001/api/v1/brands/products/f6abe715-90aa-5908-a0a6-12951a3a21cc \
-H "Authorization: Bearer $SKANNIT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-F 'product={"product_name": "Trail Tee", "status": "active", "base_sku": "TT-100", "category": "Tops", "price": 19.0, "sizes": ["S", "M"], "colors": ["White"], "variants": [{"color": "White", "size": "S", "volume_l": 0.5}, {"color": "White", "size": "M", "volume_l": 0.5}]}' \
-F image_front=@front.jpg{
"product_name": "Trail Tee",
"status": "draft",
"base_sku": "TT-100",
"category": "Tops",
"gender": "unisex",
"price": 19,
"msrp": 29,
"description": "Organic cotton tee",
"season": "AW26",
"gtin_status": "has_own",
"gtin_or_uuid": "08712345678906",
"organic": false,
"recycled_content": false,
"fabric_weight_gsm": 1,
"texture_finish": "brushed",
"sizes": [
"S",
"M",
"L"
],
"colors": [
"White",
"Black"
],
"variants": [
"White / M"
],
"id_assignment": "unique",
"authentication_hardware": {
"nfc_chip": false,
"anti_counterfeit_thread": false
},
"internal_tags": [
"internal tag"
],
"approval_status": "pending_design_lead",
"private_notes": null,
"media_urls": {},
"spec_sheet_url": "https://files.skannit.example/spec_sheet.png",
"certificate_urls": [
"https://files.skannit.example/certificate.png"
],
"product_id": "f6abe715-90aa-5908-a0a6-12951a3a21cc",
"brand_id": "8ea3462c-426c-5cc1-84d7-db99868bca1c",
"updated_at": "2026-10-09T09:30:00Z",
"created_at": "2026-10-09T09:30:00Z",
"carbon_co2": 3.2,
"water_used_l": 2700,
"circular_score": 72,
"end_of_life_instructions": "Return to any Northwind store for recycling",
"repair_difficulty": "easy",
"spare_parts_included": [
"buttons"
],
"repair_instructions_url": "https://files.skannit.example/repair_instructions.png",
"country_of_origin": "PT",
"main_supplier": "Tecidos do Norte",
"compliance_standards": {
"eu_dpp_ready": true,
"esg_certified": true,
"reach_compliant": true
},
"stock_status": "IN STOCK",
"category_path": "Apparel / Tops",
"specifications": {
"primary_material": "Organic cotton",
"membrane_type": "none",
"weight": "180 g",
"sustainability": "GOTS certified",
"warranty": "2 years"
},
"images": [
"image"
],
"stock_distribution": [
{
"location_name": "Rotterdam DC",
"units": 24
}
],
"material_specifications_compliance": "REACH compliant",
"active_catalog": true,
"lifecycle_stage": "in_production",
"inventory_on_hand": 1,
"inventory_reserved": 1,
"low_stock_threshold": 1,
"last_modified_at": null,
"last_modified_by": "ops@northwind.example",
"tech_pack_url": "https://files.skannit.example/tech_pack.png",
"protection_tier": "standard",
"geo_lock_rules": {
"allowed_countries": [
"allowed country"
],
"radius_km": 1,
"anchor_lat": 51.9244,
"anchor_lon": 4.4777
}
}List products#
Requires scope products:read
Parameters
- searchstringquery
Search name, SKU, category, or tier
- product_tierstringquery
Filter by product tier (maps to category)
- origin_countrystringquery
Filter by country of origin
- statusstringquery
Stock status: Active, Low Stock, or Inactive
One ofDraftActiveInactive - pageintegerquery
Defaults to
1 - limitintegerquery
Defaults to
5
Returns
HTTP 200- itemsarray of objectsRequired
The objects on this page.
+Show 8 child attributesHide child attributes
- idstringRequired
- namestringRequired
- categorystringRequired
- image_urlstring | null
- skustringRequired
Stock-keeping unit of the variant.
- variantsarray of strings
- product_tierstringRequired
- statusstringRequired
Current state of the object. See the allowed values.
One ofDraftActiveInactive
- paginationobjectRequired
Page position: current_page, limit, total_pages, total_results.
+Show 6 child attributesHide child attributes
- total_resultsintegerRequired
- total_pagesintegerRequired
- current_pageintegerRequired
- limitintegerRequired
- showing_fromintegerRequired
- showing_tointegerRequired
curl http://62.169.23.239:8001/api/v1/products \
-H "Authorization: Bearer $SKANNIT_TOKEN"{
"items": [
{
"id": "SKN-CRT-00402-9A1C3E7F",
"name": "Northwind Apparel",
"category": "Tops",
"image_url": "https://files.skannit.example/image.png",
"sku": "TT-100-WHT-M",
"variants": [
"White / M"
],
"product_tier": "standard",
"status": "Draft"
}
],
"pagination": {
"total_results": 24,
"total_pages": 24,
"current_page": 1,
"limit": 1,
"showing_from": 1,
"showing_to": 1
}
}Set protection tier#
Requires scope products:write
Controls how often this product's QR scanToken rotates, which is what makes a copied QR stop working:
- **standard** — rotates when custody changes hands (factory → shop → customer). Suits food and FMCG. - **premium** — also rotates on every authenticated consumer scan. Suits fashion and electronics. - **elite** — premium, plus geo-lock rules and periodic 'tap to verify' prompts to the owner so a copy cannot keep working on an item that is never scanned. Suits luxury and pharma.
Applies forward only — units already minted are not re-issued, they are simply treated under the new tier from their next scan onward.
Parameters
- product_idstringpathRequired
Skannit's id for the product.
Request body
- protection_tierstringRequired
How strongly the product is protected against counterfeits.
One ofstandardpremiumelite - geo_lock_rulesobject | null
Elite tier only; ignored for standard/premium
+Show 4 child attributesHide child attributes
- allowed_countriesarray of strings | null
ISO country codes this item may legitimately be scanned in
- radius_kmnumber | null
Allowed distance from the anchor point
- anchor_latnumber | null
- anchor_lonnumber | null
Returns
HTTP 200- product_idstringRequired
Skannit's id for the product.
- protection_tierstringRequired
How strongly the product is protected against counterfeits.
One ofstandardpremiumelite - geo_lock_rulesobject | null
Elite-tier geographic restrictions, checked at scan time (Layer 2). Both forms are optional and independent — a brand can allow-list countries, fence a radius around a point, or do both.
+Show 4 child attributesHide child attributes
- allowed_countriesarray of strings | null
ISO country codes this item may legitimately be scanned in
- radius_kmnumber | null
Allowed distance from the anchor point
- anchor_latnumber | null
- anchor_lonnumber | null
curl -X PUT http://62.169.23.239:8001/api/v1/brands/products/f6abe715-90aa-5908-a0a6-12951a3a21cc/protection \
-H "Authorization: Bearer $SKANNIT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"protection_tier": "standard"
}'{
"product_id": "f6abe715-90aa-5908-a0a6-12951a3a21cc",
"protection_tier": "standard",
"geo_lock_rules": {
"allowed_countries": [
"allowed country"
],
"radius_km": 1,
"anchor_lat": 51.9244,
"anchor_lon": 4.4777
}
}Delete a product#
Requires scope products:write
Removes the product from the catalogue, its filters and its summary counts, and stops it being selectable for new production orders.
The underlying row is retained, because production orders, QR batches and already-minted units reference this product_id and must keep resolving — a passport scanned by a consumer on an item made years ago still has to show what it was. The product's base_sku is released, so the brand can create a new product under the same SKU.
Returns 409 while a submitted production order still references the product; cancel those orders first.
Parameters
- product_idstringpathRequired
Skannit's id for the product.
Returns
HTTP 204No body.
curl -X DELETE http://62.169.23.239:8001/api/v1/brands/products/f6abe715-90aa-5908-a0a6-12951a3a21cc \
-H "Authorization: Bearer $SKANNIT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)"// 204 — no body