openapi: 3.2.0 info: title: Happy Buyers External Packages API description: 'External API for Happy Buyers organization metadata and inventory data. Requests are authenticated with an API key in the hca-api-key header. Results are scoped to the organization attached to that key. List endpoints use limit/offset pagination and return totalCount plus hasMore. ' version: v1 servers: - url: https://api.happycabbage.ai description: External API security: - ApiKeyAuth: [] tags: - name: Packages description: Package-level product inventory paths: /external/v1/product-inventory/packages: get: tags: - Packages summary: List packages description: Returns package-level product inventory for the API key organization. Requires inventory:read. operationId: findPackages parameters: - name: limit in: query description: Maximum number of packages to return. Maximum is 500. required: false schema: maximum: 500 minimum: 0 type: integer format: int32 default: 100 example: 100 - name: offset in: query description: Zero-based result offset for pagination. required: false schema: minimum: 0 type: integer format: int32 default: 0 example: 0 - name: search in: query description: Package search text matched against product name, POS package ID, and regulatory ID. required: false schema: type: string example: blue - name: storeIds in: query description: Store UUID filters. Pass repeated query parameters, for example storeIds=id1&storeIds=id2. required: false schema: type: array items: type: string format: uuid example: 11111111-1111-1111-1111-111111111111 - name: universalCategoryIds in: query description: Universal category ID filters, passed as repeated query parameters. required: false schema: type: array items: type: integer format: int32 example: 12 - name: posCategoryIds in: query description: POS category ID filters, passed as repeated query parameters. required: false schema: type: array items: type: integer format: int32 example: 34 - name: posSubCategoryIds in: query description: POS subcategory ID filters, passed as repeated query parameters. required: false schema: type: array items: type: integer format: int32 example: 56 - name: universalBrandIds in: query description: Universal brand ID filters, passed as repeated query parameters. required: false schema: type: array items: type: integer format: int32 example: 90 - name: posBrandIds in: query description: POS brand ID filters, passed as repeated query parameters. required: false schema: type: array items: type: integer format: int32 example: 42 - name: hasUniversalCategory in: query description: Filter by mapped universal category presence. Use false to return packages without a mapped universal category. required: false schema: type: boolean example: true - name: hasPosCategory in: query description: Filter by POS category presence. Use false to return packages without a POS category. required: false schema: type: boolean example: true - name: hasPosSubCategory in: query description: Filter by POS subcategory presence. Use false to return packages without a POS subcategory. required: false schema: type: boolean example: true - name: minDaysAged in: query description: Minimum package age in days. required: false schema: minimum: 0 type: integer format: int32 example: 30 - name: maxDaysAged in: query description: Maximum package age in days. required: false schema: minimum: 0 type: integer format: int32 example: 90 - name: receivedAtStart in: query description: Earliest package received timestamp, inclusive. required: false schema: type: string format: date-time - name: receivedAtEnd in: query description: Latest package received timestamp, exclusive. required: false schema: type: string format: date-time - name: minCurrentInventory in: query description: Minimum current package inventory units. required: false schema: minimum: 0 type: integer format: int32 example: 1 - name: maxCurrentInventory in: query description: Maximum current package inventory units. required: false schema: minimum: 0 type: integer format: int32 example: 100 - name: sortTarget in: query description: Field to sort by. required: false schema: type: string enum: - DAYS_AGED - RECEIVED_AT - CURRENT_INVENTORY - LAST_ACTIVITY_AT example: LAST_ACTIVITY_AT - name: sortDirection in: query description: Sort direction. Prefer ASC or DESC; lowercase values are deprecated aliases. required: false schema: type: string enum: - asc - desc - ASC - DESC - ASC_NULLS_FIRST - ASC_NULLS_LAST - DESC_NULLS_FIRST - DESC_NULLS_LAST example: DESC - name: isInStock in: query description: When true, only packages with inventory on hand are returned. required: false schema: type: boolean example: true responses: '200': description: Paged package inventory results content: application/json: schema: $ref: '#/components/schemas/LimitOffsetResponsePackageResponse' '403': description: API key does not include inventory:read '401': description: Missing, malformed, or invalid API key '400': description: Invalid query parameter components: schemas: PackageResponse: type: object properties: posId: type: string description: Package identifier from the POS. id: type: integer description: Internal package row ID. format: int64 example: 12345 posAddedAt: type: string description: Timestamp when the package was added in the POS, when available. format: date-time posCreatedAt: type: string description: Timestamp when the package was created in the POS, when available. format: date-time productId: type: integer description: Internal product ID associated with the package. format: int32 example: 987 universalBrandId: type: integer description: Mapped universal brand ID, when available. format: int32 universalBrandName: type: string description: Mapped universal brand name, when available. posCategoryId: type: integer description: POS category ID, when available. format: int32 posCategoryLabel: type: string description: POS category label, when available. posSubCategoryId: type: integer description: POS subcategory ID, when available. format: int32 posSubCategoryLabel: type: string description: POS subcategory label, when available. lastActivityAt: type: string description: Most recent product stock activity timestamp, when available. format: date-time productName: type: string description: Product display name. barcode: type: string description: Package barcode, when available. daysAged: type: integer description: Package age in days, when available. format: int32 example: 42 receivedAt: type: string description: Timestamp when the package was received, when available. format: date-time regulatoryId: type: string description: Regulatory package identifier, when available. posUnitCost: type: number description: POS unit cost for this package, when available. format: double thcPercentage: type: number description: THC percentage for this package, when available. format: double universalCategoryId: type: integer description: Mapped universal category ID, when available. format: int32 universalCategoryLabel: type: string description: Mapped universal category label, when available. posBrandId: type: integer description: POS brand ID, when available. format: int32 posBrandName: type: string description: POS brand name, when available. currentInventory: type: integer description: Current package inventory units. format: int32 example: 24 storeName: type: string description: Store/location display name for this package. storeId: type: string description: Store/location UUID for this package. format: uuid description: Records for the current page. LimitOffsetResponsePackageResponse: type: object properties: limit: type: integer description: Maximum number of records requested for this page. format: int32 example: 100 offset: type: integer description: Zero-based result offset used for this page. format: int32 example: 0 totalCount: type: integer description: Total number of matching records before pagination is applied. format: int32 example: 250 results: type: array description: Records for the current page. items: $ref: '#/components/schemas/PackageResponse' hasMore: type: boolean description: True when more records are available after this page. example: true securitySchemes: ApiKeyAuth: type: apiKey description: External API key issued by Happy Buyers. Send the key in the hca-api-key header. name: hca-api-key in: header