{"components":{"responses":{},"schemas":{"AuthTokenResponse":{"example":{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","user":{"email":"user@example.com","id":1}},"properties":{"token":{"description":"Bearer token (30-day validity)","type":"string"},"user":{"properties":{"email":{"format":"email","type":"string"},"id":{"type":"integer"}},"type":"object"}},"title":"AuthTokenResponse","type":"object"},"CreditNoteRequest":{"example":{"original_invoice_id":1,"refund_reason_code":"07"},"properties":{"invoice_id":{"description":"Alias for original_invoice_id","type":"integer"},"original_invoice_id":{"description":"ID of the invoice being credited","type":"integer"},"refund_reason_code":{"type":"string"}},"required":["original_invoice_id"],"title":"CreditNoteRequest","type":"object"},"CustomerRequest":{"example":{"email":"customer@example.com","name":"Test Customer","phone":"0977123456","tax_number":"1000000001"},"properties":{"email":{"format":"email","type":"string"},"name":{"type":"string"},"phone":{"type":"string"},"tax_number":{"description":"Customer TPIN","type":"string"}},"title":"CustomerRequest","type":"object"},"ErrorResponse":{"properties":{"error":{"description":"Error code or message","type":"string"},"errors":{"description":"Validation errors keyed by field","type":"object"},"message":{"description":"Human-readable error detail","type":"string"}},"title":"ErrorResponse","type":"object"},"GenericObject":{"additionalProperties":true,"title":"GenericObject","type":"object"},"InvoiceRequest":{"example":{"currency_code":"ZMW","exchange_rate":"1.0","line_items":[{"description":"Test Item","item_classification_code":"43232202","item_code":"ITEM-001","quantity":2,"unit_price":"50.00","vat_category_code":"A"}],"number":"INV-0042-AUG26","status":"pending","walk_in_name":"Walk-in Customer","walk_in_phone":"0977000000"},"properties":{"currency_code":{"description":"ISO currency code, default ZMW","type":"string"},"customer":{"description":"Find or create a registered customer by tax_number/tpin","properties":{"address":{"type":"string"},"email":{"type":"string"},"name":{"type":"string"},"phone":{"type":"string"},"tax_number":{"description":"Alias: tpin","type":"string"},"tpin":{"type":"string"}},"type":"object"},"customer_id":{"description":"Existing customer ID","type":"integer"},"discount_type":{"enum":["percentage","fixed"],"type":"string"},"discount_value":{"type":"string"},"exchange_rate":{"description":"Required when currency_code is not ZMW","type":"string"},"line_items":{"items":{"properties":{"description":{"type":"string"},"item_classification_code":{"description":"ZRA item class code (max 10 chars)","maxLength":10,"type":"string"},"item_code":{"type":"string"},"product_id":{"type":"integer"},"quantity":{"type":"number"},"unit_price":{"type":"string"},"vat_category_code":{"type":"string"}},"type":"object"},"type":"array"},"number":{"description":"Invoice number (required). Used as `cisInvcNo` when syncing to ZRA.\n\n**Format:** `INV-0001-JUN24` or legacy `INV-0001-JUN`\n(pattern: `INV-` + 4 digits + `-` + 3 uppercase letters + optional 2-digit year suffix).\n\nMust be unique per tenant.\n","example":"INV-0042-AUG26","pattern":"^INV-\\d{4}-[A-Z]{3}(\\d{2})?$","type":"string"},"status":{"description":"Invoice status, e.g. pending, paid, draft","type":"string"},"walk_in_name":{"description":"Customer name when no customer_id","type":"string"},"walk_in_phone":{"type":"string"},"walk_in_tpin":{"description":"10-digit TPIN for walk-in customers (optional; ZRA defaults to 2001696235)","type":"string"}},"required":["number","status","line_items"],"title":"InvoiceRequest","type":"object"},"LoginRequest":{"properties":{"email":{"format":"email","type":"string"},"password":{"format":"password","type":"string"}},"required":["email","password"],"title":"LoginRequest","type":"object"},"ProductRequest":{"example":{"item_classification_code":"43232202","name":"Test Product","origin_country_code":"ZM","packaging_unit_code":"EA","price":"100.00","quantity_unit_code":"EA","stock_qty":50,"vat_category_code":"A"},"properties":{"item_classification_code":{"description":"ZRA item class code (max 10 chars)","maxLength":10,"type":"string"},"name":{"type":"string"},"origin_country_code":{"type":"string"},"packaging_unit_code":{"type":"string"},"price":{"type":"string"},"quantity_unit_code":{"type":"string"},"stock_qty":{"type":"integer"},"vat_category_code":{"enum":["A","B","C1","C2","C3","D","E"],"type":"string"}},"title":"ProductRequest","type":"object"},"PurchaseRequest":{"example":{"items":[{"product_id":1,"quantity":2,"unit_price":"120.00"}],"purchase_date":"2026-08-19","supplier_name":"Example Supplier","supplier_tpin":"1000000000","total_amount":"240.00"},"properties":{"items":{"items":{"properties":{"product_id":{"type":"integer"},"quantity":{"type":"number"},"unit_price":{"type":"string"}},"type":"object"},"type":"array"},"purchase_date":{"format":"date","type":"string"},"supplier_name":{"type":"string"},"supplier_tpin":{"description":"10-digit supplier TPIN","type":"string"},"total_amount":{"type":"string"}},"title":"PurchaseRequest","type":"object"},"QuotationRequest":{"example":{"currency_code":"ZMW","exchange_rate":"1.0","quotation_items":[{"description":"Consulting","product_id":1,"quantity":1,"total":"60.00","unit_price":"60.00"}],"status":"draft","walk_in_name":"Quote Customer"},"properties":{"currency_code":{"type":"string"},"customer_id":{"type":"integer"},"exchange_rate":{"type":"string"},"quotation_items":{"items":{"properties":{"description":{"type":"string"},"product_id":{"type":"integer"},"quantity":{"type":"integer"},"total":{"type":"string"},"unit_price":{"type":"string"}},"type":"object"},"type":"array"},"status":{"enum":["draft","sent","accepted","rejected","expired"],"type":"string"},"walk_in_name":{"type":"string"}},"title":"QuotationRequest","type":"object"},"RegisterRequest":{"example":{"bhf_id":"000","company_name":"Example Trading Ltd","company_tpin":"1000000000","email":"api-client@example.com","password":"SecurePass123!"},"properties":{"bhf_id":{"description":"Branch ID, usually 000","type":"string"},"company_name":{"description":"Tenant company name. Unique across all tenants (case-insensitive).","type":"string"},"company_tpin":{"description":"10-digit TPIN. Unique across all tenants. Login email is also unique.","type":"string"},"email":{"format":"email","type":"string"},"password":{"format":"password","type":"string"}},"required":["email","password"],"title":"RegisterRequest","type":"object"},"SettingsUpsertRequest":{"description":"Bulk ZRA settings, a nested `settings` map, or a single `{key, value}` pair.","example":{"zra_api_url":"http://host:8080/sandboxvsdc1.0.8.0","zra_bhf_id":"000","zra_device_model":"SANDBOX","zra_device_serial":"1012260853","zra_tpin":"1012260853"},"properties":{"bhfId":{"description":"Alias for zra_bhf_id","type":"string"},"deviceModel":{"description":"Alias for zra_device_model","type":"string"},"dvcSrlNo":{"description":"Alias for zra_device_serial","type":"string"},"key":{"description":"Single-key upsert","type":"string"},"settings":{"additionalProperties":true,"type":"object"},"tpin":{"description":"Alias for zra_tpin","type":"string"},"value":{"description":"Single-key upsert value","type":"string"},"vsdcUrl":{"description":"Alias for zra_api_url","type":"string"},"zra_api_url":{"description":"Tenant VSDC base URL","type":"string"},"zra_bhf_id":{"example":"000","type":"string"},"zra_device_model":{"example":"SANDBOX","type":"string"},"zra_device_serial":{"type":"string"},"zra_tpin":{"description":"Tenant TPIN. Must be unique across all tenants.","type":"string"}},"title":"SettingsUpsertRequest","type":"object"},"SyncQueuedResponse":{"example":{"invoice_id":123,"message":"Invoice queued for ZRA sync","status":"queued","success":true},"properties":{"invoice_id":{"type":"integer"},"message":{"type":"string"},"status":{"enum":["queued"],"type":"string"},"success":{"type":"boolean"}},"title":"SyncQueuedResponse","type":"object"},"ZraInitRequest":{"example":{"bhfId":"000","dvcSrlNo":"2001696235","tpin":"2001696235"},"properties":{"bhfId":{"description":"Branch ID (alias: bhf_id)","type":"string"},"bhf_id":{"type":"string"},"device_serial":{"description":"Optional override (alias: dvcSrlNo)","type":"string"},"dvcSrlNo":{"type":"string"},"tpin":{"description":"10-digit Tax Payer Identification Number","type":"string"}},"required":["tpin","bhfId"],"title":"ZraInitRequest","type":"object"},"ZraStatusResponse":{"properties":{"data":{"properties":{"bhf_id":{"nullable":true,"type":"string"},"device_serial":{"nullable":true,"type":"string"},"initialized":{"type":"boolean"},"mrc_no":{"nullable":true,"type":"string"},"sdc_id":{"nullable":true,"type":"string"},"tpin":{"nullable":true,"type":"string"},"zra_api_url":{"nullable":true,"type":"string"}},"type":"object"}},"title":"ZraStatusResponse","type":"object"}},"securitySchemes":{"bearerAuth":{"bearerFormat":"JWT","description":"Bearer token from POST /users/log_in or POST /users/register. Valid for 30 days.","scheme":"bearer","type":"http"}}},"info":{"description":"REST API for the **Invoicing System** — a ZRA Smart Invoice gateway for SMEs, mobile apps, and ERP integrations.\n\n## Two different APIs\n\n| API | Base URL | Purpose |\n|-----|----------|---------|\n| **This API** | `/api/*` | Your invoicing app — auth, local records, ZRA sync orchestration |\n| **VSDC API** | VSDC WAR URL | ZRA sandbox/production directly (Postman: Sales & Transactions, Stock Management) |\n\n**Integrators should use this API**, not call VSDC directly unless doing low-level VSDC testing.\n\n## Typical integration flow\n\n1. `POST /users/register` or `POST /users/log_in` → Bearer token\n2. `POST /settings/upsert` with `zra_api_url`, `zra_device_model`, and other ZRA fields in one body\n3. `POST /zra/initialize` → device initialized (SDC ID, MRC)\n4. `POST /products` → `POST /products/{id}/sync_zra`\n5. `POST /invoices` → `POST /invoices/{id}/sync_zra` (returns **202 queued**)\n6. `GET /invoices/{id}` → poll until `zra_sync_status` is success\n\n## Sync prerequisites\n\nAll `/sync_zra` endpoints require ZRA device initialization. Otherwise returns **403** `zra_not_initialized`.\n\n## Rate limiting\n\nSync endpoints are limited to **60 requests per minute** per tenant (**429** `rate_limited`).\n\n## Authentication\n\nProtected routes require: `Authorization: Bearer <token>`\n","title":"Invoicing System API","version":"0.1.0"},"openapi":"3.0.0","paths":{"/settings/upload_logo":{"post":{"callbacks":{},"deprecated":false,"description":"Upload a company logo image (multipart/form-data).","operationId":"settings_upload_logo","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Logo uploaded"}},"security":[{"bearerAuth":[]}],"summary":"Upload company logo","tags":["Settings"]}},"/credit_notes/{id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Remove credit note locally.","operationId":"credit_notes_delete","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Delete credit note","tags":["Credit Notes"]},"get":{"callbacks":{},"deprecated":false,"description":"Retrieve credit note by ID.","operationId":"credit_notes_show","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get credit note","tags":["Credit Notes"]},"patch":{"callbacks":{},"deprecated":false,"description":"Partial update.","operationId":"credit_notes_patch","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Patch credit note","tags":["Credit Notes"]},"put":{"callbacks":{},"deprecated":false,"description":"Update credit note fields.","operationId":"credit_notes_update","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Update credit note","tags":["Credit Notes"]}},"/dashboard":{"get":{"callbacks":{},"deprecated":false,"description":"**Use case:** Fetch summary metrics for mobile apps or integrator dashboards.\n\nReturns sales totals, recent activity, and stock alerts.\n","operationId":"dashboard_index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Dashboard data"}},"security":[{"bearerAuth":[]}],"summary":"Get dashboard summary","tags":["Dashboard"]}},"/purchases/{id}/sync_zra":{"post":{"callbacks":{},"deprecated":false,"description":"Push a local purchase to ZRA (`trnsPurchase/savePurchase`).","operationId":"purchase_sync_zra","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Sync purchase to ZRA","tags":["Stock & Purchases"]}},"/invoices/{id}/save_provisional_invoice":{"post":{"callbacks":{},"deprecated":false,"description":"Create a provisional invoice in ZRA before finalization.","operationId":"invoice_save_provisional","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Save provisional invoice","tags":["Invoices"]}},"/products/{id}/sync_zra":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Register a local product with ZRA (`items/saveItem`).\n\nProduct must have ZRA classification codes and VAT category. Requires initialized device.\n","operationId":"product_sync_zra","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Product registered with ZRA"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"ZRA not initialized"}},"security":[{"bearerAuth":[]}],"summary":"Sync product to ZRA","tags":["Products"]}},"/zra/item_classifications":{"get":{"callbacks":{},"deprecated":false,"description":"**Use case:** Fetch UNSPSC/item classification codes for product registration. Proxies VSDC `itemClass/selectItemsClass`.","operationId":"zra_get__zra_item_classifications","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get item classifications (GET)","tags":["ZRA Pull"]},"post":{"callbacks":{},"deprecated":false,"description":"ZRA-compatible POST variant of the same pull endpoint.","operationId":"zra_post__zra_item_classifications","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get item classifications (POST)","tags":["ZRA Pull"]}},"/purchases":{"get":{"callbacks":{},"deprecated":false,"description":"List supplier purchase records.","operationId":"purchase_index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"List purchase","tags":["Stock & Purchases"]},"post":{"callbacks":{},"deprecated":false,"description":"Record a purchase locally with `items`, then sync to ZRA.","operationId":"purchase_create","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseRequest"}}},"description":"Created"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"}},"security":[{"bearerAuth":[]}],"summary":"Create purchase","tags":["Stock & Purchases"]}},"/products/{id}/save_item_composition":{"post":{"callbacks":{},"deprecated":false,"description":"Register composite/bundle item composition with ZRA.","operationId":"product_save_item_composition","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Save item composition","tags":["Products"]}},"/zra/config/initialize":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Register the fiscal device with ZRA VSDC (`initializer/selectInitInfo`).\n\nMust be completed before any sync endpoint. Stores SDC ID and MRC locally.\n\n**Prerequisites:** VSDC URL and device model configured in Settings (e.g. `SANDBOX` for sandbox).\n\n**Note:** VSDC may return 902 (\"already installed\") — local VSDC must have device keys (`cmcKey`) for sales to work.\n","operationId":"zra_config_initialize","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZraInitRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZraStatusResponse"}}},"description":"Device initialized"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"ZRA rejected initialization"}},"security":[{"bearerAuth":[]}],"summary":"Initialize device (mobile alias)","tags":["ZRA Setup"]}},"/invoices/{id}/sync_zra":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Fiscalize an existing local invoice (`trnsSales/saveSales`).\n\nQueues an Oban background job. Returns **202 Accepted** immediately.\nPoll GET /invoices/{id} or POST /invoices/{id}/check_zra_sync for progress.\n","operationId":"invoice_sync_zra","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncQueuedResponse"}}},"description":"Queued for sync"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"ZRA not initialized"}},"security":[{"bearerAuth":[]}],"summary":"Sync invoice to ZRA","tags":["Invoices"]}},"/stock_movements":{"get":{"callbacks":{},"deprecated":false,"description":"List stock adjustments, transfers, and corrections.","operationId":"stock_movement_index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"List stock_movement","tags":["Stock & Purchases"]},"post":{"callbacks":{},"deprecated":false,"description":"Record a stock movement locally, then sync to ZRA (`stock/saveStockItems`).","operationId":"stock_movement_create","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Created"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"}},"security":[{"bearerAuth":[]}],"summary":"Create stock_movement","tags":["Stock & Purchases"]}},"/invoices/{id}/save_final_invoice":{"post":{"callbacks":{},"deprecated":false,"description":"Finalize a provisional invoice in ZRA.","operationId":"invoice_save_final","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Save final invoice","tags":["Invoices"]}},"/users/log_in":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Authenticate an existing user and obtain a Bearer token.\n\nSend the token on all subsequent requests: `Authorization: Bearer <token>`.\nAccepts flat `{email, password}` or nested `{user: {email, password}}` params.\n","operationId":"auth_login","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthTokenResponse"}}},"description":"Login successful"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid email or password"}},"security":[],"summary":"Login","tags":["Authentication"]}},"/quotations":{"get":{"callbacks":{},"deprecated":false,"description":"List non-fiscal quotations.","operationId":"quotation_index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"List quotation","tags":["Quotations"]},"post":{"callbacks":{},"deprecated":false,"description":"Create a quotation. `total_amount` is computed from line items when omitted.","operationId":"quotation_create","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationRequest"}}},"description":"Created"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"}},"security":[{"bearerAuth":[]}],"summary":"Create quotation","tags":["Quotations"]}},"/zra/items":{"post":{"callbacks":{},"deprecated":false,"description":"Search items registered with ZRA.","operationId":"zra_post_items","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Search ZRA items","tags":["ZRA Pull"]}},"/branches/save_customer":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Register a customer under a specific branch in ZRA.","operationId":"branches_save_customer","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Save branch customer","tags":["Branches"]}},"/purchases/get_from_zra":{"get":{"callbacks":{},"deprecated":false,"description":"Import purchase transactions from ZRA into the local database.","operationId":"purchases_get_from_zra","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Pull purchases from ZRA","tags":["Stock & Purchases"]}},"/zra/config/update_from_response":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Manually apply a VSDC initialization response (SDC ID, MRC) to local config.\n\nUseful when initialization was done outside the app or response needs to be replayed.\n","operationId":"zra_update_from_response","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"zra_response object from VSDC","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Config updated"}},"security":[{"bearerAuth":[]}],"summary":"Update config from ZRA response","tags":["ZRA Setup"]}},"/quotations/{id}/convert_to_invoice":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Convert an accepted quotation into a local invoice.\n\nDoes not automatically sync to ZRA — call invoice sync separately.\n","operationId":"quotation_convert","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Convert to invoice","tags":["Quotations"]}},"/zra/import_items":{"get":{"callbacks":{},"deprecated":false,"description":"**Use case:** Pull import declarations from ZRA customs integration. Proxies VSDC `imports/selectImportItems`.","operationId":"zra_get__zra_import_items","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get import items (GET)","tags":["ZRA Pull"]},"post":{"callbacks":{},"deprecated":false,"description":"ZRA-compatible POST variant of the same pull endpoint.","operationId":"zra_post__zra_import_items","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get import items (POST)","tags":["ZRA Pull"]}},"/invoices/{id}/pdf":{"get":{"callbacks":{},"deprecated":false,"description":"Generate and download a PDF for the invoice.","operationId":"invoice_pdf","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"PDF document"}},"security":[{"bearerAuth":[]}],"summary":"Download invoice PDF","tags":["Invoices"]}},"/quotations/{id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Remove quotation from local database.","operationId":"quotation_delete","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Delete quotation","tags":["Quotations"]},"get":{"callbacks":{},"deprecated":false,"description":"Retrieve a single quotation by ID.","operationId":"quotation_show","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get quotation","tags":["Quotations"]},"patch":{"callbacks":{},"deprecated":false,"description":"Partially update quotation.","operationId":"quotation_patch","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Patch quotation","tags":["Quotations"]},"put":{"callbacks":{},"deprecated":false,"description":"Replace quotation fields.","operationId":"quotation_update","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotationRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Update quotation","tags":["Quotations"]}},"/credit_notes/{id}/pdf":{"get":{"callbacks":{},"deprecated":false,"description":"Generate PDF for the credit note.","operationId":"credit_notes_pdf","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"PDF document"}},"security":[{"bearerAuth":[]}],"summary":"Download credit note PDF","tags":["Credit Notes"]}},"/registered_items":{"get":{"callbacks":{},"deprecated":false,"description":"List items registered with ZRA for this tenant.","operationId":"registered_items_index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"List registered ZRA items","tags":["Stock & Purchases"]}},"/stock_movements/{id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Remove stock_movement from local database.","operationId":"stock_movement_delete","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Delete stock_movement","tags":["Stock & Purchases"]},"get":{"callbacks":{},"deprecated":false,"description":"Retrieve a single stock_movement by ID.","operationId":"stock_movement_show","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get stock_movement","tags":["Stock & Purchases"]},"patch":{"callbacks":{},"deprecated":false,"description":"Partially update stock_movement.","operationId":"stock_movement_patch","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Patch stock_movement","tags":["Stock & Purchases"]},"put":{"callbacks":{},"deprecated":false,"description":"Replace stock_movement fields.","operationId":"stock_movement_update","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Update stock_movement","tags":["Stock & Purchases"]}},"/invoices/{id}/create_debit_note":{"post":{"callbacks":{},"deprecated":false,"description":"Create a debit note linked to an existing invoice.","operationId":"invoice_create_debit_note","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Create debit note","tags":["Invoices"]}},"/users/change_password":{"post":{"callbacks":{},"deprecated":false,"description":"Update the authenticated user's password.","operationId":"auth_change_password","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"current_password, new_password","required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Password updated"}},"security":[{"bearerAuth":[]}],"summary":"Change password","tags":["Authentication"]}},"/import_items/sync_zra":{"post":{"callbacks":{},"deprecated":false,"description":"Update import item status with ZRA (`imports/updateImportItems`).","operationId":"import_items_sync_zra","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Sync import items to ZRA","tags":["Stock & Purchases"]}},"/zra/purchases":{"get":{"callbacks":{},"deprecated":false,"description":"**Use case:** Pull purchase transactions from ZRA for reconciliation. Proxies VSDC `trnsPurchase/selectTrnsPurchaseSales`.","operationId":"zra_get__zra_purchases","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get purchases (GET)","tags":["ZRA Pull"]},"post":{"callbacks":{},"deprecated":false,"description":"ZRA-compatible POST variant of the same pull endpoint.","operationId":"zra_post__zra_purchases","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get purchases (POST)","tags":["ZRA Pull"]}},"/customers/{id}/sync_zra":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Push the local customer record to ZRA VSDC.\n\nCalls VSDC `customers/saveCustomer`. Requires ZRA device initialization.\nReturns **403** with `zra_not_initialized` if device is not set up.\nRate limited to 60 sync requests per minute per tenant.\n","operationId":"customer_sync_zra","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Synced successfully"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncQueuedResponse"}}},"description":"Queued for background sync"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"ZRA not initialized"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited"}},"security":[{"bearerAuth":[]}],"summary":"Sync customer to ZRA","tags":["Customers"]}},"/zra/initialize":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Register the fiscal device with ZRA VSDC (`initializer/selectInitInfo`).\n\nMust be completed before any sync endpoint. Stores SDC ID and MRC locally.\n\n**Prerequisites:** VSDC URL and device model configured in Settings (e.g. `SANDBOX` for sandbox).\n\n**Note:** VSDC may return 902 (\"already installed\") — local VSDC must have device keys (`cmcKey`) for sales to work.\n","operationId":"zra_initialize","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZraInitRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZraStatusResponse"}}},"description":"Device initialized"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"ZRA rejected initialization"}},"security":[{"bearerAuth":[]}],"summary":"Initialize device ","tags":["ZRA Setup"]}},"/settings/upsert":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Save all ZRA connection fields in one request (or a single key/value).\n\nBulk body: `zra_api_url`, `zra_device_model`, `zra_device_serial`, `zra_tpin`, `zra_bhf_id`.\n\nAliases accepted: `vsdcUrl`, `deviceModel`, `dvcSrlNo`, `tpin`, `bhfId`.\n\nSingle-key body still works: `{ \"key\": \"zra_api_url\", \"value\": \"...\" }`.\n\nThen call `POST /zra/initialize`.\n","operationId":"settings_upsert","parameters":[],"requestBody":{"content":{"application/json":{"example":{"zra_api_url":"http://host:8080/sandboxvsdc1.0.8.0","zra_bhf_id":"000","zra_device_model":"SANDBOX","zra_device_serial":"1012260853","zra_tpin":"1012260853"},"examples":{"default":{"description":"Includes required invoice number","summary":"Example request","value":{"zra_api_url":"http://host:8080/sandboxvsdc1.0.8.0","zra_bhf_id":"000","zra_device_model":"SANDBOX","zra_device_serial":"1012260853","zra_tpin":"1012260853"}}},"schema":{"$ref":"#/components/schemas/SettingsUpsertRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Settings saved"}},"security":[{"bearerAuth":[]}],"summary":"Upsert settings","tags":["Settings"]}},"/zra/branches":{"get":{"callbacks":{},"deprecated":false,"description":"**Use case:** List ZRA-registered branches for the taxpayer. Proxies VSDC `branches/selectBranches`.","operationId":"zra_get__zra_branches","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get branches (GET)","tags":["ZRA Pull"]},"post":{"callbacks":{},"deprecated":false,"description":"ZRA-compatible POST variant of the same pull endpoint.","operationId":"zra_post__zra_branches","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get branches (POST)","tags":["ZRA Pull"]}},"/import_items":{"get":{"callbacks":{},"deprecated":false,"description":"List import declarations pulled from ZRA.","operationId":"import_items_index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"List import items","tags":["Stock & Purchases"]}},"/purchases/{id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Remove purchase from local database.","operationId":"purchase_delete","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Delete purchase","tags":["Stock & Purchases"]},"get":{"callbacks":{},"deprecated":false,"description":"Retrieve a single purchase by ID.","operationId":"purchase_show","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get purchase","tags":["Stock & Purchases"]},"patch":{"callbacks":{},"deprecated":false,"description":"Partially update purchase.","operationId":"purchase_patch","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Patch purchase","tags":["Stock & Purchases"]},"put":{"callbacks":{},"deprecated":false,"description":"Replace purchase fields.","operationId":"purchase_update","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Update purchase","tags":["Stock & Purchases"]}},"/products/{id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Remove product from local database.","operationId":"product_delete","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Delete product","tags":["Products"]},"get":{"callbacks":{},"deprecated":false,"description":"Retrieve a single product by ID.","operationId":"product_show","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get product","tags":["Products"]},"patch":{"callbacks":{},"deprecated":false,"description":"Partially update product.","operationId":"product_patch","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Patch product","tags":["Products"]},"put":{"callbacks":{},"deprecated":false,"description":"Replace product fields.","operationId":"product_update","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Update product","tags":["Products"]}},"/invoices/{id}/retry_zra_sync":{"post":{"callbacks":{},"deprecated":false,"description":"Re-queue a failed invoice sync job.","operationId":"invoice_retry_zra_sync","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Retry ZRA sync","tags":["Invoices"]}},"/invoices":{"get":{"callbacks":{},"deprecated":false,"description":"List invoices for the authenticated tenant.","operationId":"invoice_index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"List invoice","tags":["Invoices"]},"post":{"callbacks":{},"deprecated":false,"description":"Create an invoice locally. `number` is required (e.g. INV-0042-AUG26). Does not fiscalize until sync_zra is called.","operationId":"invoice_create","parameters":[],"requestBody":{"content":{"application/json":{"example":{"currency_code":"ZMW","exchange_rate":"1.0","line_items":[{"description":"Test Item","item_classification_code":"43232202","item_code":"ITEM-001","quantity":2,"unit_price":"50.00","vat_category_code":"A"}],"number":"INV-0042-AUG26","status":"pending","walk_in_name":"Walk-in Customer","walk_in_phone":"0977000000"},"examples":{"default":{"description":"Includes required invoice number","summary":"Example request","value":{"currency_code":"ZMW","exchange_rate":"1.0","line_items":[{"description":"Test Item","item_classification_code":"43232202","item_code":"ITEM-001","quantity":2,"unit_price":"50.00","vat_category_code":"A"}],"number":"INV-0042-AUG26","status":"pending","walk_in_name":"Walk-in Customer","walk_in_phone":"0977000000"}}},"schema":{"$ref":"#/components/schemas/InvoiceRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceRequest"}}},"description":"Created"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"}},"security":[{"bearerAuth":[]}],"summary":"Create invoice","tags":["Invoices"]}},"/zra/standard_codes":{"get":{"callbacks":{},"deprecated":false,"description":"**Use case:** Fetch ZRA reference code tables (units, tax types, etc.). Proxies VSDC `code/selectCodes`.","operationId":"zra_get__zra_standard_codes","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get standard codes (GET)","tags":["ZRA Pull"]},"post":{"callbacks":{},"deprecated":false,"description":"ZRA-compatible POST variant of the same pull endpoint.","operationId":"zra_post__zra_standard_codes","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get standard codes (POST)","tags":["ZRA Pull"]}},"/quotations/{id}/pdf":{"get":{"callbacks":{},"deprecated":false,"description":"Generate PDF for the quotation.","operationId":"quotation_pdf","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"PDF document"}},"security":[{"bearerAuth":[]}],"summary":"Download quotation PDF","tags":["Quotations"]}},"/zra/invoices/{sdc_id}/{cis_invoice_no}":{"get":{"callbacks":{},"deprecated":false,"description":"**Use case:** Retrieve invoice details from ZRA by SDC ID and CIS invoice number.\n\nUseful for duplicate detection and reconciliation.\n","operationId":"zra_get_invoice","parameters":[{"description":"SDC device ID","in":"path","name":"sdc_id","required":true,"schema":{"type":"string"}},{"description":"CIS invoice number","in":"path","name":"cis_invoice_no","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Lookup fiscalized invoice","tags":["ZRA Pull"]}},"/products":{"get":{"callbacks":{},"deprecated":false,"description":"List products in the local catalog.","operationId":"product_index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"List product","tags":["Products"]},"post":{"callbacks":{},"deprecated":false,"description":"Create a product locally. ZRA fields (classification, VAT category) are required for sync. Sync to ZRA with POST /products/{id}/sync_zra after creation.","operationId":"product_create","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductRequest"}}},"description":"Created"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"}},"security":[{"bearerAuth":[]}],"summary":"Create product","tags":["Products"]}},"/products/{id}/update_zra":{"post":{"callbacks":{},"deprecated":false,"description":"Push local product changes to an existing ZRA item (`items/updateItem`).","operationId":"product_update_zra","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Update product in ZRA","tags":["Products"]}},"/invoices/{id}/check_zra_sync":{"post":{"callbacks":{},"deprecated":false,"description":"Query current sync status and optionally reconcile with ZRA.","operationId":"invoice_check_zra_sync","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Check ZRA sync status","tags":["Invoices"]}},"/customers":{"get":{"callbacks":{},"deprecated":false,"description":"List customers for the authenticated tenant.","operationId":"customer_index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"List customer","tags":["Customers"]},"post":{"callbacks":{},"deprecated":false,"description":"Create a customer locally before optional ZRA sync. Use POST /customers/{id}/sync_zra to register with ZRA.","operationId":"customer_create","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerRequest"}}},"description":"Created"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"}},"security":[{"bearerAuth":[]}],"summary":"Create customer","tags":["Customers"]}},"/invoices/{id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Remove invoice from local database.","operationId":"invoice_delete","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Delete invoice","tags":["Invoices"]},"get":{"callbacks":{},"deprecated":false,"description":"Retrieve a single invoice by ID.","operationId":"invoice_show","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get invoice","tags":["Invoices"]},"patch":{"callbacks":{},"deprecated":false,"description":"Partially update invoice.","operationId":"invoice_patch","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Patch invoice","tags":["Invoices"]},"put":{"callbacks":{},"deprecated":false,"description":"Replace invoice fields.","operationId":"invoice_update","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Update invoice","tags":["Invoices"]}},"/customers/{id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Remove customer from local database.","operationId":"customer_delete","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Delete customer","tags":["Customers"]},"get":{"callbacks":{},"deprecated":false,"description":"Retrieve a single customer by ID.","operationId":"customer_show","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get customer","tags":["Customers"]},"patch":{"callbacks":{},"deprecated":false,"description":"Partially update customer.","operationId":"customer_patch","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Patch customer","tags":["Customers"]},"put":{"callbacks":{},"deprecated":false,"description":"Replace customer fields.","operationId":"customer_update","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Update customer","tags":["Customers"]}},"/credit_notes/{id}/sync_zra":{"post":{"callbacks":{},"deprecated":false,"description":"Fiscalize the credit note with ZRA.","operationId":"credit_notes_sync_zra","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Sync credit note to ZRA","tags":["Credit Notes"]}},"/branches/save_user":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Register a branch user with ZRA for multi-branch operations.","operationId":"branches_save_user","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Save branch user","tags":["Branches"]}},"/zra/items/{item_code}":{"get":{"callbacks":{},"deprecated":false,"description":"Fetch a ZRA-registered item by item code.","operationId":"zra_get_item","parameters":[{"description":"ZRA item code","in":"path","name":"item_code","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Lookup item by code","tags":["ZRA Pull"]}},"/settings/logo":{"get":{"callbacks":{},"deprecated":false,"description":"Retrieve the uploaded company logo binary.","operationId":"settings_get_logo","parameters":[],"responses":{"200":{"description":"Logo image"}},"security":[{"bearerAuth":[]}],"summary":"Get company logo","tags":["Settings"]}},"/users/log_out":{"delete":{"callbacks":{},"deprecated":false,"description":"Revoke the current Bearer token. After logout, the same token cannot be used for protected routes.","operationId":"auth_logout","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Logged out"}},"security":[{"bearerAuth":[]}],"summary":"Logout","tags":["Authentication"]}},"/products/{id}/sync_stock_master":{"post":{"callbacks":{},"deprecated":false,"description":"Sync master stock quantities for a product to ZRA.","operationId":"product_sync_stock_master","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Sync stock master","tags":["Products"]}},"/stock_movements/{id}/sync_zra":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Push the local stock movement record to ZRA VSDC.\n\nCalls VSDC `stock/saveStockItems`. Requires ZRA device initialization.\nReturns **403** with `zra_not_initialized` if device is not set up.\nRate limited to 60 sync requests per minute per tenant.\n","operationId":"stock movement_sync_zra","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Synced successfully"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncQueuedResponse"}}},"description":"Queued for background sync"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"ZRA not initialized"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited"}},"security":[{"bearerAuth":[]}],"summary":"Sync stock movement to ZRA","tags":["Stock & Purchases"]}},"/zra/notices":{"get":{"callbacks":{},"deprecated":false,"description":"**Use case:** Fetch ZRA system notices and announcements. Proxies VSDC `notices/selectNotices`.","operationId":"zra_get__zra_notices","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get notices (GET)","tags":["ZRA Pull"]},"post":{"callbacks":{},"deprecated":false,"description":"ZRA-compatible POST variant of the same pull endpoint.","operationId":"zra_post__zra_notices","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get notices (POST)","tags":["ZRA Pull"]}},"/zra/status":{"get":{"callbacks":{},"deprecated":false,"description":"**Use case:** Verify device initialization before sync operations.\n\nReturns `initialized: true` with SDC ID, MRC, TPIN, branch, and VSDC URL when ready.\nMobile clients can use `/zra/config/status` alias.\n","operationId":"zra_status","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZraStatusResponse"}}},"description":"Status"}},"security":[{"bearerAuth":[]}],"summary":"Get ZRA status","tags":["ZRA Setup"]}},"/invoices/{id}/sync_commercial_invoice":{"post":{"callbacks":{},"deprecated":false,"description":"Submit a commercial invoice variant to ZRA.","operationId":"invoice_sync_commercial","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Sync commercial invoice","tags":["Invoices"]}},"/users/register":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Onboard a new tenant (company) and obtain an API token.\n\nCreates a user account with optional company details. Returns a Bearer token valid for 30 days.\nAfter registration, complete ZRA setup before calling sync endpoints.\n","operationId":"auth_register","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthTokenResponse"}}},"description":"Account created with token"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Registration failed"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"}},"security":[],"summary":"Register account","tags":["Authentication"]}},"/credit_notes":{"get":{"callbacks":{},"deprecated":false,"description":"List all credit notes (receipt type R) for the tenant.","operationId":"credit_notes_index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"List credit notes","tags":["Credit Notes"]},"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Issue a credit note against an existing fiscalized invoice.\n\nRequires `original_invoice_id`. Sync to ZRA after creation.\n","operationId":"credit_notes_create","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditNoteRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Credit note created"}},"security":[{"bearerAuth":[]}],"summary":"Create credit note","tags":["Credit Notes"]}},"/invoices/sync_zra":{"post":{"callbacks":{},"deprecated":false,"description":"**Use case:** Create an invoice and queue fiscalization in one request.\n\n`number` is **required** (format: `INV-0001-AUG26`); requests without it return **422**.\n\nCustomer options (same as POST /invoices):\n- `customer_id` — existing customer\n- `walk_in_name` / `walk_in_phone` / optional `walk_in_tpin`\n- `customer` object with `tax_number` or `tpin` — find or create\n- If omitted, defaults to walk-in (\"Walk-in Customer\"; ZRA TPIN defaults to 2001696235)\n\nReturns **202 Accepted** with `status: queued`. Poll GET /invoices/{id} for `zra_sync_status`.\n","operationId":"invoice_create_and_sync","parameters":[],"requestBody":{"content":{"application/json":{"example":{"currency_code":"ZMW","exchange_rate":"1.0","line_items":[{"description":"Test Item","item_classification_code":"43232202","item_code":"ITEM-001","quantity":2,"unit_price":"50.00","vat_category_code":"A"}],"number":"INV-0042-AUG26","status":"pending","walk_in_name":"Walk-in Customer","walk_in_phone":"0977000000"},"examples":{"default":{"description":"Includes required invoice number","summary":"Example request","value":{"currency_code":"ZMW","exchange_rate":"1.0","line_items":[{"description":"Test Item","item_classification_code":"43232202","item_code":"ITEM-001","quantity":2,"unit_price":"50.00","vat_category_code":"A"}],"number":"INV-0042-AUG26","status":"pending","walk_in_name":"Walk-in Customer","walk_in_phone":"0977000000"}}},"schema":{"$ref":"#/components/schemas/InvoiceRequest"}}},"required":true},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncQueuedResponse"}}},"description":"Invoice created and queued"}},"security":[{"bearerAuth":[]}],"summary":"Create and queue ZRA sync","tags":["Invoices"]}},"/settings":{"get":{"callbacks":{},"deprecated":false,"description":"List tenant settings (VSDC URL, device model, company profile).","operationId":"setting_index","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"List setting","tags":["Settings"]},"post":{"callbacks":{},"deprecated":false,"description":"Create a setting key/value pair.","operationId":"setting_create","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Created"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"}},"security":[{"bearerAuth":[]}],"summary":"Create setting","tags":["Settings"]}},"/settings/{id}":{"delete":{"callbacks":{},"deprecated":false,"description":"Remove setting from local database.","operationId":"setting_delete","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"204":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"}},"security":[{"bearerAuth":[]}],"summary":"Delete setting","tags":["Settings"]},"get":{"callbacks":{},"deprecated":false,"description":"Retrieve a single setting by ID.","operationId":"setting_show","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get setting","tags":["Settings"]},"patch":{"callbacks":{},"deprecated":false,"description":"Partially update setting.","operationId":"setting_patch","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Patch setting","tags":["Settings"]},"put":{"callbacks":{},"deprecated":false,"description":"Replace setting fields.","operationId":"setting_update","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Update setting","tags":["Settings"]}},"/invoices/{id}/save_final_credit_note":{"post":{"callbacks":{},"deprecated":false,"description":"Finalize a provisional credit note in ZRA.","operationId":"invoice_save_final_credit_note","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Save final credit note","tags":["Invoices"]}},"/zra/config/status":{"get":{"callbacks":{},"deprecated":false,"description":"**Use case:** Verify device initialization before sync operations.\n\nReturns `initialized: true` with SDC ID, MRC, TPIN, branch, and VSDC URL when ready.\nMobile clients can use `/zra/config/status` alias.\n","operationId":"zra_config_status","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZraStatusResponse"}}},"description":"Status"}},"security":[{"bearerAuth":[]}],"summary":"Get ZRA status","tags":["ZRA Setup"]}},"/zra/customers/{tpin}":{"get":{"callbacks":{},"deprecated":false,"description":"Fetch customer details from ZRA by tax payer ID.","operationId":"zra_get_customer","parameters":[{"description":"Customer TPIN","in":"path","name":"tpin","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Lookup customer by TPIN","tags":["ZRA Pull"]}},"/zra/sales":{"get":{"callbacks":{},"deprecated":false,"description":"**Use case:** Pull fiscalized sales from ZRA.","operationId":"zra_get_sales","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get sales from ZRA","tags":["ZRA Pull"]},"post":{"callbacks":{},"deprecated":false,"description":"ZRA-compatible POST variant of the sales pull endpoint.","operationId":"zra_post_sales","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenericObject"}}},"description":"Success"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing or invalid Bearer token"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (e.g. ZRA not initialized)"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation or ZRA business error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Rate limited (>60 sync/min)"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Server error"}},"security":[{"bearerAuth":[]}],"summary":"Get sales from ZRA (POST)","tags":["ZRA Pull"]}}},"security":[{"bearerAuth":[]}],"servers":[{"description":"Current host (recommended for Swagger UI)","url":"/api","variables":{}},{"description":"Local development","url":"http://localhost:4001/api","variables":{}},{"description":"Local development (127.0.0.1)","url":"http://127.0.0.1:4001/api","variables":{}}],"tags":[{"description":"Register, login, and manage API access tokens for integrators and mobile clients.","name":"Authentication"},{"description":"One-time fiscal device initialization. Complete before any sync endpoint. Calls VSDC selectInitInfo.","name":"ZRA Setup"},{"description":"Tenant configuration: VSDC URL, device model/serial, company profile, and logo.","name":"Settings"},{"description":"Local product catalog and ZRA item registration (saveItem, updateItem, stock master).","name":"Products"},{"description":"Buyer management and optional ZRA customer registration.","name":"Customers"},{"description":"Core billing workflow: create locally, fiscalize via async ZRA sync (saveSales). Poll for completion.","name":"Invoices"},{"description":"Fiscal credit notes (receipt type R) against existing invoices.","name":"Credit Notes"},{"description":"Non-fiscal quotes that can be converted to invoices.","name":"Quotations"},{"description":"Purchases, stock movements, import items, and inventory sync with ZRA.","name":"Stock & Purchases"},{"description":"Read-only endpoints that proxy VSDC to fetch reference data and transactions from ZRA.","name":"ZRA Pull"},{"description":"Multi-branch ZRA registration for users and customers.","name":"Branches"},{"description":"Summary metrics for mobile and integrator dashboards.","name":"Dashboard"}]}