generated: '2026-08-09' method: derived source: openapi/canix-openapi-original.yml description: 'Entity-relationship graph derived from the Canix OpenAPI component schemas: $ref links become has_one/has_many and *_id fields that name a sibling schema become belongs_to. Canix models a cannabis seed-to-sale supply chain — Facility scopes almost everything; Strain -> PlantBatch -> Plant -> Harvest -> Package is the cultivation spine; Item/Product/Brand describe saleable goods; BillOfMaterials -> ManuBatch/ManuBatchRun is manufacturing; PurchaseOrder/Vendor and SalesOrder/Customer are the two commercial ends; Transfer/TransferDestination move packages between licensees for Metrc track-and-trace.' summary: entities: 76 resource_entities: 61 request_body_entities: 15 relationships: 126 by_kind: belongs_to: 37 has_one: 50 has_many: 39 roots: - Facility - Company - SalesOrder - PurchaseOrder - Item - Package - Plant - PlantBatch - Harvest - Transfer - BillOfMaterials - ManuBatch - ManuBatchRun - Customer - Vendor - Strain - Location - Product - NonCannabisProduct identifiers: style: integer surrogate ids path_params: - bill_of_materials_id - company_id - customer_id - facility_id - harvest_id - item_id - location_id - manu_batch_id - manu_batch_run_id - non_cannabis_product_id - package_id - payment_id - plant_batch_id - plant_id - product_id - purchase_order_id - sales_order_id - standard_cost_id - strain_id - submission_id - transfer_destination_id - transfer_id - vendor_id note: Canix ids are opaque integers with no type prefix; Metrc-facing records additionally carry Metrc tag/label strings. entities: - name: Address kind: resource properties: 7 - name: AuditedAction kind: resource properties: 10 returned_by: - GetAuditedActions - name: BillOfMaterials kind: resource properties: 9 returned_by: - GetBillOfMaterialsById - GetNonCannabisProductBOMs - name: BillOfMaterialsOutputItem kind: resource properties: 6 - name: BillOfMaterialsSourceCannabisItem kind: resource properties: 5 - name: BillOfMaterialsSourceNonCannabisProduct kind: resource properties: 5 - name: Brand kind: resource properties: 3 returned_by: - GetBrands - name: Company kind: resource properties: 4 returned_by: - GetCompanyById - name: CreateItemRequestBody kind: request-body properties: 26 - name: CreateMETRCItemFilesRequestBody kind: request-body properties: 2 - name: CreateMETRCItemPhotosRequestBody kind: request-body properties: 2 - name: CreateNonCannabisProductRequestBody kind: request-body properties: 20 - name: CreatePurchaseOrderRequestBody kind: request-body properties: 13 - name: CreateStrainRequestBody kind: request-body properties: 13 - name: CrossStrain kind: resource properties: 7 - name: Customer kind: resource properties: 18 returned_by: - GetCustomerById - name: CustomerExtended kind: resource properties: 0 returned_by: - GetCustomers - name: DestinationPackage kind: resource properties: 5 - name: Discount kind: resource properties: 3 - name: Facility kind: resource properties: 5 returned_by: - GetFacilities - GetFacilityById - name: Harvest kind: resource properties: 15 returned_by: - GetHarvestById - GetHarvests - name: IdName kind: resource properties: 2 - name: Item kind: resource properties: 45 returned_by: - CreateItem - GetItemById - GetItems - UpdateItem - name: ItemStandardCost kind: resource properties: 5 returned_by: - AddItemStandardCost - GetStandardCost - UpdateStandardCost - name: ItemStandardCostRequestBody kind: request-body properties: 3 - name: ItemSubType kind: resource properties: 5 returned_by: - GetItemSubTypes - name: ItemType kind: resource properties: 16 returned_by: - GetItemTypes - name: JobRequestBody kind: request-body properties: 3 - name: JobStatus kind: resource properties: 7 - name: LabTestInfo kind: resource properties: 2 - name: Labor kind: resource properties: 3 - name: Location kind: resource properties: 7 returned_by: - GetLocationById - GetLocations - name: Machine kind: resource properties: 7 - name: ManuBatch kind: resource properties: 11 returned_by: - GetManuBatchById - GetManuBatches - name: ManuBatchRun kind: resource properties: 22 returned_by: - GetManuBatchRunById - GetManuBatchRuns - name: ManuBatchRunCannabisInput kind: resource properties: 6 - name: ManuBatchRunCannabisOutput kind: resource properties: 4 - name: ManuBatchRunNonCannabisInput kind: resource properties: 7 - name: NonCannabisProduct kind: resource properties: 20 returned_by: - GetNonCannabisProductById - GetNonCannabisProducts - PostNonCannabisProduct - name: NonCannabisProductCategory kind: resource properties: 3 - name: NonCannabisProductStandardCosting kind: resource properties: 5 - name: Package kind: resource properties: 38 returned_by: - GetPackageById - GetPackages - name: PackageAdjustReason kind: resource properties: 2 - name: PackageAdjustment kind: resource properties: 8 - name: PackageAdjustmentRequestBody kind: request-body properties: 4 - name: PackageTransfer kind: resource properties: 8 - name: ParentLocation kind: resource properties: 6 - name: Plant kind: resource properties: 19 returned_by: - GetPlantById - GetPlants - name: PlantBatch kind: resource properties: 14 returned_by: - GetPlantBatchById - GetPlantBatches - name: Product kind: resource properties: 15 returned_by: - GetProductById - GetProducts - name: PurchaseOrder kind: resource properties: 20 returned_by: - GetPurchaseOrderById - GetPurchaseOrders - PostPurchaseOrder - name: PurchaseOrderItem kind: resource properties: 6 returned_by: - GetPurchaseOrderContentsById - name: PurchaseOrderItemRequestBody kind: request-body properties: 6 - name: PurchaseOrderPayment kind: resource properties: 2 returned_by: - GetpurchaseOrderPayments - name: RecordCount kind: resource properties: 1 returned_by: - GetLocationsCount - GetPlantsCount - name: SalesOrder kind: resource properties: 29 returned_by: - CreateSalesOrder - GetSalesOrderById - GetSalesOrders - UpdateSalesOrder - name: SalesOrderItem kind: resource properties: 14 returned_by: - GetSalesOrderContentsById - name: SalesOrderPayment kind: resource properties: 7 returned_by: - GetPaymentById - GetPayments - GetSalesOrderPayments - name: SalesOrderRequestBody kind: request-body properties: 21 - name: Sales_order_item kind: resource properties: 3 - name: SourcePackage kind: resource properties: 5 - name: StandardCostRequestBody kind: request-body properties: 3 - name: Strain kind: resource properties: 8 returned_by: - CreateStrain - GetStrainById - GetStrains - UpdateStrain - name: StrainRequestBody kind: request-body properties: 4 - name: Submission kind: resource properties: 8 returned_by: - GetSubmissionById - name: SubmissionStatus kind: resource properties: 0 - name: TestResultValue kind: resource properties: 2 - name: TestResults kind: resource properties: 24 - name: Transfer kind: resource properties: 7 returned_by: - GetTransferById - GetTransfers - name: TransferDestination kind: resource properties: 7 returned_by: - GetTransferDestinationById - GetTransferDestinations - name: UpdateItemRequestBody kind: request-body properties: 19 - name: User kind: resource properties: 3 - name: Vendor kind: resource properties: 18 returned_by: - CreateVendor - GetVendorById - GetVendors - UpdateVendor - name: VendorRequestBody kind: request-body properties: 15 - name: Waste kind: resource properties: 7 - name: WeightUnit kind: resource properties: 3 returned_by: - GetWeightUnits relationships: - from: AuditedAction kind: belongs_to to: Facility via: facility_id - from: SalesOrder kind: belongs_to to: Facility via: facility_id - from: SalesOrder kind: has_one to: Customer via: customer - from: SalesOrder kind: has_many to: SalesOrderPayment via: payments - from: SalesOrder kind: has_one to: Discount via: sales_order_credit - from: SalesOrder kind: has_many to: SalesOrderItem via: contents - from: SalesOrder kind: has_one to: User via: sales_representative - from: SalesOrderItem kind: has_one to: Sales_order_item via: item - from: SalesOrderItem kind: has_one to: IdName via: brand - from: SalesOrderItem kind: belongs_to to: Product via: product_id - from: SalesOrderItem kind: has_one to: IdName via: product_brand - from: SalesOrderItem kind: has_one to: Discount via: discount - from: SalesOrderPayment kind: belongs_to to: SalesOrder via: sales_order_id - from: Submission kind: has_one to: SubmissionStatus via: status - from: CreatePurchaseOrderRequestBody kind: belongs_to to: Facility via: facility_id - from: CreatePurchaseOrderRequestBody kind: belongs_to to: Vendor via: vendor_id - from: CreatePurchaseOrderRequestBody kind: has_many to: PurchaseOrderItemRequestBody via: purchase_order_items_attributes - from: PurchaseOrder kind: belongs_to to: Facility via: facility_id - from: PurchaseOrder kind: has_one to: Vendor via: vendor - from: PurchaseOrder kind: has_many to: PurchaseOrderPayment via: payments - from: PurchaseOrder kind: has_many to: PurchaseOrderItem via: contents - from: PurchaseOrderItemRequestBody kind: belongs_to to: Item via: item_id - from: PurchaseOrderItemRequestBody kind: belongs_to to: NonCannabisProduct via: non_cannabis_product_id - from: PurchaseOrderItemRequestBody kind: belongs_to to: WeightUnit via: weight_unit_id - from: PurchaseOrderItem kind: has_one to: Item via: item - from: PurchaseOrderItem kind: has_one to: NonCannabisProduct via: non_cannabis_product - from: Package kind: has_one to: Item via: item - from: Package kind: has_one to: Location via: location - from: Package kind: has_many to: SourcePackage via: source_packages - from: Package kind: has_many to: DestinationPackage via: destination_packages - from: Package kind: has_one to: Brand via: brand - from: Package kind: has_one to: TestResults via: test_results - from: Package kind: has_one to: LabTestInfo via: lab_test_info - from: SourcePackage kind: has_one to: IdName via: item - from: DestinationPackage kind: has_one to: IdName via: item - from: Customer kind: has_one to: Address via: address - from: Item kind: has_one to: IdName via: brand - from: Item kind: belongs_to to: Product via: product_id - from: Item kind: has_one to: IdName via: product_brand - from: Item kind: has_one to: ItemStandardCost via: current_standard_cost - from: Item kind: belongs_to to: Facility via: facility_id - from: Item kind: has_one to: Strain via: strain - from: Item kind: has_one to: ItemType via: type - from: Item kind: has_one to: ItemSubType via: sub_type - from: CreateMETRCItemPhotosRequestBody kind: belongs_to to: Facility via: facility_id - from: CreateMETRCItemFilesRequestBody kind: belongs_to to: Facility via: facility_id - from: ItemSubType kind: has_one to: ItemType via: category - from: Product kind: belongs_to to: Facility via: facility_id - from: Product kind: has_one to: ItemType via: type - from: Product kind: has_one to: ItemSubType via: sub_type - from: Product kind: has_one to: IdName via: brand - from: Product kind: has_one to: Strain via: strain - from: Strain kind: has_many to: CrossStrain via: cross_strains - from: Location kind: has_one to: ParentLocation via: parent_location - from: CreateNonCannabisProductRequestBody kind: belongs_to to: WeightUnit via: weight_unit_id - from: CreateNonCannabisProductRequestBody kind: belongs_to to: Facility via: facility_id - from: CreateNonCannabisProductRequestBody kind: belongs_to to: NonCannabisProductCategory via: non_cannabis_product_category_id - from: CreateNonCannabisProductRequestBody kind: belongs_to to: Location via: location_id - from: CreateNonCannabisProductRequestBody kind: belongs_to to: Brand via: brand_id - from: NonCannabisProduct kind: has_one to: Facility via: facilities - from: NonCannabisProduct kind: has_one to: NonCannabisProductCategory via: category - from: NonCannabisProduct kind: has_one to: Location via: location - from: NonCannabisProduct kind: has_one to: NonCannabisProductStandardCosting via: current_standard_costing - from: PlantBatch kind: has_one to: Strain via: strain - from: PlantBatch kind: has_one to: Location via: location - from: Plant kind: has_one to: PlantBatch via: plant_batch - from: Plant kind: has_one to: Strain via: strain - from: Plant kind: has_one to: Location via: location - from: Plant kind: has_one to: Harvest via: harvest - from: Harvest kind: has_one to: Strain via: strain - from: Harvest kind: has_one to: Location via: drying_location - from: Transfer kind: has_many to: TransferDestination via: destinations - from: Transfer kind: has_one to: SalesOrder via: sales_order - from: TransferDestination kind: has_many to: PackageTransfer via: contents - from: PackageTransfer kind: has_one to: Package via: package - from: Facility kind: has_one to: Address via: address - from: TestResults kind: has_many to: TestResultValue via: thc - from: TestResults kind: has_many to: TestResultValue via: cbd - from: TestResults kind: has_many to: TestResultValue via: cbn - from: TestResults kind: has_many to: TestResultValue via: cbg - from: TestResults kind: has_many to: TestResultValue via: cbga - from: TestResults kind: has_many to: TestResultValue via: cbc - from: TestResults kind: has_many to: TestResultValue via: cbca - from: TestResults kind: has_many to: TestResultValue via: cbda - from: TestResults kind: has_many to: TestResultValue via: thca - from: TestResults kind: has_many to: TestResultValue via: delta_8_thc - from: TestResults kind: has_many to: TestResultValue via: delta_9_thc - from: TestResults kind: has_many to: TestResultValue via: delta_9_thca - from: TestResults kind: has_many to: TestResultValue via: delta_8_thca - from: TestResults kind: has_many to: TestResultValue via: thcv - from: TestResults kind: has_many to: TestResultValue via: thcva - from: TestResults kind: has_many to: TestResultValue via: total_cbd - from: TestResults kind: has_many to: TestResultValue via: total_cbg - from: TestResults kind: has_many to: TestResultValue via: total_delta_9_thc - from: TestResults kind: has_many to: TestResultValue via: total_thc - from: TestResults kind: has_many to: TestResultValue via: total_cannabinoid - from: ManuBatchRun kind: belongs_to to: Facility via: facility_id - from: ManuBatchRun kind: belongs_to to: Location via: location_id - from: ManuBatchRun kind: belongs_to to: BillOfMaterials via: bill_of_materials_id - from: ManuBatchRun kind: has_one to: Machine via: machine_info - from: ManuBatchRun kind: has_many to: ManuBatchRunCannabisInput via: cannabis_inputs - from: ManuBatchRun kind: has_many to: ManuBatchRunNonCannabisInput via: non_cannabis_inputs - from: ManuBatchRun kind: has_many to: ManuBatchRunCannabisOutput via: cannabis_outputs - from: ManuBatchRun kind: has_many to: Labor via: labors - from: ManuBatchRun kind: has_many to: Waste via: wastes - from: ManuBatchRunCannabisInput kind: belongs_to to: Package via: package_id - from: ManuBatchRunNonCannabisInput kind: belongs_to to: NonCannabisProduct via: non_cannabis_product_id - from: ManuBatchRunCannabisOutput kind: belongs_to to: Package via: package_id - from: Waste kind: belongs_to to: Package via: package_id - from: BillOfMaterials kind: has_many to: BillOfMaterialsSourceNonCannabisProduct via: source_non_cannabis_products - from: BillOfMaterials kind: has_many to: BillOfMaterialsSourceCannabisItem via: source_cannabis_items - from: BillOfMaterials kind: has_many to: BillOfMaterialsOutputItem via: output_items - from: BillOfMaterialsSourceNonCannabisProduct kind: belongs_to to: NonCannabisProduct via: non_cannabis_product_id - from: BillOfMaterialsOutputItem kind: belongs_to to: Item via: item_id - from: CreateItemRequestBody kind: belongs_to to: Strain via: strain_id - from: CreateItemRequestBody kind: belongs_to to: ItemType via: item_type_id - from: CreateItemRequestBody kind: belongs_to to: ItemSubType via: item_sub_type_id - from: CreateItemRequestBody kind: belongs_to to: Brand via: brand_id - from: UpdateItemRequestBody kind: belongs_to to: Brand via: brand_id - from: JobRequestBody kind: belongs_to to: Facility via: facility_id - from: SalesOrderRequestBody kind: belongs_to to: Customer via: customer_id - from: SalesOrderRequestBody kind: has_one to: Discount via: sales_order_credit - from: SalesOrderRequestBody kind: has_many to: Discount via: contents - from: CreateStrainRequestBody kind: belongs_to to: Facility via: facility_id - from: PackageAdjustment kind: has_one to: PackageAdjustReason via: reason - from: PackageAdjustment kind: has_one to: Package via: package