{"openapi":"3.1.0","info":{"title":"Profi API","version":"2026-09-17","description":"Public REST API of the Profi family (ProfiBrew, ProfiEkonom). Paths include the `/api/v1` prefix; use the host of the product you integrate with. Quantities always travel with their unit."},"servers":[{"url":"https://www.profibrew.com","description":"ProfiBrew (brewery accounts)"},{"url":"https://app.profifirma.cz","description":"ProfiEkonom and other verticals"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key from Settings → API (`pb_live_…` or sandbox `pb_test_…`)."}},"schemas":{"Health":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"time":{"type":"string","example":"2026-09-15T07:00:00.000Z"},"api_version":{"type":"string","example":"2026-09-17"}},"required":["status","time","api_version"]},"Me":{"type":"object","properties":{"object":{"type":"string","enum":["me"]},"api_version":{"type":"string"},"livemode":{"type":"boolean","description":"false = sandbox key (demo account)."},"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":"string"},"slug":{"type":"string"},"vertical":{"type":"string","example":"brewery"},"country_code":{"type":"string","example":"CZ"}},"required":["id","name","slug","vertical","country_code"]},"key":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":"string"}},"required":["id","name"]},"scopes":{"type":"array","items":{"type":"string"},"example":["core:read","sales:write"]},"modules":{"type":"array","items":{"type":"string"},"description":"Modules and add-ons active in the subscription.","example":["core","stock","sales"]},"limits":{"type":"object","properties":{"rate_per_min":{"type":"integer"},"max_keys":{"type":"integer"},"max_webhook_endpoints":{"type":"integer"},"events_retention_days":{"type":"integer"}},"required":["rate_per_min","max_keys","max_webhook_endpoints","events_retention_days"]},"measure_profile":{"type":"object","properties":{"unit_system":{"type":"string","enum":["metric","uk","us"]},"axes":{"type":"object","additionalProperties":{"type":"object","properties":{"unit":{"type":"string","example":"c"},"canonical_unit":{"type":"string","example":"c","description":"Unit of the stored (canonical) value."}},"required":["unit","canonical_unit"]}}},"required":["unit_system","axes"]}},"required":["object","api_version","livemode","tenant","key","scopes","modules","limits","measure_profile"]},"Problem":{"type":"object","properties":{"type":{"type":"string","example":"https://www.profibrew.com/developers#errors-validation_failed"},"title":{"type":"string"},"status":{"type":"integer"},"code":{"type":"string","example":"validation_failed"},"detail":{"type":"string"},"instance":{"type":"string","description":"Request id (`X-Request-Id`)."},"errors":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["field","code","message"]}}},"required":["type","title","status","code"],"additionalProperties":{}},"UnitList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Unit"}}},"required":["data"]},"Unit":{"type":"object","properties":{"object":{"type":"string","enum":["unit"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"code":{"type":"string","example":"kg"},"symbol":{"type":"string","example":"kg"},"name_cs":{"type":"string"},"name_en":{"type":"string"},"dimension":{"type":"string","enum":["weight","volume","count"]},"base_unit_code":{"type":["string","null"],"description":"kg / l / ks; null = the unit is a base or has no conversion."},"to_base_factor":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"1 unit = factor × base unit."},"decimals":{"type":["integer","null"]},"is_system":{"type":"boolean"},"is_active":{"type":"boolean"},"systems":{"type":"array","items":{"type":"string"},"example":["metric","uk","us"]},"offered_for_materials":{"type":"array","items":{"type":"string"},"description":"Brew material types this unit may be used for (system units only).","example":["hop","yeast"]}},"required":["object","id","code","symbol","name_cs","name_en","dimension","base_unit_code","to_base_factor","decimals","is_system","is_active","systems","offered_for_materials"]},"PartnerList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Partner"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"Partner":{"type":"object","properties":{"object":{"type":"string","enum":["partner"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":"string"},"is_customer":{"type":"boolean"},"is_supplier":{"type":"boolean"},"ico":{"type":["string","null"],"example":"12345678"},"dic":{"type":["string","null"],"example":"CZ12345678"},"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"mobile":{"type":["string","null"]},"web":{"type":["string","null"]},"address":{"type":"object","properties":{"street":{"type":["string","null"]},"city":{"type":["string","null"]},"zip":{"type":["string","null"]},"country_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"}},"required":["street","city","zip","country_id"]},"payment_terms":{"type":"integer","description":"Due days."},"price_list_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"notes":{"type":["string","null"]},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"is_active":{"type":"boolean"},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","name","is_customer","is_supplier","ico","dic","email","phone","mobile","web","address","payment_terms","price_list_id","notes","external_ref","is_active","livemode","created_at","updated_at"]},"ExternalRef":{"type":["object","null"],"properties":{"system":{"type":"string","pattern":"^[a-z0-9_-]{2,32}$","example":"shoptet"},"id":{"type":"string","minLength":1,"maxLength":128,"example":"10234"}},"required":["system","id"],"additionalProperties":false,"description":"Identity of the record in the integrator's system. Unique per account; a second POST with the same reference → 409 external_ref_conflict (or the existing record with ?on_conflict=return)."},"PartnerCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"is_customer":{"type":"boolean","default":true},"is_supplier":{"type":"boolean","default":false},"ico":{"type":["string","null"],"maxLength":20},"dic":{"type":["string","null"],"maxLength":20},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"],"maxLength":40},"mobile":{"type":["string","null"],"maxLength":40},"web":{"type":["string","null"],"maxLength":200},"address":{"type":"object","properties":{"street":{"type":["string","null"],"maxLength":200},"city":{"type":["string","null"],"maxLength":120},"zip":{"type":["string","null"],"maxLength":20},"country_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"}},"additionalProperties":false},"payment_terms":{"type":"integer","minimum":0,"maximum":365},"price_list_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"notes":{"type":["string","null"],"maxLength":4000},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"is_active":{"type":"boolean"}},"required":["name"],"additionalProperties":false},"PartnerPatch":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"is_customer":{"type":"boolean"},"is_supplier":{"type":"boolean"},"ico":{"type":["string","null"],"maxLength":20},"dic":{"type":["string","null"],"maxLength":20},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"],"maxLength":40},"mobile":{"type":["string","null"],"maxLength":40},"web":{"type":["string","null"],"maxLength":200},"address":{"type":"object","properties":{"street":{"type":["string","null"],"maxLength":200},"city":{"type":["string","null"],"maxLength":120},"zip":{"type":["string","null"],"maxLength":20},"country_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"}},"additionalProperties":false},"payment_terms":{"type":"integer","minimum":0,"maximum":365},"price_list_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"notes":{"type":["string","null"],"maxLength":4000},"is_active":{"type":"boolean"}},"additionalProperties":false},"ContactList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}}},"required":["data"]},"Contact":{"type":"object","properties":{"object":{"type":"string","enum":["contact"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"partner_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":"string"},"position":{"type":["string","null"]},"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"mobile":{"type":["string","null"]},"is_primary":{"type":"boolean"},"notes":{"type":["string","null"]},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","partner_id","name","position","email","phone","mobile","is_primary","notes","created_at","updated_at"]},"ContactCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"position":{"type":["string","null"],"maxLength":120},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"],"maxLength":40},"mobile":{"type":["string","null"],"maxLength":40},"is_primary":{"type":"boolean"},"notes":{"type":["string","null"],"maxLength":4000}},"required":["name"],"additionalProperties":false},"ContactWithPartnerList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ContactWithPartner"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"ContactWithPartner":{"type":"object","properties":{"object":{"type":"string","enum":["contact"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"partner":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":"string"}},"required":["id","name"]},"name":{"type":"string"},"position":{"type":["string","null"]},"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"mobile":{"type":["string","null"]},"is_primary":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","partner","name","position","email","phone","mobile","is_primary","created_at","updated_at"]},"ItemList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Item"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"Item":{"type":"object","properties":{"object":{"type":"string","enum":["item"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"code":{"type":["string","null"]},"name":{"type":"string"},"brand":{"type":["string","null"]},"item_type":{"type":"string","enum":["brew_material","production_item","base_product","purchased_sale_item","packaging","service","other"]},"material_type":{"type":["string","null"]},"stock_category":{"type":["string","null"]},"unit":{"$ref":"#/components/schemas/UnitRef"},"recipe_unit":{"allOf":[{"$ref":"#/components/schemas/UnitRef"},{"description":"Recipe entry unit (hops); same dimension as `unit`."}]},"base_item_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Production item this packaged product is filled from (item_type base_product)."},"base_item_quantity":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"How much of the base item one piece holds, in the base item's unit (e.g. litres per keg)."},"is_packaging":{"type":"boolean"},"packaging_type":{"type":["string","null"]},"volume_l":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Litres per piece for packaging / beer items (canonical)."},"abv":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"plato":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"ean":{"type":["string","null"]},"barcode":{"type":["string","null"]},"sale_price":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"sale_vat_rate_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"pos_available":{"type":"boolean"},"web_available":{"type":"boolean"},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"is_active":{"type":"boolean"},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","code","name","brand","item_type","material_type","stock_category","unit","recipe_unit","base_item_id","base_item_quantity","is_packaging","packaging_type","volume_l","abv","plato","ean","barcode","sale_price","sale_vat_rate_id","pos_available","web_available","external_ref","is_active","livemode","created_at","updated_at"]},"UnitRef":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"code":{"type":"string","example":"kg"},"symbol":{"type":"string","example":"kg"},"dimension":{"type":"string","enum":["weight","volume","count"]},"decimals":{"type":["integer","null"],"description":"Max. decimal places; null = 3."}},"required":["id","code","symbol","dimension","decimals"]},"ItemCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"item_type":{"type":"string","enum":["brew_material","production_item","base_product","purchased_sale_item","packaging","service","other"],"default":"other"},"material_type":{"type":["string","null"],"maxLength":40},"unit":{"$ref":"#/components/schemas/UnitInput"},"recipe_unit":{"allOf":[{"$ref":"#/components/schemas/UnitInput"},{"type":["object","null"],"description":"Exactly one of `unit_id` / `unit_code`."}]},"base_item_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Required for item_type base_product (an existing production item); not allowed for other types."},"base_item_quantity":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Quantity of the base item per piece, in the base item's unit (e.g. 30 for a 30 l keg)."},"brand":{"type":["string","null"],"maxLength":120},"packaging_type":{"type":["string","null"],"maxLength":40},"volume_l":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"abv":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"plato":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"ean":{"type":["string","null"],"maxLength":40},"barcode":{"type":["string","null"],"maxLength":80},"sale_price":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"sale_vat_rate_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"pos_available":{"type":"boolean"},"web_available":{"type":"boolean"},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"is_active":{"type":"boolean"}},"required":["name","unit"],"additionalProperties":false},"UnitInput":{"type":"object","properties":{"unit_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"unit_code":{"type":"string","minLength":1,"maxLength":10,"example":"kg","description":"System code or the account's own unit code."}},"additionalProperties":false,"description":"Stock unit of the item — required."},"ItemPatch":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"item_type":{"type":"string","enum":["brew_material","production_item","base_product","purchased_sale_item","packaging","service","other"]},"material_type":{"type":["string","null"],"maxLength":40},"unit":{"$ref":"#/components/schemas/UnitInput"},"recipe_unit":{"allOf":[{"$ref":"#/components/schemas/UnitInput"},{"type":["object","null"],"description":"Exactly one of `unit_id` / `unit_code`."}]},"base_item_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Required for item_type base_product (an existing production item); not allowed for other types."},"base_item_quantity":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Quantity of the base item per piece, in the base item's unit (e.g. 30 for a 30 l keg)."},"brand":{"type":["string","null"],"maxLength":120},"packaging_type":{"type":["string","null"],"maxLength":40},"volume_l":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"abv":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"plato":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"ean":{"type":["string","null"],"maxLength":40},"barcode":{"type":["string","null"],"maxLength":80},"sale_price":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"sale_vat_rate_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"pos_available":{"type":"boolean"},"web_available":{"type":"boolean"},"is_active":{"type":"boolean"}},"additionalProperties":false},"Price":{"type":"object","properties":{"object":{"type":"string","enum":["price"]},"item_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"partner_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"$ref":"#/components/schemas/UnitRef"},"unit_price":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"currency":{"type":"string","example":"CZK"},"price_source":{"type":"string","example":"pricelist_item"},"base_price":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"discount_pct":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."}},"required":["object","item_id","partner_id","quantity","unit","unit_price","currency","price_source","base_price","discount_pct"]},"OrderList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"Order":{"type":"object","properties":{"object":{"type":"string","enum":["order"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"number":{"type":"string","example":"OBJ-2026-0012"},"status":{"type":"string","enum":["draft","confirmed","in_preparation","shipped","delivered","invoiced","cancelled"]},"partner":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]}},"required":["id","name"]},"contact_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"order_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"delivery_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"shipped_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"delivered_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"shop_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"warehouse_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"event_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"activity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"currency":{"type":"string"},"totals":{"type":"object","properties":{"excl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"incl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"deposit":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."}},"required":["excl_vat","vat","incl_vat","deposit"]},"invoice_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"stock_issue_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"stock_issue_status":{"type":["string","null"]},"cashflow_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"origin":{"type":"string","example":"api","description":"manual | template | b2b_portal | pos | api"},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"delivery":{"type":"object","properties":{"type":{"type":["string","null"],"enum":["pickup","own_transport","courier",null]},"street":{"type":["string","null"]},"city":{"type":["string","null"]},"zip":{"type":["string","null"]},"country":{"type":["string","null"]}},"required":["type","street","city","zip","country"]},"payment_method":{"type":["string","null"],"enum":["cash","bank_transfer","card",null]},"notes":{"type":["string","null"]},"internal_notes":{"type":["string","null"]},"lines":{"type":"array","items":{"$ref":"#/components/schemas/OrderLine"},"description":"Present on the detail, not in lists."},"allowed_actions":{"type":"array","items":{"type":"string"},"example":["confirm","cancel"]},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","number","status","partner","contact_id","order_date","delivery_date","shipped_date","delivered_date","shop_id","warehouse_id","category_id","event_id","activity_id","currency","totals","invoice_id","stock_issue_id","stock_issue_status","cashflow_id","origin","external_ref","delivery","payment_method","notes","internal_notes","allowed_actions","livemode","created_at","updated_at"]},"OrderLine":{"type":"object","properties":{"object":{"type":"string","enum":["order_line"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"order_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"item":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"code":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","code","name"]},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"allOf":[{"$ref":"#/components/schemas/UnitRef"},{"description":"Unit of the item — lines are always in the item's unit."}]},"unit_price":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"vat_rate_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"discount_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"totals":{"type":["object","null"],"properties":{"excl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"incl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."}},"required":["excl_vat","vat","incl_vat"]},"deposit":{"type":"object","properties":{"id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"pieces":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"total":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."}},"required":["id","pieces","total"],"description":"Returnable packaging deposit on the line: deposit item, number of pieces and total (pieces × deposit amount)."},"volume_l":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Read-only: quantity × item volume_l (packaging / beer items), litres."},"notes":{"type":["string","null"]},"sort_order":{"type":"integer"},"price_source":{"type":["string","null"]},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","order_id","item","quantity","unit","unit_price","vat_rate_pct","discount_pct","totals","deposit","volume_l","notes","sort_order","price_source","created_at"]},"OrderCreate":{"type":"object","properties":{"partner_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"contact_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"order_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"Defaults to today."},"delivery_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"warehouse_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Determines the shop of the order. Required when the account has more than one active shop (422 shop_required)."},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"event_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"activity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"notes":{"type":["string","null"],"maxLength":4000},"internal_notes":{"type":["string","null"],"maxLength":4000},"delivery":{"type":"object","properties":{"type":{"type":["string","null"],"enum":["pickup","own_transport","courier",null]},"street":{"type":["string","null"],"maxLength":200},"city":{"type":["string","null"],"maxLength":120},"zip":{"type":["string","null"],"maxLength":20},"country":{"type":["string","null"],"maxLength":120}},"additionalProperties":false},"payment_method":{"type":["string","null"],"enum":["cash","bank_transfer","card",null]},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/OrderLineCreate"},"maxItems":500}},"required":["partner_id"],"additionalProperties":false},"OrderLineCreate":{"type":"object","properties":{"item_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"allOf":[{"$ref":"#/components/schemas/UnitInput"},{"description":"Must be the item's unit (422 unit_mismatch otherwise); no conversion in v1."}]},"unit_price":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Omit to use the same price cascade as an order line in the app (partner price, price list, discounts, base price)."},"vat_rate_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"21","description":"VAT rate in percent as a decimal string: 0–100, at most 2 decimal places."},"discount_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"deposit_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"deposit_quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"notes":{"type":["string","null"],"maxLength":2000}},"required":["item_id","quantity","unit"],"additionalProperties":false},"OrderPatch":{"type":"object","properties":{"partner_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"contact_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"delivery_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"warehouse_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Determines the shop of the order. Required when the account has more than one active shop (422 shop_required)."},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"event_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"activity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"notes":{"type":["string","null"],"maxLength":4000},"internal_notes":{"type":["string","null"],"maxLength":4000},"delivery":{"type":"object","properties":{"type":{"type":["string","null"],"enum":["pickup","own_transport","courier",null]},"street":{"type":["string","null"],"maxLength":200},"city":{"type":["string","null"],"maxLength":120},"zip":{"type":["string","null"],"maxLength":20},"country":{"type":["string","null"],"maxLength":120}},"additionalProperties":false},"payment_method":{"type":["string","null"],"enum":["cash","bank_transfer","card",null]}},"additionalProperties":false},"OrderLinePatch":{"type":"object","properties":{"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"allOf":[{"$ref":"#/components/schemas/UnitInput"},{"description":"Must be the item's unit (422 unit_mismatch otherwise); no conversion in v1."}]},"unit_price":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Omit to use the same price cascade as an order line in the app (partner price, price list, discounts, base price)."},"vat_rate_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"21","description":"VAT rate in percent as a decimal string: 0–100, at most 2 decimal places."},"discount_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"deposit_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"deposit_quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"notes":{"type":["string","null"],"maxLength":2000}},"additionalProperties":false},"OrderActionResult":{"allOf":[{"$ref":"#/components/schemas/Order"},{"type":"object","properties":{"created":{"type":"object","properties":{"object":{"type":"string","enum":["stock_issue","invoice"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"}},"required":["object","id"],"description":"Document created by the action (create_stock_issue, create_invoice)."}}}]},"WarehouseList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Warehouse"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"Warehouse":{"type":"object","properties":{"object":{"type":"string","enum":["warehouse"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"code":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"shop_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"shop_name":{"type":["string","null"]},"categories":{"type":["array","null"],"items":{"type":"string"},"description":"suroviny | pivo | obaly | …"},"is_excise_relevant":{"type":"boolean"},"is_default":{"type":"boolean"},"is_active":{"type":"boolean"},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","code","name","type","shop_id","shop_name","categories","is_excise_relevant","is_default","is_active","livemode","created_at","updated_at"]},"ShopList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Shop"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"Shop":{"type":"object","properties":{"object":{"type":"string","enum":["shop"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":"string"},"shop_type":{"type":"string"},"address":{"type":["object","null"],"properties":{"street":{"type":["string","null"]},"city":{"type":["string","null"]},"zip":{"type":["string","null"]},"country":{"type":["string","null"]}},"required":["street","city","zip","country"]},"is_default":{"type":"boolean"},"is_active":{"type":"boolean"},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","name","shop_type","address","is_default","is_active","livemode","created_at","updated_at"]},"GoodsReceiptList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StockDocument"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"StockDocument":{"type":"object","properties":{"object":{"type":"string","enum":["goods_receipt","stock_issue"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"number":{"type":"string","example":"PR-2026-0012"},"movement_type":{"type":"string","enum":["receipt","issue"]},"movement_purpose":{"type":"string","enum":["purchase","production_in","production_out","sale","transfer","inventory","inventory_surplus","inventory_shortage","waste","packaging_dispatch","packaging_return","repack","tank_release","packaging_consumption","other"]},"status":{"type":"string","enum":["draft","confirmed","cancelled"]},"date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"warehouse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]}},"required":["id","name"]},"target_warehouse":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]}},"required":["id","name"],"description":"Destination warehouse of a transfer (movement_purpose=transfer); null otherwise."},"partner":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]}},"required":["id","name"]},"order_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"batch_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"totals":{"type":"object","properties":{"additional_cost":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"total_cost":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."}},"required":["additional_cost","total_cost"]},"notes":{"type":["string","null"]},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/StockLine"},"description":"Present on the detail, not in lists."},"allowed_actions":{"type":"array","items":{"type":"string"},"example":["confirm","cancel"]},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","number","movement_type","movement_purpose","status","date","warehouse","target_warehouse","partner","order_id","batch_id","totals","notes","external_ref","allowed_actions","livemode","created_at","updated_at"]},"StockLine":{"type":"object","properties":{"object":{"type":"string","enum":["stock_line"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"item":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"code":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","code","name"]},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Requested quantity, in the item's unit."},"issued_quantity":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Quantity actually posted by a confirmed document; equals `quantity` on a draft unless overridden."},"unit":{"allOf":[{"$ref":"#/components/schemas/UnitRef"},{"description":"Unit of the item — lines are always in the item's unit."}]},"unit_price":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"lot_number":{"type":["string","null"]},"expiry_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"notes":{"type":["string","null"]},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","item","quantity","issued_quantity","unit","unit_price","lot_number","expiry_date","notes","created_at"]},"StockIssueList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StockDocument"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"GoodsReceiptCreate":{"type":"object","properties":{"movement_purpose":{"type":"string","enum":["purchase","production_in","production_out","sale","transfer","inventory","inventory_surplus","inventory_shortage","waste","packaging_dispatch","packaging_return","repack","tank_release","packaging_consumption","other"],"description":"Defaults to `purchase` for a goods receipt, `sale` for a stock issue."},"date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"Defaults to today."},"warehouse_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"target_warehouse_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Destination warehouse — only meaningful for movement_purpose=transfer."},"partner_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"batch_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"notes":{"type":["string","null"],"maxLength":4000},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/GoodsReceiptLineCreate"},"maxItems":500}},"required":["warehouse_id"],"additionalProperties":false},"GoodsReceiptLineCreate":{"type":"object","properties":{"item_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"allOf":[{"$ref":"#/components/schemas/UnitInput"},{"description":"Must be the item's unit (422 unit_mismatch otherwise); no conversion in v1."}]},"unit_price":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"lot_number":{"type":["string","null"],"maxLength":120,"description":"Batch/lot label. A receipt line creates a new lot with this label."},"expiry_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"notes":{"type":["string","null"],"maxLength":2000}},"required":["item_id","quantity","unit"],"additionalProperties":false},"StockIssueCreate":{"type":"object","properties":{"movement_purpose":{"type":"string","enum":["purchase","production_in","production_out","sale","transfer","inventory","inventory_surplus","inventory_shortage","waste","packaging_dispatch","packaging_return","repack","tank_release","packaging_consumption","other"],"description":"Defaults to `purchase` for a goods receipt, `sale` for a stock issue."},"date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"Defaults to today."},"warehouse_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"target_warehouse_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Destination warehouse — only meaningful for movement_purpose=transfer."},"partner_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"batch_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"notes":{"type":["string","null"],"maxLength":4000},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"order_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Link to a sales order this issue fulfils."},"lines":{"type":"array","items":{"$ref":"#/components/schemas/StockIssueLineCreate"},"maxItems":500}},"required":["warehouse_id"],"additionalProperties":false},"StockIssueLineCreate":{"type":"object","properties":{"item_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"allOf":[{"$ref":"#/components/schemas/UnitInput"},{"description":"Must be the item's unit (422 unit_mismatch otherwise); no conversion in v1."}]},"unit_price":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"lot_number":{"type":["string","null"],"maxLength":120,"description":"Batch/lot label. A receipt line creates a new lot with this label."},"expiry_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"notes":{"type":["string","null"],"maxLength":2000},"lot_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"receipt_line_id of a stock lot (GET /v1/stock-levels/lots) — consumes exactly that FIFO layer. Omit to let the confirm action pick FIFO automatically."}},"required":["item_id","quantity","unit"],"additionalProperties":false},"StockLevelList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StockLevel"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"StockLevel":{"type":"object","properties":{"object":{"type":"string","enum":["stock_level"]},"item":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"code":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","code","name"]},"warehouse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":"string"}},"required":["id","name"]},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Stock on hand, in the item's unit (never converted)."},"reserved_quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"available_quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"`quantity − reserved_quantity`, never negative."},"unit":{"$ref":"#/components/schemas/UnitRef"},"livemode":{"type":"boolean"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","item","warehouse","quantity","reserved_quantity","available_quantity","unit","livemode","updated_at"]},"StockLotList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StockLot"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"StockLot":{"type":"object","properties":{"object":{"type":"string","enum":["stock_lot"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Receipt line id — send it as `lot_id` on a stock issue line to pick this layer (manual_lot)."},"receipt":{"type":"object","properties":{"code":{"type":"string"},"date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"}},"required":["code","date"]},"item":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"code":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","code","name"]},"warehouse_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Remaining quantity on this receipt line (FIFO layer), in the item's unit."},"received_quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"$ref":"#/components/schemas/UnitRef"},"unit_price":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"lot_number":{"type":["string","null"]},"expiry_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"supplier_name":{"type":["string","null"]},"livemode":{"type":"boolean"}},"required":["object","id","receipt","item","warehouse_id","quantity","received_quantity","unit","unit_price","lot_number","expiry_date","supplier_name","livemode"]},"InvoiceList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"Invoice":{"type":"object","properties":{"object":{"type":"string","enum":["invoice"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"number":{"type":"string","example":"FA-2026-0012"},"status":{"type":"string","enum":["draft","issued","paid","cancelled"]},"partner":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]}},"required":["id","name"]},"order_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Order the invoice was created from. Populated on the detail only (source refs are not loaded for lists) — null there and when the invoice was not created from exactly one order."},"warehouse_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Null for a tenant without the Stock module (accounting-only invoicing)."},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"event_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"activity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"issue_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"due_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"tax_point_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"paid_at":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"currency":{"type":"string"},"exchange_rate":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"totals":{"type":"object","properties":{"excl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"incl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."}},"required":["excl_vat","vat","incl_vat"]},"amount_paid":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"amount_remaining":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Read-only: totals.incl_vat minus amount_paid."},"variable_symbol":{"type":["string","null"]},"customer_order_ref":{"type":["string","null"]},"notes":{"type":["string","null"]},"internal_notes":{"type":["string","null"]},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceLine"},"description":"Present on the detail, not in lists."},"allowed_actions":{"type":"array","items":{"type":"string"},"example":["issue","cancel"]},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","number","status","partner","order_id","warehouse_id","category_id","event_id","activity_id","issue_date","due_date","tax_point_date","paid_at","currency","exchange_rate","totals","amount_paid","amount_remaining","variable_symbol","customer_order_ref","notes","internal_notes","external_ref","allowed_actions","livemode","created_at","updated_at"]},"InvoiceLine":{"type":"object","properties":{"object":{"type":"string","enum":["invoice_line"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"invoice_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"item":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"code":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","code","name"],"description":"Null for a service line without a stock item."},"description":{"type":"string"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"allOf":[{"$ref":"#/components/schemas/UnitRef"},{"description":"Unit of the item — always the item's unit. Null only for a line without item_id."}]},"unit_price":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"vat_rate_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"discount_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"totals":{"type":["object","null"],"properties":{"excl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"incl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."}},"required":["excl_vat","vat","incl_vat"]},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"event_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"activity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"source_stock_issue_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Read-only: set when the line was grouped in from a confirmed stock issue (delivery-note invoicing)."},"sort_order":{"type":"integer"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","invoice_id","item","description","quantity","unit","unit_price","vat_rate_pct","discount_pct","totals","category_id","event_id","activity_id","source_stock_issue_id","sort_order","created_at"]},"InvoiceCreateBody":{"anyOf":[{"$ref":"#/components/schemas/InvoiceCreateFromOrder"},{"$ref":"#/components/schemas/InvoiceCreate"}]},"InvoiceCreateFromOrder":{"type":"object","properties":{"order_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Creates the invoice from this order's lines (same as POST /orders/{id}/actions/create_invoice)."},"external_ref":{"$ref":"#/components/schemas/ExternalRef"}},"required":["order_id"],"additionalProperties":false},"InvoiceCreate":{"type":"object","properties":{"partner_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"warehouse_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Required when the account has the Stock module (422 warehouse_required otherwise); omit entirely for accounting-only tenants."},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"event_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"activity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"issue_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"Defaults to today."},"due_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"tax_point_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"customer_order_ref":{"type":["string","null"],"maxLength":200},"notes":{"type":["string","null"],"maxLength":4000},"internal_notes":{"type":["string","null"],"maxLength":4000},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"CZK","description":"Defaults to CZK."},"exchange_rate":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Required to issue a foreign-currency invoice (422 missing_exchange_rate at issuance otherwise)."},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceLineCreate"},"maxItems":500}},"required":["partner_id"],"additionalProperties":false},"InvoiceLineCreate":{"type":"object","properties":{"item_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Omit for a service line without a stock item; then `unit` must also be omitted."},"description":{"type":"string","minLength":1,"maxLength":500},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"allOf":[{"$ref":"#/components/schemas/UnitInput"},{"description":"Required when item_id is set — must be the item's unit (422 unit_mismatch otherwise); forbidden without item_id."}]},"unit_price":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"In the invoice's currency (foreign-currency invoices convert to the canonical CZK amount using the header exchange_rate)."},"vat_rate_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"21","description":"0–100, at most 2 decimal places. Defaults to 21 (0 for a non-VAT-payer tenant, forced server-side)."},"discount_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"event_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"activity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"}},"required":["description","quantity","unit_price"],"additionalProperties":false},"InvoicePatch":{"type":"object","properties":{"partner_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"warehouse_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Can only be set, never cleared, once the Stock module requires it."},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"event_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"activity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"due_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"tax_point_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"customer_order_ref":{"type":["string","null"],"maxLength":200},"notes":{"type":["string","null"],"maxLength":4000},"internal_notes":{"type":["string","null"],"maxLength":4000},"currency":{"type":"string","minLength":3,"maxLength":3},"exchange_rate":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."}},"additionalProperties":false},"InvoiceLinePatch":{"type":"object","properties":{"description":{"type":"string","minLength":1,"maxLength":500},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"allOf":[{"$ref":"#/components/schemas/UnitInput"},{"description":"Required when item_id is set — must be the item's unit (422 unit_mismatch otherwise); forbidden without item_id."}]},"unit_price":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"In the invoice's currency (foreign-currency invoices convert to the canonical CZK amount using the header exchange_rate)."},"vat_rate_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"21","description":"0–100, at most 2 decimal places. Defaults to 21 (0 for a non-VAT-payer tenant, forced server-side)."},"discount_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"event_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"activity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"}},"additionalProperties":false},"InvoiceActionBody":{"type":"object","properties":{"issue_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"issue only — defaults to today (or the draft's issue_date)."},"due_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"issue only — defaults to the partner's payment terms (14 days fallback)."},"tax_point_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"issue only — defaults to issue_date."},"paid_at":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"mark_paid only — defaults to today."},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"mark_paid only — defaults to the full remaining amount."},"account_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"mark_paid only — defaults to the tenant's default account for the invoice's payment method (422 account_required if none)."}},"additionalProperties":false},"ReceivedInvoiceList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ReceivedInvoice"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"ReceivedInvoice":{"type":"object","properties":{"object":{"type":"string","enum":["received_invoice"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"number":{"type":["string","null"],"description":"Internal sequence number — assigned by actions/confirm, null on a draft."},"supplier_invoice_number":{"type":"string"},"status":{"type":"string","enum":["draft","confirmed","paid","cancelled"]},"partner":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]}},"required":["id","name"]},"issue_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"tax_point_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"due_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"received_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"paid_at":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"variable_symbol":{"type":["string","null"]},"payment_method":{"type":"string","enum":["transfer","cash","card","other"]},"currency":{"type":"string"},"exchange_rate":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"totals":{"type":"object","properties":{"excl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"incl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."}},"required":["excl_vat","vat","incl_vat"]},"paid_amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"shop_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"notes":{"type":["string","null"]},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/ReceivedInvoiceLine"},"description":"Present on the detail, not in lists."},"allowed_actions":{"type":"array","items":{"type":"string"},"example":["confirm","cancel"]},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","number","supplier_invoice_number","status","partner","issue_date","tax_point_date","due_date","received_date","paid_at","variable_symbol","payment_method","currency","exchange_rate","totals","paid_amount","shop_id","notes","external_ref","allowed_actions","livemode","created_at","updated_at"]},"ReceivedInvoiceLine":{"type":"object","properties":{"object":{"type":"string","enum":["received_invoice_line"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"received_invoice_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"description":{"type":"string"},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Line amount excl. VAT. No quantity/unit — a received-invoice line is a plain accounting split, not a stock movement."},"vat_rate_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"is_exempt":{"type":"boolean"},"amount_vat":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"amount_incl_vat":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"category":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]}},"required":["id","name"]},"notes":{"type":["string","null"]},"sort_order":{"type":"integer"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","received_invoice_id","description","amount","vat_rate_pct","is_exempt","amount_vat","amount_incl_vat","category_id","category","notes","sort_order","created_at"]},"ReceivedInvoiceCreate":{"type":"object","properties":{"supplier_invoice_number":{"type":"string","maxLength":190},"partner_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"issue_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"tax_point_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"due_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"received_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"Defaults to today."},"variable_symbol":{"type":["string","null"],"maxLength":30},"payment_method":{"type":"string","enum":["transfer","cash","card","other"],"description":"Defaults to transfer."},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"Defaults to CZK."},"exchange_rate":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Foreign-currency documents only; editable while the document is a draft."},"shop_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Defaults to the account's single active shop when omitted."},"notes":{"type":["string","null"],"maxLength":4000},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/ReceivedInvoiceLineCreate"},"maxItems":200}},"required":["supplier_invoice_number","partner_id","issue_date"],"additionalProperties":false},"ReceivedInvoiceLineCreate":{"type":"object","properties":{"description":{"type":"string","minLength":1,"maxLength":500},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Excl. VAT, in the invoice's canonical (CZK) base."},"vat_rate_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"21","description":"0–100, at most 2 decimal places. Defaults to the tenant's standard rate (0 for a non-VAT-payer)."},"is_exempt":{"type":"boolean"},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"notes":{"type":["string","null"],"maxLength":2000}},"required":["description","amount"],"additionalProperties":false},"ReceivedInvoicePatch":{"type":"object","properties":{"supplier_invoice_number":{"type":"string","maxLength":190},"partner_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"issue_date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"tax_point_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"due_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"variable_symbol":{"type":["string","null"],"maxLength":30},"payment_method":{"type":"string","enum":["transfer","cash","card","other"],"description":"Defaults to transfer."},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"Defaults to CZK."},"exchange_rate":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Foreign-currency documents only; editable while the document is a draft."},"shop_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Defaults to the account's single active shop when omitted."},"notes":{"type":["string","null"],"maxLength":4000}},"additionalProperties":false},"ReceivedInvoiceLinePatch":{"type":"object","properties":{"description":{"type":"string","minLength":1,"maxLength":500},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Excl. VAT, in the invoice's canonical (CZK) base."},"vat_rate_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"21","description":"0–100, at most 2 decimal places. Defaults to the tenant's standard rate (0 for a non-VAT-payer)."},"is_exempt":{"type":"boolean"},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"notes":{"type":["string","null"],"maxLength":2000}},"additionalProperties":false},"ReceivedInvoiceActionBody":{"type":"object","properties":{"paid_at":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"Defaults to today."},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Defaults to the remaining balance."},"account_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Defaults to the account tied to the invoice's payment method."}},"additionalProperties":false},"CashFlowList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CashFlow"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"CashFlow":{"type":"object","properties":{"object":{"type":"string","enum":["cash_flow"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"number":{"type":["string","null"],"example":"VD-2026-0042"},"type":{"type":"string","enum":["income","expense"]},"status":{"type":"string","enum":["draft","confirmed","planned","pending","paid","cancelled"],"description":"Document lifecycle: draft, confirmed or cancelled. Paying a document does not change it — read `payment_status`. planned/pending/paid are legacy values no longer written."},"payment_status":{"type":"string","enum":["unpaid","partial","paid"],"description":"Derived from `paid_amount` against `amount` (Finance 3.0 payment engine)."},"date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"due_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"paid_at":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"paid_amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Cumulative amount paid so far (Finance 3.0 payment engine)."},"currency":{"type":"string"},"vat_rate_pct":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"total_excl_vat":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"total_vat":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"partner":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]}},"required":["id","name"]},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"shop_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"order_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"stock_issue_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"description":{"type":["string","null"]},"notes":{"type":["string","null"]},"is_cash":{"type":"boolean"},"payment_method":{"type":"string","enum":["transfer","cash","card","other"]},"cash_desk_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"variable_symbol":{"type":["string","null"]},"allowed_actions":{"type":"array","items":{"type":"string"},"example":["mark_paid","cancel"]},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","number","type","status","payment_status","date","due_date","paid_at","amount","paid_amount","currency","vat_rate_pct","total_excl_vat","total_vat","partner","category_id","shop_id","order_id","stock_issue_id","description","notes","is_cash","payment_method","cash_desk_id","variable_symbol","allowed_actions","livemode","created_at","updated_at"]},"CashFlowCreate":{"type":"object","properties":{"cashflow_type":{"type":"string","enum":["income","expense"]},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"date":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"currency":{"type":"string","minLength":3,"maxLength":3,"description":"Defaults to CZK."},"due_date":{"type":["string","null"],"format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"status":{"type":"string","enum":["draft","confirmed"],"description":"Defaults to confirmed. Pay and cancel through the actions (`mark_paid`, `cancel`), not through this field — the legacy values planned/pending/paid are rejected rather than silently normalized."},"partner_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"category_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"shop_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Defaults to the account's single active shop when omitted."},"order_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"stock_issue_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"description":{"type":["string","null"],"maxLength":500},"notes":{"type":["string","null"],"maxLength":4000},"is_cash":{"type":"boolean","description":"Together with cash_desk_id, posts through that cash desk (balance + till movement)."},"payment_method":{"type":"string","enum":["transfer","cash","card","other"]},"cash_desk_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"vat_rate_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"price_includes_vat":{"type":"boolean"}},"required":["cashflow_type","amount","date"],"additionalProperties":false},"CashFlowActionBody":{"type":"object","properties":{"paid_at":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"Defaults to today."},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Defaults to the remaining balance."},"account_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Defaults to the account tied to the document's payment method."}},"additionalProperties":false},"PosSale":{"type":"object","properties":{"object":{"type":"string","enum":["pos_sale"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"number":{"type":"string"},"status":{"type":"string","description":"open | settled | cancelled"},"shop_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"cash_desk_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"partner_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/PosSaleLine"}},"total_excl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"total_incl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"discount_amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"packaging_deposit":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"payment_amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"rounding":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"currency":{"type":"string","enum":["CZK"]},"stock_issue_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"revenue_cashflow_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Simplified sales document (paragon)."},"settlement_cashflow_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"stock_issue_failed":{"type":"boolean","description":"Money was posted but stock was not written off; finish it in the app."},"payment_posting_failed":{"type":"boolean","description":"The sale was settled but the payment was not posted; finish it in the app."},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"settled_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"cancelled_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","number","status","shop_id","cash_desk_id","partner_id","lines","total_excl_vat","total_incl_vat","discount_amount","packaging_deposit","payment_amount","rounding","currency","stock_issue_id","revenue_cashflow_id","settlement_cashflow_id","stock_issue_failed","payment_posting_failed","external_ref","settled_at","cancelled_at","livemode","created_at","updated_at"]},"PosSaleLine":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"item":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]},"code":{"type":["string","null"]}},"required":["id","name","code"]},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"$ref":"#/components/schemas/UnitRef"},"unit_price":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Price per unit excluding VAT."},"vat_rate_pct":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"total_excl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"total_incl_vat":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"deposit_total":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Packaging deposit of the line (not revenue)."}},"required":["id","item","quantity","unit","unit_price","vat_rate_pct","total_excl_vat","total_incl_vat","deposit_total"]},"PosSaleWrite":{"type":"object","properties":{"shop_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"cash_desk_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Required when the shop has more than one cash desk."},"partner_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"external_ref":{"$ref":"#/components/schemas/ExternalRef"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/PosSaleLineWrite"},"minItems":1,"maxItems":100},"payment":{"type":"object","properties":{"method":{"type":"string","enum":["cash","card","transfer"],"description":"`transfer` is not supported yet (422 payment_method_not_supported)."},"amount":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"What the customer paid for the whole sale, in CZK."},"currency":{"type":"string","minLength":3,"maxLength":3,"example":"CZK"}},"required":["method","amount","currency"],"additionalProperties":false}},"required":["shop_id","lines","payment"],"additionalProperties":false},"PosSaleLineWrite":{"type":"object","properties":{"item_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Greater than 0, in the unit of the item."},"unit":{"allOf":[{"$ref":"#/components/schemas/UnitInput"},{"description":"Must be the item's unit (422 unit_mismatch otherwise)."}]}},"required":["item_id","quantity","unit"],"additionalProperties":false},"FinanceAccountList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FinanceAccount"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"FinanceAccount":{"type":"object","properties":{"object":{"type":"string","enum":["finance_account"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"type":{"type":"string","enum":["bank","cash","card_clearing"]},"name":{"type":"string"},"currency":{"type":"string","example":"CZK"},"account_number":{"type":["string","null"]},"iban":{"type":["string","null"]},"is_active":{"type":"boolean"},"sort_order":{"type":"integer"},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","type","name","currency","account_number","iban","is_active","sort_order","livemode","created_at","updated_at"]},"AttachmentUploadTicket":{"type":"object","properties":{"object":{"type":"string","enum":["attachment_upload"]},"path":{"type":"string","description":"Opaque storage path — send back unchanged to POST /attachments/finalize."},"upload_url":{"type":"string","description":"Signed PUT URL for the Supabase Storage object. Valid for 2 hours (Supabase Storage default; not configurable)."},"upload_method":{"type":"string","enum":["PUT"]},"upload_headers":{"type":"object","additionalProperties":{"type":"string"},"example":{"Content-Type":"image/jpeg","x-upsert":"false"}},"expires_at":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","path","upload_url","upload_method","upload_headers","expires_at"],"description":"How to upload: PUT the raw file bytes to `upload_url` with the given headers (no other authentication — the token in the URL authorizes exactly this path once). Example: `curl -X PUT \"$upload_url\" -H \"Content-Type: image/jpeg\" --data-binary @receipt.jpg`. Then call POST /attachments/finalize with the same `path` to create the attachment record."},"AttachmentUploadCreate":{"type":"object","properties":{"entity_type":{"type":["string","null"],"enum":["partner","item","order","stock_issue","batch","purchase_order","cash_flow","received_invoice","invoice","monthly_report","document",null],"description":"Target agenda the file belongs to (order, item, batch, …). Omit together with entity_id to upload into Files (Podatelna) without binding it to a record yet."},"entity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"file_name":{"type":"string","minLength":1,"maxLength":255},"mime_type":{"type":"string","minLength":1,"maxLength":255},"file_size":{"type":"integer","exclusiveMinimum":0,"description":"Declared size in bytes; re-verified from storage on finalize."}},"required":["file_name","mime_type","file_size"],"additionalProperties":false},"Attachment":{"type":"object","properties":{"object":{"type":"string","enum":["attachment"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"file_name":{"type":"string"},"mime_type":{"type":["string","null"]},"size":{"type":["integer","null"],"description":"Bytes, verified from storage on finalize."},"entity_type":{"type":["string","null"],"enum":["partner","item","order","stock_issue","batch","purchase_order","cash_flow","received_invoice","invoice","monthly_report","document",null]},"entity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"purpose":{"type":"string","enum":["attachment","source_document"]},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Null for a file uploaded without an entity (Files/Podatelna) — the storage layer does not expose its insert timestamp without a database read."}},"required":["object","id","file_name","mime_type","size","entity_type","entity_id","purpose","created_at"]},"AttachmentFinalizeCreate":{"type":"object","properties":{"path":{"type":"string","minLength":1,"maxLength":1000,"description":"The `path` returned by POST /attachments."},"entity_type":{"type":["string","null"],"enum":["partner","item","order","stock_issue","batch","purchase_order","cash_flow","received_invoice","invoice","monthly_report","document",null],"description":"Must match what was sent to POST /attachments."},"entity_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"file_name":{"type":"string","minLength":1,"maxLength":255},"mime_type":{"type":"string","minLength":1,"maxLength":255},"purpose":{"type":"string","enum":["attachment","source_document"],"description":"Defaults to attachment. source_document marks the record's original paper (invoice scan, contract, …)."}},"required":["path","file_name","mime_type"],"additionalProperties":false},"InboxSubmissionResult":{"type":"object","properties":{"object":{"type":"string","enum":["inbox_submission"]},"outcome":{"type":"string","enum":["files","isdoc_imported","isdoc_rejected","scan"],"description":"files = waiting in Files (Podatelna) for a human to sort; isdoc_imported = a received-invoice draft was created; isdoc_rejected = looked like ISDOC but could not be imported (see note); scan = handed to the AI document inbox."},"attachment_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Null when the account's inbound routing sends files straight to the AI document inbox without a Files row."},"received_invoice_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"scan_inbox_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"supplier_name":{"type":["string","null"]},"document_number":{"type":["string","null"]},"note":{"type":["string","null"],"description":"Why an ISDOC file was rejected, or why the file was left in Files without automatic routing (ISDOC import needs finance:write; the AI inbox needs the document scan add-on)."},"duplicate":{"type":"boolean","description":"This delivery was already ingested before (safe retry)."},"held":{"type":"boolean"},"deferred":{"type":"boolean"}},"required":["object","outcome","attachment_id","received_invoice_id","scan_inbox_id","supplier_name","document_number","note","duplicate","held","deferred"]},"InboxSubmissionUpload":{"type":"object","properties":{"file":{"type":"string","format":"binary"},"batch_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Group several uploads (e.g. multi-page scans) into one submission by reusing the same batch_id across requests."}},"required":["file"]},"InboxSubmissionByAttachment":{"type":"object","properties":{"attachment_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"An attachment created via POST /attachments + /finalize without entity_type/entity_id."}},"required":["attachment_id"],"additionalProperties":false},"ReceivedInvoiceImport":{"type":"object","properties":{"object":{"type":"string","enum":["received_invoice_import"]},"received_invoice_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"supplier_name":{"type":["string","null"]},"document_number":{"type":["string","null"]},"pdf_attached":{"type":"boolean","description":"A .isdocx archive included a PDF visualisation, attached as the source document."}},"required":["object","received_invoice_id","supplier_name","document_number","pdf_attached"]},"IsdocImportCreate":{"type":"object","properties":{"attachment_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"An attachment created via POST /attachments + /finalize without entity_type/entity_id."},"storage_path":{"type":"string","minLength":1,"maxLength":1000,"description":"The `path` from a POST /attachments ticket created without entity_type/entity_id (it starts with your account's inbox prefix), when you upload directly and skip finalizing it as an attachment. Any other path returns 404."},"file_name":{"type":"string","minLength":1,"maxLength":255,"description":"Must end .isdoc or .isdocx — governs parsing, independent of the declared MIME type."},"note":{"type":["string","null"],"maxLength":2000}},"required":["file_name"],"additionalProperties":false,"description":"Exactly one of attachment_id / storage_path."},"WebhookEndpointList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"WebhookEndpoint":{"type":"object","properties":{"object":{"type":"string","enum":["webhook_endpoint"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"url":{"type":"string"},"event_types":{"type":"array","items":{"type":"string"}},"is_active":{"type":"boolean"},"exclude_own_events":{"type":"boolean","description":"Skip events caused by the key that owns this endpoint (no echo of your own writes)."},"owner_api_key_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"api_version":{"type":"string"},"description":{"type":["string","null"]},"consecutive_failures":{"type":"integer"},"disabled_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"disabled_reason":{"type":["string","null"],"enum":["gone","failing","manual","secret_unreadable",null]},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","url","event_types","is_active","exclude_own_events","owner_api_key_id","api_version","description","consecutive_failures","disabled_at","disabled_reason","created_at","updated_at"]},"WebhookEndpointSecret":{"type":"object","properties":{"object":{"type":"string","enum":["webhook_endpoint_secret"]},"endpoint":{"$ref":"#/components/schemas/WebhookEndpoint"},"secret":{"type":"string","description":"Signing secret (`whsec_…`) — shown once here and never again; store it now."}},"required":["object","endpoint","secret"]},"WebhookEndpointCreate":{"type":"object","properties":{"url":{"type":"string","maxLength":2000,"example":"https://hooks.example.com/profi"},"event_types":{"type":"array","items":{"type":"string","maxLength":64,"example":"invoice.*","description":"`*`, an exact type, or `<prefix>.*`."},"minItems":1},"description":{"type":["string","null"],"maxLength":500},"exclude_own_events":{"type":"boolean","description":"Defaults to true."}},"required":["url","event_types"],"additionalProperties":false,"description":"Known event types: partner.created, partner.updated, item.created, item.updated, order.created, order.confirmed, order.shipped, order.delivered, order.invoiced, order.cancelled, stock_issue.created, stock_issue.confirmed, stock_issue.cancelled, stock_issue.reverted_to_draft, goods_receipt.created, goods_receipt.confirmed, goods_receipt.cancelled, goods_receipt.reverted_to_draft, stock_level.changed, invoice.created, invoice.issued, invoice.paid, invoice.payment_reverted, invoice.cancelled, received_invoice.created, received_invoice.confirmed, received_invoice.paid, received_invoice.payment_reverted, received_invoice.cancelled, cashflow.created, cashflow.paid, cashflow.payment_reverted, cashflow.cancelled, inbox.submission_received, workflow.step_called, workflow.step_waiting_external, workflow.step_completed_external, batch.phase_changed, batch.measurement_added."},"WebhookEndpointPatch":{"type":"object","properties":{"url":{"type":"string","maxLength":2000},"event_types":{"type":"array","items":{"type":"string","maxLength":64,"example":"invoice.*","description":"`*`, an exact type, or `<prefix>.*`."},"minItems":1},"description":{"type":["string","null"],"maxLength":500},"exclude_own_events":{"type":"boolean"},"is_active":{"type":"boolean","description":"Set true to re-enable a disabled endpoint (clears the failure counter)."}},"additionalProperties":false},"WebhookPing":{"type":"object","properties":{"object":{"type":"string","enum":["webhook_ping"]},"delivery_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"delivered":{"type":"boolean"},"error":{"type":["string","null"]}},"required":["object","delivery_id","delivered","error"]},"EventList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"Event":{"type":"object","properties":{"object":{"type":"string","enum":["event"]},"id":{"type":"string","example":"evt_9f1c0f1e-0a4a-4a3f-9d1a-7e2b3c4d5e6f"},"type":{"type":"string","example":"invoice.paid"},"sequence":{"type":"integer","description":"Monotonic per account; use it as your cursor."},"occurred_at":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"livemode":{"type":"boolean"},"api_version":{"type":"string"},"entity_type":{"type":"string"},"entity_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"caused_by":{"type":"object","properties":{"kind":{"type":"string","enum":["api_key","user","system"]},"id":{"type":["string","null"]},"request_id":{"type":["string","null"]}},"required":["kind","id","request_id"],"description":"Who caused the change; api_key carries the key id and its request id."},"data":{"type":"object","properties":{"object":{}}}},"required":["object","id","type","sequence","occurred_at","livemode","api_version","entity_type","entity_id","caused_by","data"]},"WorkflowStepCompleteResult":{"type":"object","properties":{"object":{"type":"string","enum":["workflow_step"]},"step_instance_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"status":{"type":"string","enum":["done","blocked"]},"external_result":{"type":"string","enum":["approved","rejected"]},"completed_by_api_key_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"The key that completed the step — the key of this request. Stored on the step and sent in `workflow.step_completed_external`."},"instance_status":{"type":"string","enum":["running","blocked","completed","cancelled"],"description":"State of the whole workflow after the steps that follow ran. `blocked` after `approved` means a following step stopped — typically an action step the key has no scope for."}},"required":["object","step_instance_id","status","external_result","completed_by_api_key_id","instance_status"]},"WorkflowStepComplete":{"type":"object","properties":{"result":{"type":"string","enum":["approved","rejected"],"description":"`approved` continues the workflow; `rejected` stops it for a person to decide."},"note":{"type":"string","maxLength":2000,"description":"Shown to the person as the reason when the step is rejected."}},"required":["result"]},"InternalCronResult":{"type":"object","properties":{"object":{"type":"string","enum":["internal_cron_result"]},"delivered":{"type":"integer"},"failed":{"type":"integer"},"skipped":{"type":"integer"},"drained":{"type":"integer","description":"Events whose post-response dispatch never finished and were recovered by this run."},"purged":{"type":"object","properties":{"idempotency_keys":{"type":"integer"},"deliveries":{"type":"integer"},"request_log":{"type":"integer"},"events":{"type":"integer"}},"required":["idempotency_keys","deliveries","request_log","events"]},"key_expiry_notifications":{"type":"integer"},"workflow_waits":{"type":"object","properties":{"handed_over":{"type":"integer"},"blocked":{"type":"integer"}},"required":["handed_over","blocked"],"description":"Workflow steps waiting for an external system whose wait timed out: handed over as a task, or stopped."}},"required":["object","delivered","failed","skipped","drained","purged","key_expiry_notifications","workflow_waits"]},"BatchList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Batch"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"Batch":{"type":"object","properties":{"object":{"type":"string","enum":["batch"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"batch_number":{"type":"string"},"phase":{"type":"string","enum":["plan","preparation","brewing","fermentation","conditioning","packaging","completed","transferred","cancelled","dumped"]},"is_paused":{"type":"boolean"},"recipe":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]}},"required":["id","name"]},"item":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]},"code":{"type":["string","null"]}},"required":["id","name","code"],"description":"Beer item the batch produces."},"equipment":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]}},"required":["id","name"],"description":"Fermentation vessel."},"conditioning_equipment_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"shop_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"planned_date":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"brew_date":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"end_brew_date":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"fermentation_start":{"type":["string","null"]},"conditioning_start":{"type":["string","null"]},"estimated_end":{"type":["string","null"]},"volume_l":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Actual volume in litres."},"og_plato":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"fg_plato":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"abv":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Alcohol by volume in percent."},"lot_number":{"type":["string","null"]},"bottled_date":{"type":["string","null"]},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","batch_number","phase","is_paused","recipe","item","equipment","conditioning_equipment_id","shop_id","planned_date","brew_date","end_brew_date","fermentation_start","conditioning_start","estimated_end","volume_l","og_plato","fg_plato","abv","lot_number","bottled_date","livemode","created_at","updated_at"]},"BatchMeasurementList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BatchMeasurement"}}},"required":["data"]},"BatchMeasurement":{"type":"object","properties":{"object":{"type":"string","enum":["batch_measurement"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"batch_id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"type":{"type":"string","description":"gravity | temperature | ph | volume | pressure"},"phase":{"type":["string","null"]},"measured_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"gravity_plato":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"gravity_sg":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"temperature_c":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"volume_l":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"pressure_bar":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"ph":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"is_og":{"type":"boolean"},"is_fg":{"type":"boolean"},"notes":{"type":["string","null"]},"entered":{"$ref":"#/components/schemas/MeasurementEntered"},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","batch_id","type","phase","measured_at","gravity_plato","gravity_sg","temperature_c","volume_l","pressure_bar","ph","is_og","is_fg","notes","entered","livemode","created_at"]},"MeasurementEntered":{"type":["object","null"],"properties":{"value":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"type":"string"}},"required":["value","unit"],"description":"The value as it was entered before conversion (e.g. `64.4` `f`). `null` = entered canonically."},"BatchMeasurementWrite":{"type":"object","properties":{"measured_at":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Defaults to now."},"phase":{"type":"string","enum":["plan","preparation","brewing","fermentation","conditioning","packaging","completed","transferred","cancelled","dumped"],"description":"Defaults to the batch's current phase."},"type":{"type":"string","enum":["gravity","temperature","ph","volume","pressure"],"description":"Optional when exactly one of gravity, ph, volume, pressure (or only temperature) is sent."},"gravity":{"$ref":"#/components/schemas/GravityInput"},"temperature":{"$ref":"#/components/schemas/TemperatureInput"},"volume":{"$ref":"#/components/schemas/VolumeInput"},"pressure":{"$ref":"#/components/schemas/PressureInput"},"ph":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"notes":{"type":"string","maxLength":2000}},"additionalProperties":false},"GravityInput":{"type":"object","properties":{"value":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"type":"string","enum":["plato","sg"]}},"required":["value","unit"],"additionalProperties":false},"TemperatureInput":{"type":"object","properties":{"value":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"type":"string","enum":["c","f"]}},"required":["value","unit"],"additionalProperties":false,"description":"The measured value for `type: temperature`, otherwise the temperature at measurement."},"VolumeInput":{"type":"object","properties":{"value":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"type":"string","enum":["l","gal_us","gal_uk"]}},"required":["value","unit"],"additionalProperties":false},"PressureInput":{"type":"object","properties":{"value":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"type":"string","enum":["bar","psi"]}},"required":["value","unit"],"additionalProperties":false},"BatchAdvancePhase":{"type":"object","properties":{"target_phase":{"type":"string","enum":["preparation","brewing","fermentation","conditioning","packaging","completed"]}},"required":["target_phase"],"additionalProperties":false},"RecipeList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Recipe"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"Recipe":{"type":"object","properties":{"object":{"type":"string","enum":["recipe"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"code":{"type":["string","null"]},"name":{"type":"string"},"status":{"type":"string"},"beer_style":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]}},"required":["id","name"]},"item_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f","description":"Beer item the recipe produces."},"variant_label":{"type":["string","null"]},"is_primary":{"type":"boolean"},"batch_size_l":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"beer_volume_l":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"og_plato":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"fg_plato":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"abv":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"ibu":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"ebc":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"boil_time_min":{"type":["integer","null"]},"fermentation_days":{"type":["integer","null"]},"conditioning_days":{"type":["integer","null"]},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","code","name","status","beer_style","item_id","variant_label","is_primary","batch_size_l","beer_volume_l","og_plato","fg_plato","abv","ibu","ebc","boil_time_min","fermentation_days","conditioning_days","livemode","created_at","updated_at"]},"RecipeDetail":{"allOf":[{"$ref":"#/components/schemas/Recipe"},{"type":"object","properties":{"ingredients":{"type":"array","items":{"$ref":"#/components/schemas/RecipeIngredient"}}},"required":["ingredients"]}]},"RecipeIngredient":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"item":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":["string","null"]},"code":{"type":["string","null"]}},"required":["id","name","code"]},"category":{"type":"string","description":"malt | hop | yeast | adjunct | other"},"quantity":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"unit":{"allOf":[{"$ref":"#/components/schemas/UnitRef"},{"description":"Unit of the recipe line. `null` = the line has no own unit and uses the item's unit (for hops its recipe unit, otherwise its stock unit — see GET /items/{id})."}]},"use_stage":{"type":["string","null"]},"use_time_min":{"type":["integer","null"]},"hop_phase":{"type":["string","null"]},"percent":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"notes":{"type":["string","null"]},"sort_order":{"type":"integer"}},"required":["id","item","category","quantity","unit","use_stage","use_time_min","hop_phase","percent","notes","sort_order"]},"EquipmentList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Equipment"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"Equipment":{"type":"object","properties":{"object":{"type":"string","enum":["equipment"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"name":{"type":"string"},"type":{"type":"string"},"status":{"type":"string","description":"available | in_use | maintenance | retired"},"volume_l":{"type":["string","null"],"pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"current_batch_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"shop_id":{"type":["string","null"],"format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"sort_order":{"type":["integer","null"]},"is_active":{"type":"boolean"},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","name","type","status","volume_l","current_batch_id","shop_id","sort_order","is_active","livemode","created_at","updated_at"]},"ExciseMonthlyReportList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExciseMonthlyReport"}},"next_cursor":{"type":["string","null"]},"has_more":{"type":"boolean"}},"required":["data","next_cursor","has_more"]},"ExciseMonthlyReport":{"type":"object","properties":{"object":{"type":"string","enum":["excise_monthly_report"]},"id":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"period":{"type":"string","example":"2026-08","description":"Tax period YYYY-MM."},"status":{"type":"string","description":"draft | submitted | accepted"},"opening_balance_hl":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"production_hl":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"transfer_in_hl":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"release_hl":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"transfer_out_hl":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"loss_hl":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"destruction_hl":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"adjustment_hl":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"closing_balance_hl":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"total_tax":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Tax payable in CZK, as on the printed return."},"currency":{"type":"string","enum":["CZK"]},"tax_details":{"type":"array","items":{"$ref":"#/components/schemas/ExciseTaxDetail"}},"submitted_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"livemode":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"},"updated_at":{"type":["string","null"],"format":"date-time","example":"2026-09-15T07:00:00.000Z"}},"required":["object","id","period","status","opening_balance_hl","production_hl","transfer_in_hl","release_hl","transfer_out_hl","loss_hl","destruction_hl","adjustment_hl","closing_balance_hl","total_tax","currency","tax_details","submitted_at","livemode","created_at","updated_at"]},"ExciseTaxDetail":{"type":"object","properties":{"plato":{"type":"integer","description":"Whole degrees Plato the tax band is computed from."},"volume_hl":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Decimal as string — never a float."},"tax":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","example":"12.5","description":"Tax in CZK for the band."}},"required":["plato","volume_hl","tax"]}},"parameters":{}},"paths":{"/api/v1/health":{"get":{"tags":["Meta"],"summary":"Liveness check","description":"No authentication. Returns the API schema version.","responses":{"200":{"description":"API is up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/api/v1/me":{"get":{"tags":["Meta"],"summary":"Who am I","description":"Account, key scopes, active modules, plan limits and the account's measurement profile. Physical measurements are stored canonically (litres, °C, °P, EBC, bar) regardless of the profile; business quantities travel with their unit.","security":[{"bearerAuth":[]}],"x-scopes":["core:read","stock:read","sales:read","finance:read","brewery:read","pos:read","core:write","stock:write","sales:write","finance:write","brewery:write","pos:write","events:read","webhooks:manage","workflow:write"],"responses":{"200":{"description":"Context of the key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/units":{"get":{"tags":["Units"],"summary":"Units available to this account","description":"System units offered in the account's unit system (plus the ones enabled in Settings → Units, minus disabled) and the account's own units. Every quantity in this API references one of these by `unit_id` or `unit_code`.","security":[{"bearerAuth":[]}],"x-scopes":["core:read","stock:read","sales:read","finance:read","brewery:read","pos:read"],"responses":{"200":{"description":"Unit list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnitList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/partners":{"get":{"tags":["Partners"],"summary":"List partners","security":[{"bearerAuth":[]}],"x-scopes":["core:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"is_customer","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"is_supplier","in":"query"}],"responses":{"200":{"description":"Partners","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Partners"],"summary":"Create partner","description":"Send `Idempotency-Key` to make retries safe. Duplicate IČO → 409 `duplicate_ico`. Send `external_ref` to link your record (duplicate → 409 `external_ref_conflict`, or the existing partner with `?on_conflict=return`).","security":[{"bearerAuth":[]}],"x-scopes":["core:write"],"parameters":[{"schema":{"type":"string","enum":["error","return"],"default":"error","description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record."},"required":false,"description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record.","name":"on_conflict","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerCreate"}}}},"responses":{"200":{"description":"Existing partner (?on_conflict=return)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Partner"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Partner"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/partners/{id}":{"get":{"tags":["Partners"],"summary":"Get partner","security":[{"bearerAuth":[]}],"x-scopes":["core:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Partner","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Partner"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Partners"],"summary":"Update partner","description":"Deactivate with `is_active: false` — the API never deletes. Send `If-Match` with the ETag from GET to refuse stale writes (412 `stale_version`).","security":[{"bearerAuth":[]}],"x-scopes":["core:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins."},"required":false,"description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins.","name":"if-match","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PartnerPatch"}}}},"responses":{"200":{"description":"Updated","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Partner"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"412":{"description":"Stale version (If-Match)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/partners/by-external-ref/{system}/{external_id}":{"get":{"tags":["Partners"],"summary":"Get partner by external reference","security":[{"bearerAuth":[]}],"x-scopes":["core:read"],"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9_-]{2,32}$","example":"shoptet"},"required":true,"name":"system","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":128},"required":true,"name":"external_id","in":"path"}],"responses":{"200":{"description":"Partner","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Partner"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/partners/{id}/contacts":{"get":{"tags":["Partners"],"summary":"List partner contacts","security":[{"bearerAuth":[]}],"x-scopes":["core:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Contacts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Partners"],"summary":"Create partner contact","security":[{"bearerAuth":[]}],"x-scopes":["core:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/partners/{id}/contacts/{contact_id}":{"patch":{"tags":["Partners"],"summary":"Update partner contact","security":[{"bearerAuth":[]}],"x-scopes":["core:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"contact_id","in":"path"},{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins."},"required":false,"description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins.","name":"if-match","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"position":{"type":["string","null"],"maxLength":120},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"],"maxLength":40},"mobile":{"type":["string","null"],"maxLength":40},"is_primary":{"type":"boolean"},"notes":{"type":["string","null"],"maxLength":4000}},"additionalProperties":false}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/contacts":{"get":{"tags":["Partners"],"summary":"List contacts across partners","security":[{"bearerAuth":[]}],"x-scopes":["core:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"Contacts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactWithPartnerList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/items":{"get":{"tags":["Items"],"summary":"List catalog items","security":[{"bearerAuth":[]}],"x-scopes":["stock:read","sales:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["brew_material","production_item","base_product","purchased_sale_item","packaging","service","other"]},"required":false,"name":"item_type","in":"query"},{"schema":{"type":"string","maxLength":40},"required":false,"name":"material_type","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"is_active","in":"query"}],"responses":{"200":{"description":"Items","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Items"],"summary":"Create item","description":"`unit` is required (`unit_id` or `unit_code`, see GET /v1/units). `recipe_unit` must share the dimension of `unit` (422 `recipe_unit_dimension_mismatch`). Flags (stock category, sale/production/packaging) derive from `item_type`. `base_product` (own beer packaged for sale) requires `base_item_id` of an existing `production_item`; without it the item would read back as `purchased_sale_item`. Send `external_ref` to link your record (duplicate → 409 `external_ref_conflict`, or the existing item with `?on_conflict=return`).","security":[{"bearerAuth":[]}],"x-scopes":["stock:write"],"parameters":[{"schema":{"type":"string","enum":["error","return"],"default":"error","description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record."},"required":false,"description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record.","name":"on_conflict","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemCreate"}}}},"responses":{"200":{"description":"Existing item (?on_conflict=return)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Item"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Item"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/items/{id}":{"get":{"tags":["Items"],"summary":"Get item","security":[{"bearerAuth":[]}],"x-scopes":["stock:read","sales:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Item","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Item"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Items"],"summary":"Update item","description":"Deactivate with `is_active: false`. Changing `unit` of an item that already has stock or document lines is refused by the application rules. Send `If-Match` with the ETag from GET to refuse stale writes (412 `stale_version`).","security":[{"bearerAuth":[]}],"x-scopes":["stock:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins."},"required":false,"description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins.","name":"if-match","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItemPatch"}}}},"responses":{"200":{"description":"Updated","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Item"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"412":{"description":"Stale version (If-Match)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/items/by-external-ref/{system}/{external_id}":{"get":{"tags":["Items"],"summary":"Get item by external reference","security":[{"bearerAuth":[]}],"x-scopes":["stock:read","sales:read"],"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9_-]{2,32}$","example":"shoptet"},"required":true,"name":"system","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":128},"required":true,"name":"external_id","in":"path"}],"responses":{"200":{"description":"Item","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Item"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/items/{id}/prices":{"get":{"tags":["Items"],"summary":"Resolve the price for a partner and quantity","description":"Same cascade as an order line in the app (partner price, price list tiers, category discounts, base price). Quantity is in the item's unit.","security":[{"bearerAuth":[]}],"x-scopes":["sales:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"partner_id","in":"query"},{"schema":{"type":"string","pattern":"^-?\\d+(\\.\\d+)?$","default":"1","example":"12.5","description":"In the item's unit."},"required":false,"description":"In the item's unit.","name":"quantity","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"required":false,"name":"date","in":"query"}],"responses":{"200":{"description":"Resolved price","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Price"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/orders":{"get":{"tags":["Orders"],"summary":"List orders","description":"Sorted by updated_at; use `updated_since` + cursor to sync. Lines are not included — GET /orders/{id}.","security":[{"bearerAuth":[]}],"x-scopes":["sales:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","enum":["draft","confirmed","in_preparation","shipped","delivered","invoiced","cancelled"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"partner_id","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"shop_id","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"warehouse_id","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"required":false,"name":"date_from","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"required":false,"name":"date_to","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"Orders","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Orders"],"summary":"Create a draft order","description":"Creates a DRAFT (as in the app) with optional lines; confirm it with POST /orders/{id}/actions/confirm. Send `Idempotency-Key` to make retries safe and `external_ref` to link your record (duplicate → 409 `external_ref_conflict`, or the existing order with `?on_conflict=return`). Lines are validated (item, unit = item's unit, decimal scale) before anything is written. `origin` is set to `api`; the app shows the key name on the order.","security":[{"bearerAuth":[]}],"x-scopes":["sales:write"],"parameters":[{"schema":{"type":"string","enum":["error","return"],"default":"error","description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record."},"required":false,"description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record.","name":"on_conflict","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderCreate"}}}},"responses":{"200":{"description":"Existing order (?on_conflict=return)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"201":{"description":"Created","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/orders/{id}":{"get":{"tags":["Orders"],"summary":"Get order with lines","security":[{"bearerAuth":[]}],"x-scopes":["sales:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Order","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Orders"],"summary":"Update a draft order","description":"Only drafts (409 `invalid_transition` otherwise). Send `If-Match` to refuse stale writes (412).","security":[{"bearerAuth":[]}],"x-scopes":["sales:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins."},"required":false,"description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins.","name":"if-match","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderPatch"}}}},"responses":{"200":{"description":"Updated","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"412":{"description":"Stale version (If-Match)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/orders/by-external-ref/{system}/{external_id}":{"get":{"tags":["Orders"],"summary":"Get order by external reference","security":[{"bearerAuth":[]}],"x-scopes":["sales:read"],"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9_-]{2,32}$","example":"shoptet"},"required":true,"name":"system","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":128},"required":true,"name":"external_id","in":"path"}],"responses":{"200":{"description":"Order","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/orders/{id}/lines":{"post":{"tags":["Orders"],"summary":"Add a line to a draft order","security":[{"bearerAuth":[]}],"x-scopes":["sales:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderLineCreate"}}}},"responses":{"201":{"description":"Line","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderLine"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/orders/{id}/lines/{line_id}":{"patch":{"tags":["Orders"],"summary":"Update a line of a draft order","security":[{"bearerAuth":[]}],"x-scopes":["sales:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"line_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderLinePatch"}}}},"responses":{"200":{"description":"Line","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderLine"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Orders"],"summary":"Remove a line from a draft order","description":"The only DELETE in the API: a draft line is not a record of its own (the app's „odebrat řádek“).","security":[{"bearerAuth":[]}],"x-scopes":["sales:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"line_id","in":"path"}],"responses":{"204":{"description":"Removed"},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/orders/{id}/actions/{key}":{"post":{"tags":["Orders"],"summary":"Run a workflow action on the order","description":"Keys come from the workflow catalogue (same as the buttons in the app): confirm, start_preparation, ship, deliver, create_stock_issue, create_invoice, mark_invoiced, revert_invoiced, cancel, revert_to_draft. Unknown key → 404 `unknown_action`; key not allowed in the current status → 409 `invalid_transition` with `allowed_actions`. create_stock_issue / create_invoice return the new document in `created`. Tenant workflows (`on_create`, checks) run exactly as for a user.","security":[{"bearerAuth":[]}],"x-scopes":["sales:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z_]{2,40}$","example":"confirm","description":"Action key from the workflow catalogue of the entity."},"required":true,"description":"Action key from the workflow catalogue of the entity.","name":"key","in":"path"}],"responses":{"200":{"description":"Order after the action","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderActionResult"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/warehouses":{"get":{"tags":["Stock"],"summary":"List warehouses","description":"Use `id` as `warehouse_id` on orders, receipts and issues. System warehouses are not listed.","security":[{"bearerAuth":[]}],"x-scopes":["stock:read","sales:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"is_active","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"shop_id","in":"query"},{"schema":{"type":"string","maxLength":40},"required":false,"name":"category","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"Warehouses","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WarehouseList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/shops":{"get":{"tags":["Core"],"summary":"List shops","security":[{"bearerAuth":[]}],"x-scopes":["core:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"is_active","in":"query"},{"schema":{"type":"string","maxLength":40},"required":false,"name":"shop_type","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"Shops","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShopList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/goods-receipts":{"get":{"tags":["Goods receipts"],"summary":"List goods receipts","description":"Sorted by updated_at; use `updated_since` + cursor to sync. Lines are not included — GET the detail.","security":[{"bearerAuth":[]}],"x-scopes":["stock:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","enum":["draft","confirmed","cancelled"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"warehouse_id","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"partner_id","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"required":false,"name":"date_from","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"required":false,"name":"date_to","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"goods receipts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoodsReceiptList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Goods receipts"],"summary":"Create a draft goods receipt","description":"Creates a DRAFT (as in the app) with optional lines; confirm it with POST .../actions/confirm — stock never changes before that (CLAUDE.md: no stock without a confirmed receipt). `movement_purpose` defaults to `purchase`. Lines are validated (item, unit = item's unit, decimal scale) before anything is written. Send `Idempotency-Key` to make retries safe and `external_ref` to link your record (duplicate → 409 `external_ref_conflict`, or the existing receipt with `?on_conflict=return`; the value is shared with stock issues on this account).","security":[{"bearerAuth":[]}],"x-scopes":["stock:write"],"parameters":[{"schema":{"type":"string","enum":["error","return"],"default":"error","description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record."},"required":false,"description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record.","name":"on_conflict","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoodsReceiptCreate"}}}},"responses":{"200":{"description":"Existing receipt (?on_conflict=return)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockDocument"}}}},"201":{"description":"Created","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockDocument"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/goods-receipts/{id}":{"get":{"tags":["Goods receipts"],"summary":"Get a goods receipt with lines","security":[{"bearerAuth":[]}],"x-scopes":["stock:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"goods receipt","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockDocument"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/goods-receipts/by-external-ref/{system}/{external_id}":{"get":{"tags":["Goods receipts"],"summary":"Get a goods receipt by external reference","security":[{"bearerAuth":[]}],"x-scopes":["stock:read"],"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9_-]{2,32}$","example":"shoptet"},"required":true,"name":"system","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":128},"required":true,"name":"external_id","in":"path"}],"responses":{"200":{"description":"goods receipt","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockDocument"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/goods-receipts/{id}/actions/{key}":{"post":{"tags":["Goods receipts"],"summary":"Run a workflow action","description":"Keys come from the workflow catalogue (same as the buttons in the app): confirm, cancel. Unknown key → 404 `unknown_action`; key not allowed in the current status → 409 `invalid_transition` with `allowed_actions`. `confirm` posts the movements (stock only ever changes through a confirmed document — CLAUDE.md); a line without `lot_id` consumes FIFO automatically. `cancel` reverses the posted movements. Non-fatal warnings the app shows on confirm (e.g. a foreign reservation) are not currently surfaced on this endpoint — see the developer notes.","security":[{"bearerAuth":[]}],"x-scopes":["stock:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z_]{2,40}$","example":"confirm","description":"Action key from the workflow catalogue of the entity."},"required":true,"description":"Action key from the workflow catalogue of the entity.","name":"key","in":"path"}],"responses":{"200":{"description":"goods receipt","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockDocument"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/stock-issues":{"get":{"tags":["Stock issues"],"summary":"List stock issues","description":"Sorted by updated_at; use `updated_since` + cursor to sync. Lines are not included — GET the detail.","security":[{"bearerAuth":[]}],"x-scopes":["stock:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","enum":["draft","confirmed","cancelled"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"warehouse_id","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"partner_id","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"required":false,"name":"date_from","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"required":false,"name":"date_to","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"stock issues","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockIssueList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Stock issues"],"summary":"Create a draft stock issue","description":"Creates a DRAFT (as in the app) with optional lines; confirm it with POST .../actions/confirm — stock never changes before that (CLAUDE.md: no stock without a confirmed receipt/issue). `movement_purpose` defaults to `sale`. A line's `lot_id` (receipt_line_id from GET /v1/stock-levels/lots) picks that exact FIFO layer; omit it to let confirm pick FIFO. Lines are validated (item, unit = item's unit, decimal scale, lot availability) before anything is written. Send `Idempotency-Key` to make retries safe and `external_ref` to link your record (duplicate → 409 `external_ref_conflict`, or the existing issue with `?on_conflict=return`; the value is shared with goods receipts on this account).","security":[{"bearerAuth":[]}],"x-scopes":["stock:write"],"parameters":[{"schema":{"type":"string","enum":["error","return"],"default":"error","description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record."},"required":false,"description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record.","name":"on_conflict","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockIssueCreate"}}}},"responses":{"200":{"description":"Existing issue (?on_conflict=return)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockDocument"}}}},"201":{"description":"Created","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockDocument"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/stock-issues/{id}":{"get":{"tags":["Stock issues"],"summary":"Get a stock issue with lines","security":[{"bearerAuth":[]}],"x-scopes":["stock:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"stock issue","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockDocument"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/stock-issues/by-external-ref/{system}/{external_id}":{"get":{"tags":["Stock issues"],"summary":"Get a stock issue by external reference","security":[{"bearerAuth":[]}],"x-scopes":["stock:read"],"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9_-]{2,32}$","example":"shoptet"},"required":true,"name":"system","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":128},"required":true,"name":"external_id","in":"path"}],"responses":{"200":{"description":"stock issue","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockDocument"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/stock-issues/{id}/actions/{key}":{"post":{"tags":["Stock issues"],"summary":"Run a workflow action","description":"Keys come from the workflow catalogue (same as the buttons in the app): confirm, cancel. Unknown key → 404 `unknown_action`; key not allowed in the current status → 409 `invalid_transition` with `allowed_actions`. `confirm` posts the movements (stock only ever changes through a confirmed document — CLAUDE.md); a line without `lot_id` consumes FIFO automatically. `cancel` reverses the posted movements. Non-fatal warnings the app shows on confirm (e.g. a foreign reservation) are not currently surfaced on this endpoint — see the developer notes.","security":[{"bearerAuth":[]}],"x-scopes":["stock:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z_]{2,40}$","example":"confirm","description":"Action key from the workflow catalogue of the entity."},"required":true,"description":"Action key from the workflow catalogue of the entity.","name":"key","in":"path"}],"responses":{"200":{"description":"stock issue","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockDocument"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/goods-receipts/{id}/lines":{"post":{"tags":["Goods receipts"],"summary":"Add a line to a draft goods receipt","security":[{"bearerAuth":[]}],"x-scopes":["stock:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoodsReceiptLineCreate"}}}},"responses":{"201":{"description":"Line","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockLine"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/stock-issues/{id}/lines":{"post":{"tags":["Stock issues"],"summary":"Add a line to a draft stock issue","security":[{"bearerAuth":[]}],"x-scopes":["stock:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockIssueLineCreate"}}}},"responses":{"201":{"description":"Line","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockLine"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/stock-levels":{"get":{"tags":["Stock"],"summary":"List stock levels","description":"One row per item/warehouse combination that has ever had stock. `quantity` is on hand, in the item's unit (§3.4 — never converted); `available_quantity` = `quantity − reserved_quantity` (reservations come from orders and other internal holds; v1 does not list them separately).","security":[{"bearerAuth":[]}],"x-scopes":["stock:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"item_id","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"warehouse_id","in":"query"}],"responses":{"200":{"description":"Stock levels","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockLevelList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/stock-levels/lots":{"get":{"tags":["Stock"],"summary":"List stock lots (FIFO layers) of an item in a warehouse","description":"Remaining quantity per receipt line — the same list the app offers when picking a lot manually. `id` is the receipt line id; pass it as `lot_id` on a stock issue line to consume this layer instead of FIFO. Both `item_id` and `warehouse_id` are required.","security":[{"bearerAuth":[]}],"x-scopes":["stock:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"item_id","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"warehouse_id","in":"query"}],"responses":{"200":{"description":"Stock lots","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StockLotList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/invoices":{"get":{"tags":["Invoices"],"summary":"List issued invoices","description":"Sorted by updated_at; use `updated_since` + cursor to sync. Lines are not included — GET /invoices/{id}.","security":[{"bearerAuth":[]}],"x-scopes":["finance:read","sales:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","enum":["draft","issued","paid","cancelled"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"partner_id","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"warehouse_id","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"required":false,"name":"date_from","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"required":false,"name":"date_to","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"true = issued and past due_date."},"required":false,"description":"true = issued and past due_date.","name":"overdue","in":"query"}],"responses":{"200":{"description":"Invoices","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Invoices"],"summary":"Create a draft invoice, or issue one from an order","description":"Two shapes: `{ order_id, external_ref? }` creates it from an order's lines (same as POST /orders/{id}/actions/create_invoice; 422 order_not_invoiceable / order_already_invoiced / order_no_warehouse), or a draft body with `partner_id` and optional `lines[]`. The draft is a DRAFT (as in the app); issue it with POST /invoices/{id}/actions/issue. Send `Idempotency-Key` to make retries safe and `external_ref` to link your record (duplicate → 409 `external_ref_conflict`, or the existing invoice with `?on_conflict=return`). Lines are validated (item, unit = item's unit, decimal scale) before anything is written.","security":[{"bearerAuth":[]}],"x-scopes":["finance:write","sales:write"],"parameters":[{"schema":{"type":"string","enum":["error","return"],"default":"error","description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record."},"required":false,"description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record.","name":"on_conflict","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceCreateBody"}}}},"responses":{"200":{"description":"Existing invoice (?on_conflict=return)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invoice"}}}},"201":{"description":"Created","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invoice"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/invoices/{id}":{"get":{"tags":["Invoices"],"summary":"Get invoice with lines","security":[{"bearerAuth":[]}],"x-scopes":["finance:read","sales:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Invoice","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invoice"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Invoices"],"summary":"Update a draft invoice","description":"Only drafts (409 `invalid_transition` otherwise). Send `If-Match` to refuse stale writes (412).","security":[{"bearerAuth":[]}],"x-scopes":["finance:write","sales:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins."},"required":false,"description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins.","name":"if-match","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoicePatch"}}}},"responses":{"200":{"description":"Updated","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invoice"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"412":{"description":"Stale version (If-Match)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/invoices/by-external-ref/{system}/{external_id}":{"get":{"tags":["Invoices"],"summary":"Get invoice by external reference","security":[{"bearerAuth":[]}],"x-scopes":["finance:read","sales:read"],"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9_-]{2,32}$","example":"shoptet"},"required":true,"name":"system","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":128},"required":true,"name":"external_id","in":"path"}],"responses":{"200":{"description":"Invoice","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invoice"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/invoices/{id}/lines":{"post":{"tags":["Invoices"],"summary":"Add a line to a draft invoice","security":[{"bearerAuth":[]}],"x-scopes":["finance:write","sales:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceLineCreate"}}}},"responses":{"201":{"description":"Line","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceLine"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/invoices/{id}/lines/{line_id}":{"patch":{"tags":["Invoices"],"summary":"Update a line of a draft invoice","security":[{"bearerAuth":[]}],"x-scopes":["finance:write","sales:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"line_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceLinePatch"}}}},"responses":{"200":{"description":"Line","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceLine"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Invoices"],"summary":"Remove a line from a draft invoice","security":[{"bearerAuth":[]}],"x-scopes":["finance:write","sales:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"line_id","in":"path"}],"responses":{"204":{"description":"Removed"},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/invoices/{id}/actions/{key}":{"post":{"tags":["Invoices"],"summary":"Run an action on the invoice","description":"Keys: `issue`, `cancel` (workflow catalogue — same as the buttons in the app), plus `mark_paid` / `revert_payment` (payment engine, S89 — outside the workflow catalogue, `fromStatuses` issued / paid respectively). Unknown key → 404 `unknown_action`; key not allowed in the current status → 409 `invalid_transition` with `allowed_actions`. `mark_paid` without `account_id` uses the tenant's default finance account for the invoice's payment method (422 `account_required` if none).","security":[{"bearerAuth":[]}],"x-scopes":["finance:write","sales:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z_]{2,40}$","example":"confirm","description":"Action key from the workflow catalogue of the entity."},"required":true,"description":"Action key from the workflow catalogue of the entity.","name":"key","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceActionBody"}}}},"responses":{"200":{"description":"Invoice after the action","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invoice"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/received-invoices":{"get":{"tags":["Received invoices"],"summary":"List received (supplier) invoices","description":"Sorted by updated_at; use `updated_since` + cursor to sync. Lines are not included — GET /received-invoices/{id}.","security":[{"bearerAuth":[]}],"x-scopes":["finance:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","enum":["draft","confirmed","paid","cancelled"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"partner_id","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"Filters on received_date."},"required":false,"description":"Filters on received_date.","name":"date_from","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15","description":"Filters on received_date."},"required":false,"description":"Filters on received_date.","name":"date_to","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Matches supplier invoice no., internal number or variable symbol."},"required":false,"description":"Matches supplier invoice no., internal number or variable symbol.","name":"search","in":"query"},{"schema":{"type":"string","maxLength":30},"required":false,"name":"variable_symbol","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"confirmed AND past due_date."},"required":false,"description":"confirmed AND past due_date.","name":"overdue","in":"query"}],"responses":{"200":{"description":"Received invoices","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoiceList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Received invoices"],"summary":"Create a draft received invoice","description":"Creates a DRAFT (as in the app) with optional lines; confirm it with POST /received-invoices/{id}/actions/confirm (requires at least one line). Send `Idempotency-Key` to make retries safe and `external_ref` to link your record (duplicate → 409 `external_ref_conflict`, or the existing invoice with `?on_conflict=return`). Lines have no quantity/unit — a received-invoice line is a plain accounting split (description + amount excl. VAT + VAT rate + category). To import a scanned/ISDOC invoice, use the attachments + `POST /received-invoices/isdoc` flow instead.","security":[{"bearerAuth":[]}],"x-scopes":["finance:write"],"parameters":[{"schema":{"type":"string","enum":["error","return"],"default":"error","description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record."},"required":false,"description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record.","name":"on_conflict","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoiceCreate"}}}},"responses":{"200":{"description":"Existing invoice (?on_conflict=return)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoice"}}}},"201":{"description":"Created","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoice"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/received-invoices/{id}":{"get":{"tags":["Received invoices"],"summary":"Get a received invoice with lines","security":[{"bearerAuth":[]}],"x-scopes":["finance:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Received invoice","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoice"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Received invoices"],"summary":"Update a received invoice header","description":"Unlike an order, a received invoice stays editable after confirm (Finance 3.0 R3) — only export to accounting or cancellation lock it (409 `invalid_transition`). Currency/exchange rate stay draft-only (lines aren't recalculated once confirmed). Send `If-Match` to refuse stale writes (412).","security":[{"bearerAuth":[]}],"x-scopes":["finance:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins."},"required":false,"description":"ETag from a previous GET. Mismatch → 412 stale_version. Omit for last-write-wins.","name":"if-match","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoicePatch"}}}},"responses":{"200":{"description":"Updated","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoice"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"412":{"description":"Stale version (If-Match)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/received-invoices/by-external-ref/{system}/{external_id}":{"get":{"tags":["Received invoices"],"summary":"Get a received invoice by external reference","security":[{"bearerAuth":[]}],"x-scopes":["finance:read"],"parameters":[{"schema":{"type":"string","pattern":"^[a-z0-9_-]{2,32}$","example":"shoptet"},"required":true,"name":"system","in":"path"},{"schema":{"type":"string","minLength":1,"maxLength":128},"required":true,"name":"external_id","in":"path"}],"responses":{"200":{"description":"Received invoice","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoice"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/received-invoices/{id}/lines":{"post":{"tags":["Received invoices"],"summary":"Add a line to a received invoice","description":"Allowed until the invoice is exported to accounting (409 `invalid_transition` on an exported document).","security":[{"bearerAuth":[]}],"x-scopes":["finance:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoiceLineCreate"}}}},"responses":{"201":{"description":"Line","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoiceLine"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/received-invoices/{id}/lines/{line_id}":{"patch":{"tags":["Received invoices"],"summary":"Update a received invoice line","security":[{"bearerAuth":[]}],"x-scopes":["finance:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"line_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoiceLinePatch"}}}},"responses":{"200":{"description":"Line","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoiceLine"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Received invoices"],"summary":"Remove a received invoice line","security":[{"bearerAuth":[]}],"x-scopes":["finance:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"line_id","in":"path"}],"responses":{"204":{"description":"Removed"},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/received-invoices/{id}/actions/{key}":{"post":{"tags":["Received invoices"],"summary":"Run an action on the received invoice","description":"`confirm` (needs ≥1 line; assigns the internal number) and `cancel` come from the workflow catalogue. `mark_paid` (body `{ paid_at?, amount?, account_id? }`, from status confirmed) and `revert_payment` (from status paid) are the payment engine — outside the catalogue, same as invoices. Unknown key → 404 `unknown_action`; key not allowed in the current status → 409 `invalid_transition` with `allowed_actions`.","security":[{"bearerAuth":[]}],"x-scopes":["finance:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z_]{2,40}$","example":"confirm","description":"Action key from the workflow catalogue of the entity."},"required":true,"description":"Action key from the workflow catalogue of the entity.","name":"key","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoiceActionBody"}}}},"responses":{"200":{"description":"Received invoice after the action","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoice"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/cashflows":{"get":{"tags":["Cashflows"],"summary":"List cash-flow documents (Zjednodušené / Interní doklady)","description":"Sorted by updated_at; use `updated_since` + cursor to sync. Excludes cash-desk-only entries with no document link (transfers, direct till postings) — those live in the cash-desk ledger, not here.","security":[{"bearerAuth":[]}],"x-scopes":["finance:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","enum":["income","expense"]},"required":false,"name":"type","in":"query"},{"schema":{"type":"string","enum":["draft","confirmed","planned","pending","paid","cancelled"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"partner_id","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"required":false,"name":"date_from","in":"query"},{"schema":{"type":"string","format":"date","pattern":"^\\d{4}-\\d{2}-\\d{2}$","example":"2026-09-15"},"required":false,"name":"date_to","in":"query"},{"schema":{"type":"string","maxLength":200,"description":"Matches document code or description."},"required":false,"description":"Matches document code or description.","name":"search","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"shop_id","in":"query"}],"responses":{"200":{"description":"Cash flows","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CashFlowList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Cashflows"],"summary":"Create a cash-flow document","description":"Creates a confirmed document by default (`status` may force draft/cancelled). `is_cash` + `cash_desk_id` posts through that cash desk (till balance + mirrored ledger movement) and is settled immediately; otherwise it's a plain accounting document, payable later via `actions/mark_paid`. Send `Idempotency-Key` to make retries safe. No `external_ref` — cashflows aren't part of the external-reference set (§5.0 bod 2).","security":[{"bearerAuth":[]}],"x-scopes":["finance:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CashFlowCreate"}}}},"responses":{"201":{"description":"Created","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CashFlow"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/cashflows/{id}":{"get":{"tags":["Cashflows"],"summary":"Get a cash-flow document","security":[{"bearerAuth":[]}],"x-scopes":["finance:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Cash flow","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CashFlow"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/cashflows/{id}/actions/{key}":{"post":{"tags":["Cashflows"],"summary":"Run an action on the cash-flow document","description":"`mark_paid` (body `{ paid_at?, amount?, account_id? }`, allowed while not yet fully paid and not cancelled) and `cancel` (allowed while not cancelled) — cashflow has no workflow catalogue, so `allowed_actions` is derived from `status` and `payment_status` here, not from WORKFLOW_SOURCES. Unknown key → 404 `unknown_action`; key not allowed in the current state → 409 `invalid_transition` with `allowed_actions`, `status` and `payment_status`.","security":[{"bearerAuth":[]}],"x-scopes":["finance:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","pattern":"^[a-z_]{2,40}$","example":"confirm","description":"Action key from the workflow catalogue of the entity."},"required":true,"description":"Action key from the workflow catalogue of the entity.","name":"key","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CashFlowActionBody"}}}},"responses":{"200":{"description":"Cash flow after the action","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CashFlow"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/pos/sales/{id}":{"get":{"tags":["POS"],"summary":"Get a sale","description":"Any POS tab of the account, including those opened at the register in the app.","security":[{"bearerAuth":[]}],"x-scopes":["pos:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Sale","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosSale"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/pos/sales":{"post":{"tags":["POS"],"summary":"Record a completed sale","description":"Records a sale from your register or e-shop and settles it the way the app settles a POS tab: prices and VAT from the POS price list, stock written off from the cash desk's warehouse, a simplified sales document and the payment posted. `payment.amount` must match the total (a difference up to 0.50 CZK is rounding). Only `cash` and `card` in CZK, one payment per sale; the sale is dated when it is recorded. The key also needs `finance:write` (the payment is posted) and, when the cash desk moves stock, `stock:write`. Send `external_ref` (duplicate → 409 `external_ref_conflict`, or the existing sale with `?on_conflict=return`). If the sale is recorded but its settlement does not finish → 409 `settlement_failed` with `existing_id`; the sale stays open, so `?on_conflict=return` then answers 200 with `status: \"open\"` — check `status` before treating a returned sale as done.","security":[{"bearerAuth":[]}],"x-scopes":["pos:write"],"x-additional-scopes":["finance:write","stock:write"],"parameters":[{"schema":{"type":"string","enum":["error","return"],"default":"error","description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record."},"required":false,"description":"What to do when `external_ref` already exists: 409 (default) or 200 with the existing record.","name":"on_conflict","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosSaleWrite"}}}},"responses":{"200":{"description":"Existing sale (?on_conflict=return)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosSale"}}}},"201":{"description":"Recorded and settled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PosSale"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/finance-accounts":{"get":{"tags":["Finance"],"summary":"List finance accounts","description":"Bank, cash-desk and card-clearing accounts of the account. Use `id` as `account_id` when marking a document as paid. Balances are not exposed.","security":[{"bearerAuth":[]}],"x-scopes":["finance:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"include_inactive","in":"query"},{"schema":{"type":"string","enum":["bank","cash","card_clearing"]},"required":false,"name":"type","in":"query"}],"responses":{"200":{"description":"Finance accounts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceAccountList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/attachments":{"post":{"tags":["Attachments"],"summary":"Get a signed upload URL for a file","description":"Step 1 of 2: request a short-lived URL to upload the file's bytes directly to storage (bytes never pass through this API). Follow with POST /attachments/finalize once the PUT succeeds. Omit entity_type/entity_id together to upload into Files (Podatelna) without binding to a record yet.","security":[{"bearerAuth":[]}],"x-scopes":["core:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachmentUploadCreate"}}}},"responses":{"201":{"description":"Upload ticket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachmentUploadTicket"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/attachments/finalize":{"post":{"tags":["Attachments"],"summary":"Create the attachment record after uploading","description":"Step 2 of 2: call this once the PUT to upload_url succeeded. The actual file size is re-verified from storage (a mismatch or a plan quota breach fails here, not in step 1). entity_type/entity_id must match what was sent to POST /attachments.","security":[{"bearerAuth":[]}],"x-scopes":["core:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachmentFinalizeCreate"}}}},"responses":{"201":{"description":"Attachment created","headers":{"Location":{"schema":{"type":"string","description":"GET /attachments/{id}/content"},"required":true,"description":"GET /attachments/{id}/content"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Attachment"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/attachments/{id}/content":{"get":{"tags":["Attachments"],"summary":"Download the file behind an attachment","description":"Redirects (302) to a short-lived signed URL for the actual bytes. Returns 404 both when the attachment does not exist and when the key's owner cannot see it — the API never reveals which, matching the app's own permanent link.","security":[{"bearerAuth":[]}],"x-scopes":["core:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"302":{"description":"Redirect to a signed file URL."},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/inbox/submissions":{"post":{"tags":["Inbox"],"summary":"Submit a file into Files (Podatelna)","description":"Same entry point as e-mail and manual upload (Sprint 95 gateway): ISDOC gets imported as a received-invoice draft when the key also has finance:write (otherwise it stays in Files with a `note`), an accounting document may be classified straight to the AI document inbox (tenant setting), otherwise it waits in Files. Send either multipart/form-data with a `file` part (over 4 MB → 413 payload_too_large, use POST /attachments instead) or JSON `{ attachment_id }` for a file already uploaded via POST /attachments + /finalize (required for larger files). Send `Idempotency-Key` to make retries safe; the server fingerprints the raw bytes, so multipart uploads are safe too.","security":[{"bearerAuth":[]}],"x-scopes":["core:write"],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/InboxSubmissionUpload"}},"application/json":{"schema":{"$ref":"#/components/schemas/InboxSubmissionByAttachment"}}}},"responses":{"201":{"description":"Submission processed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxSubmissionResult"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"413":{"description":"File exceeds the inline upload limit","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/received-invoices/isdoc":{"post":{"tags":["Received invoices"],"summary":"Import a scanned ISDOC invoice","description":"Parses the ISDOC/ISDOCX file deterministically and creates a received-invoice DRAFT with the document's own totals (no OCR, no review queue) — same path as the app's Podatelna → \"Naimportovat ISDOC\". A duplicate document (matched by its ISDOC UUID) returns 409 `duplicate`; any other rejection reason (unsupported_document_type, invalid_xml, no_invoice_in_archive, file_too_large, no_finance_module, …) returns 422 with that reason as `code`.","security":[{"bearerAuth":[]}],"x-scopes":["finance:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IsdocImportCreate"}}}},"responses":{"201":{"description":"Received invoice created","headers":{"Location":{"schema":{"type":"string","description":"GET /received-invoices/{id}"},"required":true,"description":"GET /received-invoices/{id}"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceivedInvoiceImport"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/webhooks/endpoints":{"get":{"tags":["Webhooks"],"summary":"List webhook endpoints","description":"Disabled endpoints are hidden unless you pass `include_disabled=true`. Secrets are never returned here.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:manage"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":["boolean","null"]},"required":false,"name":"include_disabled","in":"query"}],"responses":{"200":{"description":"Endpoints","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Webhooks"],"summary":"Create a webhook endpoint","description":"Returns the signing secret once — store it, it is never shown again (rotate it with `actions/rotate_secret`). The URL must be https on port 443 with a public host; it is re-checked before every delivery.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:manage"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointCreate"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointSecret"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Webhooks are not configured on this deployment (signing key missing)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/webhooks/endpoints/{id}":{"get":{"tags":["Webhooks"],"summary":"Get a webhook endpoint","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:manage"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Endpoint","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"patch":{"tags":["Webhooks"],"summary":"Update a webhook endpoint","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:manage"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointPatch"}}}},"responses":{"200":{"description":"Updated","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"delete":{"tags":["Webhooks"],"summary":"Disable a webhook endpoint","description":"Soft delete: the endpoint stops receiving events, its delivery history stays. Re-enable with PATCH `is_active: true`.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:manage"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/webhooks/endpoints/{id}/actions/rotate_secret":{"post":{"tags":["Webhooks"],"summary":"Rotate the signing secret","description":"Returns the new secret once. Deliveries in flight are signed with the secret valid at send time.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:manage"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Rotated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointSecret"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"Webhooks are not configured on this deployment (signing key missing)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/webhooks/endpoints/{id}/actions/ping":{"post":{"tags":["Webhooks"],"summary":"Send a test event","description":"Delivers a `ping` event so you can verify the URL and the signature before anything happens in the account.","security":[{"bearerAuth":[]}],"x-scopes":["webhooks:manage"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Ping attempted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookPing"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/events":{"get":{"tags":["Events"],"summary":"List events since a sequence","description":"The safety net for webhooks: replay what you missed. Events are ordered by `sequence`, which is monotonic per account, so pass your last processed one as `since_sequence` and take `next_cursor` from the response. A `since_sequence` older than the plan retention returns 410 `events_expired` — do a full sync instead of silently skipping.","security":[{"bearerAuth":[]}],"x-scopes":["events:read"],"parameters":[{"schema":{"type":["integer","null"],"minimum":0,"description":"Return events after this sequence (your last processed one)."},"required":false,"description":"Return events after this sequence (your last processed one).","name":"since_sequence","in":"query"},{"schema":{"type":"string","example":"invoice.*,order.confirmed","description":"Comma-separated exact types or `<prefix>.*` patterns."},"required":false,"description":"Comma-separated exact types or `<prefix>.*` patterns.","name":"types","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":100},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"410":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/events/{id}":{"get":{"tags":["Events"],"summary":"Get one event","description":"Accepts the id as delivered (`evt_<uuid>`) or the bare uuid.","security":[{"bearerAuth":[]}],"x-scopes":["events:read"],"parameters":[{"schema":{"type":"string","maxLength":80},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Event","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/workflow-steps/{step_instance_id}/actions/complete":{"post":{"tags":["Workflow"],"summary":"Complete a step that waits for an external system","description":"Call it after a `workflow.step_waiting_external` event, with the id from `data.object.step_instance_id`. `approved` continues the workflow; `rejected` stops it and notifies the person who started it. A step can be completed only once; after its wait timed out and it was handed over to a person, it answers 409 `step_handed_over`. The steps that follow an approval run right away under THIS key: an action step (confirming an order, issuing an invoice…) needs the key's scope for that module (e.g. `sales:write`), otherwise the workflow stops — check `instance_status`. Any key of the account with `workflow:write` can complete a waiting step; the key that did is recorded (`completed_by_api_key_id`).","security":[{"bearerAuth":[]}],"x-scopes":["workflow:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"step_instance_id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowStepComplete"}}}},"responses":{"200":{"description":"Completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowStepCompleteResult"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/internal/webhook-deliveries":{"post":{"tags":["Internal"],"summary":"Run due webhook deliveries and housekeeping (cron only)","description":"Called by pg_cron every minute with `Authorization: Bearer <CRON_SECRET>`. Not part of the public contract: no API key, no scopes, no rate limit. Delivers due attempts, purges expired idempotency keys, deliveries, request log rows and events past the plan retention, and warns about API keys close to expiry.","responses":{"200":{"description":"Run summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalCronResult"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/batches":{"get":{"tags":["Brewery"],"summary":"List batches","security":[{"bearerAuth":[]}],"x-scopes":["brewery:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","enum":["plan","preparation","brewing","fermentation","conditioning","packaging","completed","transferred","cancelled","dumped"]},"required":false,"name":"phase","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"recipe_id","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"equipment_id","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"Batches","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/batches/{id}":{"get":{"tags":["Brewery"],"summary":"Get a batch","security":[{"bearerAuth":[]}],"x-scopes":["brewery:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Batch","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Batch"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/batches/{id}/measurements":{"get":{"tags":["Brewery"],"summary":"List measurements of a batch","description":"Oldest first. Values are canonical (°P, SG, °C, litres, bar); `entered` keeps the original input when it was converted.","security":[{"bearerAuth":[]}],"x-scopes":["brewery:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Measurements","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchMeasurementList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Brewery"],"summary":"Record a measurement","description":"Send each value with the unit you measured in — `{ \"value\": \"64.4\", \"unit\": \"f\" }` — and the API stores it canonically (°C, °P, litres, bar), keeping the original in `entered`. A gravity in SG is stored in `gravity_sg` and converted to `gravity_plato`. Emits `batch.measurement_added`.","security":[{"bearerAuth":[]}],"x-scopes":["brewery:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchMeasurementWrite"}}}},"responses":{"201":{"description":"Recorded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchMeasurement"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/batches/{id}/actions/advance_phase":{"post":{"tags":["Brewery"],"summary":"Move a batch to its next phase","description":"Same as the phase buttons in the app, with the same side effects (brew steps, vessel occupancy, schedule). Only the next phase on the batch's path is allowed (409 `invalid_transition` otherwise). Emits `batch.phase_changed`.","security":[{"bearerAuth":[]}],"x-scopes":["brewery:write"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchAdvancePhase"}}}},"responses":{"200":{"description":"Batch after the transition","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Batch"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"Conflict (state, duplicate external_ref, idempotency in progress)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"Validation or business rule failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/recipes":{"get":{"tags":["Brewery"],"summary":"List recipes","security":[{"bearerAuth":[]}],"x-scopes":["brewery:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","maxLength":40},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"Recipes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/recipes/{id}":{"get":{"tags":["Brewery"],"summary":"Get a recipe with its ingredients","description":"Ingredient quantities are in the unit of the recipe line; the API never converts them.","security":[{"bearerAuth":[]}],"x-scopes":["brewery:read"],"parameters":[{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Recipe","headers":{"ETag":{"schema":{"type":"string","example":"W/\"1789465519746\"","description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."},"required":true,"description":"Weak validator W/\"<updated_at ms>\" — send it back as If-Match on PATCH."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeDetail"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (also for records of another account)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/equipment":{"get":{"tags":["Brewery"],"summary":"List equipment","description":"Vessels and brewhouse equipment. Use `id` to match a batch's `equipment`.","security":[{"bearerAuth":[]}],"x-scopes":["brewery:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","maxLength":40},"required":false,"name":"type","in":"query"},{"schema":{"type":"string","maxLength":40},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"uuid","example":"8c2e5a8e-1b2f-4c3d-9e0f-1a2b3c4d5e6f"},"required":false,"name":"shop_id","in":"query"},{"schema":{"type":"string","enum":["true","false"]},"required":false,"name":"is_active","in":"query"},{"schema":{"type":"string","maxLength":200},"required":false,"name":"search","in":"query"}],"responses":{"200":{"description":"Equipment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EquipmentList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/excise/monthly-reports":{"get":{"tags":["Brewery"],"summary":"List monthly excise tax returns","description":"Read only. Volumes are always in hectolitres and gravity in whole degrees Plato, as the law requires — no unit conversion. 403 `excise_not_enabled` when the account keeps no excise records.","security":[{"bearerAuth":[]}],"x-scopes":["brewery:read"],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50,"example":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque cursor from `next_cursor`."},"required":false,"description":"Opaque cursor from `next_cursor`.","name":"cursor","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z","description":"Only records updated at or after this instant (incremental sync)."},"required":false,"description":"Only records updated at or after this instant (incremental sync).","name":"updated_since","in":"query"},{"schema":{"type":"string","format":"date-time","example":"2026-09-15T07:00:00.000Z"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","enum":["draft","submitted","accepted"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}$","example":"2026-08"},"required":false,"name":"period","in":"query"}],"responses":{"200":{"description":"Monthly returns","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExciseMonthlyReportList"}}}},"401":{"description":"Missing or invalid API key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Scope, add-on or module missing","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"webhooks":{}}