Products — Overview
Products represent items in your catalog. Each product can have multiple variants, and variants are the sellable, SKU-level items that get stored in locations and shipped to customers.
Product/Variant Hierarchy
GraphQL Types
ProductType
The root type for a product.
type ProductType {
id: ID!
title: String!
description: String
status: ProductStatusEnum! # DRAFT | ACTIVE | DISABLED | ARCHIVED
model: ProductModelEnum! # PRODUCT | BUNDLE
vendor: VendorType
organization: OrganizationType
variants: [VariantType!]!
createdAt: DateTime!
updatedAt: DateTime!
}| Field | Type | Description |
|---|---|---|
id | ID! | Unique identifier |
title | String! | Display name of the product |
description | String | Free-text product description |
status | ProductStatusEnum! | Lifecycle status — see Product Statuses |
model | ProductModelEnum! | PRODUCT or BUNDLE — see Product Models |
vendor | VendorType | Vendor/supplier associated with this product |
organization | OrganizationType | Owning organization |
variants | [VariantType!]! | All variants belonging to this product |
createdAt | DateTime! | Creation timestamp (ISO 8601) |
updatedAt | DateTime! | Last update timestamp (ISO 8601) |
VariantType
The sellable unit within a product. Each variant has a unique SKU within an organization.
type VariantType {
id: ID!
sku: String!
title: String
status: ProductStatusEnum!
model: ProductModelEnum! # PRODUCT | BUNDLE
weight: Float
weightUnit: WeightUnitEnum # G | KG | LB | OZ
height: Float
width: Float
length: Float
distanceUnit: DistanceUnitEnum # CM | IN
barcode: String
originCountry: String
hsCode: String
source: VariantSourceEnum # APP | CMS
product: ProductType
links: [VariantLinkType!] # Bundle components
createdAt: DateTime!
updatedAt: DateTime!
}| Field | Type | Description |
|---|---|---|
id | ID! | Unique identifier |
sku | String! | Unique SKU within the organization |
title | String | Variant label (e.g. "Small / Blue") |
status | ProductStatusEnum! | Lifecycle status |
model | ProductModelEnum! | PRODUCT or BUNDLE |
weight | Float | Weight value |
weightUnit | WeightUnitEnum | G, KG, LB, or OZ |
height | Float | Height in distanceUnit |
width | Float | Width in distanceUnit |
length | Float | Length in distanceUnit |
distanceUnit | DistanceUnitEnum | CM or IN |
barcode | String | EAN or UPC barcode |
originCountry | String | ISO 3166-1 alpha-2 country code (e.g. FR) |
hsCode | String | HS tariff code for customs |
source | VariantSourceEnum | Creation source — see Source Management |
product | ProductType | Parent product |
links | [VariantLinkType!] | Component variants if this is a BUNDLE |
createdAt | DateTime! | Creation timestamp (ISO 8601) |
updatedAt | DateTime! | Last update timestamp (ISO 8601) |
VariantLinkType
Describes a component variant and how many units are required per bundle.
type VariantLinkType {
destination: VariantType!
quantity: Int!
}| Field | Type | Description |
|---|---|---|
destination | VariantType! | The component variant |
quantity | Int! | Number of units required per bundle unit |
Product Models
| Model | Description |
|---|---|
PRODUCT | Standard product with physical stock tracking |
BUNDLE | Virtual product composed of other variants; stock is derived from components |
Product Statuses
| Status | Description |
|---|---|
DRAFT | Not yet published; can be modified freely |
ACTIVE | Published and visible; can be used in orders |
DISABLED | Temporarily hidden; can be re-enabled |
ARCHIVED | Permanently archived; cannot be restored |
Variant Lifecycle
Bundle Composition
A bundle variant has model: BUNDLE and references one or more component variants through links. Stock availability for a bundle is calculated as the minimum of (componentStock / requiredQuantity) across all links.
Use variantChangeModel to convert a standard variant into a bundle and define its component links.
Variant References
Variants can carry multiple external references (EAN, UPC, GTIN, ASIN, etc.) in addition to their primary SKU. References are managed via the references field in variantCreate and variantUpdate.
| Field | Type | Description |
|---|---|---|
reference | String | The reference value (e.g. "3614273474818") |
type | String | The reference type (e.g. EAN13, UPC, GTIN, ASIN) |
Each (reference, type) pair must be unique within your organization. HappyColis will reject variant creation if a duplicate reference already exists.
HappyColis uses its own internal reference for each variant. Order lines inherit this reference to avoid conflicts when requesting preparation at the fulfillment location.
Source Management
Variants track their creation source to prevent conflicting updates. As multiple systems can work with the same product (e.g. your e-commerce site and your ERP), you can choose which one is the source of truth.
| Source | Description |
|---|---|
APP | Created and managed through the HappyColis application |
CMS | Created and managed through an external CMS (e.g. Shopify, WooCommerce) |
A CMS-sourced variant can only be updated by the same OAuth client that created it. HappyColis will reject updates from a different source.
To change the source of truth for a variant, use the variantChangeSource mutation:
mutation VariantChangeSource($id: String!, $sourceType: ProductSourceEnum!, $sourceId: String) {
variantChangeSource(id: $id, sourceType: $sourceType, sourceId: $sourceId) {
id
sku
source
}
}Operations
Queries
| Operation | Scope | Description |
|---|---|---|
product | view_products | Retrieve a product by ID |
variant | view_products | Retrieve a variant by ID or SKU |
Product Mutations
| Operation | Scope | Description |
|---|---|---|
productCreate | create_products | Create a new product |
productUpdate | edit_products | Update product fields |
productActivate | edit_products | Transition product to ACTIVE |
productDisable | edit_products | Transition product to DISABLED |
productArchive | edit_products | Permanently archive a product |
Variant Mutations
| Operation | Scope | Description |
|---|---|---|
variantCreate | create_products | Create a new variant |
variantUpdate | edit_products | Update variant fields |
variantActivate | edit_products | Transition variant to ACTIVE |
variantDisable | edit_products | Transition variant to DISABLED |
variantArchive | edit_products | Permanently archive a variant |
variantChangeModel | edit_products | Convert variant to BUNDLE and set component links |
variantChangeSource | edit_products | Change the source of truth for a variant |
Best Practices
- Use meaningful SKUs. Create SKUs that are easy to identify and sort (e.g.
TSHIRT-S-BLUE). - Complete variant data. Include weight, dimensions, and customs info (
originCountry,hsCode) for international shipping. - Start in DRAFT. Create products and variants in
DRAFTstatus, review, then activate. - Bundle requirements. Bundles must have at least one link defined via
variantChangeModel. - Unique SKUs per organization. Each variant SKU must be unique within the organization.
- Irreversible archiving. Archiving a product or variant cannot be undone — prefer
DISABLEDfor temporary removal. - SKU is immutable. You cannot change a variant's SKU after creation. Archive the variant and create a new one instead.
- Stock reallocation requires support. If you need to move stock from one variant to another, contact HappyColis support — this cannot be done via the API.