openapi: 3.2.0 info: title: Happy Buyers External Orders 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: Orders description: Orders paths: /external/v1/orders/{orderId}/items: get: tags: - Orders summary: List order items description: Returns product and product-line items for an order in the API key organization. Requires `orders:read`. operationId: getOrderItems parameters: - name: orderId in: path required: true schema: type: integer format: int32 - name: limit in: query description: Maximum records to return. Defaults to `100`. required: false schema: maximum: 500 minimum: 0 type: string description: Maximum records to return. Defaults to `100`. default: '100' - name: offset in: query description: Zero-based record offset. Defaults to `0`. required: false schema: minimum: 0 type: string description: Zero-based record offset. Defaults to `0`. default: '0' - name: sortTarget in: query description: Field used to sort order items. required: false schema: type: string description: Field used to sort order items. - name: sortDirection in: query description: Sort direction. Defaults to `ASC`. required: false schema: type: string description: Sort direction. Defaults to `ASC`. default: ASC responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/LimitOffsetResponseOrderItemResponse' put: tags: - Orders summary: Add order item description: Adds a product, product-line, or custom item to an order. Requires `orders:write`. operationId: addOrderItem parameters: - name: orderId in: path required: true schema: type: integer format: int32 requestBody: content: application/json: schema: $ref: '#/components/schemas/OrderItemAddRequest' required: true responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/OrderItemResponse' /external/v1/orders/{orderId}/invoices/{invoiceId}: get: tags: - Orders summary: Get order invoice description: Returns invoice metadata for an order in the API key organization. Requires `orders:read`. operationId: getOrderInvoice parameters: - name: orderId in: path required: true schema: type: integer format: int32 - name: invoiceId in: path required: true schema: type: integer format: int32 responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/OrderInvoiceResponse' put: tags: - Orders summary: Update order invoice description: Updates invoice metadata for an order in the API key organization. Requires `orders:write`. operationId: updateOrderInvoice parameters: - name: orderId in: path required: true schema: type: integer format: int32 - name: invoiceId in: path required: true schema: type: integer format: int32 requestBody: content: application/json: schema: $ref: '#/components/schemas/OrderInvoiceUpdateRequest' required: true responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/OrderInvoiceResponse' delete: tags: - Orders summary: Remove order invoice description: Removes invoice metadata and its file from an order in the API key organization. Requires `orders:write`. operationId: removeOrderInvoice parameters: - name: orderId in: path required: true schema: type: integer format: int32 - name: invoiceId in: path required: true schema: type: integer format: int32 responses: '200': description: OK content: application/json: schema: type: object /external/v1/orders/{id}: put: tags: - Orders summary: Update an order description: Updates order metadata for the API key organization. Requires `orders:write`. operationId: updateOrder parameters: - name: id in: path required: true schema: type: integer format: int32 requestBody: content: application/json: schema: $ref: '#/components/schemas/UpdateRequest' required: true responses: '404': description: Order not found '400': description: Invalid request body '401': description: Missing, malformed, or invalid API key '403': description: API key does not include orders:write '200': description: Updated order content: application/json: schema: $ref: '#/components/schemas/OrderResponse' /external/v1/orders: get: tags: - Orders summary: List orders description: Returns `DRAFT`, `READY_TO_SEND`, `SUBMITTED`, and `RECEIVED` orders for the API key organization. Requires `orders:read`. operationId: getOrders parameters: - name: limit in: query description: Maximum records to return. Defaults to `100`. required: false schema: maximum: 500 minimum: 0 type: string description: Maximum records to return. Defaults to `100`. default: '100' - name: offset in: query description: Zero-based record offset. Defaults to `0`. required: false schema: minimum: 0 type: string description: Zero-based record offset. Defaults to `0`. default: '0' - name: sortTarget in: query description: Field used to sort orders. `CREATED_AT` sorts by order creation time. required: false schema: type: string description: Field used to sort orders. `CREATED_AT` sorts by order creation time. - name: sortDirection in: query description: Sort direction. Defaults to `DESC`. required: false schema: type: string description: Sort direction. Defaults to `DESC`. default: DESC - name: universalBrandId in: query description: Only return orders containing products for this universal brand id. required: false schema: type: string description: Only return orders containing products for this universal brand id. - name: status in: query description: Only return orders with this status, including `DRAFT`. required: false schema: type: string description: Only return orders with this status, including `DRAFT`. - name: createdAtFrom in: query description: Minimum inclusive order `createdAt` timestamp. required: false schema: type: string description: Minimum inclusive order `createdAt` timestamp. - name: createdAtUntil in: query description: Maximum exclusive order `createdAt` timestamp. required: false schema: type: string description: Maximum exclusive order `createdAt` timestamp. - name: includeArchived in: query description: Include archived orders. Defaults to `false`. required: false schema: type: string description: Include archived orders. Defaults to `false`. default: 'false' responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/LimitOffsetResponseOrderResponse' post: tags: - Orders summary: Create an order description: Creates a `DRAFT` order for the API key organization. Requires `orders:write`. operationId: createOrder requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateRequest' required: true responses: '200': description: Created order content: application/json: schema: $ref: '#/components/schemas/OrderResponse' '400': description: Invalid request body '401': description: Missing, malformed, or invalid API key '403': description: API key does not include orders:write /external/v1/orders/{orderId}/invoices: get: tags: - Orders summary: List order invoices description: Returns invoice metadata for an order in the API key organization. Requires `orders:read`. operationId: getOrderInvoices parameters: - name: orderId in: path required: true schema: type: integer format: int32 - name: limit in: query description: Maximum records to return. Defaults to `100`. required: false schema: maximum: 500 minimum: 0 type: string description: Maximum records to return. Defaults to `100`. default: '100' - name: offset in: query description: Zero-based record offset. Defaults to `0`. required: false schema: minimum: 0 type: string description: Zero-based record offset. Defaults to `0`. default: '0' - name: sortTarget in: query description: Field used to sort invoices. required: false schema: type: string description: Field used to sort invoices. - name: sortDirection in: query description: Sort direction. Defaults to `DESC`. required: false schema: type: string description: Sort direction. Defaults to `DESC`. default: DESC - name: search in: query description: Search text matched against invoice name and filename. required: false schema: type: string description: Search text matched against invoice name and filename. responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/LimitOffsetResponseOrderInvoiceResponse' post: tags: - Orders summary: Add order invoice description: Adds invoice metadata to an order in the API key organization. Requires `orders:write`. operationId: addOrderInvoice parameters: - name: orderId in: path required: true schema: type: integer format: int32 requestBody: content: application/json: schema: $ref: '#/components/schemas/OrderInvoiceCreateRequest' required: true responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/OrderInvoiceResponse' /external/v1/orders/{orderId}/invoices/{invoiceId}/upload-url: post: tags: - Orders summary: Generate order invoice upload URL description: Generates a temporary upload URL for an order invoice in the API key organization. Requires `orders:write`. operationId: generateTemporaryUploadUrl parameters: - name: orderId in: path required: true schema: type: integer format: int32 - name: invoiceId in: path required: true schema: type: integer format: int32 requestBody: content: application/json: schema: $ref: '#/components/schemas/OrderInvoiceUrlRequest' required: true responses: '200': description: OK content: application/json: schema: type: string /external/v1/orders/{orderId}/invoices/{invoiceId}/download-url: post: tags: - Orders summary: Generate order invoice download URL description: Generates a temporary download URL for an order invoice in the API key organization. Requires `orders:read`. operationId: generateTemporaryDownloadUrl parameters: - name: orderId in: path required: true schema: type: integer format: int32 - name: invoiceId in: path required: true schema: type: integer format: int32 requestBody: content: application/json: schema: $ref: '#/components/schemas/OrderInvoiceUrlRequest' required: true responses: '200': description: OK content: application/json: schema: type: string /external/v1/orders/{orderId}/items/{itemId}/store/{storeId}: delete: tags: - Orders summary: Remove order item description: Removes an item from an order. Requires `orders:write`. operationId: removeOrderItem parameters: - name: orderId in: path required: true schema: type: integer format: int32 - name: itemId in: path required: true schema: type: integer format: int64 - name: storeId in: path required: true schema: type: string format: uuid responses: '200': description: OK content: application/json: schema: type: object components: schemas: LimitOffsetResponseOrderInvoiceResponse: 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/OrderInvoiceResponse' hasMore: type: boolean description: True when more records are available after this page. example: true OrderInvoiceUrlRequest: type: object properties: durationSeconds: maximum: 604800 minimum: 1 type: integer description: Temporary URL duration in seconds. Defaults to service configuration. format: int32 description: Request body for generating a temporary invoice file URL. OrderItemAddRequest: required: - storeId type: object properties: productId: type: integer description: Product `id` when adding an individual product. format: int32 example: 123 productLineId: type: integer description: Product-line `id` when adding a product-line item. format: int32 example: 456 storeId: type: string description: Store/location `UUID` for the item. format: uuid quantity: minimum: 0 type: integer description: Quantity explicitly placed on the order item. format: int32 example: 10 desiredDaysOnHand: minimum: 0 type: integer description: Target days on hand used for order calculations. format: int32 example: 14 leadTime: minimum: 0 type: integer description: Lead time in days used for order calculations. format: int32 example: 2 lookbackPeriod: minimum: 0 type: integer description: Lookback period in days used for demand calculations. format: int32 example: 30 unitCost: minimum: 0 type: number description: Order item unit cost override. format: double example: 12.5 strainsNeeded: minimum: 0 type: integer description: Strains needed override for product-line items. format: int32 example: 4 note: type: string description: Optional order item note. customName: type: string description: Custom item name, required when adding a custom item. customPosBrandId: type: integer description: '`POS` brand `id` for a custom item.' format: int32 example: 12 customUniversalCategoryId: type: integer description: '`Universal` category `id` for a custom item.' format: int32 example: 34 customCaseSize: minimum: 1 type: integer description: Custom item case size. format: int32 example: 6 targetProductDepth: minimum: 0 type: integer description: Target product depth for product-line items. format: int32 example: 8 description: Request body for adding an item to an order. LimitOffsetResponseOrderResponse: 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/OrderResponse' hasMore: type: boolean description: True when more records are available after this page. example: true OrderInvoiceCreateRequest: required: - filename type: object properties: name: type: string description: Optional invoice display name. filename: type: string description: Invoice filename. example: invoice.pdf description: Request body for adding an invoice to an order. CreateRequest: type: object properties: note: type: string name: type: string description: type: string UpdateRequest: type: object properties: id: type: integer format: int32 note: type: string name: type: string description: type: string LimitOffsetResponseOrderItemResponse: 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/OrderItemResponse' hasMore: type: boolean description: True when more records are available after this page. example: true OrderInvoiceResponse: type: object properties: name: type: string description: Optional invoice display name. id: type: integer description: Invoice `id`. format: int32 filename: type: string description: Invoice filename. createdAt: type: string description: Timestamp the invoice metadata was created. format: date-time updatedAt: type: string description: Timestamp the invoice metadata was last updated. format: date-time orderId: type: integer description: Owning order `id`. format: int32 description: Order invoice metadata. OrderItemResponse: type: object properties: note: type: string description: Optional order item note. name: type: string description: Product or product-line name. id: type: integer description: Order item `id`. format: int32 predictedDaysOnHand: type: integer description: Predicted days on hand after current inventory and run rate. format: int32 categoryId: type: integer description: '`POS` category `id`.' format: int32 productId: type: integer description: Product `id`. Present when the item is an individual product. format: int32 categoryLabel: type: string description: '`POS` category label.' targetProductDepth: type: integer description: Target product depth for product-line items. format: int32 desiredDaysOnHand: type: integer description: Target days on hand used for order calculations. format: int32 universalBrandId: type: integer description: '`Universal` brand `id`.' format: int32 universalBrandName: type: string description: '`Universal` brand name.' unitsAtDistribution: type: integer description: Units currently available at the configured distribution location. format: int32 unitsNeeded: type: integer description: Calculated units needed for the target days on hand. format: int32 quantity: type: integer description: Current units on hand at the store for this item. format: int32 posBrandId: type: integer description: '`POS` brand `id`.' format: int32 posBrandName: type: string description: '`POS` brand name.' currentProductDepth: type: integer description: Current product depth for product-line items. format: int32 storeName: type: string description: Store/location name. storeId: type: string description: Store/location `UUID`. format: uuid strainsNeeded: type: integer description: Calculated or overridden strains needed for product-line items. format: int32 addedAt: type: string description: Timestamp the item was added to the order. format: date-time itemUnitCost: type: number description: Estimated item unit cost. format: double itemType: type: string description: The type of an item, either a product or a product line. enum: - PRODUCT - PRODUCT_LINE - CUSTOM lookbackPeriod: type: integer description: Lookback period in days used for demand calculations. format: int32 distributionFulfilmentStatus: type: string description: '`DistributionFulfillmentStatus` for the ordered quantity.' enum: - PARTIAL - UNAVAILABLE - AVAILABLE - NO_DISTRIBUTION orderQuantity: type: integer description: Quantity explicitly placed on the order item. format: int32 itemUnitCostCartOverride: type: number description: Order item unit cost override, when set. format: double currentSativaDepth: type: integer description: Current sativa depth for product-line items. format: int32 currentIndicaDepth: type: integer description: Current indica depth for product-line items. format: int32 currentHybridDepth: type: integer description: Current hybrid depth for product-line items. format: int32 productLineId: type: integer description: Product-line `id`. Present when the item is a product line. format: int32 OrderResponse: type: object properties: note: type: string description: Optional order note. name: type: string description: Optional order name. id: type: integer description: Internal order `id`. format: int32 example: 123 status: type: string description: 'Current order status: `DRAFT`, `READY_TO_SEND`, `SUBMITTED`, or `RECEIVED`.' enum: - DRAFT - READY_TO_SEND - SUBMITTED - RECEIVED description: type: string description: Optional order description. createdAt: type: string description: Order creation timestamp. format: date-time orderNumber: type: string description: Organization-facing order number. example: HB-2026-000123 createdByUserId: type: integer description: '`id` of the user who created the order.' format: int32 createdByUserFirstName: type: string description: First name of the user who created the order. createdByUserLastName: type: string description: Last name of the user who created the order. OrderInvoiceUpdateRequest: required: - filename type: object properties: name: type: string description: Optional invoice display name. filename: type: string description: Invoice filename. example: invoice.pdf description: Request body for updating an order invoice. 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