{"openapi":"3.1.0","info":{"title":"KSS API","version":"v2","description":"Programmatic access to KSS purchase and order workflows."},"servers":[{"url":"https://api.kssdata.com/api/v2","description":"Production"},{"url":"https://api.test.kssdata.com/api/v2","description":"Test"}],"tags":[{"name":"Purchases"},{"name":"Orders","description":"Place an order with POST /orders?submit=true, then track it with GET /orders/{order_id}. To build a draft first, POST /orders, edit with PATCH, then POST /orders/{order_id}/submit. Posted edits use the same PATCH and submit flow. Check allowed_actions before editing or cancelling; use DELETE to delete a draft or request cancellation of a posted order."},{"name":"API Key"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key"}},"schemas":{"ApiError":{"type":"object","required":["code","detail"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code."},"detail":{"type":"string","description":"Human-readable explanation of the error."},"field_errors":{"type":"array","items":{"$ref":"#/components/schemas/FieldError"}}},"additionalProperties":true},"FieldError":{"type":"object","required":["field","code","detail"],"properties":{"field":{"type":"string"},"code":{"type":"string"},"detail":{"type":"string"},"message":{"type":"string"},"index":{"type":"number"},"product_id":{"type":"number"}},"additionalProperties":true},"ErrorEnvelope":{"type":"object","required":["error"],"properties":{"error":{"oneOf":[{"type":"string"},{"$ref":"#/components/schemas/ApiError"}]}}},"PaginationEnvelope":{"type":"object","required":["data","page","page_size","has_next_page"],"properties":{"data":{"description":"Response payload."},"page":{"type":"number","minimum":1},"page_size":{"type":"number","minimum":1,"maximum":500},"has_next_page":{"type":"boolean"}}},"Purchase":{"type":"object","required":["purchase_id","receive_date","shipment_num","shipment_id","to_location_id","to_location_name","vendor_name","vendor_id","post_date","status","po_num","freight","tax","other_cost","total","total_cases","public_pdf_link","purchase_pdf_url_api_key_id","memo","last_edit_time","last_calc_time","time_updated","invoice_date","due_date","terms","term_id","time_created","receiving_num","purchase_global_id"],"properties":{"purchase_id":{"type":["number","null"],"description":"Numeric purchase ID. Null until the purchase has been processed."},"receive_date":{"type":["string","null"],"format":"date-time"},"shipment_num":{"type":["string","null"]},"shipment_id":{"type":["number","null"]},"to_location_id":{"type":"number"},"to_location_name":{"type":["string","null"]},"vendor_name":{"type":["string","null"]},"vendor_id":{"type":"number"},"post_date":{"type":["string","null"],"format":"date-time"},"status":{"type":"string","enum":["New","Accepted","Received","Confirmed","Verified","InProgress","Submitted","Importing","PendingActivation"]},"po_num":{"type":"string"},"freight":{"type":["string","null"],"description":"Decimal value serialized as a string."},"tax":{"type":["string","null"],"description":"Decimal value serialized as a string."},"other_cost":{"type":["string","null"],"description":"Decimal value serialized as a string."},"total":{"type":["string","null"],"description":"Decimal value serialized as a string."},"total_cases":{"type":["string","null"],"description":"Total case count serialized as a string."},"public_pdf_link":{"type":["string","null"]},"purchase_pdf_url_api_key_id":{"type":["number","null"]},"memo":{"type":["string","null"]},"last_edit_time":{"type":["string","null"],"format":"date-time"},"last_calc_time":{"type":["string","null"],"format":"date-time"},"time_updated":{"type":["string","null"],"format":"date-time"},"invoice_date":{"type":["string","null"],"format":"date-time"},"due_date":{"type":["string","null"],"format":"date-time"},"terms":{"type":["string","null"]},"term_id":{"type":["number","null"]},"time_created":{"type":["string","null"],"format":"date-time"},"receiving_num":{"type":["string","null"]},"purchase_global_id":{"type":["string","null"],"description":"Permanent global purchase identifier."},"purchase_transactions":{"type":"array","description":"Line items are included by default. Send include_transactions=false on purchases GET endpoints to omit them.","items":{"oneOf":[{"$ref":"#/components/schemas/PurchaseTransaction"},{"$ref":"#/components/schemas/PurchaseDraftTransaction"}]}}},"additionalProperties":false,"example":{"purchase_id":70001,"receive_date":"2026-06-02T06:00:00.000Z","shipment_num":"Example PO 70001","shipment_id":72001,"to_location_id":40001,"to_location_name":"Alameda","vendor_name":"EXAMPLE DISTRIBUTORS LLC (Example Location)","vendor_id":50001,"post_date":"2026-06-02T06:00:00.000Z","status":"Verified","po_num":"Example PO 70001","freight":"0.00","tax":"0.00","other_cost":"0.00","total":"35726.38","total_cases":"184.00","public_pdf_link":null,"purchase_pdf_url_api_key_id":94001,"memo":null,"last_edit_time":null,"last_calc_time":"2026-06-04T10:20:14.000Z","time_updated":"2026-08-21T18:06:57.930Z","invoice_date":"2026-06-01T06:00:00.000Z","due_date":"2026-08-30T06:00:00.000Z","terms":"Driver Accounts","term_id":80002,"time_created":"2026-06-15T22:09:09.921Z","receiving_num":null,"purchase_global_id":"00000AAAAAFFFFF00000AAAAAF"}},"PurchaseResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Purchase"}}},"PaginatedPurchaseResponse":{"allOf":[{"$ref":"#/components/schemas/PaginationEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Purchase"}}}}]},"PurchaseTransaction":{"type":"object","properties":{"purchase_trans_id":{"type":"number"},"purchase_id":{"type":"number"},"product_id":{"type":"number"},"ordered":{"type":["string","null"],"description":"Decimal value serialized as a string."},"num_units":{"type":["string","null"],"description":"Decimal value serialized as a string."},"fob":{"type":["string","null"],"description":"Decimal value serialized as a string."},"deposit_cost":{"type":["string","null"],"description":"Decimal value serialized as a string."},"ext_price":{"type":["string","null"],"description":"Decimal value serialized as a string."},"expiration_date":{"type":["string","null"],"format":"date-time"},"code_date":{"type":["string","null"],"format":"date-time"},"batch_code":{"type":["string","null"]},"laid_in_cost":{"type":["string","null"],"description":"Decimal value serialized as a string."},"pallet_tag":{"type":["string","null"]},"cases":{"type":["string","null"],"description":"Decimal value serialized as a string."},"weight":{"type":["string","null"],"description":"Decimal value serialized as a string."},"time_updated":{"type":["string","null"],"format":"date-time"}},"additionalProperties":false},"PaginatedPurchaseTransactionResponse":{"allOf":[{"$ref":"#/components/schemas/PaginationEnvelope"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseTransaction"}}}}]},"PurchaseDraftTransaction":{"type":"object","required":["product_id","num_units"],"properties":{"id":{"type":"number"},"product_id":{"type":"number"},"num_units":{"type":"number"},"batch_code":{"type":["string","null"]},"expiration_date":{"type":["string","null"],"format":"date"},"needs_activation":{"type":"boolean"},"activation_task_id":{"type":["number","null"]}},"additionalProperties":false},"PurchaseWriteTransaction":{"type":"object","required":["product_id"],"properties":{"product_id":{"type":"number","description":"Product to add to the purchase."},"cases":{"type":"number","description":"Case quantity. Send exactly one of cases or units."},"units":{"type":"number","description":"Unit quantity. Send exactly one of cases or units."},"batch_code":{"type":"string","description":"Batch code. Required when the vendor requires batch codes."},"expiration_date":{"type":"string","format":"date","description":"Expiration date as YYYY-MM-DD."}},"additionalProperties":false},"CreatePurchaseRequest":{"type":"object","required":["vendor_id","to_location_id","supplier_id","delivery_date","po_num"],"properties":{"vendor_id":{"type":"number","description":"The vendor the purchase order is placed with."},"to_location_id":{"type":"number","description":"The location receiving the purchase."},"supplier_id":{"type":"number","description":"The supplier the purchase is for. Must be one of your authorized suppliers."},"supplier_name":{"type":"string","description":"Supplier name used in the purchase memo. Falls back to the vendor's name when omitted."},"delivery_date":{"type":"string","format":"date","description":"Requested delivery date as YYYY-MM-DD."},"po_num":{"type":"string","description":"Your purchase order number. Must be unique for the vendor."},"purchase_transactions":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseWriteTransaction"},"maxItems":200},"created_by_user_id":{"type":"number","description":"Honored for Employee keys only; other keys use the key's own user."}},"additionalProperties":false},"UpdatePurchaseRequest":{"type":"object","properties":{"vendor_id":{"type":"number","description":"The vendor the purchase order is placed with."},"to_location_id":{"type":"number","description":"The location receiving the purchase."},"supplier_id":{"type":"number","description":"The supplier the purchase is for. Must be one of your authorized suppliers."},"supplier_name":{"type":"string","description":"Supplier name used in the purchase memo. Falls back to the vendor's name when omitted."},"delivery_date":{"type":"string","format":"date","description":"Requested delivery date as YYYY-MM-DD."},"po_num":{"type":"string","description":"Your purchase order number. Must remain unique for the vendor."},"purchase_transactions":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseWriteTransaction"},"maxItems":200,"description":"When present, replaces all line items on the draft purchase."}},"additionalProperties":false},"PurchaseValidationResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["valid","total_cases"],"properties":{"valid":{"type":"boolean"},"total_cases":{"type":"number"}}}}}},"parameters":{"Page":{"name":"page","in":"query","required":false,"description":"Page number to retrieve. Defaults to 1.","schema":{"type":"number","minimum":1,"default":1}},"PageSize":{"name":"page_size","in":"query","required":false,"description":"Number of rows to return per page. Defaults to 50; maximum is 500.","schema":{"type":"number","minimum":1,"maximum":500,"default":50}},"States":{"name":"states","in":"query","required":false,"description":"Comma-separated list of state abbreviations to filter by. Example: \"CA,NJ\".","schema":{"type":"string","pattern":"^[^,]+(,[^,]+)*$","example":"CA,NJ"},"example":"CA,NJ"},"CustomerIDs":{"name":"customer_ids","in":"query","required":false,"description":"Comma-separated list of customer IDs to filter by.","schema":{"type":"string","pattern":"^\\d+(,\\d+)*$","example":"1,2,3"},"example":"1,2,3"},"SupplierIDs":{"name":"supplier_ids","in":"query","required":false,"description":"Comma-separated list of supplier IDs to filter by.","schema":{"type":"string","pattern":"^\\d+(,\\d+)*$","example":"1,2,3"},"example":"1,2,3"},"ProductIDs":{"name":"product_ids","in":"query","required":false,"description":"Comma-separated list of product IDs to filter by.","schema":{"type":"string","pattern":"^\\d+(,\\d+)*$","example":"1,2,3"},"example":"1,2,3"},"LocationIDs":{"name":"location_ids","in":"query","required":false,"description":"Comma-separated list of location IDs to filter by.","schema":{"type":"string","pattern":"^\\d+(,\\d+)*$","example":"1,2,3"},"example":"1,2,3"},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional for POST and PATCH requests. Send a unique key for each logical mutation so an exact retry can replay the original response instead of running the operation again.","schema":{"type":"string"}},"Prefer":{"name":"Prefer","in":"header","required":false,"description":"Use return=minimal to omit the response body; return=representation is the default. Use handling=lenient to ignore unrecognized fields where supported.","schema":{"type":"string"}}},"responses":{"BadRequest":{"description":"The request is missing required input or contains invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Unauthorized":{"description":"The request is missing a valid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Forbidden":{"description":"The API key is not authorized to access this resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"NotFound":{"description":"The requested resource was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"Conflict":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"UnprocessableEntity":{"description":"The request is well-formed but could not be accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"PayloadTooLarge":{"description":"The request body is too large.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"UnsupportedMediaType":{"description":"The request content type is not supported.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"TooManyRequests":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"ServerError":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"security":[{"ApiKeyAuth":[]}],"paths":{"/purchases":{"get":{"tags":["Purchases"],"operationId":"getPurchasesPurchases","description":"Returns purchase orders filtered by purchase ID, vendor, location, status, and date range. purchase_transactions are included by default; send include_transactions=false to return headers only. Results cover every purchase order you can access at every stage, from drafts that have not been submitted yet through processed purchases, in one paginated list, and each purchase order appears once. A status filter returns only purchases currently in one of the requested statuses. Not accessible to Customer API keys.","parameters":[{"name":"purchase_ids","in":"query","required":false,"description":"Comma-separated list of purchase identifiers to filter by. Each value may be a numeric purchase_id or a purchase_global_id.","schema":{"type":"string","pattern":"^([1-9]\\d*|[0-9A-HJKMNP-TV-Z]{26})(,([1-9]\\d*|[0-9A-HJKMNP-TV-Z]{26}))*$","example":"70002,11111BBBBBEEEEE11111BBBBBE"},"example":"70002,11111BBBBBEEEEE11111BBBBBE"},{"name":"vendor_ids","in":"query","required":false,"description":"Comma-separated list of vendor IDs to filter by.","schema":{"type":"string","pattern":"^\\d+(,\\d+)*$","example":"1,2,3"},"example":"1,2,3"},{"name":"location_ids","in":"query","required":false,"description":"Comma-separated list of destination location IDs to filter by.","schema":{"type":"string","pattern":"^\\d+(,\\d+)*$","example":"1,2,3"},"example":"1,2,3"},{"name":"statuses","in":"query","required":false,"description":"Comma-separated list of purchase statuses to filter by. Omitted, purchases in every status are returned. InProgress is an editable draft; Submitted is queued for processing; Importing is being processed; PendingActivation is waiting on one or more products to be activated before processing can finish; New, Accepted, Received, Confirmed, and Verified are the stages of a processed purchase order.","schema":{"type":"string","pattern":"^[^,]+(,[^,]+)*$","example":"Verified,Received"},"example":"Verified,Received"},{"name":"start_date","in":"query","required":false,"description":"Calendar date formatted YYYY-MM-DD. Returns processed purchases with a post_date on or after this date, and purchases not yet processed with a delivery_date on or after this date. An empty value is ignored; any other value that is not a valid YYYY-MM-DD date returns 400.","schema":{"type":"string","format":"date"}},{"name":"end_date","in":"query","required":false,"description":"Calendar date formatted YYYY-MM-DD. Returns processed purchases with a post_date on or before this date, and purchases not yet processed with a delivery_date on or before this date. An empty value is ignored; any other value that is not a valid YYYY-MM-DD date returns 400.","schema":{"type":"string","format":"date"}},{"name":"include_transactions","in":"query","required":false,"description":"Line items are included by default. Send false to omit purchase_transactions from each purchase.","schema":{"type":"boolean","default":true}},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedPurchaseResponse"},"example":{"data":[{"purchase_id":70001,"receive_date":"2026-06-02T06:00:00.000Z","shipment_num":"Example PO 70001","shipment_id":72001,"to_location_id":40001,"to_location_name":"Alameda","vendor_name":"EXAMPLE DISTRIBUTORS LLC (Example Location)","vendor_id":50001,"post_date":"2026-06-02T06:00:00.000Z","status":"Verified","po_num":"Example PO 70001","freight":"0.00","tax":"0.00","other_cost":"0.00","total":"35726.38","total_cases":"184.00","public_pdf_link":null,"purchase_pdf_url_api_key_id":94001,"memo":null,"last_edit_time":null,"last_calc_time":"2026-06-04T10:20:14.000Z","time_updated":"2026-08-21T18:06:57.930Z","invoice_date":"2026-06-01T06:00:00.000Z","due_date":"2026-08-30T06:00:00.000Z","terms":"Driver Accounts","term_id":80002,"time_created":"2026-06-15T22:09:09.921Z","purchase_global_id":"00000AAAAAFFFFF00000AAAAAF","receiving_num":null,"purchase_transactions":[{"purchase_trans_id":71001,"purchase_id":70001,"product_id":30006,"ordered":"10","num_units":"120","fob":"12.50","deposit_cost":"0.00","ext_price":"1500.00","expiration_date":"2026-01-01T00:00:00.000Z","code_date":"2025-01-15T00:00:00.000Z","batch_code":"BCH-001","laid_in_cost":"13.00","pallet_tag":null,"cases":"10","weight":"120.00","time_updated":"2025-03-02T10:00:00.000Z"}]},{"purchase_id":null,"receive_date":null,"shipment_num":null,"shipment_id":null,"to_location_id":40002,"to_location_name":null,"vendor_name":null,"vendor_id":50002,"post_date":null,"status":"InProgress","po_num":"PO-2026-00000","freight":"0.00","tax":"0.00","other_cost":"0.00","total":"0.00","total_cases":"30","public_pdf_link":null,"purchase_pdf_url_api_key_id":null,"memo":"Acme Brands - Submitted via KSS Live by Jamie Example","last_edit_time":null,"last_calc_time":null,"time_updated":"2026-08-13T15:04:05.000Z","invoice_date":null,"due_date":null,"terms":null,"term_id":null,"time_created":"2026-08-13T15:04:05.000Z","purchase_global_id":"11111BBBBBEEEEE11111BBBBBE","receiving_num":null,"purchase_transactions":[{"id":71101,"product_id":30008,"num_units":288,"batch_code":"B-1042","expiration_date":"2027-01-15","needs_activation":false,"activation_task_id":null}]}],"page":1,"page_size":50,"has_next_page":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":true},"x-kss-pagination":true,"x-kss-beta":true,"summary":"Returns purchase orders filtered by purchase ID, vendor, location, status, and date range."},"post":{"tags":["Purchases"],"operationId":"createPurchase","description":"Creates a purchase order. By default the purchase is created as an editable draft; pass submit=true as a query parameter to create and submit it in a single call. The response carries the new purchase's global ID, and a Location header pointing at the purchase, which is how you address it for later reads, edits, and submission. Not accessible to Customer API keys.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"},{"name":"submit","in":"query","required":false,"description":"When true, creates the purchase directly in Submitted status after validating it is ready to submit.","schema":{"type":"boolean","default":false}}],"responses":{"201":{"description":"Created. If Prefer: return=minimal is sent, the Location header is returned with no response body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseResponse"},"example":{"data":{"purchase_id":null,"receive_date":null,"shipment_num":null,"shipment_id":null,"to_location_id":40002,"to_location_name":null,"vendor_name":null,"vendor_id":50002,"post_date":null,"status":"InProgress","po_num":"PO-2026-00000","freight":"0.00","tax":"0.00","other_cost":"0.00","total":"0.00","total_cases":"30","public_pdf_link":null,"purchase_pdf_url_api_key_id":null,"memo":"Acme Brands - Submitted via KSS Live by Jamie Example","last_edit_time":null,"last_calc_time":null,"time_updated":"2026-08-13T15:04:05.000Z","invoice_date":null,"due_date":null,"terms":null,"term_id":null,"time_created":"2026-08-13T15:04:05.000Z","purchase_global_id":"11111BBBBBEEEEE11111BBBBBE","receiving_num":null,"purchase_transactions":[{"id":71101,"product_id":30008,"num_units":288,"batch_code":"B-1042","expiration_date":"2027-01-15","needs_activation":false,"activation_task_id":null}]}}}},"headers":{"Location":{"description":"Canonical URL for the created purchase, addressed by purchase_global_id.","schema":{"type":"string"}},"Idempotency-Replayed":{"description":"true when this response was replayed from a previous request with the same Idempotency-Key.","schema":{"type":"string"}},"Preference-Applied":{"description":"Echoes honored Prefer tokens, such as return=minimal or handling=lenient.","schema":{"type":"string"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"SCHEMA_VIOLATION","detail":"The request could not be processed as written.","field_errors":[{"field":"purchase_transactions[0].product_id","code":"SCHEMA_VIOLATION","detail":"ProductID is required and must be a positive integer.","index":0}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"description":"The request conflicts with an existing purchase or idempotency key.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"DUPLICATE_PO_NUMBER","detail":"A purchase order with that PO number already exists for this vendor. Fetch the existing purchase instead of creating another. The existing purchase is 11111BBBBBEEEEE11111BBBBBE.","field_errors":[{"field":"po_num","code":"DUPLICATE_PO_NUMBER","detail":"This PO number is already in use for this vendor. The existing purchase is 11111BBBBBEEEEE11111BBBBBE."}]}}}}},"413":{"description":"The purchase body is too large.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"REQUEST_TOO_LARGE","detail":"The request body exceeds the maximum size for a purchase. A purchase may contain at most 200 line items."}}}}},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":true},"x-kss-pagination":false,"x-kss-beta":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePurchaseRequest"},"example":{"vendor_id":50002,"to_location_id":40002,"supplier_id":20001,"supplier_name":"Acme Brands","delivery_date":"2026-08-20","po_num":"PO-2026-00000","purchase_transactions":[{"product_id":30008,"cases":12,"batch_code":"B-1042","expiration_date":"2027-01-15"},{"product_id":30009,"units":48}]}}}},"x-kss-callout":"po_num must be unique for the vendor, and that is what makes a retry safe: if a request times out after the purchase was already created, sending it again with the same po_num returns 409 DUPLICATE_PO_NUMBER instead of creating a second purchase order. The error's detail names the existing purchase's global ID, so you can go read it directly rather than searching for it.","x-kss-fieldDefinitions":[{"name":"purchase_global_id","description":"The purchase's permanent identifier. Use it to read, edit, submit, or delete the purchase."},{"name":"purchase_id","description":"The numeric purchase ID. Null until the purchase has been processed."},{"name":"status","description":"InProgress for an editable draft, Submitted once it is queued for processing."},{"name":"total_cases","description":"Total case count across all line items."}],"summary":"Creates a purchase order."}},"/purchases/validate":{"post":{"tags":["Purchases"],"operationId":"validatePurchase","description":"Validates a purchase order without creating anything, returning whether it is acceptable and its computed totals. Validates against the rules that apply at submit time: the purchase must have at least one line item, every quantity must be positive, and batch codes must be present where the vendor requires them, and po_num must be unique for the vendor. Not accessible to Customer API keys.","parameters":[{"$ref":"#/components/parameters/Prefer"}],"responses":{"200":{"description":"Validation result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseValidationResponse"},"example":{"data":{"valid":true,"total_cases":30}}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"SCHEMA_VIOLATION","detail":"The request could not be processed as written.","field_errors":[{"field":"purchase_transactions[0].product_id","code":"SCHEMA_VIOLATION","detail":"ProductID is required and must be a positive integer.","index":0}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"description":"The purchase conflicts with an existing purchase.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"DUPLICATE_PO_NUMBER","detail":"A purchase order with that PO number already exists for this vendor. Fetch the existing purchase instead of creating another. The existing purchase is 11111BBBBBEEEEE11111BBBBBE.","field_errors":[{"field":"po_num","code":"DUPLICATE_PO_NUMBER","detail":"This PO number is already in use for this vendor. The existing purchase is 11111BBBBBEEEEE11111BBBBBE."}]}}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":true},"x-kss-pagination":false,"x-kss-beta":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePurchaseRequest"},"example":{"vendor_id":50002,"to_location_id":40002,"supplier_id":20001,"supplier_name":"Acme Brands","delivery_date":"2026-08-20","po_num":"PO-2026-00000","purchase_transactions":[{"product_id":30008,"cases":12,"batch_code":"B-1042","expiration_date":"2027-01-15"},{"product_id":30009,"units":48}]}}}},"x-kss-fieldDefinitions":[{"name":"valid","description":"True when the purchase passed every validation check."},{"name":"total_cases","description":"Total case count derived across all line items."}],"summary":"Validates a purchase order without creating anything, returning whether it is acceptabl..."}},"/purchases/{purchaseID}":{"get":{"tags":["Purchases"],"operationId":"getPurchasesPurchasesPurchaseID","description":"Returns a single purchase order. purchase_transactions are included by default; send include_transactions=false to return the purchase header only. Accepts either the purchase's global ID or its numeric purchase ID. The global ID resolves for the whole life of the purchase, from draft through processing and beyond, so the URL returned when a purchase is created never stops working. The numeric purchase ID resolves once the purchase has been processed and assigned one.","parameters":[{"name":"purchaseID","in":"path","required":true,"description":"The purchase's global ID or its numeric purchase ID.","schema":{"type":"string"}},{"name":"include_transactions","in":"query","required":false,"description":"Line items are included by default. Send false to omit purchase_transactions.","schema":{"type":"boolean","default":true}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseResponse"},"example":{"data":{"purchase_id":70001,"receive_date":"2026-06-02T06:00:00.000Z","shipment_num":"Example PO 70001","shipment_id":72001,"to_location_id":40001,"to_location_name":"Alameda","vendor_name":"EXAMPLE DISTRIBUTORS LLC (Example Location)","vendor_id":50001,"post_date":"2026-06-02T06:00:00.000Z","status":"Verified","po_num":"Example PO 70001","freight":"0.00","tax":"0.00","other_cost":"0.00","total":"35726.38","total_cases":"184.00","public_pdf_link":null,"purchase_pdf_url_api_key_id":94001,"memo":null,"last_edit_time":null,"last_calc_time":"2026-06-04T10:20:14.000Z","time_updated":"2026-08-21T18:06:57.930Z","invoice_date":"2026-06-01T06:00:00.000Z","due_date":"2026-08-30T06:00:00.000Z","terms":"Driver Accounts","term_id":80002,"time_created":"2026-06-15T22:09:09.921Z","purchase_global_id":"00000AAAAAFFFFF00000AAAAAF","receiving_num":null,"purchase_transactions":[{"purchase_trans_id":71001,"purchase_id":70001,"product_id":30006,"ordered":"10","num_units":"120","fob":"12.50","deposit_cost":"0.00","ext_price":"1500.00","expiration_date":"2026-01-01T00:00:00.000Z","code_date":"2025-01-15T00:00:00.000Z","batch_code":"BCH-001","laid_in_cost":"13.00","pallet_tag":null,"cases":"10","weight":"120.00","time_updated":"2025-03-02T10:00:00.000Z"}]}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":true},"x-kss-pagination":false,"x-kss-beta":true,"summary":"Returns a single purchase order."}},"/purchases/{purchaseGlobalID}":{"patch":{"tags":["Purchases"],"operationId":"updatePurchase","description":"Updates a draft purchase order. Send only the fields you want to change; anything you omit is left as it is. Only drafts can be edited: a purchase that has already been submitted returns 409. Not accessible to Customer API keys.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"purchaseGlobalID","in":"path","required":true,"description":"The global ID of the draft purchase to update.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Prefer"}],"responses":{"200":{"description":"Updated draft purchase with the updated representation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseResponse"},"example":{"data":{"purchase_id":null,"receive_date":null,"shipment_num":null,"shipment_id":null,"to_location_id":40002,"to_location_name":null,"vendor_name":null,"vendor_id":50002,"post_date":null,"status":"InProgress","po_num":"PO-2026-00000-REV2","freight":"0.00","tax":"0.00","other_cost":"0.00","total":"0.00","total_cases":"45","public_pdf_link":null,"purchase_pdf_url_api_key_id":null,"memo":"Acme Brands - Submitted via KSS Live by Jamie Example","last_edit_time":null,"last_calc_time":null,"time_updated":"2026-08-13T16:20:11.000Z","invoice_date":null,"due_date":null,"terms":null,"term_id":null,"time_created":"2026-08-13T15:04:05.000Z","purchase_global_id":"11111BBBBBEEEEE11111BBBBBE","receiving_num":null,"purchase_transactions":[{"id":71101,"product_id":30008,"num_units":288,"batch_code":"B-1042","expiration_date":"2027-01-15","needs_activation":false,"activation_task_id":null}]}}}},"headers":{"Idempotency-Replayed":{"description":"true when this response was replayed from a previous request with the same Idempotency-Key.","schema":{"type":"string"}},"Preference-Applied":{"description":"Echoes any honored Prefer tokens, such as return=minimal or handling=lenient.","schema":{"type":"string"}}}},"204":{"description":"Updated draft purchase. Returned when Prefer: return=minimal is sent."},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"LINE_QUANTITY_AMBIGUOUS","detail":"The request could not be processed as written.","field_errors":[{"field":"purchase_transactions[0].cases","code":"LINE_QUANTITY_AMBIGUOUS","detail":"Each line item must specify exactly one of Cases or Units so the unit of measure is unambiguous.","index":0,"product_id":30008}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Purchase not found.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"PURCHASE_NOT_FOUND","detail":"Purchase not found."}}}}},"409":{"description":"The purchase cannot be edited in its current state.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ALREADY_SUBMITTED","detail":"A purchase in status Submitted cannot be edited."}}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"description":"Unsupported request content type.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"UNSUPPORTED_MEDIA_TYPE","detail":"PATCH bodies must be application/json."}}}}},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":true},"x-kss-pagination":false,"x-kss-beta":true,"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePurchaseRequest"},"example":{"delivery_date":"2026-08-22","po_num":"PO-2026-00000-REV2","purchase_transactions":[{"product_id":30008,"cases":15,"batch_code":"B-1042","expiration_date":"2027-01-15"}]}}}},"x-kss-callout":"Including purchase_transactions replaces every line item on the purchase with the array you send, and an empty array removes them all. Leave the field out entirely to keep the existing line items. Status is never set here, use the submit action instead.","summary":"Updates a draft purchase order."},"delete":{"tags":["Purchases"],"operationId":"deletePurchase","description":"Deletes a draft purchase order. Responds 204 with no body. Only drafts can be deleted: a purchase that has already been submitted returns 409, and a purchase that does not exist or has already been deleted returns 404. Not accessible to Customer API keys.","parameters":[{"name":"purchaseGlobalID","in":"path","required":true,"description":"The global ID of the draft purchase to delete.","schema":{"type":"string"}}],"responses":{"204":{"description":"No Content"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Purchase not found.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"PURCHASE_NOT_FOUND","detail":"Purchase not found."}}}}},"409":{"description":"The purchase cannot be deleted in its current state.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ALREADY_SUBMITTED","detail":"A purchase in status Submitted cannot be deleted."}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":true},"x-kss-pagination":false,"x-kss-beta":true,"summary":"Deletes a draft purchase order."}},"/purchases/{purchaseGlobalID}/submit":{"post":{"tags":["Purchases"],"operationId":"submitPurchase","description":"Submits a draft purchase order for processing. The stored purchase is re-checked in full at this point, so a draft that was valid when it was saved can still be refused. A purchase that has already been submitted returns 409. Processing happens in the background and the response does not wait for it to finish; read the purchase to follow its status. Not accessible to Customer API keys.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"purchaseGlobalID","in":"path","required":true,"description":"The global ID of the draft purchase to submit.","schema":{"type":"string"}},{"$ref":"#/components/parameters/Prefer"}],"responses":{"200":{"description":"Submitted purchase with the updated representation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseResponse"},"example":{"data":{"purchase_id":null,"receive_date":null,"shipment_num":null,"shipment_id":null,"to_location_id":40002,"to_location_name":null,"vendor_name":null,"vendor_id":50002,"post_date":null,"status":"Submitted","po_num":"PO-2026-00000","freight":"0.00","tax":"0.00","other_cost":"0.00","total":"0.00","total_cases":"30","public_pdf_link":null,"purchase_pdf_url_api_key_id":null,"memo":"Acme Brands - Submitted via KSS Live by Jamie Example","last_edit_time":null,"last_calc_time":null,"time_updated":"2026-08-13T17:02:44.000Z","invoice_date":null,"due_date":null,"terms":null,"term_id":null,"time_created":"2026-08-13T15:04:05.000Z","purchase_global_id":"11111BBBBBEEEEE11111BBBBBE","receiving_num":null,"purchase_transactions":[{"id":71101,"product_id":30008,"num_units":288,"batch_code":"B-1042","expiration_date":"2027-01-15","needs_activation":false,"activation_task_id":null}]}}}},"headers":{"Idempotency-Replayed":{"description":"true when this response was replayed from a previous request with the same Idempotency-Key.","schema":{"type":"string"}},"Preference-Applied":{"description":"Echoes any honored Prefer tokens, such as return=minimal or handling=lenient.","schema":{"type":"string"}}}},"204":{"description":"Submitted purchase. Returned when Prefer: return=minimal is sent."},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"Purchase not found.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"PURCHASE_NOT_FOUND","detail":"Purchase not found."}}}}},"409":{"description":"The purchase cannot be submitted in its current state.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ALREADY_SUBMITTED","detail":"A purchase in status Submitted cannot be submitted."}}}}},"422":{"description":"The purchase cannot be submitted as it stands. Everything stored on the draft is re-checked: the vendor must still be active, a delivery date must be set (DELIVERY_DATE_REQUIRED) and be one the vendor allows, there must be at least one line item, every line item must be a valid product for the vendor with a positive quantity, and batch codes must be present where the vendor requires them. Every problem found is listed in field_errors.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"NO_LINE_ITEMS","detail":"This purchase cannot be submitted as it stands.","field_errors":[{"field":"purchase_transactions","code":"NO_LINE_ITEMS","detail":"A purchase must contain at least one line item before it can be submitted."}]}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":true},"x-kss-pagination":false,"x-kss-beta":true,"summary":"Submits a draft purchase order for processing."}},"/me":{"get":{"tags":["API Key"],"operationId":"getCaller","description":"Returns the scope of the API key making the request and its current rate-limit status. The request itself counts toward the limit, and the response is never cached, so the numbers always reflect the moment you asked. Useful for checking which suppliers, customers, and states a key can act for before debugging a 403.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","required":["api_key_id","type","environment","user_id","supplier_ids","customer_ids","states","rate_limit"],"properties":{"api_key_id":{"type":"number"},"type":{"type":"string","enum":["Employee","Supplier","Customer"]},"environment":{"type":"string"},"user_id":{"type":"number"},"supplier_ids":{"type":["array","null"],"items":{"type":"number"}},"customer_ids":{"type":["array","null"],"items":{"type":"number"}},"states":{"type":"array","items":{"type":"string"}},"rate_limit":{"type":["object","null"],"required":["limit","remaining","reset_seconds"],"properties":{"limit":{"type":"number"},"remaining":{"type":"number"},"reset_seconds":{"type":"number"}},"additionalProperties":false}},"additionalProperties":false}}},"example":{"data":{"api_key_id":94001,"type":"Supplier","environment":"Production","user_id":10042,"supplier_ids":[20001,20002],"customer_ids":null,"states":["CA","NJ"],"rate_limit":{"limit":1000,"remaining":962,"reset_seconds":2718}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":false},"x-kss-pagination":false,"x-kss-beta":true,"x-kss-fieldDefinitions":[{"name":"api_key_id","description":"The numeric identifier of the API key making the request."},{"name":"type","description":"The kind of access the key has: Supplier, Customer, or Employee."},{"name":"environment","description":"The environment the key is issued for: Production, Test, or Development."},{"name":"user_id","description":"The numeric identifier of the user the key belongs to."},{"name":"supplier_ids","description":"The suppliers the key can act for. Null means the key is not restricted to particular suppliers."},{"name":"customer_ids","description":"The customers the key can act for. Null means the key is not restricted to particular customers."},{"name":"states","description":"The states the key can access."},{"name":"rate_limit","description":"The key's request allowance over a rolling 60-minute window. Null when rate-limit status is not available for the request."},{"name":"rate_limit.limit","description":"The maximum number of requests the key may make in a rolling 60-minute window."},{"name":"rate_limit.remaining","description":"The number of requests left in the current window, after counting this request."},{"name":"rate_limit.reset_seconds","description":"The number of seconds until the oldest request counted in the window ages out and frees up an allowance."}],"summary":"Returns the scope of the API key making the request and its current rate-limit status.","parameters":[]}},"/orders":{"get":{"tags":["Orders"],"operationId":"getOrders","description":"Lists orders, newest first. By default, returns submitted and posted orders without lines. Use stages=draft for drafts and include_lines=true for line items.","parameters":[{"name":"order_ids","in":"query","required":false,"description":"Comma-separated order IDs or invoice IDs; both can be mixed.","schema":{"type":"string","pattern":"^([1-9]\\d*|[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26})(,([1-9]\\d*|[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}))*$","example":"90017,01K9X7M2QH4T8VZ3BN6CRWD5EJ"},"example":"90017,01K9X7M2QH4T8VZ3BN6CRWD5EJ"},{"name":"customer_ids","in":"query","required":false,"description":"Comma-separated list of customer IDs to filter by.","schema":{"type":"string","pattern":"^\\d+(,\\d+)*$","example":"1,2,3"},"example":"1,2,3"},{"name":"states","in":"query","required":false,"description":"Comma-separated customer state abbreviations.","schema":{"type":"string","pattern":"^[^,]+(,[^,]+)*$","example":"CA,NJ"},"example":"CA,NJ"},{"name":"stages","in":"query","required":false,"description":"Comma-separated draft, submitted, posted. Default: submitted,posted; invoice_statuses restricts to posted. A statuses filter can also select drafts.","schema":{"type":"string","pattern":"^(draft|submitted|posted)(,(draft|submitted|posted))*$","example":"submitted,posted"},"example":"submitted,posted"},{"name":"statuses","in":"query","required":false,"description":"Comma-separated statuses; see status in Response Fields. Without stages, searches all stages. Deleted drafts require statuses=deleted.","schema":{"type":"string","pattern":"^(draft|deleted|queued|importing|rejected|accepted|on_the_way|delivered|cancelled)(,(draft|deleted|queued|importing|rejected|accepted|on_the_way|delivered|cancelled))*$","example":"queued,importing"},"example":"queued,importing"},{"name":"invoice_statuses","in":"query","required":false,"description":"Posted orders only. Comma-separated: 1 New, 2 Locked for Routing, 3 Loaded, 4 Returned, 5 Balanced, 7 Verified.","schema":{"type":"string","pattern":"^\\d+(,\\d+)*$","example":"1"},"example":"1"},{"name":"start_date","in":"query","required":false,"description":"Delivery date on or after YYYY-MM-DD. Empty is ignored; invalid dates return 400.","schema":{"type":"string","format":"date"}},{"name":"end_date","in":"query","required":false,"description":"Delivery date on or before YYYY-MM-DD. Empty is ignored; invalid dates return 400.","schema":{"type":"string","format":"date"}},{"name":"has_pending_changes","in":"query","required":false,"description":"true: posted orders with pending edits or cancellation. false: orders with neither. Omit for both.","schema":{"type":"boolean"}},{"name":"include_lines","in":"query","required":false,"description":"Lines are omitted by default on lists. Send true to include lines on each order.","schema":{"type":"boolean","default":false}},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data","page","page_size","has_next_page"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"page":{"type":"number"},"page_size":{"type":"number"},"has_next_page":{"type":"boolean"}}},"example":{"data":[{"id":"01K9X7M2QH4T8VZ3BN6CRWD5EJ","invoice_id":null,"invoice_num":null,"stage":"submitted","status":"queued","invoice_status":null,"invoice_status_name":null,"is_credit":false,"version":"v1.Hd7Fk2PzQw9XcN4rVyLm1TbS8gJeA6uOiYtCs0RnE3U","customer_id":41001,"customer_name":"Example Dispensary","state":"CA","po_num":"PO-1042","po_date":null,"memo":"Deliver to the back dock","delivery_date":"2026-10-14","emails":["buyer@example.com"],"term_id":null,"credit_term_id":80003,"credit_term":"Net 30","split_invoice_id":null,"due_date":null,"invoice_total":null,"open_debit":null,"open_credit":null,"open_balance":null,"pdf_url":null,"ar_note":null,"submitted_by_user_id":10042,"built_by_user_id":10042,"built_by_user_name":"Jamie Example","time_created":"2026-10-08T15:04:05.000Z","time_updated":"2026-10-08T15:20:31.000Z","totals":{"units":144,"backorder_units":24,"cases":12,"full_price":"2076.00","discount":"120.00","ext_price":"1956.00"},"order_overrides":{},"pending_import_rows":[],"pending_change":null,"cancellation":null,"processing":{"attempts":0,"message":"Queued by user 10042 via API","updated_at":"2026-10-08T15:20:31.000Z"},"related_orders":{"parent_id":null,"parent_invoice_id":null,"split_children":[]},"allowed_actions":{"update":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"submit":{"allowed":false,"reason":"ALREADY_SUBMITTED","detail":"This order has already been submitted."},"discard_changes":{"allowed":false,"reason":"REVISION_NOT_FOUND","detail":"This order has no pending changes."},"cancel":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"delete":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"change_terms":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"set_promotions":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."}}},{"id":"01K9X7P5TD0A1MFY6S2GHQ8RNC","invoice_id":90017,"invoice_num":"INV-90017","stage":"posted","status":"accepted","invoice_status":1,"invoice_status_name":"New","is_credit":false,"version":"v1.Zq4N8cXw1LmT6vYb0RhPjK3sDfG7uEaO9iWtSyCe2Bk","customer_id":41001,"customer_name":"Example Dispensary","state":"CA","po_num":"PO-1031","po_date":"2026-10-06T07:00:00.000Z","memo":null,"delivery_date":"2026-10-14","emails":["buyer@example.com"],"term_id":70002,"credit_term_id":80003,"credit_term":"Net 30","split_invoice_id":null,"due_date":"2026-11-13T07:00:00.000Z","invoice_total":"1380.00","open_debit":"1380.00","open_credit":"0.00","open_balance":"1380.00","pdf_url":null,"ar_note":null,"submitted_by_user_id":10042,"submitted_by_user_name":"Jamie Example","submitted_by_user_email":"jamie@example.com","built_by_user_id":10042,"built_by_user_name":"Jamie Example","built_by_user_email":"jamie@example.com","time_created":"2026-10-06T16:12:44.000Z","time_updated":"2026-10-06T16:30:02.000Z","totals":{"units":120,"cases":10,"full_price":"1500.00","discount":"120.00","ext_price":"1380.00"},"pending_change":null,"cancellation":null,"processing":null,"related_orders":{"parent_id":null,"parent_invoice_id":null,"split_children":[]},"allowed_actions":{"update":{"allowed":true},"submit":{"allowed":false,"reason":"NO_PENDING_CHANGES","detail":"There are no pending changes to submit."},"discard_changes":{"allowed":false,"reason":"REVISION_NOT_FOUND","detail":"This order has no pending changes."},"cancel":{"allowed":true},"delete":{"allowed":true},"change_terms":{"allowed":true},"set_promotions":{"allowed":true}}}],"page":1,"page_size":50,"has_next_page":false}}}},"400":{"description":"Invalid filter (SCHEMA_VIOLATION) or order ID (ORDER_IDENTIFIER_INVALID). IDs must be 26-character order IDs or positive invoice IDs.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"SCHEMA_VIOLATION","detail":"stages must be one or more of: draft, submitted, posted.","field_errors":[{"field":"stages","code":"SCHEMA_VIOLATION","detail":"stages must be one or more of: draft, submitted, posted."}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Key cannot read orders: USER_INACTIVE (linked user deactivated) or ACTOR_SCOPE_MISMATCH (supplier key linked to a customer user).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"USER_INACTIVE","detail":"The user behind this API key is deactivated. Storefront login access is not required for API use."}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":false},"x-kss-pagination":true,"x-kss-beta":true,"x-kss-callout":"Migrating from v1 GET /invoices? Use invoice_statuses=1 for its default view of New invoices. For conditional writes, use each order's version; the list ETag identifies the page.","x-kss-fieldDefinitions":[{"name":"id","description":"Permanent 26-character order ID, valid across all stages. If null on a posted order, use invoice_id."},{"name":"invoice_id","description":"Numeric invoice ID, also accepted in order URLs. Null until posted."},{"name":"invoice_num","description":"The invoice number shown to the customer. Null until the order is posted."},{"name":"stage","description":"draft: editable, not submitted. submitted: queued or processing. posted: processed, with an invoice."},{"name":"status","description":"Draft: draft, deleted. Submitted: queued → importing → accepted (awaiting posting), or rejected (see processing.message). Posted: accepted (new), on_the_way, delivered, cancelled."},{"name":"invoice_status","description":"Numeric invoice status, the same values as Statuses in v1 invoices: 1 New, 2 Locked for Routing, 3 Loaded, 4 Returned, 5 Balanced, 7 Verified. Null until the order is posted."},{"name":"invoice_status_name","description":"The name of invoice_status. Null until the order is posted."},{"name":"is_credit","description":"True for a credit order. Credit orders cannot be edited."},{"name":"version","description":"Changes when the order or pending change changes. Also returned as ETag; use for If-Match or validation's version."},{"name":"customer_id","description":"The customer the order is placed for."},{"name":"customer_name","description":"The customer's name."},{"name":"state","description":"The customer's state."},{"name":"po_num","description":"The customer's purchase order number."},{"name":"po_date","description":"The PO date recorded on the posted order. Null until the order is posted."},{"name":"memo","description":"Free-text note on the order."},{"name":"delivery_date","description":"Requested delivery date as YYYY-MM-DD. On a posted order this is the order's delivery date."},{"name":"emails","description":"Buyer email addresses that receive order communications."},{"name":"term_id","description":"Payment term ID recorded on the posted order. Null before posting."},{"name":"credit_term_id","description":"The payment terms the order is on. On an unsubmitted order this is the terms it would be created with. Use GET /orders/creditTerms to look terms up."},{"name":"credit_term","description":"The name of credit_term_id."},{"name":"split_invoice_id","description":"Set when the order belongs to a separate invoice series, which a product can require."},{"name":"due_date","description":"When payment is due. Null until the order is posted."},{"name":"invoice_total","description":"Invoice total as a string with 2 decimals. Null until the order is posted. open_debit, open_credit, and open_balance are the outstanding amounts in the same format."},{"name":"pdf_url","description":"Link to the invoice PDF when one is available."},{"name":"ar_note","description":"Accounts receivable note on the invoice, when one exists."},{"name":"submitted_by_user_id","description":"The user who submitted the order. submitted_by_user_name and submitted_by_user_email identify them on posted orders; built_by_user_id, built_by_user_name, and built_by_user_email identify the user who built it."},{"name":"time_created","description":"When the order was created."},{"name":"time_updated","description":"When the order was last updated."},{"name":"totals","description":"Money uses strings with 2 decimals. units/cases count requested quantities. Drafts include shipped_units, ext_price (shippable total), and requested_ext_price (all requested units). full_price is before discounts; discount is the total discount. Keys limited to certain suppliers see totals for their suppliers' lines only, except on unsubmitted drafts they can edit."},{"name":"lines","description":"Line items. Omitted by default on lists; included by default on single-order reads. Drafts include credit_term_id, accept_backorder, minimum_applied (raised to product minimum), and issues. Posted lines include invoice_trans_id. Keys limited to certain suppliers see only their suppliers' lines, except on unsubmitted drafts they can edit."},{"name":"lines[].units","description":"Requested units on draft/posted orders; shippable units during submission processing. backorder_units counts unavailable units; shipped_units counts units that will or did ship."},{"name":"lines[].unit_price","description":"Per-unit price; full_price and discount are also per unit. ext_price = unit_price × shipped_units; requested_ext_price = unit_price × requested units."},{"name":"lines[].promotion_id","description":"Manual promotion to send back when editing. On posted lines, set only when promotion_overridden is true; applied_promotion_id identifies the pricing promotion, including automatic promotions."},{"name":"lines[].batch_code","description":"Batch the posted line was picked from. Null until assigned."},{"name":"lines[].coa_url","description":"Batch certificate of analysis URL. Null until attached."},{"name":"lines[].issues","description":"Submission blockers with code and detail: OUT_OF_STOCK, PRODUCT_INACTIVE, PRODUCT_NOT_AUTHORIZED, PRODUCT_NOT_FOUND, PROMOTION_UNAVAILABLE, PRICE_NOT_FOUND. Drafts can be saved with issues; submission returns 422."},{"name":"groups","description":"Draft split preview on single-order reads/writes. Separate invoice requirements or payment terms can split an order. Each group has group_key, order_number, credit terms, totals, line_indexes, and split_reason (SEPARATE_INVOICE_REQUIRED, CUSTOM_TERMS, SPLIT_INVOICE, DIFFERENT_TERMS; null for the first group)."},{"name":"order_overrides","description":"PO number and memo overrides for individual orders an order splits into, keyed by group_key. Present on unsubmitted orders."},{"name":"pending_import_rows","description":"Rows from an imported file that could not be turned into line items. Each entry has a row_number. An order with pending rows cannot be submitted until they are resolved or discarded."},{"name":"pending_change","description":"Posted-order edit preview with the proposed header, lines, groups, and totals. Keys limited to certain suppliers see only their suppliers' lines, groups, and totals. state: draft → submitted → processing → applied (awaiting sync), or rejected (see message). editor and updated_by identify the first and last editors by user_id/name."},{"name":"cancellation","description":"Posted cancellation request: state, requested_at, requested_by_user_id, message. state: pending → applied (awaiting sync) → completed, or rejected (see message)."},{"name":"processing","description":"Present on submitted orders: attempts is how many times processing has been tried, message the latest processing message, and updated_at when it last changed."},{"name":"related_orders","description":"Orders this order is connected to. parent_id and parent_invoice_id identify the order it was split from, and split_children lists the orders split from it, each with an id and invoice_id."},{"name":"allowed_actions","description":"Available actions: update, submit, discard_changes, cancel, delete, change_terms, set_promotions. Each has allowed; blocked actions include reason and detail matching write-error codes. Check these before offering an action."},{"name":"warnings","description":"Present on write responses when the request succeeded with caveats. Each warning has a field, code, and detail, and line warnings carry an index and product_id. Codes are QUANTITY_ADJUSTED, DELIVERY_DATE_WILL_BE_ADJUSTED, CUSTOMER_ON_HOLD, and ORIGINAL_INVOICE_WILL_BE_CANCELLED."},{"name":"resulting_orders","description":"Present on responses to submitting. See the field definitions on POST /orders/{order_id}/submit."}],"summary":"Lists orders, newest first."},"post":{"tags":["Orders"],"operationId":"createOrder","description":"Creates a draft (201). Add ?submit=true to create and submit in one request (202). Drafts may be incomplete; lines are validated and priced. Use the returned id for later requests. Requires an API key linked to an active user.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"$ref":"#/components/parameters/Prefer"},{"name":"submit","in":"query","required":false,"description":"Create and submit atomically (202). If submission fails, nothing is saved.","schema":{"type":"boolean","default":false}}],"responses":{"201":{"description":"Created as an unsubmitted draft. If Prefer: return=minimal is sent, the Location and ETag headers are returned with no response body.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":true}}},"example":{"data":{"id":"01K9X7M2QH4T8VZ3BN6CRWD5EJ","invoice_id":null,"invoice_num":null,"stage":"draft","status":"draft","invoice_status":null,"invoice_status_name":null,"is_credit":false,"version":"v1.8s3Yk0dQJ2mXw4Zr1pVb7NcLhT6aUeF9gOiSyKjRnM0","customer_id":41001,"customer_name":"Example Dispensary","state":"CA","po_num":"PO-1042","po_date":null,"memo":"Deliver to the back dock","delivery_date":"2026-10-14","emails":["buyer@example.com"],"term_id":null,"credit_term_id":80003,"credit_term":"Net 30","split_invoice_id":null,"due_date":null,"invoice_total":null,"open_debit":null,"open_credit":null,"open_balance":null,"pdf_url":null,"ar_note":null,"submitted_by_user_id":null,"built_by_user_id":10042,"built_by_user_name":"Jamie Example","time_created":"2026-10-08T15:04:05.000Z","time_updated":"2026-10-08T15:04:05.000Z","totals":{"units":168,"backorder_units":24,"shipped_units":144,"cases":14,"full_price":"2076.00","discount":"120.00","ext_price":"1956.00","requested_ext_price":"2532.00"},"order_overrides":{},"pending_import_rows":[],"pending_change":null,"cancellation":null,"processing":null,"related_orders":{"parent_id":null,"parent_invoice_id":null,"split_children":[]},"allowed_actions":{"update":{"allowed":true},"submit":{"allowed":true},"discard_changes":{"allowed":false,"reason":"REVISION_NOT_FOUND","detail":"Unsubmitted orders have no pending changes to discard."},"cancel":{"allowed":false,"reason":"NOT_SUBMITTED","detail":"This order has not been submitted. Delete it instead."},"delete":{"allowed":true},"change_terms":{"allowed":true},"set_promotions":{"allowed":true}},"lines":[{"product_id":30008,"product_name":"Acme Gummies 10pk","supplier_id":20001,"supplier_name":"Acme Brands","promotion_id":null,"quantity_promotion_id":null,"units":120,"backorder_units":0,"shipped_units":120,"cases":10,"unit_price":"11.50","full_price":"12.50","discount":"1.00","ext_price":"1380.00","requested_ext_price":"1380.00","credit_term_id":80003,"credit_term":"Net 30","term_overridden":false,"accept_backorder":false,"minimum_applied":false,"exception":null,"issues":[]},{"product_id":30009,"product_name":"Acme Chews 10pk","supplier_id":20001,"supplier_name":"Acme Brands","promotion_id":null,"quantity_promotion_id":null,"units":48,"backorder_units":24,"shipped_units":24,"cases":4,"unit_price":"24.00","full_price":"24.00","discount":"0.00","ext_price":"576.00","requested_ext_price":"1152.00","credit_term_id":80003,"credit_term":"Net 30","term_overridden":false,"accept_backorder":true,"minimum_applied":false,"exception":"Backorder accepted","issues":[]}],"groups":[{"group_key":"shared:0:0","order_number":1,"split_invoice_id":null,"credit_term_id":80003,"credit_term":"Net 30","term_overridden":false,"split_reason":null,"line_indexes":[0,1],"totals":{"units":168,"backorder_units":24,"shipped_units":144,"cases":14,"full_price":"2076.00","discount":"120.00","ext_price":"1956.00","requested_ext_price":"2532.00"}}]}}}},"headers":{"Location":{"description":"Canonical URL for the created order, addressed by its order ID.","schema":{"type":"string"}},"ETag":{"description":"Quoted order version. Send it in If-Match to prevent overwriting a changed order.","schema":{"type":"string"}},"Idempotency-Replayed":{"description":"true when this response was replayed from a previous request with the same Idempotency-Key.","schema":{"type":"string"}},"Preference-Applied":{"description":"Echoes honored Prefer tokens, such as return=minimal or handling=lenient.","schema":{"type":"string"}}}},"202":{"description":"Created and submitted with submit=true. The order is queued for processing; resulting_orders lists the orders it produced. If Prefer: return=minimal is sent, the Location and ETag headers are returned with no response body.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":true}}},"example":{"data":{"id":"01K9X7M2QH4T8VZ3BN6CRWD5EJ","invoice_id":null,"invoice_num":null,"stage":"submitted","status":"queued","invoice_status":null,"invoice_status_name":null,"is_credit":false,"version":"v1.Hd7Fk2PzQw9XcN4rVyLm1TbS8gJeA6uOiYtCs0RnE3U","customer_id":41001,"customer_name":"Example Dispensary","state":"CA","po_num":"PO-1042","po_date":null,"memo":"Deliver to the back dock","delivery_date":"2026-10-14","emails":["buyer@example.com"],"term_id":null,"credit_term_id":80003,"credit_term":"Net 30","split_invoice_id":null,"due_date":null,"invoice_total":null,"open_debit":null,"open_credit":null,"open_balance":null,"pdf_url":null,"ar_note":null,"submitted_by_user_id":10042,"built_by_user_id":10042,"built_by_user_name":"Jamie Example","time_created":"2026-10-08T15:04:05.000Z","time_updated":"2026-10-08T15:20:31.000Z","totals":{"units":144,"backorder_units":24,"cases":12,"full_price":"2076.00","discount":"120.00","ext_price":"1956.00"},"order_overrides":{},"pending_import_rows":[],"pending_change":null,"cancellation":null,"processing":{"attempts":0,"message":"Queued by user 10042 via API","updated_at":"2026-10-08T15:20:31.000Z"},"related_orders":{"parent_id":null,"parent_invoice_id":null,"split_children":[]},"allowed_actions":{"update":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"submit":{"allowed":false,"reason":"ALREADY_SUBMITTED","detail":"This order has already been submitted."},"discard_changes":{"allowed":false,"reason":"REVISION_NOT_FOUND","detail":"This order has no pending changes."},"cancel":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"delete":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"change_terms":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"set_promotions":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."}},"lines":[{"product_id":30008,"product_name":"Acme Gummies 10pk","supplier_id":20001,"promotion_id":null,"quantity_promotion_id":null,"units":120,"backorder_units":0,"cases":10,"unit_price":"11.50","discount":"1.00","ext_price":"1380.00","credit_term_id":null,"term_overridden":false,"exception":null},{"product_id":30009,"product_name":"Acme Chews 10pk","supplier_id":20001,"promotion_id":null,"quantity_promotion_id":null,"units":24,"backorder_units":24,"cases":2,"unit_price":"24.00","discount":"0.00","ext_price":"576.00","credit_term_id":null,"term_overridden":false,"exception":"Backorder accepted"}],"resulting_orders":[{"id":"01K9X7M2QH4T8VZ3BN6CRWD5EJ","invoice_id":null,"role":"original","group_key":"shared:0:0","order_number":1,"status":"queued","split_reason":null,"totals":{"units":168,"backorder_units":24,"shipped_units":144,"cases":14,"full_price":"2076.00","discount":"120.00","ext_price":"1956.00","requested_ext_price":"2532.00"}}]}}}},"headers":{"Location":{"description":"Canonical URL for the created order, addressed by its order ID.","schema":{"type":"string"}},"ETag":{"description":"Quoted order version. Send it in If-Match to prevent overwriting a changed order.","schema":{"type":"string"}},"Idempotency-Replayed":{"description":"true when this response was replayed from a previous request with the same Idempotency-Key.","schema":{"type":"string"}},"Preference-Applied":{"description":"Echoes honored Prefer tokens, such as return=minimal or handling=lenient.","schema":{"type":"string"}}}},"400":{"description":"Invalid request; see field_errors for each problem. Codes: SCHEMA_VIOLATION, ORDER_IDENTIFIER_INVALID, LINE_QUANTITY_AMBIGUOUS (send exactly one of units or cases), QUANTITY_INVALID, TOO_MANY_LINE_ITEMS, DUPLICATE_LINE_CONFLICT (conflicting terms/backorder settings on repeated lines), DELIVERY_DATE_NOT_CALENDAR, FIELD_TOO_LONG, BATCH_NOT_SUPPORTED (send one order, not an array).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"LINE_QUANTITY_AMBIGUOUS","detail":"The request could not be processed as written.","field_errors":[{"field":"lines[0].cases","code":"LINE_QUANTITY_AMBIGUOUS","detail":"Each line must specify exactly one of Cases or Units so the unit of measure is unambiguous.","index":0,"product_id":30008}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Key cannot make this change. Codes: CUSTOMER_NOT_PERMITTED, NOT_PERMITTED, TERMS_NOT_PERMITTED (own brands only), OTHER_SUPPLIERS, MANUAL_PROMOTION (sales rep required), FEATURE_DISABLED, ORDER_ACTOR_REQUIRED (linked user required), USER_INACTIVE, ACTOR_SCOPE_MISMATCH (supplier key linked to a customer user).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"CUSTOMER_NOT_PERMITTED","detail":"You cannot place orders for that customer."}}}}},"409":{"description":"Conflict: FIELD_IMMUTABLE (changed read-only field), or reused Idempotency-Key with a different request. With submit=true: DUPLICATE_PO_NUMBER (another recent order), DUPLICATE_PO_IN_ORDER (duplicate across splits), DUPLICATE_PO_IN_REVISION (duplicate across revised splits).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"DUPLICATE_PO_NUMBER","detail":"This order cannot be submitted as it stands.","field_errors":[{"field":"po_num","code":"DUPLICATE_PO_NUMBER","detail":"That PO number is already used on another recent order for this customer."}]}}}}},"413":{"description":"The order body is larger than 256 KB. An order may contain at most 200 lines.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"REQUEST_TOO_LARGE","detail":"The request body exceeds the maximum size for an order. An order may contain at most 200 lines."}}}}},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"description":"Line or import-row validation failed; see field_errors. Codes: PRODUCT_NOT_FOUND (unavailable in the customer's state), PRODUCT_NOT_FOR_SUPPLIER, PROMOTION_NOT_PERMITTED, SAMPLE_NOT_PERMITTED (Customer keys cannot add or increase samples), NOT_CASE_MULTIPLE, BELOW_MIN_ORDER, PRODUCT_MISSING_UNITS_PER_CASE (send units), QUANTITY_INVALID, CREDIT_TERM_NOT_FOUND, TERM_NOT_OFFERED, PENDING_ROW_NOT_FOUND. With submit=true: Submission blocked; see field_errors. Codes: NO_LINE_ITEMS (cancel instead of removing all lines), DELIVERY_DATE_REQUIRED, DELIVERY_DATE_PAST_CUTOFF, PENDING_IMPORT_ROWS, OUT_OF_STOCK, PRODUCT_INACTIVE, PRODUCT_NOT_AUTHORIZED, PRODUCT_NOT_FOUND, PROMOTION_UNAVAILABLE, PRICE_NOT_FOUND, PRICING_UNAVAILABLE. Line errors include index and product_id.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"PRODUCT_NOT_FOUND","detail":"The order lines could not be accepted.","field_errors":[{"field":"lines[1].product_id","code":"PRODUCT_NOT_FOUND","detail":"No product with that ProductID is sold in the customer's state.","index":1,"product_id":39999}]}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":false},"x-kss-pagination":false,"x-kss-beta":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["customer_id"],"properties":{"customer_id":{"type":"number","description":"The customer the order is placed for. Must be one you can act for."},"po_num":{"type":["string","null"],"description":"PO number, up to 50 characters. Must be unique among the customer's orders from the last 7 days when validated or submitted. Splits append -1, -2, etc. unless overridden; no number is generated if omitted."},"memo":{"type":["string","null"],"description":"Free-text note on the order, at most 500 characters."},"delivery_date":{"type":["string","null"],"format":"date","description":"Requested delivery date as YYYY-MM-DD with no time component. Required to submit."},"emails":{"type":["array","null"],"items":{"type":"string","format":"email"},"description":"Up to 20 buyer email addresses for order communications. Replaces the existing list; null or [] clears it."},"order_overrides":{"type":["object","null"],"description":"Optional po_num and memo per split order, keyed by groups[].group_key. Updates merge by key. Null removes a key or value; null for the whole field clears all overrides. An empty po_num suppresses the PO number.","additionalProperties":{"type":["object","null"],"properties":{"po_num":{"type":["string","null"]},"memo":{"type":["string","null"]}}}},"lines":{"type":"array","items":{"type":"object","required":["product_id"],"properties":{"product_id":{"type":"number","description":"Product to order."},"promotion_id":{"type":["number","null"],"description":"Manual promotion. Not available to Customer keys. Different promotions allow separate lines for the same product."},"units":{"type":"number","description":"Unit quantity, a positive whole number. Send exactly one of units or cases."},"cases":{"type":"number","description":"Case quantity, a positive number that must convert to a whole number of units. Send exactly one of units or cases."},"credit_term_id":{"type":["number","null"],"description":"Payment term override; may split this line into a separate order. The brand must allow overrides and offer this term. Omit to keep existing terms; null removes the override."},"accept_backorder":{"type":"boolean","description":"Accept unavailable units as a backorder instead of an out-of-stock issue."}}},"maxItems":200,"description":"Up to 200 lines, each with units or cases. Replaces ALL existing lines when sent. Repeated product/promotion pairs are combined."},"save_term_defaults":{"type":"object","description":"On submission, save selected custom payment terms as the customer's supplier defaults.","properties":{"group_keys":{"type":"array","items":{"type":"string"},"description":"Group keys whose custom terms should become defaults."},"supplier_ids":{"type":"array","items":{"type":"number"},"description":"Suppliers whose custom terms should become defaults."}}}}},"example":{"customer_id":41001,"po_num":"PO-1042","memo":"Deliver to the back dock","delivery_date":"2026-10-14","emails":["buyer@example.com"],"lines":[{"product_id":30008,"cases":10},{"product_id":30009,"units":48,"accept_backorder":true}]}}}},"x-kss-callout":"Send Idempotency-Key to avoid duplicate orders on retries. Invalid case multiples or minimum quantities return 422; Prefer: handling=lenient adjusts them. Matching read-only fields are ignored; changed values return 409 FIELD_IMMUTABLE.","x-kss-fieldDefinitions":[{"name":"id","description":"The order's permanent 26-character order ID. Use it to read, edit, submit, or delete the order."},{"name":"version","description":"The order's current version, also returned as the ETag header. Send it back in If-Match to make later changes conditional."},{"name":"warnings","description":"Non-blocking notices: QUANTITY_ADJUSTED, CUSTOMER_ON_HOLD, DELIVERY_DATE_WILL_BE_ADJUSTED."},{"name":"resulting_orders","description":"Orders produced by submission. Separate invoice requirements or payment terms can split one order into several."},{"name":"resulting_orders[].id","description":"The resulting order's 26-character order ID. Null for an order whose ID is not confirmed yet; use invoice_id."},{"name":"resulting_orders[].invoice_id","description":"The invoice ID, when the order already has one. Null for new orders."},{"name":"resulting_orders[].role","description":"original is the submitted order itself, split is a new order created from it, revised is a posted order updated by a pending change, and cancelled is a posted order cancelled because none of its remaining lines belong on it."},{"name":"resulting_orders[].group_key","description":"Identifies the group of lines the order covers, the same value used in order_overrides. Null for cancelled."},{"name":"resulting_orders[].order_number","description":"Position of the order among the orders produced, starting at 1. Null for cancelled."},{"name":"resulting_orders[].status","description":"Always queued at submission time. Read the order to follow its progress."},{"name":"resulting_orders[].split_reason","description":"Why the order was created separately, with a code and a detail. Null for the original and revised orders."},{"name":"resulting_orders[].totals","description":"The order's totals, in the same shape as the totals field. Null for cancelled."}],"summary":"Creates a draft (201)."}},"/orders/creditTerms":{"get":{"tags":["Orders"],"operationId":"getOrderCreditTerms","description":"Returns the payment terms that can be used as credit_term_id on an order line, ordered by term_id.","parameters":[{"name":"term_ids","in":"query","required":false,"description":"Comma-separated list of term IDs to filter by.","schema":{"type":"string","pattern":"^\\d+(,\\d+)*$","example":"1,2,3"},"example":"1,2,3"},{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PageSize"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data","page","page_size","has_next_page"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"page":{"type":"number"},"page_size":{"type":"number"},"has_next_page":{"type":"boolean"}}},"example":{"data":[{"term_id":80003,"term":"Net 30","days_of_credit":30,"account_on_hold":false,"time_updated":"2026-01-15T18:00:00.000Z"}],"page":1,"page_size":50,"has_next_page":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Key cannot read orders: USER_INACTIVE (linked user deactivated) or ACTOR_SCOPE_MISMATCH (supplier key linked to a customer user).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"USER_INACTIVE","detail":"The user behind this API key is deactivated. Storefront login access is not required for API use."}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":false},"x-kss-pagination":true,"x-kss-beta":true,"x-kss-fieldDefinitions":[{"name":"term_id","description":"The payment term's ID, used as credit_term_id on order lines."},{"name":"term","description":"The payment term's name."},{"name":"days_of_credit","description":"How many days of credit the term allows."},{"name":"account_on_hold","description":"True when the term places the customer's account on hold."},{"name":"time_updated","description":"When the payment term was last updated."}],"summary":"Returns the payment terms that can be used as credit_term_id on an order line, ordered ..."}},"/orders/validate":{"post":{"tags":["Orders"],"operationId":"validateOrder","description":"Checks whether an order can be submitted, without saving it. Returns valid, errors, warnings, and a pricing/split preview. For an existing order, send order_id and the changes you would PATCH. An API key without a linked user can validate.","parameters":[{"$ref":"#/components/parameters/Prefer"}],"responses":{"200":{"description":"Validation result.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":true}}},"example":{"data":{"valid":false,"errors":[{"field":"delivery_date","code":"DELIVERY_DATE_REQUIRED","detail":"A delivery date is required before the order can be submitted."}],"warnings":[],"pricing_date":"2026-10-08","lines":[{"product_id":30008,"product_name":"Acme Gummies 10pk","supplier_id":20001,"supplier_name":"Acme Brands","promotion_id":null,"quantity_promotion_id":null,"units":120,"backorder_units":0,"shipped_units":120,"cases":10,"unit_price":"11.50","full_price":"12.50","discount":"1.00","ext_price":"1380.00","requested_ext_price":"1380.00","credit_term_id":80003,"credit_term":"Net 30","term_overridden":false,"accept_backorder":false,"minimum_applied":false,"exception":null,"issues":[]},{"product_id":30009,"product_name":"Acme Chews 10pk","supplier_id":20001,"supplier_name":"Acme Brands","promotion_id":null,"quantity_promotion_id":null,"units":48,"backorder_units":24,"shipped_units":24,"cases":4,"unit_price":"24.00","full_price":"24.00","discount":"0.00","ext_price":"576.00","requested_ext_price":"1152.00","credit_term_id":80003,"credit_term":"Net 30","term_overridden":false,"accept_backorder":true,"minimum_applied":false,"exception":"Backorder accepted","issues":[]}],"totals":{"units":168,"backorder_units":24,"shipped_units":144,"cases":14,"full_price":"2076.00","discount":"120.00","ext_price":"1956.00","requested_ext_price":"2532.00"},"groups":[{"group_key":"shared:0:0","order_number":1,"split_invoice_id":null,"credit_term_id":80003,"credit_term":"Net 30","term_overridden":false,"split_reason":null,"line_indexes":[0,1],"totals":{"units":168,"backorder_units":24,"shipped_units":144,"cases":14,"full_price":"2076.00","discount":"120.00","ext_price":"1956.00","requested_ext_price":"2532.00"},"is_original":true,"po_num":"PO-1042"}],"cancels_original":false}}}}},"400":{"description":"Invalid request; see field_errors for each problem. Codes: SCHEMA_VIOLATION, ORDER_IDENTIFIER_INVALID, LINE_QUANTITY_AMBIGUOUS (send exactly one of units or cases), QUANTITY_INVALID, TOO_MANY_LINE_ITEMS, DUPLICATE_LINE_CONFLICT (conflicting terms/backorder settings on repeated lines), DELIVERY_DATE_NOT_CALENDAR, FIELD_TOO_LONG, BATCH_NOT_SUPPORTED (send one order, not an array).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"SCHEMA_VIOLATION","detail":"The request could not be processed as written.","field_errors":[{"field":"customer_id","code":"SCHEMA_VIOLATION","detail":"CustomerID is required."}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Key cannot make this change. Codes: CUSTOMER_NOT_PERMITTED, NOT_PERMITTED, TERMS_NOT_PERMITTED (own brands only), OTHER_SUPPLIERS, MANUAL_PROMOTION (sales rep required), FEATURE_DISABLED, ORDER_ACTOR_REQUIRED (linked user required), USER_INACTIVE, ACTOR_SCOPE_MISMATCH (supplier key linked to a customer user).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"CUSTOMER_NOT_PERMITTED","detail":"You cannot place orders for that customer."}}}}},"404":{"description":"The order named by order_id does not exist or is outside what the key can access. Code: ORDER_NOT_FOUND.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ORDER_NOT_FOUND","detail":"Order not found."}}}}},"409":{"description":"The body cannot be validated against the order. Code: CUSTOMER_IMMUTABLE (customer_id differs from the customer on an existing order).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"CUSTOMER_IMMUTABLE","detail":"The customer on a submitted order cannot be changed."}}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"description":"Line or import-row validation failed; see field_errors. Codes: PRODUCT_NOT_FOUND (unavailable in the customer's state), PRODUCT_NOT_FOR_SUPPLIER, PROMOTION_NOT_PERMITTED, SAMPLE_NOT_PERMITTED (Customer keys cannot add or increase samples), NOT_CASE_MULTIPLE, BELOW_MIN_ORDER, PRODUCT_MISSING_UNITS_PER_CASE (send units), QUANTITY_INVALID, CREDIT_TERM_NOT_FOUND, TERM_NOT_OFFERED, PENDING_ROW_NOT_FOUND.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"PRODUCT_NOT_FOUND","detail":"The order lines could not be accepted.","field_errors":[{"field":"lines[1].product_id","code":"PRODUCT_NOT_FOUND","detail":"No product with that ProductID is sold in the customer's state.","index":1,"product_id":39999}]}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":false},"x-kss-pagination":false,"x-kss-beta":true,"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"order_id":{"type":"string","description":"Existing order ID or invoice ID to validate changes against. Omit for a new order and supply customer_id."},"version":{"type":"string","description":"Last-read version. A stale version adds a VERSION_MISMATCH warning; validation uses the current order."},"customer_id":{"type":"number","description":"Required when order_id is omitted."},"po_num":{"type":["string","null"],"description":"PO number, up to 50 characters. Must be unique among the customer's orders from the last 7 days when validated or submitted. Splits append -1, -2, etc. unless overridden; no number is generated if omitted."},"memo":{"type":["string","null"],"description":"Free-text note on the order, at most 500 characters."},"delivery_date":{"type":["string","null"],"format":"date","description":"Requested delivery date as YYYY-MM-DD with no time component. Required to submit."},"emails":{"type":["array","null"],"items":{"type":"string","format":"email"},"description":"Up to 20 buyer email addresses for order communications. Replaces the existing list; null or [] clears it."},"order_overrides":{"type":["object","null"],"description":"Optional po_num and memo per split order, keyed by groups[].group_key. Updates merge by key. Null removes a key or value; null for the whole field clears all overrides. An empty po_num suppresses the PO number.","additionalProperties":{"type":["object","null"],"properties":{"po_num":{"type":["string","null"]},"memo":{"type":["string","null"]}}}},"lines":{"type":"array","items":{"type":"object","required":["product_id"],"properties":{"product_id":{"type":"number","description":"Product to order."},"promotion_id":{"type":["number","null"],"description":"Manual promotion. Not available to Customer keys. Different promotions allow separate lines for the same product."},"units":{"type":"number","description":"Unit quantity, a positive whole number. Send exactly one of units or cases."},"cases":{"type":"number","description":"Case quantity, a positive number that must convert to a whole number of units. Send exactly one of units or cases."},"credit_term_id":{"type":["number","null"],"description":"Payment term override; may split this line into a separate order. The brand must allow overrides and offer this term. Omit to keep existing terms; null removes the override."},"accept_backorder":{"type":"boolean","description":"Accept unavailable units as a backorder instead of an out-of-stock issue."}}},"maxItems":200,"description":"Up to 200 lines, each with units or cases. Replaces ALL existing lines when sent. Repeated product/promotion pairs are combined."},"pending_import_rows":{"type":["array","null"],"items":{"type":"number"},"description":"Unresolved import row numbers to KEEP; unlisted rows are discarded. Null or [] discards all. A row that is not pending returns 422."}}},"example":{"customer_id":41001,"po_num":"PO-1042","lines":[{"product_id":30008,"cases":10},{"product_id":30009,"units":48,"accept_backorder":true}]}}}},"x-kss-callout":"Check valid, even on a 200 response: submission problems are reported in errors. A missed delivery cutoff is a warning for new orders and an error for posted edits. A blocked posted edit reports its reason under field order_id.","x-kss-fieldDefinitions":[{"name":"valid","description":"True when errors is empty, so the order could be submitted as it stands."},{"name":"errors","description":"Problems that would block submission, each with a field, code, and detail. Line problems carry an index and product_id."},{"name":"warnings","description":"Caveats that do not block submission, in the same shape as errors. Codes: QUANTITY_ADJUSTED, DELIVERY_DATE_WILL_BE_ADJUSTED, CUSTOMER_ON_HOLD, ORIGINAL_INVOICE_WILL_BE_CANCELLED, and VERSION_MISMATCH, which is returned only here when the version you sent no longer matches the order."},{"name":"pricing_date","description":"The date the lines were priced for. Null when no lines could be priced."},{"name":"lines","description":"The priced lines, in the same shape as lines on an unsubmitted order, including issues."},{"name":"totals","description":"Totals across all lines, in the same shape as totals on an order. Null when no lines could be priced. For an existing order, keys limited to certain suppliers see lines, groups, totals, and line issues for their suppliers only, except on unsubmitted drafts they can edit."},{"name":"groups","description":"Split preview: group_key, order_number, is_original (stays on the existing order), split_reason, totals, line_indexes, po_num. PO numbers use overrides or the original with -1, -2, etc. for splits; null if none was supplied."},{"name":"cancels_original","description":"True when validating a change to a posted order in which none of the remaining lines belong on the original order, so submitting would cancel it and move the lines to new orders."}],"summary":"Checks whether an order can be submitted, without saving it."}},"/orders/{order_id}":{"get":{"tags":["Orders"],"operationId":"getOrder","description":"Returns an order with lines and allowed_actions. Drafts are repriced on each read. The ETag holds the current version for If-Match; responses are not cached.","parameters":[{"name":"order_id","in":"path","required":true,"description":"26-character order ID (all stages) or numeric invoice ID (posted orders only).","schema":{"type":"string","pattern":"^([1-9]\\d*|[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26})$"}},{"name":"include_lines","in":"query","required":false,"description":"Lines are included by default. Send false to omit lines.","schema":{"type":"boolean","default":true}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":true}}},"example":{"data":{"id":"01K9X7P5TD0A1MFY6S2GHQ8RNC","invoice_id":90017,"invoice_num":"INV-90017","stage":"posted","status":"accepted","invoice_status":1,"invoice_status_name":"New","is_credit":false,"version":"v1.Zq4N8cXw1LmT6vYb0RhPjK3sDfG7uEaO9iWtSyCe2Bk","customer_id":41001,"customer_name":"Example Dispensary","state":"CA","po_num":"PO-1031","po_date":"2026-10-06T07:00:00.000Z","memo":null,"delivery_date":"2026-10-14","emails":["buyer@example.com"],"term_id":70002,"credit_term_id":80003,"credit_term":"Net 30","split_invoice_id":null,"due_date":"2026-11-13T07:00:00.000Z","invoice_total":"1380.00","open_debit":"1380.00","open_credit":"0.00","open_balance":"1380.00","pdf_url":null,"ar_note":null,"submitted_by_user_id":10042,"submitted_by_user_name":"Jamie Example","submitted_by_user_email":"jamie@example.com","built_by_user_id":10042,"built_by_user_name":"Jamie Example","built_by_user_email":"jamie@example.com","time_created":"2026-10-06T16:12:44.000Z","time_updated":"2026-10-06T16:30:02.000Z","totals":{"units":120,"cases":10,"full_price":"1500.00","discount":"120.00","ext_price":"1380.00"},"pending_change":null,"cancellation":null,"processing":null,"related_orders":{"parent_id":null,"parent_invoice_id":null,"split_children":[]},"allowed_actions":{"update":{"allowed":true},"submit":{"allowed":false,"reason":"NO_PENDING_CHANGES","detail":"There are no pending changes to submit."},"discard_changes":{"allowed":false,"reason":"REVISION_NOT_FOUND","detail":"This order has no pending changes."},"cancel":{"allowed":true},"delete":{"allowed":true},"change_terms":{"allowed":true},"set_promotions":{"allowed":true}},"lines":[{"invoice_trans_id":91001,"product_id":30008,"product_name":"Acme Gummies 10pk","supplier_id":20001,"promotion_id":null,"applied_promotion_id":null,"promotion_overridden":false,"units":120,"shipped_units":120,"backorder_units":0,"cases":10,"unit_price":"11.50","full_price":"12.50","discount":"1.00","ext_price":"1380.00","batch_code":"26191BBB01","coa_url":"https://cdn.example.com/coa/26191BBB01.pdf"}]}}}},"headers":{"ETag":{"description":"Quoted order version. Send it in If-Match to prevent overwriting a changed order.","schema":{"type":"string"}},"Cache-Control":{"description":"Always no-store.","schema":{"type":"string"}}}},"400":{"description":"Invalid filter (SCHEMA_VIOLATION) or order ID (ORDER_IDENTIFIER_INVALID). IDs must be 26-character order IDs or positive invoice IDs.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ORDER_IDENTIFIER_INVALID","detail":"Order identifiers must be a 26-character order ID or a positive integer invoice ID."}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Key cannot read orders: USER_INACTIVE (linked user deactivated) or ACTOR_SCOPE_MISMATCH (supplier key linked to a customer user).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"USER_INACTIVE","detail":"The user behind this API key is deactivated. Storefront login access is not required for API use."}}}}},"404":{"description":"ORDER_NOT_FOUND: order does not exist or is outside the key's access.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ORDER_NOT_FOUND","detail":"Order not found."}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":false},"x-kss-pagination":false,"x-kss-beta":true,"x-kss-fieldDefinitions":[{"name":"id","description":"Permanent 26-character order ID, valid across all stages. If null on a posted order, use invoice_id."},{"name":"invoice_id","description":"Numeric invoice ID, also accepted in order URLs. Null until posted."},{"name":"invoice_num","description":"The invoice number shown to the customer. Null until the order is posted."},{"name":"stage","description":"draft: editable, not submitted. submitted: queued or processing. posted: processed, with an invoice."},{"name":"status","description":"Draft: draft, deleted. Submitted: queued → importing → accepted (awaiting posting), or rejected (see processing.message). Posted: accepted (new), on_the_way, delivered, cancelled."},{"name":"invoice_status","description":"Numeric invoice status, the same values as Statuses in v1 invoices: 1 New, 2 Locked for Routing, 3 Loaded, 4 Returned, 5 Balanced, 7 Verified. Null until the order is posted."},{"name":"invoice_status_name","description":"The name of invoice_status. Null until the order is posted."},{"name":"is_credit","description":"True for a credit order. Credit orders cannot be edited."},{"name":"version","description":"Changes when the order or pending change changes. Also returned as ETag; use for If-Match or validation's version."},{"name":"customer_id","description":"The customer the order is placed for."},{"name":"customer_name","description":"The customer's name."},{"name":"state","description":"The customer's state."},{"name":"po_num","description":"The customer's purchase order number."},{"name":"po_date","description":"The PO date recorded on the posted order. Null until the order is posted."},{"name":"memo","description":"Free-text note on the order."},{"name":"delivery_date","description":"Requested delivery date as YYYY-MM-DD. On a posted order this is the order's delivery date."},{"name":"emails","description":"Buyer email addresses that receive order communications."},{"name":"term_id","description":"Payment term ID recorded on the posted order. Null before posting."},{"name":"credit_term_id","description":"The payment terms the order is on. On an unsubmitted order this is the terms it would be created with. Use GET /orders/creditTerms to look terms up."},{"name":"credit_term","description":"The name of credit_term_id."},{"name":"split_invoice_id","description":"Set when the order belongs to a separate invoice series, which a product can require."},{"name":"due_date","description":"When payment is due. Null until the order is posted."},{"name":"invoice_total","description":"Invoice total as a string with 2 decimals. Null until the order is posted. open_debit, open_credit, and open_balance are the outstanding amounts in the same format."},{"name":"pdf_url","description":"Link to the invoice PDF when one is available."},{"name":"ar_note","description":"Accounts receivable note on the invoice, when one exists."},{"name":"submitted_by_user_id","description":"The user who submitted the order. submitted_by_user_name and submitted_by_user_email identify them on posted orders; built_by_user_id, built_by_user_name, and built_by_user_email identify the user who built it."},{"name":"time_created","description":"When the order was created."},{"name":"time_updated","description":"When the order was last updated."},{"name":"totals","description":"Money uses strings with 2 decimals. units/cases count requested quantities. Drafts include shipped_units, ext_price (shippable total), and requested_ext_price (all requested units). full_price is before discounts; discount is the total discount. Keys limited to certain suppliers see totals for their suppliers' lines only, except on unsubmitted drafts they can edit."},{"name":"lines","description":"Line items. Omitted by default on lists; included by default on single-order reads. Drafts include credit_term_id, accept_backorder, minimum_applied (raised to product minimum), and issues. Posted lines include invoice_trans_id. Keys limited to certain suppliers see only their suppliers' lines, except on unsubmitted drafts they can edit."},{"name":"lines[].units","description":"Requested units on draft/posted orders; shippable units during submission processing. backorder_units counts unavailable units; shipped_units counts units that will or did ship."},{"name":"lines[].unit_price","description":"Per-unit price; full_price and discount are also per unit. ext_price = unit_price × shipped_units; requested_ext_price = unit_price × requested units."},{"name":"lines[].promotion_id","description":"Manual promotion to send back when editing. On posted lines, set only when promotion_overridden is true; applied_promotion_id identifies the pricing promotion, including automatic promotions."},{"name":"lines[].batch_code","description":"Batch the posted line was picked from. Null until assigned."},{"name":"lines[].coa_url","description":"Batch certificate of analysis URL. Null until attached."},{"name":"lines[].issues","description":"Submission blockers with code and detail: OUT_OF_STOCK, PRODUCT_INACTIVE, PRODUCT_NOT_AUTHORIZED, PRODUCT_NOT_FOUND, PROMOTION_UNAVAILABLE, PRICE_NOT_FOUND. Drafts can be saved with issues; submission returns 422."},{"name":"groups","description":"Draft split preview on single-order reads/writes. Separate invoice requirements or payment terms can split an order. Each group has group_key, order_number, credit terms, totals, line_indexes, and split_reason (SEPARATE_INVOICE_REQUIRED, CUSTOM_TERMS, SPLIT_INVOICE, DIFFERENT_TERMS; null for the first group)."},{"name":"order_overrides","description":"PO number and memo overrides for individual orders an order splits into, keyed by group_key. Present on unsubmitted orders."},{"name":"pending_import_rows","description":"Rows from an imported file that could not be turned into line items. Each entry has a row_number. An order with pending rows cannot be submitted until they are resolved or discarded."},{"name":"pending_change","description":"Posted-order edit preview with the proposed header, lines, groups, and totals. Keys limited to certain suppliers see only their suppliers' lines, groups, and totals. state: draft → submitted → processing → applied (awaiting sync), or rejected (see message). editor and updated_by identify the first and last editors by user_id/name."},{"name":"cancellation","description":"Posted cancellation request: state, requested_at, requested_by_user_id, message. state: pending → applied (awaiting sync) → completed, or rejected (see message)."},{"name":"processing","description":"Present on submitted orders: attempts is how many times processing has been tried, message the latest processing message, and updated_at when it last changed."},{"name":"related_orders","description":"Orders this order is connected to. parent_id and parent_invoice_id identify the order it was split from, and split_children lists the orders split from it, each with an id and invoice_id."},{"name":"allowed_actions","description":"Available actions: update, submit, discard_changes, cancel, delete, change_terms, set_promotions. Each has allowed; blocked actions include reason and detail matching write-error codes. Check these before offering an action."},{"name":"warnings","description":"Present on write responses when the request succeeded with caveats. Each warning has a field, code, and detail, and line warnings carry an index and product_id. Codes are QUANTITY_ADJUSTED, DELIVERY_DATE_WILL_BE_ADJUSTED, CUSTOMER_ON_HOLD, and ORIGINAL_INVOICE_WILL_BE_CANCELLED."},{"name":"resulting_orders","description":"Present on responses to submitting. See the field definitions on POST /orders/{order_id}/submit."}],"summary":"Returns an order with lines and allowed_actions."},"patch":{"tags":["Orders"],"operationId":"updateOrder","description":"Edits a draft directly, or saves pending_change on a posted order for later submission. Send only changed fields; omitted fields stay unchanged and null clears nullable fields. Add ?submit=true to save and submit atomically (202). Requires an API key linked to an active user.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"order_id","in":"path","required":true,"description":"26-character order ID (all stages) or numeric invoice ID (posted orders only).","schema":{"type":"string","pattern":"^([1-9]\\d*|[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26})$"}},{"$ref":"#/components/parameters/Prefer"},{"name":"If-Match","in":"header","required":false,"description":"Last-read version or ETag; stale values return 412 VERSION_MISMATCH. Required when another user last edited the pending change; omitting it returns 409 REVISION_DRAFT_IN_USE.","schema":{"type":"string"}},{"name":"submit","in":"query","required":false,"description":"Save and submit the draft or pending change atomically (202). If submission fails, nothing is saved.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Updated. On a posted order the pending change is shown in pending_change. If Prefer: return=minimal is sent, the response is 204 with no body.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":true}}},"example":{"data":{"id":"01K9X7P5TD0A1MFY6S2GHQ8RNC","invoice_id":90017,"invoice_num":"INV-90017","stage":"posted","status":"accepted","invoice_status":1,"invoice_status_name":"New","is_credit":false,"version":"v1.Tn5Vb2KcXq8LzW1mRyHj7PdSf4GgA9uEoIeYtCs6Mw0","customer_id":41001,"customer_name":"Example Dispensary","state":"CA","po_num":"PO-1031","po_date":"2026-10-06T07:00:00.000Z","memo":null,"delivery_date":"2026-10-14","emails":["buyer@example.com"],"term_id":70002,"credit_term_id":80003,"credit_term":"Net 30","split_invoice_id":null,"due_date":"2026-11-13T07:00:00.000Z","invoice_total":"1380.00","open_debit":"1380.00","open_credit":"0.00","open_balance":"1380.00","pdf_url":null,"ar_note":null,"submitted_by_user_id":10042,"submitted_by_user_name":"Jamie Example","submitted_by_user_email":"jamie@example.com","built_by_user_id":10042,"built_by_user_name":"Jamie Example","built_by_user_email":"jamie@example.com","time_created":"2026-10-06T16:12:44.000Z","time_updated":"2026-10-08T16:02:10.000Z","totals":{"units":120,"cases":10,"full_price":"1500.00","discount":"120.00","ext_price":"1380.00"},"pending_change":{"state":"draft","updated_at":"2026-10-08T16:02:10.000Z","editor":{"user_id":10042,"name":"Jamie Example"},"updated_by":{"user_id":10042,"name":"Jamie Example"},"message":null,"delivery_date":"2026-10-15","po_num":"PO-1031","memo":null,"emails":["buyer@example.com"],"order_overrides":{},"totals":{"units":144,"backorder_units":0,"shipped_units":144,"cases":12,"full_price":"1800.00","discount":"144.00","ext_price":"1656.00","requested_ext_price":"1656.00"},"lines":[{"product_id":30008,"product_name":"Acme Gummies 10pk","supplier_id":20001,"supplier_name":"Acme Brands","promotion_id":null,"quantity_promotion_id":null,"units":144,"backorder_units":0,"shipped_units":144,"cases":12,"unit_price":"11.50","full_price":"12.50","discount":"1.00","ext_price":"1656.00","requested_ext_price":"1656.00","credit_term_id":80003,"credit_term":"Net 30","term_overridden":false,"accept_backorder":false,"minimum_applied":false,"exception":null,"issues":[]}],"groups":[{"group_key":"shared:0:0","order_number":1,"split_invoice_id":null,"credit_term_id":80003,"credit_term":"Net 30","term_overridden":false,"split_reason":null,"line_indexes":[0],"totals":{"units":144,"backorder_units":0,"shipped_units":144,"cases":12,"full_price":"1800.00","discount":"144.00","ext_price":"1656.00","requested_ext_price":"1656.00"}}]},"cancellation":null,"processing":null,"related_orders":{"parent_id":null,"parent_invoice_id":null,"split_children":[]},"allowed_actions":{"update":{"allowed":true},"submit":{"allowed":true},"discard_changes":{"allowed":true},"cancel":{"allowed":false,"reason":"REVISION_DRAFT_EXISTS","detail":"Discard or submit the pending changes before cancelling the order."},"delete":{"allowed":false,"reason":"REVISION_DRAFT_EXISTS","detail":"Discard or submit the pending changes before cancelling the order."},"change_terms":{"allowed":true},"set_promotions":{"allowed":true}},"lines":[{"invoice_trans_id":91001,"product_id":30008,"product_name":"Acme Gummies 10pk","supplier_id":20001,"promotion_id":null,"applied_promotion_id":null,"promotion_overridden":false,"units":120,"shipped_units":120,"backorder_units":0,"cases":10,"unit_price":"11.50","full_price":"12.50","discount":"1.00","ext_price":"1380.00","batch_code":"26191BBB01","coa_url":"https://cdn.example.com/coa/26191BBB01.pdf"}]}}}},"headers":{"ETag":{"description":"Quoted order version. Send it in If-Match to prevent overwriting a changed order.","schema":{"type":"string"}},"Idempotency-Replayed":{"description":"true when this response was replayed from a previous request with the same Idempotency-Key.","schema":{"type":"string"}},"Preference-Applied":{"description":"Echoes honored Prefer tokens, such as return=minimal or handling=lenient.","schema":{"type":"string"}}}},"202":{"description":"Updated and submitted with submit=true. resulting_orders lists the orders it produced. If Prefer: return=minimal is sent, the ETag header is returned with no response body.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":true}}},"example":{"data":{"id":"01K9X7M2QH4T8VZ3BN6CRWD5EJ","invoice_id":null,"invoice_num":null,"stage":"submitted","status":"queued","invoice_status":null,"invoice_status_name":null,"is_credit":false,"version":"v1.Hd7Fk2PzQw9XcN4rVyLm1TbS8gJeA6uOiYtCs0RnE3U","customer_id":41001,"customer_name":"Example Dispensary","state":"CA","po_num":"PO-1042","po_date":null,"memo":"Deliver to the back dock","delivery_date":"2026-10-14","emails":["buyer@example.com"],"term_id":null,"credit_term_id":80003,"credit_term":"Net 30","split_invoice_id":null,"due_date":null,"invoice_total":null,"open_debit":null,"open_credit":null,"open_balance":null,"pdf_url":null,"ar_note":null,"submitted_by_user_id":10042,"built_by_user_id":10042,"built_by_user_name":"Jamie Example","time_created":"2026-10-08T15:04:05.000Z","time_updated":"2026-10-08T15:20:31.000Z","totals":{"units":144,"backorder_units":24,"cases":12,"full_price":"2076.00","discount":"120.00","ext_price":"1956.00"},"order_overrides":{},"pending_import_rows":[],"pending_change":null,"cancellation":null,"processing":{"attempts":0,"message":"Queued by user 10042 via API","updated_at":"2026-10-08T15:20:31.000Z"},"related_orders":{"parent_id":null,"parent_invoice_id":null,"split_children":[]},"allowed_actions":{"update":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"submit":{"allowed":false,"reason":"ALREADY_SUBMITTED","detail":"This order has already been submitted."},"discard_changes":{"allowed":false,"reason":"REVISION_NOT_FOUND","detail":"This order has no pending changes."},"cancel":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"delete":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"change_terms":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"set_promotions":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."}},"lines":[{"product_id":30008,"product_name":"Acme Gummies 10pk","supplier_id":20001,"promotion_id":null,"quantity_promotion_id":null,"units":120,"backorder_units":0,"cases":10,"unit_price":"11.50","discount":"1.00","ext_price":"1380.00","credit_term_id":null,"term_overridden":false,"exception":null},{"product_id":30009,"product_name":"Acme Chews 10pk","supplier_id":20001,"promotion_id":null,"quantity_promotion_id":null,"units":24,"backorder_units":24,"cases":2,"unit_price":"24.00","discount":"0.00","ext_price":"576.00","credit_term_id":null,"term_overridden":false,"exception":"Backorder accepted"}],"resulting_orders":[{"id":"01K9X7M2QH4T8VZ3BN6CRWD5EJ","invoice_id":null,"role":"original","group_key":"shared:0:0","order_number":1,"status":"queued","split_reason":null,"totals":{"units":168,"backorder_units":24,"shipped_units":144,"cases":14,"full_price":"2076.00","discount":"120.00","ext_price":"1956.00","requested_ext_price":"2532.00"}}]}}}},"headers":{"ETag":{"description":"Quoted order version. Send it in If-Match to prevent overwriting a changed order.","schema":{"type":"string"}},"Idempotency-Replayed":{"description":"true when this response was replayed from a previous request with the same Idempotency-Key.","schema":{"type":"string"}},"Preference-Applied":{"description":"Echoes honored Prefer tokens, such as return=minimal or handling=lenient.","schema":{"type":"string"}}}},"204":{"description":"Updated. Returned when Prefer: return=minimal is sent."},"400":{"description":"Invalid request; see field_errors for each problem. Codes: SCHEMA_VIOLATION, ORDER_IDENTIFIER_INVALID, LINE_QUANTITY_AMBIGUOUS (send exactly one of units or cases), QUANTITY_INVALID, TOO_MANY_LINE_ITEMS, DUPLICATE_LINE_CONFLICT (conflicting terms/backorder settings on repeated lines), DELIVERY_DATE_NOT_CALENDAR, FIELD_TOO_LONG, BATCH_NOT_SUPPORTED (send one order, not an array).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"DELIVERY_DATE_NOT_CALENDAR","detail":"The request could not be processed as written.","field_errors":[{"field":"delivery_date","code":"DELIVERY_DATE_NOT_CALENDAR","detail":"DeliveryDate must be a calendar date formatted YYYY-MM-DD, with no time component."}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Key cannot make this change. Codes: CUSTOMER_NOT_PERMITTED, NOT_PERMITTED, TERMS_NOT_PERMITTED (own brands only), OTHER_SUPPLIERS, MANUAL_PROMOTION (sales rep required), FEATURE_DISABLED, ORDER_ACTOR_REQUIRED (linked user required), USER_INACTIVE, ACTOR_SCOPE_MISMATCH (supplier key linked to a customer user).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"NOT_PERMITTED","detail":"You cannot edit this order."}}}}},"404":{"description":"ORDER_NOT_FOUND: order does not exist or is outside the key's access.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ORDER_NOT_FOUND","detail":"Order not found."}}}}},"409":{"description":"State conflict. Drafts: ALREADY_SUBMITTED, NOT_EDITABLE_IN_STATE, ORDER_DELETED. Posted: NOT_NEW, LOCKED, PAYMENT_APPLIED, CREDIT_INVOICE, HAS_DOCUMENTS, PAST_CUTOFF, NO_DELIVERY_DATES, REVISION_PENDING (change processing), REVISION_SYNCING (change applied, awaiting sync), REVISION_DRAFT_IN_USE (send If-Match), REVISION_REJECTED (discard rejected cancellation), INVOICE_CHANGED_SINCE_DRAFT (discard stale edits and restart), CUSTOMER_IMMUTABLE, NO_EDITABLE_LINES. Read-only fields: FIELD_IMMUTABLE. With submit=true: DUPLICATE_PO_NUMBER (another recent order), DUPLICATE_PO_IN_ORDER (duplicate across splits), DUPLICATE_PO_IN_REVISION (duplicate across revised splits).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"NOT_NEW","detail":"This order is being processed for delivery and can no longer be changed."}}}}},"412":{"description":"If-Match no longer matches the order's version. Code: VERSION_MISMATCH. Fetch the order again and retry with its new version.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"VERSION_MISMATCH","detail":"The order changed since you last read it. Fetch it again and retry with the new version."}}}}},"413":{"description":"The order body is larger than 256 KB. An order may contain at most 200 lines.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"REQUEST_TOO_LARGE","detail":"The request body exceeds the maximum size for an order. An order may contain at most 200 lines."}}}}},"415":{"description":"Unsupported request content type.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"UNSUPPORTED_MEDIA_TYPE","detail":"PATCH bodies must be application/json. Fields present are applied, absent fields are left unchanged, and a Lines array replaces all lines."}}}}},"422":{"description":"Line or import-row validation failed; see field_errors. Codes: PRODUCT_NOT_FOUND (unavailable in the customer's state), PRODUCT_NOT_FOR_SUPPLIER, PROMOTION_NOT_PERMITTED, SAMPLE_NOT_PERMITTED (Customer keys cannot add or increase samples), NOT_CASE_MULTIPLE, BELOW_MIN_ORDER, PRODUCT_MISSING_UNITS_PER_CASE (send units), QUANTITY_INVALID, CREDIT_TERM_NOT_FOUND, TERM_NOT_OFFERED, PENDING_ROW_NOT_FOUND. With submit=true: Submission blocked; see field_errors. Codes: NO_LINE_ITEMS (cancel instead of removing all lines), DELIVERY_DATE_REQUIRED, DELIVERY_DATE_PAST_CUTOFF, PENDING_IMPORT_ROWS, OUT_OF_STOCK, PRODUCT_INACTIVE, PRODUCT_NOT_AUTHORIZED, PRODUCT_NOT_FOUND, PROMOTION_UNAVAILABLE, PRICE_NOT_FOUND, PRICING_UNAVAILABLE. Line errors include index and product_id.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"BELOW_MIN_ORDER","detail":"The order lines could not be accepted.","field_errors":[{"field":"lines[0].units","code":"BELOW_MIN_ORDER","detail":"This product has a minimum order of 24 units.","index":0,"product_id":30008}]}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":false},"x-kss-pagination":false,"x-kss-beta":true,"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"customer_id":{"type":"number","description":"May be repeated, but the customer on an order cannot be changed once it has been submitted."},"po_num":{"type":["string","null"],"description":"PO number, up to 50 characters. Must be unique among the customer's orders from the last 7 days when validated or submitted. Splits append -1, -2, etc. unless overridden; no number is generated if omitted."},"memo":{"type":["string","null"],"description":"Free-text note on the order, at most 500 characters."},"delivery_date":{"type":["string","null"],"format":"date","description":"Requested delivery date as YYYY-MM-DD with no time component. Required to submit."},"emails":{"type":["array","null"],"items":{"type":"string","format":"email"},"description":"Up to 20 buyer email addresses for order communications. Replaces the existing list; null or [] clears it."},"order_overrides":{"type":["object","null"],"description":"Optional po_num and memo per split order, keyed by groups[].group_key. Updates merge by key. Null removes a key or value; null for the whole field clears all overrides. An empty po_num suppresses the PO number.","additionalProperties":{"type":["object","null"],"properties":{"po_num":{"type":["string","null"]},"memo":{"type":["string","null"]}}}},"lines":{"type":"array","items":{"type":"object","required":["product_id"],"properties":{"product_id":{"type":"number","description":"Product to order."},"promotion_id":{"type":["number","null"],"description":"Manual promotion. Not available to Customer keys. Different promotions allow separate lines for the same product."},"units":{"type":"number","description":"Unit quantity, a positive whole number. Send exactly one of units or cases."},"cases":{"type":"number","description":"Case quantity, a positive number that must convert to a whole number of units. Send exactly one of units or cases."},"credit_term_id":{"type":["number","null"],"description":"Payment term override; may split this line into a separate order. The brand must allow overrides and offer this term. Omit to keep existing terms; null removes the override."},"accept_backorder":{"type":"boolean","description":"Accept unavailable units as a backorder instead of an out-of-stock issue."}}},"maxItems":200,"description":"Up to 200 lines, each with units or cases. Replaces ALL existing lines when sent. Repeated product/promotion pairs are combined."},"pending_import_rows":{"type":["array","null"],"items":{"type":"number"},"description":"Unresolved import row numbers to KEEP; unlisted rows are discarded. Null or [] discards all. A row that is not pending returns 422."},"save_term_defaults":{"type":"object","description":"On submission, save selected custom payment terms as the customer's supplier defaults.","properties":{"group_keys":{"type":"array","items":{"type":"string"},"description":"Group keys whose custom terms should become defaults."},"supplier_ids":{"type":"array","items":{"type":"number"},"description":"Suppliers whose custom terms should become defaults."}}}}},"example":{"delivery_date":"2026-10-15","lines":[{"product_id":30008,"units":144}]}}}},"x-kss-callout":"Sending lines replaces ALL lines: include every line to keep. Matching product/promotion pairs retain their terms unless credit_term_id is sent. Check allowed_actions.update and send If-Match. Posted edits take effect after submission and processing; status cannot be set directly.","x-kss-fieldDefinitions":[{"name":"pending_change","description":"Proposed posted-order changes. Updated on each edit; the posted order changes only after submission and processing."},{"name":"version","description":"The order's new version, also returned as the ETag header. It changes after every edit."},{"name":"warnings","description":"Present when the update was saved with caveats, such as a QUANTITY_ADJUSTED line under Prefer: handling=lenient."},{"name":"resulting_orders","description":"Orders produced by submission. Separate invoice requirements or payment terms can split one order into several."},{"name":"resulting_orders[].id","description":"The resulting order's 26-character order ID. Null for an order whose ID is not confirmed yet; use invoice_id."},{"name":"resulting_orders[].invoice_id","description":"The invoice ID, when the order already has one. Null for new orders."},{"name":"resulting_orders[].role","description":"original is the submitted order itself, split is a new order created from it, revised is a posted order updated by a pending change, and cancelled is a posted order cancelled because none of its remaining lines belong on it."},{"name":"resulting_orders[].group_key","description":"Identifies the group of lines the order covers, the same value used in order_overrides. Null for cancelled."},{"name":"resulting_orders[].order_number","description":"Position of the order among the orders produced, starting at 1. Null for cancelled."},{"name":"resulting_orders[].status","description":"Always queued at submission time. Read the order to follow its progress."},{"name":"resulting_orders[].split_reason","description":"Why the order was created separately, with a code and a detail. Null for the original and revised orders."},{"name":"resulting_orders[].totals","description":"The order's totals, in the same shape as the totals field. Null for cancelled."}],"summary":"Edits a draft directly, or saves pending_change on a posted order for later submission."},"delete":{"tags":["Orders"],"operationId":"deleteOrder","description":"Deletes a draft (204) or requests cancellation of a posted order (202). Repeated requests return the current outcome. Submitted orders still being processed cannot be deleted or cancelled. Requires an API key linked to an active user.","parameters":[{"name":"order_id","in":"path","required":true,"description":"26-character order ID (all stages) or numeric invoice ID (posted orders only).","schema":{"type":"string","pattern":"^([1-9]\\d*|[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26})$"}},{"$ref":"#/components/parameters/Prefer"},{"name":"If-Match","in":"header","required":false,"description":"Last-read version or ETag; stale values return 412 VERSION_MISMATCH.","schema":{"type":"string"}}],"responses":{"202":{"description":"Cancellation of a posted order was requested, or is already under way or complete. If Prefer: return=minimal is sent, the ETag header is returned with no response body.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":true}}},"example":{"data":{"id":"01K9X7P5TD0A1MFY6S2GHQ8RNC","invoice_id":90017,"invoice_num":"INV-90017","stage":"posted","status":"accepted","invoice_status":1,"invoice_status_name":"New","is_credit":false,"version":"v1.Pw3Lc8XnQ1VzK6mRtHj2YdSf5GgA7uEoIbTeCs9Nk4","customer_id":41001,"customer_name":"Example Dispensary","state":"CA","po_num":"PO-1031","po_date":"2026-10-06T07:00:00.000Z","memo":null,"delivery_date":"2026-10-14","emails":["buyer@example.com"],"term_id":70002,"credit_term_id":80003,"credit_term":"Net 30","split_invoice_id":null,"due_date":"2026-11-13T07:00:00.000Z","invoice_total":"1380.00","open_debit":"1380.00","open_credit":"0.00","open_balance":"1380.00","pdf_url":null,"ar_note":null,"submitted_by_user_id":10042,"submitted_by_user_name":"Jamie Example","submitted_by_user_email":"jamie@example.com","built_by_user_id":10042,"built_by_user_name":"Jamie Example","built_by_user_email":"jamie@example.com","time_created":"2026-10-06T16:12:44.000Z","time_updated":"2026-10-06T16:30:02.000Z","totals":{"units":120,"cases":10,"full_price":"1500.00","discount":"120.00","ext_price":"1380.00"},"pending_change":null,"cancellation":{"state":"pending","requested_at":"2026-10-08T16:40:12.000Z","requested_by_user_id":10042,"message":null},"processing":null,"related_orders":{"parent_id":null,"parent_invoice_id":null,"split_children":[]},"allowed_actions":{"update":{"allowed":false,"reason":"REVISION_PENDING","detail":"This update is being processed. Try again after it is confirmed."},"submit":{"allowed":false,"reason":"REVISION_PENDING","detail":"This update is being processed. Try again after it is confirmed."},"discard_changes":{"allowed":false,"reason":"REVISION_NOT_FOUND","detail":"This order has no pending changes."},"cancel":{"allowed":false,"reason":"CANCELLATION_REQUESTED","detail":"Cancellation has already been requested."},"delete":{"allowed":false,"reason":"CANCELLATION_REQUESTED","detail":"Cancellation has already been requested."},"change_terms":{"allowed":false,"reason":"TERMS_NOT_PERMITTED","detail":"You cannot change payment terms on this order."},"set_promotions":{"allowed":false,"reason":"PROMOTION_NOT_PERMITTED","detail":"You cannot apply manual promotions."}}}}}},"headers":{"ETag":{"description":"Quoted order version. Send it in If-Match to prevent overwriting a changed order.","schema":{"type":"string"}},"Preference-Applied":{"description":"Echoes honored Prefer tokens, such as return=minimal or handling=lenient.","schema":{"type":"string"}}}},"204":{"description":"The draft was deleted, or had already been deleted."},"400":{"description":"Invalid filter (SCHEMA_VIOLATION) or order ID (ORDER_IDENTIFIER_INVALID). IDs must be 26-character order IDs or positive invoice IDs.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ORDER_IDENTIFIER_INVALID","detail":"Order identifiers must be a 26-character order ID or a positive integer invoice ID."}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Key cannot make this change. Codes: CUSTOMER_NOT_PERMITTED, NOT_PERMITTED, TERMS_NOT_PERMITTED (own brands only), OTHER_SUPPLIERS, MANUAL_PROMOTION (sales rep required), FEATURE_DISABLED, ORDER_ACTOR_REQUIRED (linked user required), USER_INACTIVE, ACTOR_SCOPE_MISMATCH (supplier key linked to a customer user).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"NOT_PERMITTED","detail":"You cannot delete this order."}}}}},"404":{"description":"ORDER_NOT_FOUND: order does not exist or is outside the key's access.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ORDER_NOT_FOUND","detail":"Order not found."}}}}},"409":{"description":"State conflict: REVISION_DRAFT_EXISTS (submit/discard edits first), NOTHING_TO_CANCEL, ORDER_PROCESSING, INVOICE_NOT_SYNCED (wait for posting), NOT_EDITABLE_IN_STATE. Posted orders also use: NOT_NEW, LOCKED, PAYMENT_APPLIED, CREDIT_INVOICE, HAS_DOCUMENTS, PAST_CUTOFF, NO_DELIVERY_DATES, REVISION_PENDING (change processing), REVISION_SYNCING (change applied, awaiting sync).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"REVISION_DRAFT_EXISTS","detail":"Discard or submit the pending changes before cancelling the order."}}}}},"412":{"description":"If-Match no longer matches the order's version. Code: VERSION_MISMATCH. Fetch the order again and retry with its new version.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"VERSION_MISMATCH","detail":"The order changed since you last read it. Fetch it again and retry with the new version."}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":false},"x-kss-pagination":false,"x-kss-beta":true,"x-kss-callout":"Submit or discard pending edits before cancelling. Poll GET /orders/{order_id}: cancellation.state progresses pending → applied → completed. If rejected, read cancellation.message and discard the request with DELETE /orders/{order_id}/revision before retrying.","x-kss-fieldDefinitions":[{"name":"cancellation.state","description":"pending while the cancellation is queued or being processed, applied once it has been accepted and is waiting to sync, completed once the order is cancelled, and rejected if it was refused."},{"name":"cancellation.requested_at","description":"When cancellation was requested."},{"name":"cancellation.requested_by_user_id","description":"The user who requested cancellation."},{"name":"cancellation.message","description":"Why a cancellation was rejected. Null otherwise."}],"summary":"Deletes a draft (204) or requests cancellation of a posted order (202)."}},"/orders/{order_id}/submit":{"post":{"tags":["Orders"],"operationId":"submitOrder","description":"Submits a draft or a posted order's pending change. Revalidates the order and returns 202 when queued; processing continues in the background. Poll GET /orders/{order_id} for progress. Requires an API key linked to an active user.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"},{"name":"order_id","in":"path","required":true,"description":"26-character order ID (all stages) or numeric invoice ID (posted orders only).","schema":{"type":"string","pattern":"^([1-9]\\d*|[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26})$"}},{"$ref":"#/components/parameters/Prefer"},{"name":"If-Match","in":"header","required":false,"description":"Last-read version or ETag; stale values return 412 VERSION_MISMATCH. Required when another user last edited the pending change; omitting it returns 409 REVISION_DRAFT_IN_USE.","schema":{"type":"string"}}],"responses":{"202":{"description":"Accepted for processing. If Prefer: return=minimal is sent, the ETag header is returned with no response body.","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"object","additionalProperties":true}}},"example":{"data":{"id":"01K9X7M2QH4T8VZ3BN6CRWD5EJ","invoice_id":null,"invoice_num":null,"stage":"submitted","status":"queued","invoice_status":null,"invoice_status_name":null,"is_credit":false,"version":"v1.Hd7Fk2PzQw9XcN4rVyLm1TbS8gJeA6uOiYtCs0RnE3U","customer_id":41001,"customer_name":"Example Dispensary","state":"CA","po_num":"PO-1042","po_date":null,"memo":"Deliver to the back dock","delivery_date":"2026-10-14","emails":["buyer@example.com"],"term_id":null,"credit_term_id":80003,"credit_term":"Net 30","split_invoice_id":null,"due_date":null,"invoice_total":null,"open_debit":null,"open_credit":null,"open_balance":null,"pdf_url":null,"ar_note":null,"submitted_by_user_id":10042,"built_by_user_id":10042,"built_by_user_name":"Jamie Example","time_created":"2026-10-08T15:04:05.000Z","time_updated":"2026-10-08T15:20:31.000Z","totals":{"units":144,"backorder_units":24,"cases":12,"full_price":"2076.00","discount":"120.00","ext_price":"1956.00"},"order_overrides":{},"pending_import_rows":[],"pending_change":null,"cancellation":null,"processing":{"attempts":0,"message":"Queued by user 10042 via API","updated_at":"2026-10-08T15:20:31.000Z"},"related_orders":{"parent_id":null,"parent_invoice_id":null,"split_children":[]},"allowed_actions":{"update":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"submit":{"allowed":false,"reason":"ALREADY_SUBMITTED","detail":"This order has already been submitted."},"discard_changes":{"allowed":false,"reason":"REVISION_NOT_FOUND","detail":"This order has no pending changes."},"cancel":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"delete":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"change_terms":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."},"set_promotions":{"allowed":false,"reason":"ORDER_PROCESSING","detail":"This order is being processed and cannot be changed."}},"lines":[{"product_id":30008,"product_name":"Acme Gummies 10pk","supplier_id":20001,"promotion_id":null,"quantity_promotion_id":null,"units":120,"backorder_units":0,"cases":10,"unit_price":"11.50","discount":"1.00","ext_price":"1380.00","credit_term_id":null,"term_overridden":false,"exception":null},{"product_id":30009,"product_name":"Acme Chews 10pk","supplier_id":20001,"promotion_id":null,"quantity_promotion_id":null,"units":24,"backorder_units":24,"cases":2,"unit_price":"24.00","discount":"0.00","ext_price":"576.00","credit_term_id":null,"term_overridden":false,"exception":"Backorder accepted"}],"resulting_orders":[{"id":"01K9X7M2QH4T8VZ3BN6CRWD5EJ","invoice_id":null,"role":"original","group_key":"shared:0:0","order_number":1,"status":"queued","split_reason":null,"totals":{"units":168,"backorder_units":24,"shipped_units":144,"cases":14,"full_price":"2076.00","discount":"120.00","ext_price":"1956.00","requested_ext_price":"2532.00"}}]}}}},"headers":{"ETag":{"description":"Quoted order version. Send it in If-Match to prevent overwriting a changed order.","schema":{"type":"string"}},"Idempotency-Replayed":{"description":"true when this response was replayed from a previous request with the same Idempotency-Key.","schema":{"type":"string"}},"Preference-Applied":{"description":"Echoes honored Prefer tokens, such as return=minimal or handling=lenient.","schema":{"type":"string"}}}},"400":{"description":"Invalid request; see field_errors for each problem. Codes: SCHEMA_VIOLATION, ORDER_IDENTIFIER_INVALID, LINE_QUANTITY_AMBIGUOUS (send exactly one of units or cases), QUANTITY_INVALID, TOO_MANY_LINE_ITEMS, DUPLICATE_LINE_CONFLICT (conflicting terms/backorder settings on repeated lines), DELIVERY_DATE_NOT_CALENDAR, FIELD_TOO_LONG, BATCH_NOT_SUPPORTED (send one order, not an array).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"SCHEMA_VIOLATION","detail":"The submit body may only contain SaveTermDefaults. Update the order with PATCH first.","field_errors":[{"field":"memo","code":"SCHEMA_VIOLATION","detail":"Memo is not accepted when submitting."}]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Key cannot make this change. Codes: CUSTOMER_NOT_PERMITTED, NOT_PERMITTED, TERMS_NOT_PERMITTED (own brands only), OTHER_SUPPLIERS, MANUAL_PROMOTION (sales rep required), FEATURE_DISABLED, ORDER_ACTOR_REQUIRED (linked user required), USER_INACTIVE, ACTOR_SCOPE_MISMATCH (supplier key linked to a customer user).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"NOT_PERMITTED","detail":"You cannot submit this order."}}}}},"404":{"description":"ORDER_NOT_FOUND: order does not exist or is outside the key's access.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ORDER_NOT_FOUND","detail":"Order not found."}}}}},"409":{"description":"State conflict: ALREADY_SUBMITTED, ORDER_DELETED, NO_PENDING_CHANGES, REVISION_REJECTED (edit to reopen), INVOICE_CHANGED_SINCE_DRAFT (discard stale edits and restart), REVISION_DRAFT_IN_USE (send If-Match), DUPLICATE_PO_NUMBER (another recent order), DUPLICATE_PO_IN_ORDER (duplicate across splits), DUPLICATE_PO_IN_REVISION (duplicate across revised splits). Posted orders also use: NOT_NEW, LOCKED, PAYMENT_APPLIED, CREDIT_INVOICE, HAS_DOCUMENTS, PAST_CUTOFF, NO_DELIVERY_DATES, REVISION_PENDING (change processing), REVISION_SYNCING (change applied, awaiting sync).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ALREADY_SUBMITTED","detail":"An order in status Submitted cannot be submitted."}}}}},"412":{"description":"If-Match no longer matches the order's version. Code: VERSION_MISMATCH. Fetch the order again and retry with its new version.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"VERSION_MISMATCH","detail":"The order changed since you last read it. Fetch it again and retry with the new version."}}}}},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"description":"Submission blocked; see field_errors. Codes: NO_LINE_ITEMS (cancel instead of removing all lines), DELIVERY_DATE_REQUIRED, DELIVERY_DATE_PAST_CUTOFF, PENDING_IMPORT_ROWS, OUT_OF_STOCK, PRODUCT_INACTIVE, PRODUCT_NOT_AUTHORIZED, PRODUCT_NOT_FOUND, PROMOTION_UNAVAILABLE, PRICE_NOT_FOUND, PRICING_UNAVAILABLE. Line errors include index and product_id.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"DELIVERY_DATE_REQUIRED","detail":"This order cannot be submitted as it stands.","field_errors":[{"field":"delivery_date","code":"DELIVERY_DATE_REQUIRED","detail":"A delivery date is required before the order can be submitted."}]}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":false},"x-kss-pagination":false,"x-kss-beta":true,"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"save_term_defaults":{"type":"object","description":"On submission, save selected custom payment terms as the customer's supplier defaults.","properties":{"group_keys":{"type":"array","items":{"type":"string"},"description":"Group keys whose custom terms should become defaults."},"supplier_ids":{"type":"array","items":{"type":"number"},"description":"Suppliers whose custom terms should become defaults."}}}}},"example":{"save_term_defaults":{"group_keys":["shared:0:80003"],"supplier_ids":[20001]}}}}},"x-kss-callout":"No body is needed; only save_term_defaults is accepted. Send Idempotency-Key for safe retries. Missed delivery cutoffs move new orders to the next available date with a warning; posted edits return 422 DELIVERY_DATE_PAST_CUTOFF.","x-kss-fieldDefinitions":[{"name":"stage","description":"submitted in the response to a draft, with status queued. In the response to a posted order's pending change the order stays posted and pending_change.state is submitted."},{"name":"warnings","description":"Present when the order was accepted with caveats: CUSTOMER_ON_HOLD, DELIVERY_DATE_WILL_BE_ADJUSTED, or ORIGINAL_INVOICE_WILL_BE_CANCELLED."},{"name":"resulting_orders","description":"Orders produced by submission. Separate invoice requirements or payment terms can split one order into several."},{"name":"resulting_orders[].id","description":"The resulting order's 26-character order ID. Null for an order whose ID is not confirmed yet; use invoice_id."},{"name":"resulting_orders[].invoice_id","description":"The invoice ID, when the order already has one. Null for new orders."},{"name":"resulting_orders[].role","description":"original is the submitted order itself, split is a new order created from it, revised is a posted order updated by a pending change, and cancelled is a posted order cancelled because none of its remaining lines belong on it."},{"name":"resulting_orders[].group_key","description":"Identifies the group of lines the order covers, the same value used in order_overrides. Null for cancelled."},{"name":"resulting_orders[].order_number","description":"Position of the order among the orders produced, starting at 1. Null for cancelled."},{"name":"resulting_orders[].status","description":"Always queued at submission time. Read the order to follow its progress."},{"name":"resulting_orders[].split_reason","description":"Why the order was created separately, with a code and a detail. Null for the original and revised orders."},{"name":"resulting_orders[].totals","description":"The order's totals, in the same shape as the totals field. Null for cancelled."}],"summary":"Submits a draft or a posted order's pending change."}},"/orders/{order_id}/revision":{"delete":{"tags":["Orders"],"operationId":"discardOrderPendingChanges","description":"Discards unsubmitted edits or a rejected cancellation on a posted order (204). The posted order stays unchanged. Already-submitted changes cannot be discarded. For drafts, use DELETE /orders/{order_id}. Requires an API key linked to an active user.","parameters":[{"name":"order_id","in":"path","required":true,"description":"The posted order's 26-character order ID or its numeric invoice ID.","schema":{"type":"string","pattern":"^([1-9]\\d*|[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26})$"}},{"name":"If-Match","in":"header","required":false,"description":"Last-read version or ETag; stale values return 412 VERSION_MISMATCH. Required when another user last edited the pending change; omitting it returns 409 REVISION_DRAFT_IN_USE.","schema":{"type":"string"}}],"responses":{"204":{"description":"The pending changes were discarded, or there were none."},"400":{"description":"Invalid filter (SCHEMA_VIOLATION) or order ID (ORDER_IDENTIFIER_INVALID). IDs must be 26-character order IDs or positive invoice IDs.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"ORDER_IDENTIFIER_INVALID","detail":"Order identifiers must be a 26-character order ID or a positive integer invoice ID."}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Key cannot make this change. Codes: CUSTOMER_NOT_PERMITTED, NOT_PERMITTED, TERMS_NOT_PERMITTED (own brands only), OTHER_SUPPLIERS, MANUAL_PROMOTION (sales rep required), FEATURE_DISABLED, ORDER_ACTOR_REQUIRED (linked user required), USER_INACTIVE, ACTOR_SCOPE_MISMATCH (supplier key linked to a customer user).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"OTHER_SUPPLIERS","detail":"This order includes products from other suppliers."}}}}},"404":{"description":"No order with that identifier exists, the key cannot access it, or the order is an unsubmitted draft. Codes: ORDER_NOT_FOUND, REVISION_NOT_FOUND (the order has not been posted, so it has no pending changes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"REVISION_NOT_FOUND","detail":"Only submitted orders have pending changes to discard."}}}}},"409":{"description":"The pending changes cannot be discarded right now. Codes: REVISION_PENDING (the changes are being processed), REVISION_SYNCING (the changes were applied and are waiting to sync), REVISION_DRAFT_IN_USE (another user last edited the pending change and no If-Match was sent).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"REVISION_PENDING","detail":"These changes are being processed and cannot be discarded."}}}}},"412":{"description":"If-Match no longer matches the order's version. Code: VERSION_MISMATCH. Fetch the order again and retry with its new version.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"example":{"error":{"code":"VERSION_MISMATCH","detail":"The order changed since you last read it. Fetch it again and retry with the new version."}}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"500":{"$ref":"#/components/responses/ServerError"}},"x-kss-auth":{"supplierRestricted":false,"customerRestricted":false},"x-kss-pagination":false,"x-kss-beta":true,"summary":"Discards unsubmitted edits or a rejected cancellation on a posted order (204)."}}}}