generated: '2026-08-22' method: derived source: openapi/happy-cabbage-analytics-happy-buyers-external-openapi.yml note: Entity graph derived from the 49 component schemas and their $ref links plus *Id/*Ids reference fields in the Happy Buyers External API contract. The API has no published object reference page and no id-prefix scheme; identifiers are opaque integers/UUIDs per resource. LimitOffsetResponse* wrappers are the pagination envelope, not domain entities. core_entities: - StoreResponse - ProductDetailResponse - ProductInventoryResponse - ProductLineDetailResponse - ProductLineInventoryResponse - PackageResponse - OrderResponse - OrderItemResponse - OrderInvoiceResponse - PosBrandResponse - PosCategoryResponse - UniversalBrandResponse - UniversalCategoryResponse - BlockoutDateResponse - DailySalesMetadataResponse - IdentityResponse pagination_envelope: schema_prefix: LimitOffsetResponse fields: - limit - offset - totalCount - results - hasMore entity_count: 49 relationship_count: 64 entities: - name: ProductLineUpdateRequest fields: 11 field_names: - autoDemandGroupCreateLogId - autoRunDays - desiredDaysOnHand - isFavorite - leadTime - lookbackPeriod - minimumOrderQuantityDefault - name - productQueryParams - reportEmailTargetDefaults - targetProductDepth - name: ProductQueryParams fields: 24 field_names: - activeInLastDays - includePosSubUncategorized - includePosUncategorized - includeUniversalUncategorized - limit - matchingSearchTerms - maxCost - maxPrice - maxWeight - minCost - minPrice - minWeight - notMatchingSearchTerms - offset - posBrandIds - posCategoryIds - posSubCategoryIds - restockOnly - sortDirection - sortTarget - strainClassificationIds - universalBrandIds - universalCategoryIds - vendorIds - name: ProductLineDetailResponse fields: 14 field_names: - desiredDaysOnHand - id - leadTime - lookbackPeriod - minimumOrderQuantity - name - posBrandId - posBrandName - productQueryParams - targetProductDepth - universalBrandId - universalBrandName - universalCategoryId - universalCategoryLabel - name: CarryStatusUpdateRequest fields: 1 field_names: - continueToCarry - name: CarryStatusUpdateResponse fields: 3 field_names: - continueToCarry - productId - storeId - name: OrderItemAddRequest fields: 15 field_names: - customCaseSize - customName - customPosBrandId - customUniversalCategoryId - desiredDaysOnHand - leadTime - lookbackPeriod - note - productId - productLineId - quantity - storeId - strainsNeeded - targetProductDepth - unitCost - name: OrderItemResponse fields: 31 field_names: - addedAt - categoryId - categoryLabel - currentHybridDepth - currentIndicaDepth - currentProductDepth - currentSativaDepth - desiredDaysOnHand - distributionFulfilmentStatus - id - itemType - itemUnitCost - itemUnitCostCartOverride - lookbackPeriod - name - note - orderQuantity - posBrandId - posBrandName - predictedDaysOnHand - productId - productLineId - quantity - storeId - storeName - strainsNeeded - targetProductDepth - unitsAtDistribution - unitsNeeded - universalBrandId - universalBrandName - name: OrderInvoiceUpdateRequest fields: 2 field_names: - filename - name - name: OrderInvoiceResponse fields: 6 field_names: - createdAt - filename - id - name - orderId - updatedAt - name: UpdateRequest fields: 4 field_names: - description - id - name - note - name: OrderResponse fields: 10 field_names: - createdAt - createdByUserFirstName - createdByUserId - createdByUserLastName - description - id - name - note - orderNumber - status - name: BlockoutDateRequest fields: 9 field_names: - description - endDate - isAllStores - isRecurring - name - posBrandIds - startDate - storeIds - universalCategoryIds - name: BlockoutDateResponse fields: 12 field_names: - createdAt - description - endDate - id - isAllStores - isRecurring - name - posBrandIds - startDate - storeIds - universalCategoryIds - updatedAt - name: ProductLineCreateRequest fields: 10 field_names: - autoRunDays - desiredDaysOnHand - isFavorite - leadTime - lookbackPeriod - minimumOrderQuantityDefault - name - productQueryParams - reportEmailTargetDefaults - targetProductDepth - name: CreateRequest fields: 3 field_names: - description - name - note - name: OrderInvoiceCreateRequest fields: 2 field_names: - filename - name - name: OrderInvoiceUrlRequest fields: 1 field_names: - durationSeconds - name: IdentityResponse fields: 4 field_names: - keyCreatedAt - keyName - organizationCreatedAt - organizationName - name: LimitOffsetResponseUniversalCategoryResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: UniversalCategoryResponse fields: 3 field_names: - id - label - name - name: LimitOffsetResponseUniversalBrandResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: UniversalBrandResponse fields: 3 field_names: - id - name - productCount - name: LimitOffsetResponseStoreResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: StoreResponse fields: 7 field_names: - createdAt - fulfilledById - fulfilledByStoreName - id - name - stateCode - type - name: LimitOffsetResponseProductLineDetailResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: LimitOffsetResponseProductInventoryResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: ProductDetailResponse fields: 21 field_names: - caseSize - id - name - posBrandId - posBrandName - posCategoryId - posCategoryLabel - posIdentifier - posSubCategoryId - posSubCategoryLabel - sku - strainClassificationId - strainClassificationLabel - strainFamily - universalBrandId - universalBrandName - universalCategoryId - universalCategoryLabel - vendorId - vendorName - weight - name: ProductInventoryResponse fields: 35 field_names: - agedInventoryCost - averageDiscountPercent - averageMargin - averageThcPercentageOnHand - averageThcPercentageSold - continueToCarry - currentInventory - daysOutOfStock - discountDollars - distributionFulfillmentStatus - dollarsSold - estimatedProfit - firstSold - inventoryCost - lastActivity - lastSold - medPrice - predictedDaysOnHand - productDetail - recPrice - sellableInventory - sellableUnitsOnHand - storeId - storeName - unitCost - unitPrice - unitsAged0To30 - unitsAged31To60 - unitsAged61To90 - unitsAged90Plus - unitsAtDistro - unitsNeeded - unitsPerDay - unitsSold - unitsToOrder - name: LimitOffsetResponseProductLineInventoryResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: ProductLineInventoryResponse fields: 29 field_names: - agedInventoryCost - averageDiscountPercent - averageMarginPercent - averageThcPercentageOnHand - averageThcPercentageSold - currentDepth - currentInventory - dollarsSold - estimatedProfit - hybridProductDepth - indicaProductDepth - inventoryCost - predictedDaysOnHand - productLineDetail - productLineId - reportRunAt - sativaProductDepth - status - storeId - storeName - targetProductDepth - unitsAged0To30 - unitsAged31To60 - unitsAged61To90 - unitsAged90Plus - unitsAtDistro - unitsNeeded - unitsPerDay - unitsSold - name: LimitOffsetResponsePackageResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: PackageResponse fields: 26 field_names: - barcode - currentInventory - daysAged - id - lastActivityAt - posAddedAt - posBrandId - posBrandName - posCategoryId - posCategoryLabel - posCreatedAt - posId - posSubCategoryId - posSubCategoryLabel - posUnitCost - productId - productName - receivedAt - regulatoryId - storeId - storeName - thcPercentage - universalBrandId - universalBrandName - universalCategoryId - universalCategoryLabel - name: LimitOffsetResponsePosCategoryResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: PosCategoryResponse fields: 7 field_names: - isSubCategory - label - mappedCategoryId - mappedCategoryLabel - mappedCategoryName - name - posIdentifier - name: LimitOffsetResponsePosBrandResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: PosBrandResponse fields: 6 field_names: - id - mappedUniversalBrandId - mappedUniversalBrandName - name - posIdentifier - productCount - name: LimitOffsetResponseOrderResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: LimitOffsetResponseOrderItemResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: LimitOffsetResponseOrderInvoiceResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: LimitOffsetResponseStoreHistoryResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: StoreHistoryResponse fields: 27 field_names: - agedInventoryCost - averageDiscountPercent - averageMargin - createdAt - discountDollars - dollarsSold - endDate - inventoryCost - percentShareOfAgedInventoryCost - percentShareOfDollarsSold - percentShareOfProfit - percentShareOfUnitsSold - periodType - predictedDaysOnHand - sellableUnitsInStock - startDate - storeId - storeName - totalProfit - unitsAged0To30 - unitsAged31To60 - unitsAged61To90 - unitsAged90Plus - unitsInStock - unitsPerDay - unitsSold - updatedAt - name: LimitOffsetResponsePosBrandHistoryResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: PosBrandHistoryResponse fields: 29 field_names: - agedInventoryCost - averageDiscountPercent - averageMargin - createdAt - discountDollars - dollarsSold - endDate - inventoryCost - percentShareOfAgedInventoryCost - percentShareOfDollarsSold - percentShareOfProfit - percentShareOfUnitsSold - periodType - posBrandId - posBrandName - predictedDaysOnHand - sellableUnitsInStock - startDate - storeId - storeName - totalProfit - unitsAged0To30 - unitsAged31To60 - unitsAged61To90 - unitsAged90Plus - unitsInStock - unitsPerDay - unitsSold - updatedAt - name: CategoryResponse fields: 26 field_names: - agedInventoryCost - averageDiscountPercent - averageMargin - categoryId - categoryName - createdAt - discountDollars - dollarsSold - inventoryCost - percentShareOfAgedInventoryCost - percentShareOfDollarsSold - percentShareOfProfit - percentShareOfUnitsSold - predictedDaysOnHand - sellableUnitsInStock - storeId - storeName - totalProfit - unitsAged0To30 - unitsAged31To60 - unitsAged61To90 - unitsAged90Plus - unitsInStock - unitsPerDay - unitsSold - updatedAt - name: LimitOffsetResponseCategoryResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: CategoryHistoryResponse fields: 29 field_names: - agedInventoryCost - averageDiscountPercent - averageMargin - categoryId - categoryName - createdAt - discountDollars - dollarsSold - endDate - inventoryCost - percentShareOfAgedInventoryCost - percentShareOfDollarsSold - percentShareOfProfit - percentShareOfUnitsSold - periodType - predictedDaysOnHand - sellableUnitsInStock - startDate - storeId - storeName - totalProfit - unitsAged0To30 - unitsAged31To60 - unitsAged61To90 - unitsAged90Plus - unitsInStock - unitsPerDay - unitsSold - updatedAt - name: LimitOffsetResponseCategoryHistoryResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount - name: DailySalesMetadataResponse fields: 7 field_names: - day - discountDollars - dollarsSold - inStockAtEndOfDay - quantitySoldWithTHCPercentage - thcPercentageSold - unitsSold - name: LimitOffsetResponseBlockoutDateResponse fields: 5 field_names: - hasMore - limit - offset - results - totalCount relationships: - from: ProductLineUpdateRequest to: ProductQueryParams kind: has_one via: productQueryParams - from: ProductQueryParams to: UniversalCategoryResponse kind: belongs_to via: universalCategoryIds - from: ProductQueryParams to: PosCategoryResponse kind: belongs_to via: posCategoryIds - from: ProductQueryParams to: UniversalBrandResponse kind: belongs_to via: universalBrandIds - from: ProductQueryParams to: PosBrandResponse kind: belongs_to via: posBrandIds - from: ProductLineDetailResponse to: UniversalBrandResponse kind: belongs_to via: universalBrandId - from: ProductLineDetailResponse to: UniversalCategoryResponse kind: belongs_to via: universalCategoryId - from: ProductLineDetailResponse to: PosBrandResponse kind: belongs_to via: posBrandId - from: ProductLineDetailResponse to: ProductQueryParams kind: has_one via: productQueryParams - from: CarryStatusUpdateResponse to: ProductDetailResponse kind: belongs_to via: productId - from: CarryStatusUpdateResponse to: StoreResponse kind: belongs_to via: storeId - from: OrderItemAddRequest to: ProductDetailResponse kind: belongs_to via: productId - from: OrderItemAddRequest to: ProductLineDetailResponse kind: belongs_to via: productLineId - from: OrderItemAddRequest to: StoreResponse kind: belongs_to via: storeId - from: OrderItemResponse to: ProductDetailResponse kind: belongs_to via: productId - from: OrderItemResponse to: UniversalBrandResponse kind: belongs_to via: universalBrandId - from: OrderItemResponse to: PosBrandResponse kind: belongs_to via: posBrandId - from: OrderItemResponse to: StoreResponse kind: belongs_to via: storeId - from: OrderItemResponse to: ProductLineDetailResponse kind: belongs_to via: productLineId - from: OrderInvoiceResponse to: OrderResponse kind: belongs_to via: orderId - from: BlockoutDateRequest to: StoreResponse kind: belongs_to via: storeIds - from: BlockoutDateRequest to: PosBrandResponse kind: belongs_to via: posBrandIds - from: BlockoutDateRequest to: UniversalCategoryResponse kind: belongs_to via: universalCategoryIds - from: BlockoutDateResponse to: StoreResponse kind: belongs_to via: storeIds - from: BlockoutDateResponse to: PosBrandResponse kind: belongs_to via: posBrandIds - from: BlockoutDateResponse to: UniversalCategoryResponse kind: belongs_to via: universalCategoryIds - from: ProductLineCreateRequest to: ProductQueryParams kind: has_one via: productQueryParams - from: LimitOffsetResponseUniversalCategoryResponse to: UniversalCategoryResponse kind: has_many via: results - from: LimitOffsetResponseUniversalBrandResponse to: UniversalBrandResponse kind: has_many via: results - from: LimitOffsetResponseStoreResponse to: StoreResponse kind: has_many via: results - from: LimitOffsetResponseProductLineDetailResponse to: ProductLineDetailResponse kind: has_many via: results - from: LimitOffsetResponseProductInventoryResponse to: ProductInventoryResponse kind: has_many via: results - from: ProductDetailResponse to: UniversalBrandResponse kind: belongs_to via: universalBrandId - from: ProductDetailResponse to: PosCategoryResponse kind: belongs_to via: posCategoryId - from: ProductDetailResponse to: UniversalCategoryResponse kind: belongs_to via: universalCategoryId - from: ProductDetailResponse to: PosBrandResponse kind: belongs_to via: posBrandId - from: ProductInventoryResponse to: StoreResponse kind: belongs_to via: storeId - from: ProductInventoryResponse to: ProductDetailResponse kind: has_one via: productDetail - from: LimitOffsetResponseProductLineInventoryResponse to: ProductLineInventoryResponse kind: has_many via: results - from: ProductLineInventoryResponse to: StoreResponse kind: belongs_to via: storeId - from: ProductLineInventoryResponse to: ProductLineDetailResponse kind: has_one via: productLineDetail - from: ProductLineInventoryResponse to: ProductLineDetailResponse kind: belongs_to via: productLineId - from: LimitOffsetResponsePackageResponse to: PackageResponse kind: has_many via: results - from: PackageResponse to: ProductDetailResponse kind: belongs_to via: productId - from: PackageResponse to: UniversalBrandResponse kind: belongs_to via: universalBrandId - from: PackageResponse to: PosCategoryResponse kind: belongs_to via: posCategoryId - from: PackageResponse to: UniversalCategoryResponse kind: belongs_to via: universalCategoryId - from: PackageResponse to: PosBrandResponse kind: belongs_to via: posBrandId - from: PackageResponse to: StoreResponse kind: belongs_to via: storeId - from: LimitOffsetResponsePosCategoryResponse to: PosCategoryResponse kind: has_many via: results - from: LimitOffsetResponsePosBrandResponse to: PosBrandResponse kind: has_many via: results - from: LimitOffsetResponseOrderResponse to: OrderResponse kind: has_many via: results - from: LimitOffsetResponseOrderItemResponse to: OrderItemResponse kind: has_many via: results - from: LimitOffsetResponseOrderInvoiceResponse to: OrderInvoiceResponse kind: has_many via: results - from: LimitOffsetResponseStoreHistoryResponse to: StoreHistoryResponse kind: has_many via: results - from: StoreHistoryResponse to: StoreResponse kind: belongs_to via: storeId - from: LimitOffsetResponsePosBrandHistoryResponse to: PosBrandHistoryResponse kind: has_many via: results - from: PosBrandHistoryResponse to: PosBrandResponse kind: belongs_to via: posBrandId - from: PosBrandHistoryResponse to: StoreResponse kind: belongs_to via: storeId - from: CategoryResponse to: StoreResponse kind: belongs_to via: storeId - from: LimitOffsetResponseCategoryResponse to: CategoryResponse kind: has_many via: results - from: CategoryHistoryResponse to: StoreResponse kind: belongs_to via: storeId - from: LimitOffsetResponseCategoryHistoryResponse to: CategoryHistoryResponse kind: has_many via: results - from: LimitOffsetResponseBlockoutDateResponse to: BlockoutDateResponse kind: has_many via: results