{
  "components": {
    "schemas": {
      "AddressBlock": {
        "properties": {
          "city": {
            "default": "",
            "description": "City.",
            "examples": [
              "Bratislava"
            ],
            "maxLength": 100,
            "title": "City",
            "type": "string"
          },
          "country_code": {
            "default": "SK",
            "description": "ISO 3166-1 alpha-2 country code. Defaults to 'SK' for Slovak domestic invoices.",
            "examples": [
              "SK"
            ],
            "maxLength": 2,
            "title": "Country Code",
            "type": "string"
          },
          "dic": {
            "anyOf": [
              {
                "maxLength": 20,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak tax identification number (DI\u010c). 10 digits.",
            "examples": [
              "1234567890"
            ],
            "title": "Dic"
          },
          "ico": {
            "anyOf": [
              {
                "maxLength": 10,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak business identification number (I\u010cO). 8 digits.",
            "examples": [
              "12345678"
            ],
            "title": "Ico"
          },
          "name": {
            "description": "Legal name of the business.",
            "examples": [
              "Acme s.r.o."
            ],
            "maxLength": 255,
            "title": "Name",
            "type": "string"
          },
          "peppol_id": {
            "anyOf": [
              {
                "maxLength": 100,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Peppol Participant Identifier in '<scheme>:<identifier>' form. For Slovak businesses identified by I\u010cO, scheme 0210 is conventional. Required to deliver via the Peppol network.",
            "examples": [
              "0210:12345678"
            ],
            "title": "Peppol Id"
          },
          "postal_code": {
            "default": "",
            "description": "Postal code (PS\u010c). Slovak format: 'NNN NN' or 'NNNNN'.",
            "examples": [
              "811 01"
            ],
            "maxLength": 10,
            "title": "Postal Code",
            "type": "string"
          },
          "street": {
            "default": "",
            "description": "Street name and number.",
            "examples": [
              "Hlavn\u00e1 12"
            ],
            "maxLength": 255,
            "title": "Street",
            "type": "string"
          },
          "vat_id": {
            "description": "Slovak / EU VAT identification number (I\u010c DPH). SK format: 'SK' followed by 10 digits. For non-VAT-registered counterparties, set an empty string and supply ico/dic instead.",
            "examples": [
              "SK1234567890"
            ],
            "maxLength": 20,
            "title": "Vat Id",
            "type": "string"
          }
        },
        "required": [
          "name",
          "vat_id"
        ],
        "title": "AddressBlock",
        "type": "object"
      },
      "ApiKeyCreate": {
        "properties": {
          "expires_in_days": {
            "anyOf": [
              {
                "maximum": 365.0,
                "minimum": 1.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Days until this key auto-expires (1-365). Null means the key never expires automatically.",
            "examples": [
              90
            ],
            "title": "Expires In Days"
          },
          "name": {
            "description": "Human-readable name for this key, shown in the dashboard.",
            "examples": [
              "Production backend"
            ],
            "maxLength": 100,
            "title": "Name",
            "type": "string"
          },
          "scopes": {
            "default": [
              "invoices:read",
              "invoices:write",
              "invoices:send"
            ],
            "description": "Permission scopes. One of: invoices:read, invoices:write, invoices:send, validate:only.",
            "examples": [
              [
                "invoices:read",
                "invoices:write"
              ]
            ],
            "items": {
              "type": "string"
            },
            "title": "Scopes",
            "type": "array"
          }
        },
        "required": [
          "name"
        ],
        "title": "ApiKeyCreate",
        "type": "object"
      },
      "ApiKeyCreated": {
        "description": "Returned ONCE on creation \u2014 includes the plaintext API key.",
        "properties": {
          "api_key": {
            "description": "Plaintext API key. Shown only once at creation time \u2014 store it securely. Use it as a Bearer token in the Authorization header.",
            "examples": [
              "efk_live_abc123def456ghi789jkl012mno345pqr678stu"
            ],
            "title": "Api Key",
            "type": "string"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "expires_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When this key auto-expires (ISO 8601). Null means the key never expires automatically.",
            "examples": [
              "2027-01-01T00:00:00Z"
            ],
            "title": "Expires At"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "key_prefix": {
            "description": "First few characters of the key (e.g. 'efk_live_abc...'), shown in the dashboard so users can identify a key without exposing the full secret.",
            "examples": [
              "efk_live_abc"
            ],
            "title": "Key Prefix",
            "type": "string"
          },
          "last_used_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "title": "Scopes",
            "type": "array"
          }
        },
        "required": [
          "id",
          "name",
          "key_prefix",
          "scopes",
          "is_active",
          "last_used_at",
          "created_at",
          "api_key"
        ],
        "title": "ApiKeyCreated",
        "type": "object"
      },
      "ApiKeyResponse": {
        "properties": {
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "expires_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When this key auto-expires (ISO 8601). Null means the key never expires automatically.",
            "examples": [
              "2027-01-01T00:00:00Z"
            ],
            "title": "Expires At"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "key_prefix": {
            "description": "First few characters of the key (e.g. 'efk_live_abc...'), shown in the dashboard so users can identify a key without exposing the full secret.",
            "examples": [
              "efk_live_abc"
            ],
            "title": "Key Prefix",
            "type": "string"
          },
          "last_used_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "title": "Scopes",
            "type": "array"
          }
        },
        "required": [
          "id",
          "name",
          "key_prefix",
          "scopes",
          "is_active",
          "last_used_at",
          "created_at"
        ],
        "title": "ApiKeyResponse",
        "type": "object"
      },
      "ApiKeyRevokeResponse": {
        "description": "Acknowledgement returned after an API key has been deactivated.",
        "properties": {
          "id": {
            "description": "UUID of the API key that was revoked, for client-side state updates.",
            "examples": [
              "8f5a1c20-1f6e-4f6c-9f5e-2f5a1c201f6e"
            ],
            "title": "Id",
            "type": "string"
          },
          "message": {
            "description": "Human-readable confirmation message.",
            "examples": [
              "API key deactivated"
            ],
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "message",
          "id"
        ],
        "title": "ApiKeyRevokeResponse",
        "type": "object"
      },
      "ApiKeyUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "maxLength": 100,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "New human-readable name. Omit to leave unchanged.",
            "examples": [
              "CI/CD pipeline"
            ],
            "title": "Name"
          },
          "scopes": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Replacement permission scopes. One of: invoices:read, invoices:write, invoices:send, validate:only. Omit to leave unchanged.",
            "examples": [
              [
                "invoices:read"
              ]
            ],
            "title": "Scopes"
          }
        },
        "title": "ApiKeyUpdate",
        "type": "object"
      },
      "ApprovalActionResponse": {
        "description": "Acknowledgement returned by request-approval / approve / reject routes.",
        "properties": {
          "id": {
            "description": "Approval record id (UUID, stringified).",
            "title": "Id",
            "type": "string"
          },
          "invoice_id": {
            "description": "Invoice whose approval state changed.",
            "format": "uuid",
            "title": "Invoice Id",
            "type": "string"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Echoed rejection reason \u2014 only present on the reject route.",
            "title": "Reason"
          },
          "status": {
            "description": "Approval status after the action ('pending', 'approved', 'rejected').",
            "examples": [
              "approved"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id",
          "invoice_id",
          "status"
        ],
        "title": "ApprovalActionResponse",
        "type": "object"
      },
      "ApprovalRecord": {
        "description": "Approval request snapshot returned in approval responses.",
        "properties": {
          "id": {
            "description": "Approval record id (UUID, stringified).",
            "title": "Id",
            "type": "string"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Free-text rejection reason (only populated for rejected requests).",
            "title": "Reason"
          },
          "requested_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO-8601 timestamp when approval was requested.",
            "title": "Requested At"
          },
          "requested_by": {
            "description": "UUID of the user who requested approval.",
            "title": "Requested By",
            "type": "string"
          },
          "reviewed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO-8601 timestamp when the request was reviewed.",
            "title": "Reviewed At"
          },
          "reviewed_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the reviewer once the request has been actioned.",
            "title": "Reviewed By"
          },
          "status": {
            "description": "Approval status: 'pending', 'approved', or 'rejected'.",
            "examples": [
              "pending"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "requested_by"
        ],
        "title": "ApprovalRecord",
        "type": "object"
      },
      "ApprovalStateResponse": {
        "description": "Current approval state for an invoice (or `null` if no request was ever filed).",
        "properties": {
          "approval": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ApprovalRecord"
              },
              {
                "type": "null"
              }
            ],
            "description": "Approval record, or null if no approval has been requested for this invoice."
          },
          "invoice_id": {
            "format": "uuid",
            "title": "Invoice Id",
            "type": "string"
          }
        },
        "required": [
          "invoice_id"
        ],
        "title": "ApprovalStateResponse",
        "type": "object"
      },
      "BulkImportError": {
        "description": "A single row-level failure recorded by the bulk-import worker.",
        "properties": {
          "column": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Column name when the failure can be localised to one field.",
            "title": "Column"
          },
          "message": {
            "description": "Human-readable explanation of the failure.",
            "title": "Message",
            "type": "string"
          },
          "row": {
            "description": "1-based CSV row index that failed.",
            "title": "Row",
            "type": "integer"
          }
        },
        "required": [
          "row",
          "message"
        ],
        "title": "BulkImportError",
        "type": "object"
      },
      "BulkImportJobResponse": {
        "description": "Acknowledgement returned when a bulk-import job is queued (202 Accepted).",
        "properties": {
          "job_id": {
            "description": "UUID identifying the queued import job.",
            "examples": [
              "7c1a4e3a-9b2c-4d5e-8a6f-1234567890ab"
            ],
            "title": "Job Id",
            "type": "string"
          },
          "status": {
            "description": "Initial status (always 'processing' on enqueue).",
            "examples": [
              "processing"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "job_id",
          "status"
        ],
        "title": "BulkImportJobResponse",
        "type": "object"
      },
      "BulkImportStatusResponse": {
        "description": "Snapshot of a bulk-import job \u2014 written by the Celery worker, polled by clients.",
        "properties": {
          "created": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Number of invoices successfully created (populated once completed).",
            "title": "Created"
          },
          "errors": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/BulkImportError"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Row-level failures (only populated for completed/failed jobs).",
            "title": "Errors"
          },
          "job_id": {
            "description": "Job UUID that was returned by POST /bulk-import.",
            "title": "Job Id",
            "type": "string"
          },
          "status": {
            "description": "One of 'processing', 'completed', 'failed'.",
            "examples": [
              "completed"
            ],
            "title": "Status",
            "type": "string"
          },
          "total_rows": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Total CSV rows the worker processed (populated once the job leaves 'processing').",
            "title": "Total Rows"
          }
        },
        "required": [
          "job_id",
          "status"
        ],
        "title": "BulkImportStatusResponse",
        "type": "object"
      },
      "ChangePasswordRequest": {
        "properties": {
          "current_password": {
            "description": "The user's current password (re-authentication required).",
            "title": "Current Password",
            "type": "string"
          },
          "new_password": {
            "description": "Replacement password. 8-128 characters. Must contain at least one uppercase letter, one lowercase letter, one digit, and one special character.",
            "examples": [
              "NoveHeslo123!"
            ],
            "maxLength": 128,
            "minLength": 8,
            "title": "New Password",
            "type": "string"
          }
        },
        "required": [
          "current_password",
          "new_password"
        ],
        "title": "ChangePasswordRequest",
        "type": "object"
      },
      "ClientCreate": {
        "properties": {
          "name": {
            "maxLength": 255,
            "title": "Name",
            "type": "string"
          },
          "scopes": {
            "default": "invoices:read,invoices:write,invoices:send",
            "title": "Scopes",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "ClientCreate",
        "type": "object"
      },
      "ClientCreateResponse": {
        "description": "Response on creation \u2014 includes plaintext client_secret (shown once).",
        "properties": {
          "client_id": {
            "title": "Client Id",
            "type": "string"
          },
          "client_secret": {
            "title": "Client Secret",
            "type": "string"
          },
          "created_at": {
            "title": "Created At",
            "type": "string"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "scopes": {
            "title": "Scopes",
            "type": "string"
          }
        },
        "required": [
          "client_id",
          "name",
          "scopes",
          "is_active",
          "created_at",
          "client_secret"
        ],
        "title": "ClientCreateResponse",
        "type": "object"
      },
      "CompanyLookupResponse": {
        "description": "Result of a Slovak company lookup by I\u010cO.\n\nFields are best-effort: each source (RPO, registeruz, VIES) contributes\na subset. Unknown fields are `None` so the frontend can auto-fill only\nwhat it learned.",
        "properties": {
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "City of the registered address.",
            "examples": [
              "Bratislava"
            ],
            "title": "City"
          },
          "country_code": {
            "default": "SK",
            "description": "ISO 3166-1 alpha-2 country code.",
            "examples": [
              "SK"
            ],
            "maxLength": 2,
            "title": "Country Code",
            "type": "string"
          },
          "dic": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak tax identification number (DI\u010c). 10 digits.",
            "examples": [
              "1234567890"
            ],
            "title": "Dic"
          },
          "ic_dph": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak/EU VAT identification number (I\u010c DPH). SK format: SK followed by 10 digits. Present only if the company is VAT-registered.",
            "examples": [
              "SK1234567890"
            ],
            "title": "Ic Dph"
          },
          "ico": {
            "description": "Slovak business identification number (I\u010cO). 8 digits.",
            "examples": [
              "12345678"
            ],
            "title": "Ico",
            "type": "string"
          },
          "is_vat_registered": {
            "default": false,
            "description": "True if SK<dic> is registered for VAT according to VIES.",
            "examples": [
              true
            ],
            "title": "Is Vat Registered",
            "type": "boolean"
          },
          "legal_form_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak legal form code (RPO codelist CL000056), e.g. '112' for s.r.o.",
            "examples": [
              "112"
            ],
            "title": "Legal Form Code"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Legal name as recorded in the Slovak business register (RPO fullNames).",
            "examples": [
              "Acme s.r.o."
            ],
            "title": "Name"
          },
          "postal_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Postal code of the registered address.",
            "examples": [
              "81101"
            ],
            "title": "Postal Code"
          },
          "sources": {
            "description": "Which sources contributed data. One of: rpo, registeruz, vies.",
            "examples": [
              [
                "rpo",
                "vies"
              ]
            ],
            "items": {
              "type": "string"
            },
            "title": "Sources",
            "type": "array"
          },
          "street": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Street and number of the registered address.",
            "examples": [
              "Hlavn\u00e1 12"
            ],
            "title": "Street"
          }
        },
        "required": [
          "ico"
        ],
        "title": "CompanyLookupResponse",
        "type": "object"
      },
      "CompanySearchResponse": {
        "properties": {
          "query": {
            "description": "The original search query that produced these results.",
            "examples": [
              "Acme"
            ],
            "title": "Query",
            "type": "string"
          },
          "results": {
            "description": "Matching companies, ordered by registry relevance.",
            "items": {
              "$ref": "#/components/schemas/CompanySuggestion"
            },
            "title": "Results",
            "type": "array"
          }
        },
        "required": [
          "query",
          "results"
        ],
        "title": "CompanySearchResponse",
        "type": "object"
      },
      "CompanySuggestion": {
        "description": "One hit from a name / I\u010cO search \u2014 enough for the user to pick.",
        "properties": {
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "City of the company's registered address, if known.",
            "examples": [
              "Bratislava"
            ],
            "title": "City"
          },
          "ico": {
            "description": "Slovak business identification number (I\u010cO). 8 digits.",
            "examples": [
              "12345678"
            ],
            "title": "Ico",
            "type": "string"
          },
          "name": {
            "description": "Legal name of the company as registered in the Slovak business register.",
            "examples": [
              "Acme s.r.o."
            ],
            "title": "Name",
            "type": "string"
          },
          "street": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Street and number of the company's registered address, if known.",
            "examples": [
              "Hlavn\u00e1 12"
            ],
            "title": "Street"
          },
          "terminated": {
            "default": false,
            "description": "True if the company has been struck from the register.",
            "examples": [
              false
            ],
            "title": "Terminated",
            "type": "boolean"
          }
        },
        "required": [
          "ico",
          "name"
        ],
        "title": "CompanySuggestion",
        "type": "object"
      },
      "CustomerCreate": {
        "properties": {
          "city": {
            "anyOf": [
              {
                "maxLength": 100,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "City of the customer's billing address.",
            "examples": [
              "Bratislava"
            ],
            "title": "City"
          },
          "country_code": {
            "default": "SK",
            "description": "ISO 3166-1 alpha-2 country code of the customer's billing address.",
            "examples": [
              "SK"
            ],
            "maxLength": 2,
            "title": "Country Code",
            "type": "string"
          },
          "dic": {
            "anyOf": [
              {
                "maxLength": 20,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak tax identification number (DI\u010c). 10 digits.",
            "examples": [
              "1234567890"
            ],
            "title": "Dic"
          },
          "email": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Customer's primary contact email (used for invoice delivery notifications).",
            "examples": [
              "billing@acme.sk"
            ],
            "title": "Email"
          },
          "ico": {
            "anyOf": [
              {
                "maxLength": 10,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak business identification number (I\u010cO). 8 digits.",
            "examples": [
              "12345678"
            ],
            "title": "Ico"
          },
          "name": {
            "description": "Customer's legal name as registered in the Slovak business register.",
            "examples": [
              "Acme s.r.o."
            ],
            "maxLength": 255,
            "title": "Name",
            "type": "string"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Internal note about the customer. Not shown on invoices.",
            "examples": [
              "Prefers email delivery"
            ],
            "title": "Note"
          },
          "peppol_id": {
            "anyOf": [
              {
                "maxLength": 100,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Peppol Participant Identifier. Format <scheme>:<identifier> (e.g. 0210:<I\u010cO> for Slovak entities). Required for Peppol delivery; auto-discovered via SMP if omitted.",
            "examples": [
              "0210:12345678"
            ],
            "title": "Peppol Id"
          },
          "phone": {
            "anyOf": [
              {
                "maxLength": 50,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Customer's primary contact phone, in international format.",
            "examples": [
              "+421 911 234 567"
            ],
            "title": "Phone"
          },
          "postal_code": {
            "anyOf": [
              {
                "maxLength": 10,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Postal code of the customer's billing address.",
            "examples": [
              "81101"
            ],
            "title": "Postal Code"
          },
          "street": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Street and number of the customer's billing address.",
            "examples": [
              "Hlavn\u00e1 12"
            ],
            "title": "Street"
          },
          "vat_id": {
            "description": "Slovak/EU VAT identification number (I\u010c DPH). SK format: SK followed by 10 digits. Required for Peppol invoicing.",
            "examples": [
              "SK1234567890"
            ],
            "maxLength": 20,
            "title": "Vat Id",
            "type": "string"
          }
        },
        "required": [
          "name",
          "vat_id"
        ],
        "title": "CustomerCreate",
        "type": "object"
      },
      "CustomerListPaginated": {
        "properties": {
          "items": {
            "description": "Customers on this page.",
            "items": {
              "$ref": "#/components/schemas/CustomerListResponse"
            },
            "title": "Items",
            "type": "array"
          },
          "page": {
            "description": "Current page number (1-based).",
            "examples": [
              1
            ],
            "title": "Page",
            "type": "integer"
          },
          "page_size": {
            "description": "Number of items per page.",
            "examples": [
              20
            ],
            "title": "Page Size",
            "type": "integer"
          },
          "total": {
            "description": "Total number of customers matching the query (across all pages).",
            "examples": [
              42
            ],
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "items",
          "total",
          "page",
          "page_size"
        ],
        "title": "CustomerListPaginated",
        "type": "object"
      },
      "CustomerListResponse": {
        "properties": {
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "City of the customer's billing address.",
            "examples": [
              "Bratislava"
            ],
            "title": "City"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_active": {
            "description": "False if the customer has been archived.",
            "examples": [
              true
            ],
            "title": "Is Active",
            "type": "boolean"
          },
          "name": {
            "description": "Customer's legal name.",
            "examples": [
              "Acme s.r.o."
            ],
            "title": "Name",
            "type": "string"
          },
          "peppol_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Peppol Participant Identifier. Format <scheme>:<identifier>.",
            "examples": [
              "0210:12345678"
            ],
            "title": "Peppol Id"
          },
          "vat_id": {
            "description": "Slovak/EU VAT identification number (I\u010c DPH). SK format: SK followed by 10 digits.",
            "examples": [
              "SK1234567890"
            ],
            "title": "Vat Id",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "vat_id",
          "is_active"
        ],
        "title": "CustomerListResponse",
        "type": "object"
      },
      "CustomerResponse": {
        "properties": {
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "City of the customer's billing address.",
            "examples": [
              "Bratislava"
            ],
            "title": "City"
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country code.",
            "examples": [
              "SK"
            ],
            "title": "Country Code",
            "type": "string"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "dic": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak tax identification number (DI\u010c). 10 digits.",
            "examples": [
              "1234567890"
            ],
            "title": "Dic"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Customer's primary contact email.",
            "examples": [
              "billing@acme.sk"
            ],
            "title": "Email"
          },
          "ico": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak business identification number (I\u010cO). 8 digits.",
            "examples": [
              "12345678"
            ],
            "title": "Ico"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_active": {
            "description": "False if the customer has been archived.",
            "examples": [
              true
            ],
            "title": "Is Active",
            "type": "boolean"
          },
          "name": {
            "description": "Customer's legal name.",
            "examples": [
              "Acme s.r.o."
            ],
            "title": "Name",
            "type": "string"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Internal note about the customer.",
            "examples": [
              "Prefers email delivery"
            ],
            "title": "Note"
          },
          "peppol_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Peppol Participant Identifier. Format <scheme>:<identifier>.",
            "examples": [
              "0210:12345678"
            ],
            "title": "Peppol Id"
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Customer's primary contact phone.",
            "examples": [
              "+421 911 234 567"
            ],
            "title": "Phone"
          },
          "postal_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Postal code of the customer's billing address.",
            "examples": [
              "81101"
            ],
            "title": "Postal Code"
          },
          "street": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Street and number of the customer's billing address.",
            "examples": [
              "Hlavn\u00e1 12"
            ],
            "title": "Street"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          },
          "vat_id": {
            "description": "Slovak/EU VAT identification number (I\u010c DPH). SK format: SK followed by 10 digits.",
            "examples": [
              "SK1234567890"
            ],
            "title": "Vat Id",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "vat_id",
          "country_code",
          "is_active",
          "created_at",
          "updated_at"
        ],
        "title": "CustomerResponse",
        "type": "object"
      },
      "CustomerSearchResult": {
        "properties": {
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "City of the customer's billing address.",
            "examples": [
              "Bratislava"
            ],
            "title": "City"
          },
          "country_code": {
            "description": "ISO 3166-1 alpha-2 country code.",
            "examples": [
              "SK"
            ],
            "title": "Country Code",
            "type": "string"
          },
          "dic": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak tax identification number (DI\u010c). 10 digits.",
            "examples": [
              "1234567890"
            ],
            "title": "Dic"
          },
          "ico": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak business identification number (I\u010cO). 8 digits.",
            "examples": [
              "12345678"
            ],
            "title": "Ico"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "description": "Customer's legal name.",
            "examples": [
              "Acme s.r.o."
            ],
            "title": "Name",
            "type": "string"
          },
          "peppol_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Peppol Participant Identifier. Format <scheme>:<identifier>.",
            "examples": [
              "0210:12345678"
            ],
            "title": "Peppol Id"
          },
          "postal_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Postal code of the customer's billing address.",
            "examples": [
              "81101"
            ],
            "title": "Postal Code"
          },
          "street": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Street and number of the customer's billing address.",
            "examples": [
              "Hlavn\u00e1 12"
            ],
            "title": "Street"
          },
          "vat_id": {
            "description": "Slovak/EU VAT identification number (I\u010c DPH). SK format: SK followed by 10 digits.",
            "examples": [
              "SK1234567890"
            ],
            "title": "Vat Id",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "vat_id",
          "country_code"
        ],
        "title": "CustomerSearchResult",
        "type": "object"
      },
      "CustomerUpdate": {
        "properties": {
          "city": {
            "anyOf": [
              {
                "maxLength": 100,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "City of the customer's billing address.",
            "examples": [
              "Bratislava"
            ],
            "title": "City"
          },
          "country_code": {
            "anyOf": [
              {
                "maxLength": 2,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO 3166-1 alpha-2 country code.",
            "examples": [
              "SK"
            ],
            "title": "Country Code"
          },
          "dic": {
            "anyOf": [
              {
                "maxLength": 20,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak tax identification number (DI\u010c). 10 digits.",
            "examples": [
              "1234567890"
            ],
            "title": "Dic"
          },
          "email": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Customer's primary contact email.",
            "examples": [
              "billing@acme.sk"
            ],
            "title": "Email"
          },
          "ico": {
            "anyOf": [
              {
                "maxLength": 10,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak business identification number (I\u010cO). 8 digits.",
            "examples": [
              "12345678"
            ],
            "title": "Ico"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Replacement legal name. Omit to leave unchanged.",
            "examples": [
              "Acme s.r.o."
            ],
            "title": "Name"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Internal note about the customer.",
            "examples": [
              "Prefers email delivery"
            ],
            "title": "Note"
          },
          "peppol_id": {
            "anyOf": [
              {
                "maxLength": 100,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Peppol Participant Identifier. Format <scheme>:<identifier>.",
            "examples": [
              "0210:12345678"
            ],
            "title": "Peppol Id"
          },
          "phone": {
            "anyOf": [
              {
                "maxLength": 50,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Customer's primary contact phone, in international format.",
            "examples": [
              "+421 911 234 567"
            ],
            "title": "Phone"
          },
          "postal_code": {
            "anyOf": [
              {
                "maxLength": 10,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Postal code of the customer's billing address.",
            "examples": [
              "81101"
            ],
            "title": "Postal Code"
          },
          "street": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Street and number of the customer's billing address.",
            "examples": [
              "Hlavn\u00e1 12"
            ],
            "title": "Street"
          }
        },
        "title": "CustomerUpdate",
        "type": "object"
      },
      "ErrorDetail": {
        "description": "Inner error envelope produced by HTTPException(detail=\u2026).",
        "properties": {
          "error": {
            "description": "Stable error code suitable for programmatic handling.",
            "examples": [
              "invalid_credentials",
              "rate_limit_exceeded"
            ],
            "title": "Error",
            "type": "string"
          },
          "message": {
            "description": "Human-readable error message.",
            "examples": [
              "Invalid email or password."
            ],
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "error",
          "message"
        ],
        "title": "ErrorDetail",
        "type": "object"
      },
      "ErrorResponse": {
        "description": "Standard error response envelope (FastAPI wraps `detail`).",
        "properties": {
          "detail": {
            "$ref": "#/components/schemas/ErrorDetail"
          }
        },
        "required": [
          "detail"
        ],
        "title": "ErrorResponse",
        "type": "object"
      },
      "FSAcknowledgement": {
        "description": "Acknowledgement from Financna sprava that a submission was processed.",
        "properties": {
          "processed_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Processed At"
          },
          "rejection_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rejection Reason"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "submission_id": {
            "title": "Submission Id",
            "type": "string"
          }
        },
        "required": [
          "submission_id",
          "status"
        ],
        "title": "FSAcknowledgement",
        "type": "object"
      },
      "FSAcknowledgementAck": {
        "description": "Acknowledgement returned to Slovak Finan\u010dn\u00e1 spr\u00e1va after processing the callback.",
        "properties": {
          "status": {
            "description": "Always `processed`.",
            "examples": [
              "processed"
            ],
            "title": "Status",
            "type": "string"
          },
          "submission_id": {
            "description": "Echo of the FS submission id.",
            "title": "Submission Id",
            "type": "string"
          }
        },
        "required": [
          "status",
          "submission_id"
        ],
        "title": "FSAcknowledgementAck",
        "type": "object"
      },
      "ForgotPasswordRequest": {
        "properties": {
          "email": {
            "description": "Email address of the account to reset. The endpoint always returns success to avoid leaking whether an account exists.",
            "examples": [
              "jana.kovacova@example.sk"
            ],
            "format": "email",
            "title": "Email",
            "type": "string"
          }
        },
        "required": [
          "email"
        ],
        "title": "ForgotPasswordRequest",
        "type": "object"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "InviteMemberRequest": {
        "properties": {
          "email": {
            "format": "email",
            "title": "Email",
            "type": "string"
          },
          "role": {
            "default": "readonly",
            "title": "Role",
            "type": "string"
          }
        },
        "required": [
          "email"
        ],
        "title": "InviteMemberRequest",
        "type": "object"
      },
      "InvoiceCreate": {
        "properties": {
          "buyer": {
            "$ref": "#/components/schemas/AddressBlock",
            "description": "The customer being invoiced."
          },
          "currency_code": {
            "default": "EUR",
            "description": "ISO 4217 currency code. EUR for domestic Slovak invoices.",
            "examples": [
              "EUR"
            ],
            "maxLength": 3,
            "title": "Currency Code",
            "type": "string"
          },
          "customer_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional reference to an existing customer record. When set, the buyer block may be auto-filled from the customer record.",
            "examples": [
              "550e8400-e29b-41d4-a716-446655440000"
            ],
            "title": "Customer Id"
          },
          "due_date": {
            "description": "Date payment is due. ISO 8601 (YYYY-MM-DD). Must be on or after issue_date.",
            "examples": [
              "2026-02-14"
            ],
            "format": "date",
            "title": "Due Date",
            "type": "string"
          },
          "invoice_number": {
            "anyOf": [
              {
                "maxLength": 50,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Your internal invoice number. Must be unique per workspace and per tax year. We do not enforce a format \u2014 bring your own numbering scheme. Omit to let eFakturuj reserve the next number per the workspace's pattern (see GET /invoices/numbering/next).",
            "examples": [
              "2026-001",
              "INV-2026-001"
            ],
            "title": "Invoice Number"
          },
          "invoice_type": {
            "default": "380",
            "description": "UN/CEFACT 1001 invoice type code. Common values: 380=Commercial Invoice (default), 381=Credit Note, 325=Proforma, 326=Partial Invoice.",
            "examples": [
              "380"
            ],
            "title": "Invoice Type",
            "type": "string"
          },
          "issue_date": {
            "description": "Date the invoice was issued. ISO 8601 (YYYY-MM-DD).",
            "examples": [
              "2026-01-15"
            ],
            "format": "date",
            "title": "Issue Date",
            "type": "string"
          },
          "lines": {
            "description": "At least one invoice line. Note: Peppol BIS Billing 3.0 imposes a soft limit of 200 lines per document; very large invoices may be rejected by downstream Access Points.",
            "items": {
              "$ref": "#/components/schemas/InvoiceLineCreate"
            },
            "minItems": 1,
            "title": "Lines",
            "type": "array"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Free-form key-value metadata for your own bookkeeping. Not transmitted on the UBL document.",
            "examples": [
              {
                "po_number": "PO-12345",
                "project": "alpha"
              }
            ],
            "title": "Metadata"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Free-form note shown on the rendered invoice \u2014 useful for payment instructions, thank-you copy, or other prose.",
            "examples": [
              "Thank you for your business."
            ],
            "title": "Note"
          },
          "payment_means_code": {
            "default": "30",
            "description": "UN/CEFACT 4461 payment means code. Common values: 30=Credit transfer (default), 42=Payment to bank account, 48=Bank card.",
            "examples": [
              "30"
            ],
            "maxLength": 10,
            "title": "Payment Means Code",
            "type": "string"
          },
          "source": {
            "default": "manual",
            "description": "Internal marker for where this invoice originated. Common values: 'manual' (default \u2014 created via UI / API), 'api', 'bulk_import', 'peppol' (inbound from the Peppol network).",
            "examples": [
              "manual"
            ],
            "maxLength": 50,
            "title": "Source",
            "type": "string"
          },
          "supplier": {
            "$ref": "#/components/schemas/AddressBlock",
            "description": "Your business \u2014 the party issuing this invoice."
          },
          "supplier_iban": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "IBAN to receive payment. Slovak format: 'SK' followed by 22 digits. If omitted, falls back to the workspace's default IBAN.",
            "examples": [
              "SK1234567890123456789012"
            ],
            "title": "Supplier Iban"
          },
          "variable_symbol": {
            "anyOf": [
              {
                "maxLength": 20,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak variable symbol (variabiln\u00fd symbol) used as the payment reference in Slovak banking. Numeric, typically up to 10 digits, and conventionally derived from the invoice number stripped to digits.",
            "examples": [
              "2026001"
            ],
            "title": "Variable Symbol"
          }
        },
        "required": [
          "issue_date",
          "due_date",
          "supplier",
          "buyer",
          "lines"
        ],
        "title": "InvoiceCreate",
        "type": "object"
      },
      "InvoiceLineCreate": {
        "properties": {
          "discount_amount": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "number"
              },
              {
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional line-level discount expressed as an absolute amount in the invoice currency. Mutually exclusive with discount_percentage.",
            "examples": [
              "15.00"
            ],
            "title": "Discount Amount"
          },
          "discount_percentage": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional line-level discount expressed as a percentage of the gross line value (quantity \u00d7 unit_price). Mutually exclusive with discount_amount in practice \u2014 set one or the other.",
            "examples": [
              "10.00"
            ],
            "title": "Discount Percentage"
          },
          "item_description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional longer description shown beneath the item name.",
            "examples": [
              "On-site engagement: 10h \u00d7 2 days"
            ],
            "title": "Item Description"
          },
          "item_name": {
            "description": "Short name of the goods or services on this line.",
            "examples": [
              "Consulting services \u2014 January 2026"
            ],
            "maxLength": 500,
            "title": "Item Name",
            "type": "string"
          },
          "line_number": {
            "description": "1-based position of this line on the invoice. Must be unique within the invoice and is preserved on the rendered UBL.",
            "examples": [
              1
            ],
            "minimum": 1.0,
            "title": "Line Number",
            "type": "integer"
          },
          "quantity": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "type": "number"
              },
              {
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,4}0*$",
                "type": "string"
              }
            ],
            "description": "Quantity. Up to 4 decimal places. Must be greater than zero.",
            "examples": [
              "10",
              "1.5"
            ],
            "title": "Quantity"
          },
          "unit_code": {
            "default": "C62",
            "description": "UN/ECE Recommendation 20 unit of measure code. Common values: C62=one (default), EA=each, HUR=hour, DAY=day, KGM=kilogram, MTR=metre, LTR=litre.",
            "examples": [
              "C62",
              "HUR"
            ],
            "maxLength": 10,
            "title": "Unit Code",
            "type": "string"
          },
          "unit_price": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "number"
              },
              {
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,4}0*$",
                "type": "string"
              }
            ],
            "description": "Net unit price excluding VAT, in the invoice currency. Up to 4 decimal places.",
            "examples": [
              "100.00"
            ],
            "title": "Unit Price"
          },
          "vat_category_code": {
            "default": "S",
            "description": "UN/CEFACT 5305 VAT category code. Common values: S=Standard rate (default), Z=Zero rated, E=Exempt, AE=VAT reverse charge, K=Intra-community supply.",
            "examples": [
              "S"
            ],
            "maxLength": 5,
            "title": "Vat Category Code",
            "type": "string"
          },
          "vat_rate": {
            "anyOf": [
              {
                "maximum": 100.0,
                "minimum": 0.0,
                "type": "number"
              },
              {
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$",
                "type": "string"
              }
            ],
            "description": "VAT rate as a percentage. Slovak rates as of 2025: 0, 5 (food / medicines), 19 (intermediate), 23 (standard). A 0% rate must be paired with a non-'S' vat_category_code (Z, E, AE, K).",
            "examples": [
              "23.00",
              "5.00"
            ],
            "title": "Vat Rate"
          }
        },
        "required": [
          "line_number",
          "item_name",
          "quantity",
          "unit_price",
          "vat_rate"
        ],
        "title": "InvoiceLineCreate",
        "type": "object"
      },
      "InvoiceLineResponse": {
        "properties": {
          "discount_amount": {
            "anyOf": [
              {
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional line-level discount expressed as an absolute amount in the invoice currency. Mutually exclusive with discount_percentage.",
            "examples": [
              "15.00"
            ],
            "title": "Discount Amount"
          },
          "discount_percentage": {
            "anyOf": [
              {
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional line-level discount expressed as a percentage of the gross line value (quantity \u00d7 unit_price). Mutually exclusive with discount_amount in practice \u2014 set one or the other.",
            "examples": [
              "10.00"
            ],
            "title": "Discount Percentage"
          },
          "id": {
            "description": "Server-generated UUID for this invoice line.",
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "item_description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional longer description shown beneath the item name.",
            "examples": [
              "On-site engagement: 10h \u00d7 2 days"
            ],
            "title": "Item Description"
          },
          "item_name": {
            "description": "Short name of the goods or services on this line.",
            "examples": [
              "Consulting services \u2014 January 2026"
            ],
            "maxLength": 500,
            "title": "Item Name",
            "type": "string"
          },
          "line_gross_amount": {
            "description": "Gross line total (line_net_amount + line_vat_amount), in the invoice currency. 2 decimal places.",
            "examples": [
              "1230.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Line Gross Amount",
            "type": "string"
          },
          "line_net_amount": {
            "description": "Net line total after any discounts, in the invoice currency. 2 decimal places.",
            "examples": [
              "1000.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Line Net Amount",
            "type": "string"
          },
          "line_net_before_discount": {
            "anyOf": [
              {
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Net line value before any line-level discount was applied. Only populated when discount_percentage or discount_amount is set.",
            "examples": [
              "1100.00"
            ],
            "title": "Line Net Before Discount"
          },
          "line_number": {
            "description": "1-based position of this line on the invoice. Must be unique within the invoice and is preserved on the rendered UBL.",
            "examples": [
              1
            ],
            "minimum": 1.0,
            "title": "Line Number",
            "type": "integer"
          },
          "line_vat_amount": {
            "description": "VAT amount for this line (line_net_amount \u00d7 vat_rate / 100), in the invoice currency. 2 decimal places.",
            "examples": [
              "230.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Line Vat Amount",
            "type": "string"
          },
          "quantity": {
            "description": "Quantity. Up to 4 decimal places. Must be greater than zero.",
            "examples": [
              "10",
              "1.5"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,4}0*$",
            "title": "Quantity",
            "type": "string"
          },
          "unit_code": {
            "default": "C62",
            "description": "UN/ECE Recommendation 20 unit of measure code. Common values: C62=one (default), EA=each, HUR=hour, DAY=day, KGM=kilogram, MTR=metre, LTR=litre.",
            "examples": [
              "C62",
              "HUR"
            ],
            "maxLength": 10,
            "title": "Unit Code",
            "type": "string"
          },
          "unit_price": {
            "description": "Net unit price excluding VAT, in the invoice currency. Up to 4 decimal places.",
            "examples": [
              "100.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,4}0*$",
            "title": "Unit Price",
            "type": "string"
          },
          "vat_category_code": {
            "default": "S",
            "description": "UN/CEFACT 5305 VAT category code. Common values: S=Standard rate (default), Z=Zero rated, E=Exempt, AE=VAT reverse charge, K=Intra-community supply.",
            "examples": [
              "S"
            ],
            "maxLength": 5,
            "title": "Vat Category Code",
            "type": "string"
          },
          "vat_rate": {
            "description": "VAT rate as a percentage. Slovak rates as of 2025: 0, 5 (food / medicines), 19 (intermediate), 23 (standard). A 0% rate must be paired with a non-'S' vat_category_code (Z, E, AE, K).",
            "examples": [
              "23.00",
              "5.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$",
            "title": "Vat Rate",
            "type": "string"
          }
        },
        "required": [
          "line_number",
          "item_name",
          "quantity",
          "unit_price",
          "vat_rate",
          "id",
          "line_net_amount",
          "line_vat_amount",
          "line_gross_amount"
        ],
        "title": "InvoiceLineResponse",
        "type": "object"
      },
      "InvoiceListPaginated": {
        "properties": {
          "items": {
            "description": "Page of invoice list rows.",
            "items": {
              "$ref": "#/components/schemas/InvoiceListResponse"
            },
            "title": "Items",
            "type": "array"
          },
          "page": {
            "description": "Current 1-based page index.",
            "examples": [
              1
            ],
            "title": "Page",
            "type": "integer"
          },
          "page_size": {
            "description": "Number of items per page.",
            "examples": [
              20
            ],
            "title": "Page Size",
            "type": "integer"
          },
          "total": {
            "description": "Total number of invoices matching the query (across all pages).",
            "examples": [
              123
            ],
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "items",
          "total",
          "page",
          "page_size"
        ],
        "title": "InvoiceListPaginated",
        "type": "object"
      },
      "InvoiceListResponse": {
        "properties": {
          "buyer_name": {
            "description": "Legal name of the buyer.",
            "title": "Buyer Name",
            "type": "string"
          },
          "created_at": {
            "description": "Creation timestamp. ISO 8601.",
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "due_date": {
            "description": "Date payment is due. ISO 8601.",
            "format": "date",
            "title": "Due Date",
            "type": "string"
          },
          "id": {
            "description": "Server-generated UUID for this invoice.",
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "invoice_number": {
            "description": "Invoice number.",
            "examples": [
              "2026-001"
            ],
            "title": "Invoice Number",
            "type": "string"
          },
          "invoice_type": {
            "description": "UN/CEFACT 1001 invoice type code.",
            "examples": [
              "380"
            ],
            "title": "Invoice Type",
            "type": "string"
          },
          "issue_date": {
            "description": "Date the invoice was issued. ISO 8601.",
            "format": "date",
            "title": "Issue Date",
            "type": "string"
          },
          "payment_status": {
            "description": "Payment lifecycle.",
            "examples": [
              "unpaid"
            ],
            "title": "Payment Status",
            "type": "string"
          },
          "status": {
            "description": "Lifecycle status.",
            "examples": [
              "draft"
            ],
            "title": "Status",
            "type": "string"
          },
          "supplier_name": {
            "description": "Legal name of the supplier.",
            "title": "Supplier Name",
            "type": "string"
          },
          "total_gross": {
            "description": "Total amount payable, in the invoice currency. 2 decimal places.",
            "examples": [
              "1230.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Total Gross",
            "type": "string"
          }
        },
        "required": [
          "id",
          "invoice_number",
          "invoice_type",
          "status",
          "payment_status",
          "issue_date",
          "due_date",
          "supplier_name",
          "buyer_name",
          "total_gross",
          "created_at"
        ],
        "title": "InvoiceListResponse",
        "type": "object"
      },
      "InvoicePaymentSummary": {
        "properties": {
          "invoice_id": {
            "description": "The invoice these payments belong to.",
            "examples": [
              "550e8400-e29b-41d4-a716-446655440000"
            ],
            "format": "uuid",
            "title": "Invoice Id",
            "type": "string"
          },
          "payment_status": {
            "description": "Aggregate payment state. One of: unpaid, partially_paid, paid, overpaid.",
            "examples": [
              "paid"
            ],
            "title": "Payment Status",
            "type": "string"
          },
          "payments": {
            "description": "All payments recorded against this invoice, oldest first.",
            "items": {
              "$ref": "#/components/schemas/PaymentResponse"
            },
            "title": "Payments",
            "type": "array"
          },
          "remaining": {
            "description": "Outstanding balance (total_gross - total_paid). Negative if the invoice was overpaid.",
            "examples": [
              "0.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Remaining",
            "type": "string"
          },
          "total_gross": {
            "description": "Total invoice amount (gross, including VAT).",
            "examples": [
              "1234.56"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Total Gross",
            "type": "string"
          },
          "total_paid": {
            "description": "Sum of all payments recorded against this invoice.",
            "examples": [
              "1234.56"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Total Paid",
            "type": "string"
          }
        },
        "required": [
          "invoice_id",
          "total_gross",
          "total_paid",
          "remaining",
          "payment_status",
          "payments"
        ],
        "title": "InvoicePaymentSummary",
        "type": "object"
      },
      "InvoiceResponse": {
        "properties": {
          "buyer_city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Buyer city.",
            "title": "Buyer City"
          },
          "buyer_country_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Buyer country (ISO 3166-1 alpha-2).",
            "examples": [
              "SK"
            ],
            "title": "Buyer Country Code"
          },
          "buyer_dic": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Buyer Slovak tax ID (DI\u010c).",
            "title": "Buyer Dic"
          },
          "buyer_ico": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Buyer Slovak business ID (I\u010cO).",
            "title": "Buyer Ico"
          },
          "buyer_name": {
            "description": "Legal name of the buyer (customer).",
            "title": "Buyer Name",
            "type": "string"
          },
          "buyer_postal_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Buyer postal code (PS\u010c).",
            "title": "Buyer Postal Code"
          },
          "buyer_street": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Buyer street + number.",
            "title": "Buyer Street"
          },
          "buyer_vat_id": {
            "description": "Buyer I\u010c DPH. SK format: 'SK' + 10 digits (empty if not VAT-registered).",
            "examples": [
              "SK9876543210"
            ],
            "title": "Buyer Vat Id",
            "type": "string"
          },
          "created_at": {
            "description": "Creation timestamp. ISO 8601.",
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "currency_code": {
            "description": "ISO 4217 currency code in use on this invoice.",
            "examples": [
              "EUR"
            ],
            "title": "Currency Code",
            "type": "string"
          },
          "customer_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Linked customer record, if the invoice was issued against one.",
            "title": "Customer Id"
          },
          "due_date": {
            "description": "Date payment is due. ISO 8601.",
            "examples": [
              "2026-02-14"
            ],
            "format": "date",
            "title": "Due Date",
            "type": "string"
          },
          "fs_submission_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak Financial Administration (Finan\u010dn\u00e1 spr\u00e1va) submission ID issued when the invoice has been reported to FS \u2014 relevant after the 1 January 2027 mandate.",
            "title": "Fs Submission Id"
          },
          "id": {
            "description": "Server-generated UUID for this invoice.",
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "invoice_number": {
            "description": "Final invoice number (assigned at creation if not provided).",
            "examples": [
              "2026-001"
            ],
            "title": "Invoice Number",
            "type": "string"
          },
          "invoice_type": {
            "description": "UN/CEFACT 1001 invoice type code (see InvoiceCreate.invoice_type).",
            "examples": [
              "380"
            ],
            "title": "Invoice Type",
            "type": "string"
          },
          "issue_date": {
            "description": "Date the invoice was issued. ISO 8601.",
            "examples": [
              "2026-01-15"
            ],
            "format": "date",
            "title": "Issue Date",
            "type": "string"
          },
          "lines": {
            "description": "Invoice lines with computed net / VAT / gross amounts.",
            "items": {
              "$ref": "#/components/schemas/InvoiceLineResponse"
            },
            "title": "Lines",
            "type": "array"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Free-form note shown on the invoice.",
            "title": "Note"
          },
          "payment_status": {
            "description": "Payment lifecycle. Common values: 'unpaid', 'partial', 'paid', 'overdue'.",
            "examples": [
              "unpaid"
            ],
            "title": "Payment Status",
            "type": "string"
          },
          "peppol_message_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Peppol message identifier returned by the Access Point once the document has been transmitted on the network.",
            "title": "Peppol Message Id"
          },
          "source": {
            "description": "Origin marker (see InvoiceCreate.source).",
            "examples": [
              "manual"
            ],
            "title": "Source",
            "type": "string"
          },
          "source_invoice_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "For credit notes (invoice_type=381), the UUID of the original invoice being credited.",
            "title": "Source Invoice Id"
          },
          "status": {
            "description": "Lifecycle status. Common values: 'draft', 'validated', 'queued', 'sent', 'delivered', 'acknowledged', 'failed', 'voided'.",
            "examples": [
              "draft"
            ],
            "title": "Status",
            "type": "string"
          },
          "supplier_city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Supplier city.",
            "title": "Supplier City"
          },
          "supplier_country_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Supplier country (ISO 3166-1 alpha-2).",
            "examples": [
              "SK"
            ],
            "title": "Supplier Country Code"
          },
          "supplier_dic": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Supplier Slovak tax ID (DI\u010c). 10 digits.",
            "title": "Supplier Dic"
          },
          "supplier_ico": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Supplier Slovak business ID (I\u010cO). 8 digits.",
            "title": "Supplier Ico"
          },
          "supplier_name": {
            "description": "Legal name of the supplier (issuer).",
            "title": "Supplier Name",
            "type": "string"
          },
          "supplier_postal_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Supplier postal code (PS\u010c).",
            "title": "Supplier Postal Code"
          },
          "supplier_street": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Supplier street + number.",
            "title": "Supplier Street"
          },
          "supplier_vat_id": {
            "description": "Supplier I\u010c DPH. SK format: 'SK' + 10 digits.",
            "examples": [
              "SK1234567890"
            ],
            "title": "Supplier Vat Id",
            "type": "string"
          },
          "total_discount": {
            "default": "0.00",
            "description": "Sum of all line-level discounts, in the invoice currency. 2 decimal places.",
            "examples": [
              "0.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Total Discount",
            "type": "string"
          },
          "total_gross": {
            "description": "Total amount payable (total_net + total_vat), in the invoice currency. 2 decimal places. This is the amount the buyer owes.",
            "examples": [
              "1230.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Total Gross",
            "type": "string"
          },
          "total_net": {
            "description": "Sum of all line net amounts after discounts, in the invoice currency. 2 decimal places.",
            "examples": [
              "1000.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Total Net",
            "type": "string"
          },
          "total_vat": {
            "description": "Sum of VAT across all rates, in the invoice currency. 2 decimal places. Includes the ZZZ rounding correction (see zzz_correction_amount).",
            "examples": [
              "230.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Total Vat",
            "type": "string"
          },
          "updated_at": {
            "description": "Last-modified timestamp. ISO 8601.",
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          },
          "variable_symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak variable symbol (variabiln\u00fd symbol) used as payment reference.",
            "examples": [
              "2026001"
            ],
            "title": "Variable Symbol"
          },
          "vat_breakdown": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/VatBreakdownItem"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-rate VAT breakdown \u2014 one row per distinct rate appearing on the invoice. Mirrors the cac:TaxSubtotal section of the UBL.",
            "title": "Vat Breakdown"
          },
          "voided_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Timestamp when this invoice was voided. ISO 8601.",
            "title": "Voided At"
          },
          "voided_by_id": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "If this invoice has been voided by a credit note, the UUID of the credit note that voided it.",
            "title": "Voided By Id"
          },
          "zzz_correction_amount": {
            "anyOf": [
              {
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak VAT rounding reconciliation amount, expressed as a document-level UBL AllowanceCharge with reason code 'ZZZ'. Reconciles the difference between Slovakia's reverse-from-gross VAT calculation and Peppol's forward-from-net calculation. Typically a few cents per invoice.",
            "examples": [
              "0.01",
              "-0.02"
            ],
            "title": "Zzz Correction Amount"
          }
        },
        "required": [
          "id",
          "invoice_number",
          "invoice_type",
          "status",
          "payment_status",
          "issue_date",
          "due_date",
          "currency_code",
          "supplier_name",
          "supplier_vat_id",
          "buyer_name",
          "buyer_vat_id",
          "total_net",
          "total_vat",
          "total_gross",
          "source",
          "lines",
          "created_at",
          "updated_at"
        ],
        "title": "InvoiceResponse",
        "type": "object"
      },
      "LoginRequest": {
        "properties": {
          "email": {
            "description": "The user's email address.",
            "examples": [
              "jana.kovacova@example.sk"
            ],
            "format": "email",
            "title": "Email",
            "type": "string"
          },
          "password": {
            "description": "The user's password.",
            "examples": [
              "Heslo123!"
            ],
            "title": "Password",
            "type": "string"
          }
        },
        "required": [
          "email",
          "password"
        ],
        "title": "LoginRequest",
        "type": "object"
      },
      "LoginResponse": {
        "properties": {
          "access_token": {
            "description": "JWT (RS256) bearer token. Send as `Authorization: Bearer <token>` on subsequent API calls.",
            "title": "Access Token",
            "type": "string"
          },
          "expires_in": {
            "description": "Lifetime of the access_token in seconds.",
            "examples": [
              3600
            ],
            "title": "Expires In",
            "type": "integer"
          },
          "refresh_token": {
            "description": "Opaque token used to obtain a new access_token via POST /auth/refresh.",
            "title": "Refresh Token",
            "type": "string"
          },
          "token_type": {
            "default": "bearer",
            "description": "Always 'bearer' \u2014 for OAuth2 compatibility.",
            "examples": [
              "bearer"
            ],
            "title": "Token Type",
            "type": "string"
          },
          "user": {
            "$ref": "#/components/schemas/LoginUser",
            "description": "Profile of the authenticated user."
          }
        },
        "required": [
          "access_token",
          "refresh_token",
          "expires_in",
          "user"
        ],
        "title": "LoginResponse",
        "type": "object"
      },
      "LoginUser": {
        "properties": {
          "email": {
            "description": "The user's email address.",
            "examples": [
              "jana.kovacova@example.sk"
            ],
            "title": "Email",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_platform_admin": {
            "default": false,
            "description": "True if this user has platform-wide admin privileges.",
            "examples": [
              false
            ],
            "title": "Is Platform Admin",
            "type": "boolean"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The user's display name.",
            "examples": [
              "Jana Kov\u00e1\u010dov\u00e1"
            ],
            "title": "Name"
          }
        },
        "required": [
          "id",
          "email"
        ],
        "title": "LoginUser",
        "type": "object"
      },
      "MeResponse": {
        "description": "Decoded auth context for the current request.\n\nMirrors the JWT/API-key claims used internally by the backend (user id,\norganisation, workspace, role, plan tier) \u2014 it's not the persisted user\nrecord. Frontends use this to scope the UI to the current\norganisation/workspace and gate features by role + plan tier.",
        "properties": {
          "organisation_id": {
            "title": "Organisation Id",
            "type": "string"
          },
          "plan_tier": {
            "title": "Plan Tier",
            "type": "string"
          },
          "role": {
            "title": "Role",
            "type": "string"
          },
          "user_id": {
            "title": "User Id",
            "type": "string"
          },
          "workspace_id": {
            "title": "Workspace Id",
            "type": "string"
          }
        },
        "required": [
          "user_id",
          "organisation_id",
          "workspace_id",
          "role",
          "plan_tier"
        ],
        "title": "MeResponse",
        "type": "object"
      },
      "MessageResponse": {
        "description": "Generic success acknowledgement for endpoints with no specific response shape.",
        "properties": {
          "message": {
            "description": "Human-readable confirmation message.",
            "examples": [
              "Verification email sent."
            ],
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "message"
        ],
        "title": "MessageResponse",
        "type": "object"
      },
      "NextNumberResponse": {
        "description": "Result of previewing the next invoice number under the current numbering scheme.",
        "properties": {
          "invoice_number_pattern": {
            "description": "Numbering pattern template used to render the next number.",
            "examples": [
              "{YYYY}-{SEQ}"
            ],
            "title": "Invoice Number Pattern",
            "type": "string"
          },
          "next_number": {
            "description": "The number that will be assigned to the next invoice.",
            "examples": [
              "2026-001"
            ],
            "title": "Next Number",
            "type": "string"
          },
          "seq_padding": {
            "description": "Zero-padding width for the sequence portion of the number.",
            "examples": [
              3
            ],
            "title": "Seq Padding",
            "type": "integer"
          }
        },
        "required": [
          "next_number",
          "invoice_number_pattern",
          "seq_padding"
        ],
        "title": "NextNumberResponse",
        "type": "object"
      },
      "NumberingConfigUpdate": {
        "properties": {
          "invoice_number_pattern": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Invoice Number Pattern"
          },
          "reset_sequence_to": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reset Sequence To"
          },
          "seq_padding": {
            "anyOf": [
              {
                "maximum": 10.0,
                "minimum": 1.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Seq Padding"
          }
        },
        "title": "NumberingConfigUpdate",
        "type": "object"
      },
      "OAuth2TokenResponse": {
        "properties": {
          "access_token": {
            "title": "Access Token",
            "type": "string"
          },
          "expires_in": {
            "title": "Expires In",
            "type": "integer"
          },
          "token_type": {
            "default": "Bearer",
            "title": "Token Type",
            "type": "string"
          }
        },
        "required": [
          "access_token",
          "expires_in"
        ],
        "title": "OAuth2TokenResponse",
        "type": "object"
      },
      "OrganisationResponse": {
        "properties": {
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "City"
          },
          "country_code": {
            "title": "Country Code",
            "type": "string"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "dic": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Dic"
          },
          "iban": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Iban"
          },
          "ico": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ico"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "onboarding_complete": {
            "title": "Onboarding Complete",
            "type": "boolean"
          },
          "peppol_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Peppol Id"
          },
          "plan_tier": {
            "title": "Plan Tier",
            "type": "string"
          },
          "postal_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Postal Code"
          },
          "street": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Street"
          },
          "updated_at": {
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          },
          "vat_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Vat Id"
          }
        },
        "required": [
          "id",
          "name",
          "vat_id",
          "ico",
          "peppol_id",
          "street",
          "city",
          "postal_code",
          "country_code",
          "iban",
          "plan_tier",
          "onboarding_complete",
          "created_at",
          "updated_at"
        ],
        "title": "OrganisationResponse",
        "type": "object"
      },
      "OrganisationUpdate": {
        "description": "Partial update for organisation details.",
        "properties": {
          "city": {
            "anyOf": [
              {
                "maxLength": 100,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "City"
          },
          "country_code": {
            "anyOf": [
              {
                "maxLength": 2,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country Code"
          },
          "dic": {
            "anyOf": [
              {
                "maxLength": 20,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Dic"
          },
          "iban": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Iban"
          },
          "ico": {
            "anyOf": [
              {
                "maxLength": 10,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ico"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "onboarding_complete": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Onboarding Complete"
          },
          "peppol_id": {
            "anyOf": [
              {
                "maxLength": 100,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Peppol Id"
          },
          "postal_code": {
            "anyOf": [
              {
                "maxLength": 10,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Postal Code"
          },
          "street": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Street"
          },
          "vat_id": {
            "anyOf": [
              {
                "maxLength": 20,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Vat Id"
          }
        },
        "title": "OrganisationUpdate",
        "type": "object"
      },
      "OrganisationUsageResponse": {
        "properties": {
          "invoices_this_month": {
            "title": "Invoices This Month",
            "type": "integer"
          },
          "plan_limit": {
            "title": "Plan Limit",
            "type": "integer"
          },
          "plan_tier": {
            "title": "Plan Tier",
            "type": "string"
          }
        },
        "required": [
          "invoices_this_month",
          "plan_limit",
          "plan_tier"
        ],
        "title": "OrganisationUsageResponse",
        "type": "object"
      },
      "PasskeyCredentialResponse": {
        "description": "Info about a registered passkey credential.",
        "properties": {
          "backed_up": {
            "description": "True if the credential is synced to a cloud keychain (e.g. iCloud Keychain).",
            "examples": [
              true
            ],
            "title": "Backed Up",
            "type": "boolean"
          },
          "created_at": {
            "description": "When this passkey was registered. ISO 8601 timestamp.",
            "examples": [
              "2026-01-15T12:34:56Z"
            ],
            "title": "Created At",
            "type": "string"
          },
          "device_type": {
            "description": "Authenticator class. One of: single_device, multi_device.",
            "examples": [
              "multi_device"
            ],
            "title": "Device Type",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When this passkey was last used to sign in. ISO 8601 timestamp, or null if unused.",
            "examples": [
              "2026-04-12T09:21:03Z"
            ],
            "title": "Last Used At"
          }
        },
        "required": [
          "id",
          "device_type",
          "backed_up",
          "created_at"
        ],
        "title": "PasskeyCredentialResponse",
        "type": "object"
      },
      "PasskeyLoginCompleteRequest": {
        "description": "Browser credential response from navigator.credentials.get().",
        "properties": {
          "id": {
            "description": "Credential id (base64url) selected by the authenticator.",
            "title": "Id",
            "type": "string"
          },
          "rawId": {
            "description": "Raw credential id (base64url) selected by the authenticator.",
            "title": "Rawid",
            "type": "string"
          },
          "response": {
            "additionalProperties": true,
            "description": "AuthenticatorAssertionResponse payload (clientDataJSON, authenticatorData, signature, userHandle) \u2014 pass through from navigator.credentials.get().",
            "title": "Response",
            "type": "object"
          },
          "type": {
            "description": "WebAuthn credential type. Always 'public-key'.",
            "examples": [
              "public-key"
            ],
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "rawId",
          "type",
          "response"
        ],
        "title": "PasskeyLoginCompleteRequest",
        "type": "object"
      },
      "PasskeyLoginOptionsRequest": {
        "description": "Request body to start passkey login flow.",
        "properties": {
          "email": {
            "description": "Email of the account attempting passkey login.",
            "examples": [
              "jana.kovacova@example.sk"
            ],
            "format": "email",
            "title": "Email",
            "type": "string"
          }
        },
        "required": [
          "email"
        ],
        "title": "PasskeyLoginOptionsRequest",
        "type": "object"
      },
      "PasskeyLoginOptionsResponse": {
        "additionalProperties": true,
        "description": "WebAuthn `PublicKeyCredentialRequestOptions` returned to the browser.\n\nThe body is the JSON form of the spec object \u2014 `challenge`, `rpId`,\n`allowCredentials`, `userVerification`, `timeout`, etc. Clients should\npass it straight to `navigator.credentials.get({ publicKey })`. Field\nnames are kept in mixedCase via aliases to match the WebAuthn spec JSON.",
        "properties": {
          "allowCredentials": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Allowcredentials"
          },
          "challenge": {
            "title": "Challenge",
            "type": "string"
          },
          "extensions": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extensions"
          },
          "rpId": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rpid"
          },
          "timeout": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Timeout"
          },
          "userVerification": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Userverification"
          }
        },
        "required": [
          "challenge"
        ],
        "title": "PasskeyLoginOptionsResponse",
        "type": "object"
      },
      "PasskeyRegisterCompleteRequest": {
        "description": "Browser credential response from navigator.credentials.create().",
        "properties": {
          "id": {
            "description": "Credential id (base64url) returned by the authenticator.",
            "title": "Id",
            "type": "string"
          },
          "rawId": {
            "description": "Raw credential id (base64url) returned by the authenticator.",
            "title": "Rawid",
            "type": "string"
          },
          "response": {
            "additionalProperties": true,
            "description": "AuthenticatorAttestationResponse payload (clientDataJSON, attestationObject, etc.) \u2014 pass through from navigator.credentials.create().",
            "title": "Response",
            "type": "object"
          },
          "type": {
            "description": "WebAuthn credential type. Always 'public-key'.",
            "examples": [
              "public-key"
            ],
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "rawId",
          "type",
          "response"
        ],
        "title": "PasskeyRegisterCompleteRequest",
        "type": "object"
      },
      "PasskeyRegisterOptionsResponse": {
        "additionalProperties": true,
        "description": "WebAuthn `PublicKeyCredentialCreationOptions` returned to the browser.\n\nThe body is the JSON form of the spec object \u2014 `rp`, `user`, `challenge`,\n`pubKeyCredParams`, `excludeCredentials`, `authenticatorSelection`,\n`attestation`, `timeout`, etc. We type it as a free-form mapping to avoid\nduplicating the full WebAuthn schema; clients should pass the body\nstraight to `navigator.credentials.create({ publicKey })`. Field names\nare kept in mixedCase via aliases to match the WebAuthn spec JSON.",
        "properties": {
          "attestation": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Attestation"
          },
          "authenticatorSelection": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Authenticatorselection"
          },
          "challenge": {
            "title": "Challenge",
            "type": "string"
          },
          "excludeCredentials": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Excludecredentials"
          },
          "extensions": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extensions"
          },
          "pubKeyCredParams": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Pubkeycredparams",
            "type": "array"
          },
          "rp": {
            "additionalProperties": true,
            "title": "Rp",
            "type": "object"
          },
          "timeout": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Timeout"
          },
          "user": {
            "additionalProperties": true,
            "title": "User",
            "type": "object"
          }
        },
        "required": [
          "rp",
          "user",
          "challenge",
          "pubKeyCredParams"
        ],
        "title": "PasskeyRegisterOptionsResponse",
        "type": "object"
      },
      "PaymentCreate": {
        "properties": {
          "amount": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "type": "number"
              },
              {
                "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$",
                "type": "string"
              }
            ],
            "description": "Payment amount in the specified currency. Must be > 0. Should not exceed the invoice's outstanding balance.",
            "examples": [
              "1234.56"
            ],
            "title": "Amount"
          },
          "currency_code": {
            "default": "EUR",
            "description": "ISO 4217 currency code. Should match the invoice's currency.",
            "examples": [
              "EUR"
            ],
            "maxLength": 3,
            "title": "Currency Code",
            "type": "string"
          },
          "invoice_id": {
            "description": "The invoice this payment settles. Get from POST /invoices.",
            "examples": [
              "550e8400-e29b-41d4-a716-446655440000"
            ],
            "format": "uuid",
            "title": "Invoice Id",
            "type": "string"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Internal note about the payment. Not shown to the customer.",
            "examples": [
              "Paid in cash at office"
            ],
            "title": "Note"
          },
          "payment_date": {
            "description": "When the payment was received. ISO 8601 (YYYY-MM-DD).",
            "examples": [
              "2026-01-15"
            ],
            "format": "date",
            "title": "Payment Date",
            "type": "string"
          },
          "payment_method": {
            "default": "bank_transfer",
            "description": "How the payment was made. One of: bank_transfer, cash, card, other.",
            "examples": [
              "bank_transfer"
            ],
            "maxLength": 50,
            "title": "Payment Method",
            "type": "string"
          },
          "reference": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Payment reference / variable symbol provided by the payer (typically used to match bank transfers to invoices).",
            "examples": [
              "VS-2026-001"
            ],
            "title": "Reference"
          }
        },
        "required": [
          "invoice_id",
          "amount",
          "payment_date"
        ],
        "title": "PaymentCreate",
        "type": "object"
      },
      "PaymentResponse": {
        "properties": {
          "amount": {
            "description": "Payment amount in the specified currency.",
            "examples": [
              "1234.56"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Amount",
            "type": "string"
          },
          "created_at": {
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "currency_code": {
            "description": "ISO 4217 currency code.",
            "examples": [
              "EUR"
            ],
            "title": "Currency Code",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "invoice_id": {
            "description": "The invoice this payment settles.",
            "examples": [
              "550e8400-e29b-41d4-a716-446655440000"
            ],
            "format": "uuid",
            "title": "Invoice Id",
            "type": "string"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Internal note about the payment.",
            "examples": [
              "Paid in cash at office"
            ],
            "title": "Note"
          },
          "payment_date": {
            "description": "When the payment was received. ISO 8601 (YYYY-MM-DD).",
            "examples": [
              "2026-01-15"
            ],
            "format": "date",
            "title": "Payment Date",
            "type": "string"
          },
          "payment_method": {
            "description": "How the payment was made. One of: bank_transfer, cash, card, other.",
            "examples": [
              "bank_transfer"
            ],
            "title": "Payment Method",
            "type": "string"
          },
          "recorded_by": {
            "anyOf": [
              {
                "format": "uuid",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The user who recorded this payment. Null for automated reconciliation.",
            "examples": [
              "550e8400-e29b-41d4-a716-446655440000"
            ],
            "title": "Recorded By"
          },
          "reference": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Payment reference / variable symbol provided by the payer.",
            "examples": [
              "VS-2026-001"
            ],
            "title": "Reference"
          }
        },
        "required": [
          "id",
          "invoice_id",
          "amount",
          "currency_code",
          "payment_date",
          "payment_method",
          "created_at"
        ],
        "title": "PaymentResponse",
        "type": "object"
      },
      "PdfTemplate": {
        "properties": {
          "accent_color": {
            "default": "#1e40af",
            "title": "Accent Color",
            "type": "string"
          },
          "footer_text_cs": {
            "default": "D\u011bkujeme za va\u0161i d\u016fv\u011bru.",
            "title": "Footer Text Cs",
            "type": "string"
          },
          "footer_text_en": {
            "default": "Thank you for your business.",
            "title": "Footer Text En",
            "type": "string"
          },
          "footer_text_sk": {
            "default": "\u010eakujeme za va\u0161u d\u00f4veru.",
            "title": "Footer Text Sk",
            "type": "string"
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Logo Url"
          },
          "show_iban": {
            "default": true,
            "title": "Show Iban",
            "type": "boolean"
          },
          "show_qr_code": {
            "default": false,
            "title": "Show Qr Code",
            "type": "boolean"
          }
        },
        "title": "PdfTemplate",
        "type": "object"
      },
      "PeppolDeliveryNotification": {
        "description": "Notification from Oxalis that a document was received.",
        "properties": {
          "document_type": {
            "title": "Document Type",
            "type": "string"
          },
          "message_id": {
            "title": "Message Id",
            "type": "string"
          },
          "recipient_id": {
            "title": "Recipient Id",
            "type": "string"
          },
          "sender_id": {
            "title": "Sender Id",
            "type": "string"
          },
          "timestamp": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Timestamp"
          }
        },
        "required": [
          "message_id",
          "sender_id",
          "recipient_id",
          "document_type"
        ],
        "title": "PeppolDeliveryNotification",
        "type": "object"
      },
      "PeppolDeliveryStatusAck": {
        "description": "Acknowledgement returned to Oxalis after recording a delivery-status callback.",
        "properties": {
          "message_id": {
            "description": "Echo of the supplied Peppol message id.",
            "title": "Message Id",
            "type": "string"
          },
          "status": {
            "description": "Always `acknowledged`.",
            "examples": [
              "acknowledged"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "status",
          "message_id"
        ],
        "title": "PeppolDeliveryStatusAck",
        "type": "object"
      },
      "PeppolReceiveAck": {
        "description": "Receipt confirmation returned to Oxalis after a UBL invoice has been stored.",
        "properties": {
          "invoice_id": {
            "description": "UUID of the inbound invoice row created in the database.",
            "title": "Invoice Id",
            "type": "string"
          },
          "invoice_number": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Invoice number extracted from the UBL `cbc:ID` element, if present.",
            "title": "Invoice Number"
          },
          "message_id": {
            "description": "Echo of the X-Peppol-Message-Id header (or a generated id if absent).",
            "title": "Message Id",
            "type": "string"
          },
          "status": {
            "description": "Always `received` on success.",
            "examples": [
              "received"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "status",
          "message_id",
          "invoice_id"
        ],
        "title": "PeppolReceiveAck",
        "type": "object"
      },
      "RefreshRequest": {
        "properties": {
          "refresh_token": {
            "description": "The refresh_token returned by /auth/login or a previous /auth/refresh call.",
            "title": "Refresh Token",
            "type": "string"
          }
        },
        "required": [
          "refresh_token"
        ],
        "title": "RefreshRequest",
        "type": "object"
      },
      "RegisterRequest": {
        "properties": {
          "email": {
            "description": "The new user's email address. Used for login and notifications.",
            "examples": [
              "jana.kovacova@example.sk"
            ],
            "format": "email",
            "title": "Email",
            "type": "string"
          },
          "ico": {
            "anyOf": [
              {
                "maxLength": 10,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak business identification number (I\u010cO). 8 digits. Optional at registration; required before sending invoices.",
            "examples": [
              "12345678"
            ],
            "title": "Ico"
          },
          "name": {
            "description": "Full name of the user (used as the display name).",
            "examples": [
              "Jana Kov\u00e1\u010dov\u00e1"
            ],
            "maxLength": 255,
            "title": "Name",
            "type": "string"
          },
          "organisation_name": {
            "description": "Legal name of the organisation that will own this account.",
            "examples": [
              "Acme s.r.o."
            ],
            "maxLength": 255,
            "title": "Organisation Name",
            "type": "string"
          },
          "password": {
            "description": "Account password. 8-128 characters. Must contain at least one uppercase letter, one lowercase letter, one digit, and one special character.",
            "examples": [
              "Heslo123!"
            ],
            "maxLength": 128,
            "minLength": 8,
            "title": "Password",
            "type": "string"
          },
          "vat_id": {
            "anyOf": [
              {
                "maxLength": 20,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Slovak/EU VAT identification number (I\u010c DPH). SK format: SK followed by 10 digits. Optional at registration; required before sending invoices.",
            "examples": [
              "SK1234567890"
            ],
            "title": "Vat Id"
          }
        },
        "required": [
          "email",
          "password",
          "name",
          "organisation_name"
        ],
        "title": "RegisterRequest",
        "type": "object"
      },
      "RejectBody": {
        "properties": {
          "reason": {
            "title": "Reason",
            "type": "string"
          }
        },
        "required": [
          "reason"
        ],
        "title": "RejectBody",
        "type": "object"
      },
      "ResetPasswordRequest": {
        "properties": {
          "new_password": {
            "description": "Replacement password. 8-128 characters. Must contain at least one uppercase letter, one lowercase letter, one digit, and one special character.",
            "examples": [
              "NoveHeslo123!"
            ],
            "maxLength": 128,
            "minLength": 8,
            "title": "New Password",
            "type": "string"
          },
          "token": {
            "description": "Single-use password-reset token, delivered in the password-reset email link.",
            "title": "Token",
            "type": "string"
          }
        },
        "required": [
          "token",
          "new_password"
        ],
        "title": "ResetPasswordRequest",
        "type": "object"
      },
      "SendResponse": {
        "description": "Acknowledgement returned when an invoice is queued for delivery (202 Accepted).",
        "properties": {
          "invoice_id": {
            "description": "Invoice that was queued for delivery.",
            "format": "uuid",
            "title": "Invoice Id",
            "type": "string"
          },
          "message": {
            "description": "Human-readable confirmation.",
            "examples": [
              "Invoice queued for delivery"
            ],
            "title": "Message",
            "type": "string"
          },
          "status": {
            "description": "New invoice status (always 'queued' on success).",
            "examples": [
              "queued"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "invoice_id",
          "status",
          "message"
        ],
        "title": "SendResponse",
        "type": "object"
      },
      "SettingsUpdate": {
        "properties": {
          "default_currency": {
            "anyOf": [
              {
                "maxLength": 3,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Default Currency"
          },
          "default_payment_terms_days": {
            "anyOf": [
              {
                "maximum": 365.0,
                "minimum": 1.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Default Payment Terms Days"
          },
          "default_vat_rate": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Default Vat Rate"
          },
          "invoice_number_pattern": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Invoice Number Pattern"
          },
          "pdf_template": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PdfTemplate"
              },
              {
                "type": "null"
              }
            ]
          },
          "seq_padding": {
            "anyOf": [
              {
                "maximum": 10.0,
                "minimum": 1.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Seq Padding"
          }
        },
        "title": "SettingsUpdate",
        "type": "object"
      },
      "StatusTransitionResponse": {
        "description": "Generic acknowledgement for routes that flip an invoice between statuses.",
        "properties": {
          "invoice_id": {
            "description": "Invoice whose status was changed.",
            "format": "uuid",
            "title": "Invoice Id",
            "type": "string"
          },
          "message": {
            "description": "Human-readable confirmation.",
            "title": "Message",
            "type": "string"
          },
          "status": {
            "description": "New invoice status after the transition.",
            "examples": [
              "approved",
              "delivered"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "invoice_id",
          "status",
          "message"
        ],
        "title": "StatusTransitionResponse",
        "type": "object"
      },
      "TokenRequest": {
        "properties": {
          "client_id": {
            "title": "Client Id",
            "type": "string"
          },
          "client_secret": {
            "title": "Client Secret",
            "type": "string"
          },
          "grant_type": {
            "default": "client_credentials",
            "title": "Grant Type",
            "type": "string"
          }
        },
        "required": [
          "client_id",
          "client_secret"
        ],
        "title": "TokenRequest",
        "type": "object"
      },
      "TokenResponse": {
        "properties": {
          "access_token": {
            "description": "JWT (RS256) bearer token. Send as `Authorization: Bearer <token>` on subsequent API calls.",
            "title": "Access Token",
            "type": "string"
          },
          "expires_in": {
            "description": "Lifetime of the access_token in seconds.",
            "examples": [
              3600
            ],
            "title": "Expires In",
            "type": "integer"
          },
          "refresh_token": {
            "description": "Opaque token used to obtain a new access_token via POST /auth/refresh.",
            "title": "Refresh Token",
            "type": "string"
          },
          "token_type": {
            "default": "bearer",
            "description": "Always 'bearer' \u2014 for OAuth2 compatibility.",
            "examples": [
              "bearer"
            ],
            "title": "Token Type",
            "type": "string"
          }
        },
        "required": [
          "access_token",
          "refresh_token",
          "expires_in"
        ],
        "title": "TokenResponse",
        "type": "object"
      },
      "UpdateMemberRoleRequest": {
        "properties": {
          "role": {
            "title": "Role",
            "type": "string"
          }
        },
        "required": [
          "role"
        ],
        "title": "UpdateMemberRoleRequest",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "ctx": {
            "title": "Context",
            "type": "object"
          },
          "input": {
            "title": "Input"
          },
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      },
      "ValidationIssue": {
        "description": "A single validation error or warning emitted by the business-rule validator.",
        "properties": {
          "field": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Dotted path to the field that failed the rule, when applicable.",
            "examples": [
              "lines[0].quantity"
            ],
            "title": "Field"
          },
          "message": {
            "description": "Human-readable explanation of the failure.",
            "examples": [
              "Quantity must be greater than zero."
            ],
            "title": "Message",
            "type": "string"
          },
          "rule": {
            "description": "Stable rule identifier (e.g. 'BR-CO-15', 'SK-001').",
            "examples": [
              "BR-01"
            ],
            "title": "Rule",
            "type": "string"
          }
        },
        "required": [
          "rule",
          "message"
        ],
        "title": "ValidationIssue",
        "type": "object"
      },
      "ValidationResult": {
        "description": "Combined business-rule + XML validation report for an invoice.\n\nMirrors the response of `POST /invoices/{id}/validate`. The route also\npromotes a passing DRAFT invoice to VALIDATED \u2014 the new status is\nsurfaced in the `status` field.",
        "properties": {
          "errors": {
            "items": {
              "$ref": "#/components/schemas/ValidationIssue"
            },
            "title": "Errors",
            "type": "array"
          },
          "schemas_available": {
            "additionalProperties": {
              "type": "boolean"
            },
            "description": "Which XML schemas were actually loaded at validation time.",
            "examples": [
              {
                "schematron_peppol": true,
                "schematron_slovak": false,
                "xsd_credit": true,
                "xsd_invoice": true
              }
            ],
            "title": "Schemas Available",
            "type": "object"
          },
          "status": {
            "description": "Invoice status after validation (may be promoted from 'draft' to 'validated').",
            "examples": [
              "validated"
            ],
            "title": "Status",
            "type": "string"
          },
          "valid": {
            "description": "True if all checks passed (including XSD/Schematron).",
            "title": "Valid",
            "type": "boolean"
          },
          "warnings": {
            "items": {
              "$ref": "#/components/schemas/ValidationIssue"
            },
            "title": "Warnings",
            "type": "array"
          },
          "xml_validation": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/XmlValidationSummary"
              },
              {
                "type": "null"
              }
            ],
            "description": "XSD/Schematron results, or null if no XML schemas are installed."
          }
        },
        "required": [
          "valid",
          "status"
        ],
        "title": "ValidationResult",
        "type": "object"
      },
      "VatBreakdownItem": {
        "properties": {
          "amount": {
            "description": "VAT charged at this rate (base \u00d7 rate / 100), in the invoice currency. 2 decimal places.",
            "examples": [
              "230.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Amount",
            "type": "string"
          },
          "base": {
            "description": "Sum of the net amounts taxed at this rate, in the invoice currency. 2 decimal places.",
            "examples": [
              "1000.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Base",
            "type": "string"
          },
          "rate": {
            "description": "VAT rate as a percentage. One row per distinct rate appearing on the invoice.",
            "examples": [
              "23.00"
            ],
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Rate",
            "type": "string"
          }
        },
        "required": [
          "rate",
          "base",
          "amount"
        ],
        "title": "VatBreakdownItem",
        "type": "object"
      },
      "VerifyEmailRequest": {
        "properties": {
          "token": {
            "description": "Single-use email-verification token, delivered in the verification email link.",
            "title": "Token",
            "type": "string"
          }
        },
        "required": [
          "token"
        ],
        "title": "VerifyEmailRequest",
        "type": "object"
      },
      "WebhookCreate": {
        "properties": {
          "description": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "events": {
            "default": "invoice.delivered,invoice.rejected,invoice.fs_acknowledged",
            "title": "Events",
            "type": "string"
          },
          "url": {
            "maxLength": 2048,
            "title": "Url",
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "title": "WebhookCreate",
        "type": "object"
      },
      "WebhookCreateResponse": {
        "description": "Response on creation \u2014 includes the plaintext secret (shown once).",
        "properties": {
          "created_at": {
            "title": "Created At",
            "type": "string"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "events": {
            "title": "Events",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "secret": {
            "title": "Secret",
            "type": "string"
          },
          "url": {
            "title": "Url",
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "is_active",
          "description",
          "created_at",
          "secret"
        ],
        "title": "WebhookCreateResponse",
        "type": "object"
      },
      "WebhookDeliveryResponse": {
        "properties": {
          "attempt": {
            "title": "Attempt",
            "type": "integer"
          },
          "created_at": {
            "title": "Created At",
            "type": "string"
          },
          "event_type": {
            "title": "Event Type",
            "type": "string"
          },
          "http_status": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Http Status"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id",
          "event_type",
          "status",
          "http_status",
          "attempt",
          "created_at"
        ],
        "title": "WebhookDeliveryResponse",
        "type": "object"
      },
      "WebhookResponse": {
        "properties": {
          "created_at": {
            "title": "Created At",
            "type": "string"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "events": {
            "title": "Events",
            "type": "string"
          },
          "id": {
            "format": "uuid",
            "title": "Id",
            "type": "string"
          },
          "is_active": {
            "title": "Is Active",
            "type": "boolean"
          },
          "url": {
            "title": "Url",
            "type": "string"
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "is_active",
          "description",
          "created_at"
        ],
        "title": "WebhookResponse",
        "type": "object"
      },
      "XmlValidationIssue": {
        "description": "A single XSD or Schematron failure raised against the generated UBL document.",
        "properties": {
          "message": {
            "description": "Human-readable description of the failure.",
            "title": "Message",
            "type": "string"
          },
          "rule": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Schematron / XSD rule identifier when available.",
            "examples": [
              "BR-CO-10"
            ],
            "title": "Rule"
          },
          "source": {
            "description": "Validator that produced the issue: 'xsd', 'peppol', or 'slovak'.",
            "examples": [
              "peppol"
            ],
            "title": "Source",
            "type": "string"
          }
        },
        "required": [
          "source",
          "message"
        ],
        "title": "XmlValidationIssue",
        "type": "object"
      },
      "XmlValidationSummary": {
        "description": "Result of running XSD + Schematron checks against the generated UBL XML.",
        "properties": {
          "errors": {
            "items": {
              "$ref": "#/components/schemas/XmlValidationIssue"
            },
            "title": "Errors",
            "type": "array"
          },
          "peppol_valid": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "True if Peppol BIS3 Schematron passed; None if not loaded.",
            "title": "Peppol Valid"
          },
          "slovak_valid": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "True if Slovak Schematron rules passed; None if not loaded.",
            "title": "Slovak Valid"
          },
          "warnings": {
            "items": {
              "type": "string"
            },
            "title": "Warnings",
            "type": "array"
          },
          "xsd_valid": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "True if the XML matched the UBL XSD; None if the XSD wasn't loaded.",
            "title": "Xsd Valid"
          }
        },
        "title": "XmlValidationSummary",
        "type": "object"
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "description": "Long-lived API key created at POST /api-keys. Send as `X-Api-Key: <key>`. Use this for server-to-server integrations (your accounting backend \u2192 eFakturuj).",
        "in": "header",
        "name": "X-Api-Key",
        "type": "apiKey"
      },
      "BearerJWT": {
        "bearerFormat": "JWT",
        "description": "Short-lived (15 min) RS256 JWT issued by POST /auth/login or POST /auth/refresh. Send as `Authorization: Bearer <token>`. Use this for end-user-facing apps (mobile, browser SPAs).",
        "scheme": "bearer",
        "type": "http"
      },
      "OAuth2": {
        "description": "OAuth2 client-credentials flow for server-to-server integrations. POST /api/v1/oauth2/token with grant_type=client_credentials, client_id, client_secret, and scope to receive a short-lived access token. Currently implements client_credentials only \u2014 the authorization-code flow (third-party apps acting on behalf of a user) is on the roadmap but not yet wired.",
        "flows": {
          "clientCredentials": {
            "scopes": {
              "invoices:read": "Read invoices",
              "invoices:send": "Send invoices via Peppol (subset of invoices:write for fine-grained delegation)",
              "invoices:write": "Create, update, send, void invoices"
            },
            "tokenUrl": "https://api.efakturuj.sk/api/v1/oauth2/token"
          }
        },
        "type": "oauth2"
      }
    }
  },
  "info": {
    "description": "Slovak Peppol e-invoicing compliance engine",
    "title": "eFakturuj",
    "version": "docs"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api/v1/admin/audit-logs": {
      "get": {
        "operationId": "audit_logs_api_v1_admin_audit_logs_get",
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "action",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Action"
            }
          },
          {
            "in": "query",
            "name": "org_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "uuid",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Org Id"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Audit Logs Api V1 Admin Audit Logs Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Audit Logs",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/billing/overview": {
      "get": {
        "operationId": "billing_overview_api_v1_admin_billing_overview_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Billing Overview Api V1 Admin Billing Overview Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Billing Overview",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/deliveries/failed": {
      "get": {
        "operationId": "failed_deliveries_api_v1_admin_deliveries_failed_get",
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Failed Deliveries Api V1 Admin Deliveries Failed Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Failed Deliveries",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/deliveries/{invoice_id}/retry": {
      "post": {
        "operationId": "retry_delivery_api_v1_admin_deliveries__invoice_id__retry_post",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Retry Delivery Api V1 Admin Deliveries  Invoice Id  Retry Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Retry Delivery",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/health": {
      "get": {
        "operationId": "system_health_api_v1_admin_health_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response System Health Api V1 Admin Health Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "System Health",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/invoices": {
      "get": {
        "operationId": "search_invoices_api_v1_admin_invoices_get",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Q"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Search Invoices Api V1 Admin Invoices Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Search Invoices",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/organisations": {
      "get": {
        "operationId": "list_organisations_api_v1_admin_organisations_get",
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Q"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Organisations Api V1 Admin Organisations Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "List Organisations",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/organisations/{org_id}": {
      "get": {
        "operationId": "get_organisation_api_v1_admin_organisations__org_id__get",
        "parameters": [
          {
            "in": "path",
            "name": "org_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Org Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Get Organisation Api V1 Admin Organisations  Org Id  Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Get Organisation",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/plans": {
      "get": {
        "operationId": "list_plans_api_v1_admin_plans_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "additionalProperties": true,
                    "type": "object"
                  },
                  "title": "Response List Plans Api V1 Admin Plans Get",
                  "type": "array"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "List Plans",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/plans/{tier_key}": {
      "patch": {
        "operationId": "update_plan_api_v1_admin_plans__tier_key__patch",
        "parameters": [
          {
            "in": "path",
            "name": "tier_key",
            "required": true,
            "schema": {
              "title": "Tier Key",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": true,
                "title": "Updates",
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Update Plan Api V1 Admin Plans  Tier Key  Patch",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Update Plan",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/security-events": {
      "get": {
        "operationId": "security_events_api_v1_admin_security_events_get",
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "severity",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Severity"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Security Events Api V1 Admin Security Events Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Security Events",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/users": {
      "get": {
        "operationId": "list_users_api_v1_admin_users_get",
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Q"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response List Users Api V1 Admin Users Get",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "List Users",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/users/{user_id}/deactivate": {
      "post": {
        "operationId": "deactivate_user_api_v1_admin_users__user_id__deactivate_post",
        "parameters": [
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "User Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Deactivate User Api V1 Admin Users  User Id  Deactivate Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Deactivate User",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/users/{user_id}/demote-admin": {
      "post": {
        "operationId": "demote_admin_api_v1_admin_users__user_id__demote_admin_post",
        "parameters": [
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "User Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Demote Admin Api V1 Admin Users  User Id  Demote Admin Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Demote Admin",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/admin/users/{user_id}/promote-admin": {
      "post": {
        "operationId": "promote_admin_api_v1_admin_users__user_id__promote_admin_post",
        "parameters": [
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "User Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "title": "Response Promote Admin Api V1 Admin Users  User Id  Promote Admin Post",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Promote Admin",
        "tags": [
          "admin"
        ]
      }
    },
    "/api/v1/analytics/by-status": {
      "get": {
        "description": "Invoice counts grouped by status.",
        "operationId": "analytics_by_status_api_v1_analytics_by_status_get",
        "parameters": [
          {
            "in": "query",
            "name": "from_date",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "From Date"
            }
          },
          {
            "in": "query",
            "name": "to_date",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "To Date"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Analytics By Status",
        "tags": [
          "analytics"
        ]
      }
    },
    "/api/v1/analytics/by-user": {
      "get": {
        "description": "Invoice counts grouped by creator user.",
        "operationId": "analytics_by_user_api_v1_analytics_by_user_get",
        "parameters": [
          {
            "in": "query",
            "name": "from_date",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "From Date"
            }
          },
          {
            "in": "query",
            "name": "to_date",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "To Date"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Analytics By User",
        "tags": [
          "analytics"
        ]
      }
    },
    "/api/v1/analytics/overview": {
      "get": {
        "description": "High-level analytics: total invoices, total value, delivery success rate.",
        "operationId": "analytics_overview_api_v1_analytics_overview_get",
        "parameters": [
          {
            "in": "query",
            "name": "from_date",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "From Date"
            }
          },
          {
            "in": "query",
            "name": "to_date",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "To Date"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Analytics Overview",
        "tags": [
          "analytics"
        ]
      }
    },
    "/api/v1/analytics/timeseries": {
      "get": {
        "description": "Daily or weekly invoice count time series.",
        "operationId": "analytics_timeseries_api_v1_analytics_timeseries_get",
        "parameters": [
          {
            "in": "query",
            "name": "from_date",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "From Date"
            }
          },
          {
            "in": "query",
            "name": "to_date",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "To Date"
            }
          },
          {
            "in": "query",
            "name": "granularity",
            "required": false,
            "schema": {
              "default": "day",
              "pattern": "^(day|week)$",
              "title": "Granularity",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Analytics Timeseries",
        "tags": [
          "analytics"
        ]
      }
    },
    "/api/v1/api-keys": {
      "get": {
        "description": "List every API key (active or revoked) belonging to the organisation.\n\nRequires the `admin` role. Returns rows ordered by `created_at`\ndescending, including each key's `key_prefix`, scopes,\n`is_active` flag, last-used timestamp, and expiry. The plaintext\nkey and its SHA-256 hash are never exposed \u2014 use the prefix to\nidentify a key the user is looking at in the dashboard.",
        "operationId": "api_keys.list",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/ApiKeyResponse"
                  },
                  "title": "Response Api Keys.List",
                  "type": "array"
                }
              }
            },
            "description": "Successful Response"
          },
          "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": "Caller does not hold the `admin` role."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "List API keys for the workspace",
        "tags": [
          "api-keys"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/api-keys \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/api-keys');"
          }
        ]
      },
      "post": {
        "description": "Mint a fresh API key for the caller's organisation.\n\nRequires the `admin` role. Generates a cryptographically random\nplaintext key, stores only its SHA-256 hash plus a 12-character\n`key_prefix` for display, and returns the full plaintext exactly\nonce in the `api_key` field of `ApiKeyCreated` \u2014 the rest of the\nAPI will only ever expose the prefix and hash, so this response\nmust be treated as a one-time secret. Optional `expires_in_days`\nsets a hard expiry. The action is recorded in `audit_logs`.",
        "operationId": "api_keys.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreated"
                }
              }
            },
            "description": "Successful Response"
          },
          "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": "Caller does not hold the `admin` role."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid payload \u2014 unknown scope or out-of-range expiry."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Create a new API key",
        "tags": [
          "api-keys"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/api-keys \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/api-keys', data: {...});"
          }
        ]
      }
    },
    "/api/v1/api-keys/{key_id}": {
      "delete": {
        "description": "Soft-delete (revoke) an API key so it can no longer authenticate.\n\nRequires the `admin` role. Sets `is_active=False` on the row \u2014\nthe key is retained for audit history but every subsequent\nrequest that presents it gets 401. Re-revoking an already-\ninactive key returns 409. The action is recorded in\n`audit_logs`. There is no un-revoke; mint a new key instead.",
        "operationId": "api_keys.revoke",
        "parameters": [
          {
            "in": "path",
            "name": "key_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Key Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyRevokeResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "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": "Caller does not hold the `admin` role."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "API key not found in this organisation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "API key has already been deactivated."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Revoke an API key",
        "tags": [
          "api-keys"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X DELETE https://api.efakturuj.sk/api/v1/api-keys/{key_id} \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.delete('/api/v1/api-keys/{key_id}');"
          }
        ]
      },
      "patch": {
        "description": "Patch an API key's display name and/or scopes in place.\n\nRequires the `admin` role. Only the `name` and `scopes` fields\ncan be changed \u2014 the secret material is immutable. At least one\nfield must be supplied or the request returns 422. Scopes are\nvalidated against the `VALID_SCOPES` allowlist before persisting.\nThe action is recorded in `audit_logs` with a `changes` payload\nlisting the modified fields.",
        "operationId": "api_keys.update",
        "parameters": [
          {
            "in": "path",
            "name": "key_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Key Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "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": "Caller does not hold the `admin` role."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "API key not found in this organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "No fields supplied to update, or one of the requested scopes is unknown."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Update an API key's name or scopes",
        "tags": [
          "api-keys"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X PATCH https://api.efakturuj.sk/api/v1/api-keys/{key_id} \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.patch('/api/v1/api-keys/{key_id}', data: {...});"
          }
        ]
      }
    },
    "/api/v1/auth/change-password": {
      "post": {
        "description": "Change the password of the currently authenticated user.\n\nRequires a valid `Authorization: Bearer <jwt>` access token. The\ncaller must supply the current password (re-verified server-side\nwith Argon2id) plus a new password that satisfies the same\ncomplexity rules enforced at registration. The new password is\nhashed and stored; existing refresh tokens are NOT invalidated by\nthis call. Returns 400 if the current password is wrong.",
        "operationId": "auth.change_password",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Current password incorrect or new password invalid"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Change the password of the signed-in user",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/auth/change-password \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/auth/change-password', data: {...});"
          }
        ]
      }
    },
    "/api/v1/auth/forgot-password": {
      "post": {
        "description": "Trigger a password-reset email for the supplied address.\n\nNo authentication required. The endpoint always returns 200 with the\nsame generic message \u2014 whether or not an account exists for the\nemail \u2014 to prevent account enumeration. If the address matches an\nactive account, the service generates a single-use reset token and\nqueues a transactional email containing a link to the reset page.",
        "operationId": "auth.forgot_password",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ForgotPasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Send a password-reset email",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/auth/forgot-password \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/auth/forgot-password', data: {...});"
          }
        ]
      }
    },
    "/api/v1/auth/login": {
      "post": {
        "description": "Authenticate a user and issue access + refresh JWT tokens.\n\nThe access token is a short-lived (default 15 min) JWT signed with\nRS256 and is sent as `Authorization: Bearer <token>` on subsequent\nrequests. The refresh token is a longer-lived JWT used at\n`POST /auth/refresh` to mint new access tokens without re-prompting\nthe user for their password. Failed attempts are recorded as a\n`login_failed` security event with the source IP and user agent so\nrepeated abuse is observable. Returns 401 for invalid credentials\nor a disabled account.",
        "operationId": "auth.login",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoginResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid credentials or disabled account"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Too many login attempts"
          }
        },
        "summary": "Sign in with email and password",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/auth/login \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"email\": \"jana.kovacova@example.sk\",\n    \"password\": \"<YOUR_PASSWORD>\"\n  }'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk/api/v1',\n));\n\nfinal response = await dio.post('/auth/login', data: {\n  'email': 'jana.kovacova@example.sk',\n  'password': '<YOUR_PASSWORD>',\n});\nfinal accessToken = response.data['access_token'] as String;\nfinal refreshToken = response.data['refresh_token'] as String;"
          },
          {
            "label": "Python",
            "lang": "Python",
            "source": "import httpx\n\nr = httpx.post(\n    'https://api.efakturuj.sk/api/v1/auth/login',\n    json={\n        'email': 'jana.kovacova@example.sk',\n        'password': '<YOUR_PASSWORD>',\n    },\n)\nr.raise_for_status()\ntokens = r.json()\naccess_token = tokens['access_token']\nrefresh_token = tokens['refresh_token']"
          },
          {
            "label": "TypeScript",
            "lang": "JavaScript",
            "source": "const r = await fetch('https://api.efakturuj.sk/api/v1/auth/login', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({\n    email: 'jana.kovacova@example.sk',\n    password: '<YOUR_PASSWORD>',\n  }),\n});\nif (!r.ok) throw new Error(`HTTP ${r.status}`);\nconst { access_token, refresh_token } = await r.json();"
          },
          {
            "label": "PHP",
            "lang": "PHP",
            "source": "<?php\n$client = new GuzzleHttp\\Client(['base_uri' => 'https://api.efakturuj.sk/api/v1/']);\n$response = $client->post('auth/login', [\n    'json' => [\n        'email' => 'jana.kovacova@example.sk',\n        'password' => '<YOUR_PASSWORD>',\n    ],\n]);\n$body = json_decode($response->getBody(), true);\n$accessToken = $body['access_token'];\n$refreshToken = $body['refresh_token'];"
          }
        ]
      }
    },
    "/api/v1/auth/me": {
      "get": {
        "description": "Return the decoded auth context for the current request.\n\nRequires a valid `Authorization: Bearer <jwt>` access token (or a\nvalid API key, which produces the same `AuthContext`). The response\nmirrors the JWT/API-key claims \u2014 user id, organisation id,\nworkspace id, role, and plan tier \u2014 and is the canonical way for\nthe frontend to discover which org/workspace the current session is\nscoped to. No database query is performed.",
        "operationId": "auth.me",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Return the signed-in user's profile",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/auth/me \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/auth/me');"
          }
        ]
      }
    },
    "/api/v1/auth/passkey/login/complete": {
      "post": {
        "description": "Finalise WebAuthn sign-in by verifying the assertion and issuing JWT tokens.\n\nNo bearer auth required \u2014 the WebAuthn assertion is the credential.\nThe request body is the credential object returned by\n`navigator.credentials.get()`. The endpoint extracts and decodes\n`userHandle` (the user's UUID encoded as base64url bytes), verifies\nthe assertion against the challenge issued by\n`POST /auth/passkey/login/options`, and on success issues an access\n+ refresh JWT pair just like password login. Returns 400 for a\nmissing/malformed `userHandle` and 401 for failed assertion\nverification or token issuance.",
        "operationId": "auth.passkey_login_complete",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasskeyLoginCompleteRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoginResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or malformed userHandle"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "WebAuthn authentication failed"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Complete WebAuthn passkey sign-in",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/auth/passkey/login/complete \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/auth/passkey/login/complete', data: {...});"
          }
        ]
      }
    },
    "/api/v1/auth/passkey/login/options": {
      "post": {
        "description": "Start the WebAuthn authentication ceremony for an email address.\n\nNo bearer auth required \u2014 the email identifies the candidate user.\nThe service looks up the user, gathers their registered passkeys,\nand generates a `PublicKeyCredentialRequestOptions` object\n(challenge, allowed credentials, user-verification preference). The\nchallenge is stored server-side keyed by user id. The browser passes\nthe response straight to `navigator.credentials.get({ publicKey })`,\nthen submits the result to `POST /auth/passkey/login/complete`.\nReturns 400 if the email is unknown or the user has no passkeys.",
        "operationId": "auth.passkey_login_options",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasskeyLoginOptionsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PasskeyLoginOptionsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unknown email or no registered passkeys"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Begin WebAuthn passkey sign-in",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/auth/passkey/login/options \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/auth/passkey/login/options', data: {...});"
          }
        ]
      }
    },
    "/api/v1/auth/passkey/register/complete": {
      "post": {
        "description": "Finalise WebAuthn registration by verifying the browser's attestation response.\n\nRequires a valid `Authorization: Bearer <jwt>` access token. The\nrequest body is the credential object returned by\n`navigator.credentials.create()`. The service validates the\nattestation against the challenge issued by\n`POST /auth/passkey/register/options`, persists a new\n`PasskeyCredential` row (credential id, public key, sign counter,\ndevice type, AAGUID, transports), and returns a summary of the\nstored credential. Returns 400 if attestation verification fails.",
        "operationId": "auth.passkey_register_complete",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasskeyRegisterCompleteRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PasskeyCredentialResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "WebAuthn registration verification failed"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "User not found"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Complete WebAuthn passkey registration",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/auth/passkey/register/complete \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/auth/passkey/register/complete', data: {...});"
          }
        ]
      }
    },
    "/api/v1/auth/passkey/register/options": {
      "post": {
        "description": "Start the WebAuthn registration ceremony for the signed-in user.\n\nRequires a valid `Authorization: Bearer <jwt>` access token. The\nservice generates a `PublicKeyCredentialCreationOptions` object\n(challenge, relying-party info, user info, allowed credential\nparameters, exclude-list of already-registered passkeys) and stores\nthe challenge server-side keyed by user id. The browser passes the\nresponse straight to `navigator.credentials.create({ publicKey })`,\nthen submits the result to `POST /auth/passkey/register/complete`.",
        "operationId": "auth.passkey_register_options",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PasskeyRegisterOptionsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "WebAuthn options could not be generated"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "User not found"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Begin WebAuthn passkey registration",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/auth/passkey/register/options \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/auth/passkey/register/options');"
          }
        ]
      }
    },
    "/api/v1/auth/refresh": {
      "post": {
        "description": "Trade a valid refresh token for a fresh access token (and a rotated refresh token).\n\nNo bearer auth required \u2014 the refresh token itself is the credential.\nThe service decodes the refresh token, looks up the user's first\nworkspace membership and organisation, then issues a new access\ntoken plus a brand-new refresh token (token rotation). Returns 401\nif the refresh token is invalid, expired, or the user is missing /\ndisabled / has no workspace.",
        "operationId": "auth.refresh",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid or expired refresh token"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Exchange a refresh token for a new access token",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/auth/refresh \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"refresh_token\": \"<YOUR_REFRESH_TOKEN>\"\n  }'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk/api/v1',\n));\n\nfinal response = await dio.post('/auth/refresh', data: {\n  'refresh_token': storedRefreshToken,\n});\nfinal accessToken = response.data['access_token'] as String;\nfinal refreshToken = response.data['refresh_token'] as String;"
          },
          {
            "label": "Python",
            "lang": "Python",
            "source": "import httpx\n\nr = httpx.post(\n    'https://api.efakturuj.sk/api/v1/auth/refresh',\n    json={'refresh_token': stored_refresh_token},\n)\nr.raise_for_status()\ntokens = r.json()\naccess_token = tokens['access_token']\nrefresh_token = tokens['refresh_token']  # rotate stored copy"
          },
          {
            "label": "TypeScript",
            "lang": "JavaScript",
            "source": "const r = await fetch('https://api.efakturuj.sk/api/v1/auth/refresh', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ refresh_token: storedRefreshToken }),\n});\nif (!r.ok) throw new Error(`HTTP ${r.status}`);\nconst { access_token, refresh_token } = await r.json();\n// Persist the rotated refresh_token for the next call."
          },
          {
            "label": "PHP",
            "lang": "PHP",
            "source": "<?php\n$client = new GuzzleHttp\\Client(['base_uri' => 'https://api.efakturuj.sk/api/v1/']);\n$response = $client->post('auth/refresh', [\n    'json' => ['refresh_token' => $storedRefreshToken],\n]);\n$body = json_decode($response->getBody(), true);\n$accessToken = $body['access_token'];\n$refreshToken = $body['refresh_token']; // rotate stored copy"
          }
        ]
      }
    },
    "/api/v1/auth/register": {
      "post": {
        "description": "Sign up a new account by creating a user, organisation, and workspace in one call.\n\nNo authentication required. The caller supplies an email, password\n(validated for length and complexity by the request schema),\ndisplay name, organisation name, and optional Slovak tax IDs\n(`vat_id`, `ico`). The service hashes the password with Argon2id,\nprovisions a workspace and an `admin` membership, and returns the\nsame `TokenResponse` shape as `POST /auth/login` so the client can\nsign the user in immediately. Returns 409 if the email is already\nregistered.",
        "operationId": "auth.register",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Email already registered"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Password does not meet complexity rules"
          }
        },
        "summary": "Register a new user account",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/auth/register \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/auth/register', data: {...});"
          }
        ]
      }
    },
    "/api/v1/auth/reset-password": {
      "post": {
        "description": "Complete a password reset using the token from the password-reset email.\n\nNo bearer auth required \u2014 the reset token is the credential. The\nnew password must satisfy the same complexity rules enforced at\nregistration. On success the password hash is updated and the reset\ntoken is consumed so it cannot be reused. Returns 400 if the token\nis unknown, already used, or expired.",
        "operationId": "auth.reset_password",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResetPasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid or expired reset token, or weak new password"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Set a new password from a reset token",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/auth/reset-password \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/auth/reset-password', data: {...});"
          }
        ]
      }
    },
    "/api/v1/auth/verify-email": {
      "post": {
        "description": "Mark an account's email address as verified using the token from the welcome email.\n\nNo authentication required \u2014 the opaque token is the credential.\nThe service validates the token, marks the user as email-verified,\nand consumes the token. Returns a generic acknowledgement on\nsuccess or 400 if the token is unknown, already used, or expired.",
        "operationId": "auth.verify_email",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyEmailRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid or expired verification token"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Confirm an email-verification link",
        "tags": [
          "auth"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/auth/verify-email \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/auth/verify-email', data: {...});"
          }
        ]
      }
    },
    "/api/v1/billing/cancel": {
      "post": {
        "description": "Cancel current subscription at period end.",
        "operationId": "cancel_subscription_endpoint_api_v1_billing_cancel_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Cancel Subscription Endpoint",
        "tags": [
          "billing"
        ]
      }
    },
    "/api/v1/billing/history": {
      "get": {
        "description": "Paginated billing event history for the organisation.",
        "operationId": "get_billing_history_api_v1_billing_history_get",
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Get Billing History",
        "tags": [
          "billing"
        ]
      }
    },
    "/api/v1/billing/subscribe": {
      "post": {
        "description": "Create or upgrade a subscription.",
        "operationId": "subscribe_endpoint_api_v1_billing_subscribe_post",
        "parameters": [
          {
            "in": "query",
            "name": "plan",
            "required": true,
            "schema": {
              "title": "Plan",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Subscribe Endpoint",
        "tags": [
          "billing"
        ]
      }
    },
    "/api/v1/billing/subscription": {
      "get": {
        "description": "Current subscription details from Stripe.",
        "operationId": "get_subscription_api_v1_billing_subscription_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Get Subscription",
        "tags": [
          "billing"
        ]
      }
    },
    "/api/v1/billing/upgrade": {
      "post": {
        "description": "Upgrade or downgrade an existing subscription to a new plan.",
        "operationId": "upgrade_subscription_endpoint_api_v1_billing_upgrade_post",
        "parameters": [
          {
            "in": "query",
            "name": "new_plan",
            "required": true,
            "schema": {
              "title": "New Plan",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Upgrade Subscription Endpoint",
        "tags": [
          "billing"
        ]
      }
    },
    "/api/v1/billing/usage": {
      "get": {
        "description": "Current month usage vs plan limit, with overage info.",
        "operationId": "get_usage_api_v1_billing_usage_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Get Usage",
        "tags": [
          "billing"
        ]
      }
    },
    "/api/v1/billing/webhook/stripe": {
      "post": {
        "description": "Handle Stripe webhook events.\n\nNo JWT auth \u2014 verified via Stripe signature.",
        "operationId": "stripe_webhook_api_v1_billing_webhook_stripe_post",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Stripe Webhook",
        "tags": [
          "billing"
        ]
      }
    },
    "/api/v1/connect/webhooks": {
      "get": {
        "description": "List all webhook endpoints for the organisation.",
        "operationId": "list_webhooks_api_v1_connect_webhooks_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/WebhookResponse"
                  },
                  "title": "Response List Webhooks Api V1 Connect Webhooks Get",
                  "type": "array"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "List Webhooks",
        "tags": [
          "connect-webhooks"
        ]
      },
      "post": {
        "description": "Register a new webhook endpoint. Returns the signing secret once.",
        "operationId": "register_webhook_api_v1_connect_webhooks_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Register Webhook",
        "tags": [
          "connect-webhooks"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/connect/webhooks \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"url\": \"https://your-app.example.com/webhooks/efakturuj\",\n    \"events\": \"invoice.delivered,invoice.rejected,invoice.fs_acknowledged\",\n    \"description\": \"Production webhook\"\n  }'\n# 201 Created \u2014 response.secret is the plaintext signing secret,\n# returned ONCE. Store it now: the server only keeps sha256(secret)."
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk/api/v1',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\n\nfinal response = await dio.post('/connect/webhooks', data: {\n  'url': 'https://your-app.example.com/webhooks/efakturuj',\n  'events': 'invoice.delivered,invoice.rejected,invoice.fs_acknowledged',\n  'description': 'Production webhook',\n});\n// secret is shown ONCE \u2014 persist it now to verify HMAC signatures.\nfinal webhookId = response.data['id'] as String;\nfinal signingSecret = response.data['secret'] as String;"
          },
          {
            "label": "Python",
            "lang": "Python",
            "source": "import httpx\n\nr = httpx.post(\n    'https://api.efakturuj.sk/api/v1/connect/webhooks',\n    headers={'X-Api-Key': '<YOUR_API_KEY>'},\n    json={\n        'url': 'https://your-app.example.com/webhooks/efakturuj',\n        'events': 'invoice.delivered,invoice.rejected,invoice.fs_acknowledged',\n        'description': 'Production webhook',\n    },\n)\nr.raise_for_status()\nsubscription = r.json()\nwebhook_id = subscription['id']\n# Persist the plaintext secret now \u2014 it will not be shown again.\nsigning_secret = subscription['secret']"
          },
          {
            "label": "TypeScript",
            "lang": "JavaScript",
            "source": "const r = await fetch('https://api.efakturuj.sk/api/v1/connect/webhooks', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': '<YOUR_API_KEY>',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    url: 'https://your-app.example.com/webhooks/efakturuj',\n    events: 'invoice.delivered,invoice.rejected,invoice.fs_acknowledged',\n    description: 'Production webhook',\n  }),\n});\nif (!r.ok) throw new Error(`HTTP ${r.status}`);\nconst { id, secret } = await r.json();\n// secret is shown ONCE. Store it securely to verify HMAC signatures."
          },
          {
            "label": "PHP",
            "lang": "PHP",
            "source": "<?php\n$client = new GuzzleHttp\\Client([\n    'base_uri' => 'https://api.efakturuj.sk/api/v1/',\n    'headers' => ['X-Api-Key' => '<YOUR_API_KEY>'],\n]);\n$response = $client->post('connect/webhooks', [\n    'json' => [\n        'url' => 'https://your-app.example.com/webhooks/efakturuj',\n        'events' => 'invoice.delivered,invoice.rejected,invoice.fs_acknowledged',\n        'description' => 'Production webhook',\n    ],\n]);\n$subscription = json_decode($response->getBody(), true);\n$webhookId = $subscription['id'];\n// secret is shown ONCE \u2014 persist it now to verify HMAC signatures.\n$signingSecret = $subscription['secret'];"
          }
        ]
      }
    },
    "/api/v1/connect/webhooks/{webhook_id}": {
      "delete": {
        "description": "Deactivate a webhook endpoint.",
        "operationId": "delete_webhook_api_v1_connect_webhooks__webhook_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "webhook_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Webhook Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Delete Webhook",
        "tags": [
          "connect-webhooks"
        ]
      }
    },
    "/api/v1/connect/webhooks/{webhook_id}/deliveries": {
      "get": {
        "description": "List recent delivery attempts for a webhook endpoint.",
        "operationId": "list_deliveries_api_v1_connect_webhooks__webhook_id__deliveries_get",
        "parameters": [
          {
            "in": "path",
            "name": "webhook_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Webhook Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/WebhookDeliveryResponse"
                  },
                  "title": "Response List Deliveries Api V1 Connect Webhooks  Webhook Id  Deliveries Get",
                  "type": "array"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "List Deliveries",
        "tags": [
          "connect-webhooks"
        ]
      }
    },
    "/api/v1/connect/webhooks/{webhook_id}/test": {
      "post": {
        "description": "Send a test event to a webhook endpoint.",
        "operationId": "test_webhook_api_v1_connect_webhooks__webhook_id__test_post",
        "parameters": [
          {
            "in": "path",
            "name": "webhook_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Webhook Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Test Webhook",
        "tags": [
          "connect-webhooks"
        ]
      }
    },
    "/api/v1/customers": {
      "get": {
        "description": "List active customers in the caller's organisation, paginated.\n\nAvailable to any authenticated workspace member. By default, results\nare ordered alphabetically by `name`. Supplying `q` filters to\ncustomers whose `name` or `vat_id` matches the substring\n(case-insensitive). Supplying `sort` overrides the default ordering;\naccepts both `-field` (Stripe/GitHub style) and `field:desc` syntax.\nAllowed sort columns: `name`, `vat_id`, `created_at`, `updated_at`.\nUnknown columns are silently ignored. Returns the items plus\n`total`, `page`, and `page_size` so the UI can render pagination\ncontrols.",
        "operationId": "customers.list",
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 200,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Q"
            }
          },
          {
            "description": "Sort columns. Use `-name` or `name:desc` for descending. Allowed: name, vat_id, created_at, updated_at. Multi-column: `-created_at,name`.",
            "in": "query",
            "name": "sort",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 200,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Sort columns. Use `-name` or `name:desc` for descending. Allowed: name, vat_id, created_at, updated_at. Multi-column: `-created_at,name`.",
              "title": "Sort"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerListPaginated"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid pagination parameters."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "List customers",
        "tags": [
          "customers"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/customers \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/customers');"
          }
        ]
      },
      "post": {
        "description": "Create a new customer entry in the caller's organisation directory.\n\nRequires an `admin` or `accountant` role. Persists the customer's\nlegal identity (`name`, `vat_id`, `ico`), postal address,\noptional Peppol participant identifier, and contact details. The\n`(organisation_id, vat_id)` pair is unique \u2014 a duplicate VAT id\ntriggers a 409. Returns the freshly created `CustomerResponse`.",
        "operationId": "customers.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "A customer with the same VAT id already exists in this organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid customer payload."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Create a new customer",
        "tags": [
          "customers"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/customers \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"name\": \"Pr\u00edklad s.r.o.\",\n    \"vat_id\": \"SK1234567890\",\n    \"ico\": \"12345678\",\n    \"dic\": \"1234567890\",\n    \"street\": \"Hlavn\u00e1 12\",\n    \"city\": \"Bratislava\",\n    \"postal_code\": \"81101\",\n    \"country_code\": \"SK\",\n    \"peppol_id\": \"0210:12345678\",\n    \"email\": \"billing@priklad.sk\"\n  }'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk/api/v1',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\n\nfinal response = await dio.post('/customers', data: {\n  'name': 'Pr\u00edklad s.r.o.',\n  'vat_id': 'SK1234567890',\n  'ico': '12345678',\n  'dic': '1234567890',\n  'street': 'Hlavn\u00e1 12',\n  'city': 'Bratislava',\n  'postal_code': '81101',\n  'country_code': 'SK',\n  'peppol_id': '0210:12345678',\n  'email': 'billing@priklad.sk',\n});\nfinal customerId = response.data['id'] as String;"
          },
          {
            "label": "Python",
            "lang": "Python",
            "source": "import httpx\n\nr = httpx.post(\n    'https://api.efakturuj.sk/api/v1/customers',\n    headers={'X-Api-Key': '<YOUR_API_KEY>'},\n    json={\n        'name': 'Pr\u00edklad s.r.o.',\n        'vat_id': 'SK1234567890',\n        'ico': '12345678',\n        'dic': '1234567890',\n        'street': 'Hlavn\u00e1 12',\n        'city': 'Bratislava',\n        'postal_code': '81101',\n        'country_code': 'SK',\n        'peppol_id': '0210:12345678',\n        'email': 'billing@priklad.sk',\n    },\n)\nr.raise_for_status()\ncustomer_id = r.json()['id']"
          },
          {
            "label": "TypeScript",
            "lang": "JavaScript",
            "source": "const r = await fetch('https://api.efakturuj.sk/api/v1/customers', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': '<YOUR_API_KEY>',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    name: 'Pr\u00edklad s.r.o.',\n    vat_id: 'SK1234567890',\n    ico: '12345678',\n    dic: '1234567890',\n    street: 'Hlavn\u00e1 12',\n    city: 'Bratislava',\n    postal_code: '81101',\n    country_code: 'SK',\n    peppol_id: '0210:12345678',\n    email: 'billing@priklad.sk',\n  }),\n});\nif (!r.ok) throw new Error(`HTTP ${r.status}`);\nconst { id: customerId } = await r.json();"
          },
          {
            "label": "PHP",
            "lang": "PHP",
            "source": "<?php\n$client = new GuzzleHttp\\Client([\n    'base_uri' => 'https://api.efakturuj.sk/api/v1/',\n    'headers' => ['X-Api-Key' => '<YOUR_API_KEY>'],\n]);\n$response = $client->post('customers', [\n    'json' => [\n        'name' => 'Pr\u00edklad s.r.o.',\n        'vat_id' => 'SK1234567890',\n        'ico' => '12345678',\n        'dic' => '1234567890',\n        'street' => 'Hlavn\u00e1 12',\n        'city' => 'Bratislava',\n        'postal_code' => '81101',\n        'country_code' => 'SK',\n        'peppol_id' => '0210:12345678',\n        'email' => 'billing@priklad.sk',\n    ],\n]);\n$customer = json_decode($response->getBody(), true);\n$customerId = $customer['id'];"
          }
        ]
      }
    },
    "/api/v1/customers/search": {
      "get": {
        "description": "Type-ahead search for customers matching `q` in name or VAT id.\n\nAvailable to any authenticated workspace member. Returns up to\n10 active matches as a slim `CustomerSearchResult` payload\n(id, name, key identifiers) intended for invoice-form\nautocompletion. The full record can be fetched with\n`GET /customers/{id}`.",
        "operationId": "customers.search",
        "parameters": [
          {
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "maxLength": 200,
              "minLength": 1,
              "title": "Q",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/CustomerSearchResult"
                  },
                  "title": "Response Customers.Search",
                  "type": "array"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid search query."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Search customers by name, VAT id, or business id",
        "tags": [
          "customers"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/customers/search \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/customers/search');"
          }
        ]
      }
    },
    "/api/v1/customers/{customer_id}": {
      "delete": {
        "description": "Hard-delete a customer record from the directory.\n\nRequires an `admin` or `accountant` role. Any invoices that\nreference this customer have their `customer_id` foreign key\nnulled before the delete so historical invoices keep their own\nembedded buyer snapshot intact and the FK constraint is not\nviolated. Returns 204 No Content on success.",
        "operationId": "customers.delete",
        "parameters": [
          {
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Customer Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Customer not found in this organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Delete a customer",
        "tags": [
          "customers"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X DELETE https://api.efakturuj.sk/api/v1/customers/{customer_id} \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.delete('/api/v1/customers/{customer_id}');"
          }
        ]
      },
      "get": {
        "description": "Fetch a single customer record by id.\n\nAvailable to any authenticated workspace member. The lookup is\norganisation-scoped: a customer that belongs to a different\norganisation returns 404 (not 403) to avoid leaking existence.",
        "operationId": "customers.get",
        "parameters": [
          {
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Customer Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Customer not found in this organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Fetch one customer by id",
        "tags": [
          "customers"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/customers/{customer_id} \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/customers/{customer_id}');"
          }
        ]
      },
      "put": {
        "description": "Apply a partial update to a customer record.\n\nRequires an `admin` or `accountant` role. Only fields present in\nthe request body are touched (Pydantic `exclude_unset`). Existing\ninvoices retain their own embedded buyer snapshot, so editing a\ncustomer does not rewrite historical invoice data. Returns the\nupdated `CustomerResponse`.",
        "operationId": "customers.update",
        "parameters": [
          {
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Customer Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Customer not found in this organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid customer payload."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Update an existing customer",
        "tags": [
          "customers"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X PUT https://api.efakturuj.sk/api/v1/customers/{customer_id} \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.put('/api/v1/customers/{customer_id}', data: {...});"
          }
        ]
      }
    },
    "/api/v1/health": {
      "get": {
        "operationId": "health_check_api_v1_health_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Health Check",
        "tags": [
          "health"
        ]
      }
    },
    "/api/v1/invoices": {
      "get": {
        "description": "Page through invoices in the caller's organisation with optional filtering and sorting.\n\nRequires any authenticated workspace member. Supports free-text\nsearch (`q` matches invoice number, supplier, buyer), comma-\nseparated status filtering (`status=draft,validated`), date range\nfiltering on `issue_date` (`from_date` / `to_date`),\n`created_by` filtering, and sortable columns (e.g.\n`sort=-issue_date,total_gross`). Returns a paginated envelope\nwith summary rows (full invoice payload available via\n`GET /invoices/{id}`).",
        "operationId": "invoices.list",
        "parameters": [
          {
            "in": "query",
            "name": "page",
            "required": false,
            "schema": {
              "default": 1,
              "minimum": 1,
              "title": "Page",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "page_size",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "title": "Page Size",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 200,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Q"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "in": "query",
            "name": "from_date",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "From Date"
            }
          },
          {
            "in": "query",
            "name": "to_date",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "date",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "To Date"
            }
          },
          {
            "in": "query",
            "name": "created_by",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "format": "uuid",
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Created By"
            }
          },
          {
            "in": "query",
            "name": "sort",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 200,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Sort"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceListPaginated"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "List invoices",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/invoices \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/invoices');"
          }
        ]
      },
      "post": {
        "description": "Create a new invoice in DRAFT status under the caller's organisation/workspace.\n\nRequires an `admin` or `accountant` role. The endpoint enforces the\nplan's monthly invoice quota (paid plans allow overage and bill at\nmonth-end via Stripe metered billing; free plans hard-block with\n402). When `invoice_number` is omitted the service auto-generates\none from the workspace numbering pattern. A duplicate\n`invoice_number` for the caller's organisation returns\n`409 invoice_number_conflict` (uniqueness is enforced at the\ndatabase level \u2014 the same number is allowed in different orgs). On\nsuccess it persists the invoice + lines, writes a `created` audit\nlog entry and increments the monthly usage counter, then returns\nthe freshly created invoice.",
        "operationId": "invoices.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "402": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Monthly invoice quota exceeded on a non-overage plan."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Duplicate invoice_number for this organisation \u2014 pick another number or call GET /invoices/numbering/next."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid invoice payload."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Create a draft invoice",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/invoices \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"invoice_number\": \"2026-001\",\n    \"issue_date\": \"2026-05-06\",\n    \"due_date\": \"2026-06-05\",\n    \"currency_code\": \"EUR\",\n    \"supplier\": {\n      \"name\": \"Va\u0161a firma s.r.o.\",\n      \"vat_id\": \"SK9876543210\",\n      \"ico\": \"87654321\",\n      \"street\": \"Mlynsk\u00e1 5\",\n      \"city\": \"Bratislava\",\n      \"postal_code\": \"81109\",\n      \"country_code\": \"SK\",\n      \"peppol_id\": \"0210:87654321\"\n    },\n    \"supplier_iban\": \"SK1234567890123456789012\",\n    \"buyer\": {\n      \"name\": \"Pr\u00edklad s.r.o.\",\n      \"vat_id\": \"SK1234567890\",\n      \"ico\": \"12345678\",\n      \"street\": \"Hlavn\u00e1 12\",\n      \"city\": \"Bratislava\",\n      \"postal_code\": \"81101\",\n      \"country_code\": \"SK\",\n      \"peppol_id\": \"0210:12345678\"\n    },\n    \"lines\": [\n      {\n        \"line_number\": 1,\n        \"item_name\": \"Konzulta\u010dn\u00e9 slu\u017eby \u2014 apr\u00edl 2026\",\n        \"quantity\": \"10\",\n        \"unit_code\": \"HUR\",\n        \"unit_price\": \"100.00\",\n        \"vat_rate\": \"23.00\",\n        \"vat_category_code\": \"S\"\n      }\n    ],\n    \"payment_means_code\": \"30\",\n    \"variable_symbol\": \"2026001\"\n  }'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk/api/v1',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\n\nfinal response = await dio.post('/invoices', data: {\n  'invoice_number': '2026-001',\n  'issue_date': '2026-05-06',\n  'due_date': '2026-06-05',\n  'currency_code': 'EUR',\n  'supplier': {\n    'name': 'Va\u0161a firma s.r.o.',\n    'vat_id': 'SK9876543210',\n    'ico': '87654321',\n    'street': 'Mlynsk\u00e1 5',\n    'city': 'Bratislava',\n    'postal_code': '81109',\n    'country_code': 'SK',\n    'peppol_id': '0210:87654321',\n  },\n  'supplier_iban': 'SK1234567890123456789012',\n  'buyer': {\n    'name': 'Pr\u00edklad s.r.o.',\n    'vat_id': 'SK1234567890',\n    'ico': '12345678',\n    'street': 'Hlavn\u00e1 12',\n    'city': 'Bratislava',\n    'postal_code': '81101',\n    'country_code': 'SK',\n    'peppol_id': '0210:12345678',\n  },\n  'lines': [\n    {\n      'line_number': 1,\n      'item_name': 'Konzulta\u010dn\u00e9 slu\u017eby \u2014 apr\u00edl 2026',\n      'quantity': '10',\n      'unit_code': 'HUR',\n      'unit_price': '100.00',\n      'vat_rate': '23.00',\n      'vat_category_code': 'S',\n    },\n  ],\n  'payment_means_code': '30',\n  'variable_symbol': '2026001',\n});\nfinal invoiceId = response.data['id'] as String;"
          },
          {
            "label": "Python",
            "lang": "Python",
            "source": "import httpx\n\nr = httpx.post(\n    'https://api.efakturuj.sk/api/v1/invoices',\n    headers={'X-Api-Key': '<YOUR_API_KEY>'},\n    json={\n        'invoice_number': '2026-001',\n        'issue_date': '2026-05-06',\n        'due_date': '2026-06-05',\n        'currency_code': 'EUR',\n        'supplier': {\n            'name': 'Va\u0161a firma s.r.o.',\n            'vat_id': 'SK9876543210',\n            'ico': '87654321',\n            'street': 'Mlynsk\u00e1 5',\n            'city': 'Bratislava',\n            'postal_code': '81109',\n            'country_code': 'SK',\n            'peppol_id': '0210:87654321',\n        },\n        'supplier_iban': 'SK1234567890123456789012',\n        'buyer': {\n            'name': 'Pr\u00edklad s.r.o.',\n            'vat_id': 'SK1234567890',\n            'ico': '12345678',\n            'street': 'Hlavn\u00e1 12',\n            'city': 'Bratislava',\n            'postal_code': '81101',\n            'country_code': 'SK',\n            'peppol_id': '0210:12345678',\n        },\n        'lines': [\n            {\n                'line_number': 1,\n                'item_name': 'Konzulta\u010dn\u00e9 slu\u017eby \u2014 apr\u00edl 2026',\n                'quantity': '10',\n                'unit_code': 'HUR',\n                'unit_price': '100.00',\n                'vat_rate': '23.00',\n                'vat_category_code': 'S',\n            }\n        ],\n        'payment_means_code': '30',\n        'variable_symbol': '2026001',\n    },\n)\nr.raise_for_status()\ninvoice_id = r.json()['id']"
          },
          {
            "label": "TypeScript",
            "lang": "JavaScript",
            "source": "const r = await fetch('https://api.efakturuj.sk/api/v1/invoices', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': '<YOUR_API_KEY>',\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    invoice_number: '2026-001',\n    issue_date: '2026-05-06',\n    due_date: '2026-06-05',\n    currency_code: 'EUR',\n    supplier: {\n      name: 'Va\u0161a firma s.r.o.',\n      vat_id: 'SK9876543210',\n      ico: '87654321',\n      street: 'Mlynsk\u00e1 5',\n      city: 'Bratislava',\n      postal_code: '81109',\n      country_code: 'SK',\n      peppol_id: '0210:87654321',\n    },\n    supplier_iban: 'SK1234567890123456789012',\n    buyer: {\n      name: 'Pr\u00edklad s.r.o.',\n      vat_id: 'SK1234567890',\n      ico: '12345678',\n      street: 'Hlavn\u00e1 12',\n      city: 'Bratislava',\n      postal_code: '81101',\n      country_code: 'SK',\n      peppol_id: '0210:12345678',\n    },\n    lines: [\n      {\n        line_number: 1,\n        item_name: 'Konzulta\u010dn\u00e9 slu\u017eby \u2014 apr\u00edl 2026',\n        quantity: '10',\n        unit_code: 'HUR',\n        unit_price: '100.00',\n        vat_rate: '23.00',\n        vat_category_code: 'S',\n      },\n    ],\n    payment_means_code: '30',\n    variable_symbol: '2026001',\n  }),\n});\nif (!r.ok) throw new Error(`HTTP ${r.status}`);\nconst { id: invoiceId } = await r.json();"
          },
          {
            "label": "PHP",
            "lang": "PHP",
            "source": "<?php\n$client = new GuzzleHttp\\Client([\n    'base_uri' => 'https://api.efakturuj.sk/api/v1/',\n    'headers' => ['X-Api-Key' => '<YOUR_API_KEY>'],\n]);\n$response = $client->post('invoices', [\n    'json' => [\n        'invoice_number' => '2026-001',\n        'issue_date' => '2026-05-06',\n        'due_date' => '2026-06-05',\n        'currency_code' => 'EUR',\n        'supplier' => [\n            'name' => 'Va\u0161a firma s.r.o.',\n            'vat_id' => 'SK9876543210',\n            'ico' => '87654321',\n            'street' => 'Mlynsk\u00e1 5',\n            'city' => 'Bratislava',\n            'postal_code' => '81109',\n            'country_code' => 'SK',\n            'peppol_id' => '0210:87654321',\n        ],\n        'supplier_iban' => 'SK1234567890123456789012',\n        'buyer' => [\n            'name' => 'Pr\u00edklad s.r.o.',\n            'vat_id' => 'SK1234567890',\n            'ico' => '12345678',\n            'street' => 'Hlavn\u00e1 12',\n            'city' => 'Bratislava',\n            'postal_code' => '81101',\n            'country_code' => 'SK',\n            'peppol_id' => '0210:12345678',\n        ],\n        'lines' => [\n            [\n                'line_number' => 1,\n                'item_name' => 'Konzulta\u010dn\u00e9 slu\u017eby \u2014 apr\u00edl 2026',\n                'quantity' => '10',\n                'unit_code' => 'HUR',\n                'unit_price' => '100.00',\n                'vat_rate' => '23.00',\n                'vat_category_code' => 'S',\n            ],\n        ],\n        'payment_means_code' => '30',\n        'variable_symbol' => '2026001',\n    ],\n]);\n$invoice = json_decode($response->getBody(), true);\n$invoiceId = $invoice['id'];"
          }
        ]
      }
    },
    "/api/v1/invoices/bulk-import": {
      "post": {
        "description": "Accept a multipart CSV upload and queue a bulk-import worker (asynchronous).\n\nRequires the `has_bulk_import` plan feature. Expects a multipart\nbody with a `file` field containing the CSV (template available\nvia `GET /invoices/bulk-import/template`) and an optional\n`strict` flag (default `true`) controlling whether the worker\naborts on the first row error or imports valid rows and reports\nthe rest. The endpoint generates a job UUID, writes a\n`bulk_import_started` audit entry, and dispatches the\n`process_bulk_import` Celery task. Returns **202 Accepted**\nwith the job id \u2014 poll status via\n`GET /invoices/bulk-import/{job_id}/status`.",
        "operationId": "invoices.bulk_import",
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkImportJobResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "No file uploaded or the uploaded file is empty."
          },
          "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": "Plan does not include the bulk-import feature."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Queue a bulk-import job from a CSV/JSON file",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/invoices/bulk-import \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/invoices/bulk-import');"
          }
        ]
      }
    },
    "/api/v1/invoices/bulk-import/template": {
      "get": {
        "description": "Return an empty CSV template with the column headers required by `POST /bulk-import`.\n\nRequires any authenticated workspace member. The body is the raw\nCSV (no JSON envelope) served as `text/csv` with a\n`Content-Disposition: attachment; filename=\"efakturuj-import-template.csv\"`\nheader. The call has no side effects.",
        "operationId": "invoices.bulk_import_template",
        "responses": {
          "200": {
            "content": {
              "text/csv": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "Empty CSV file with the column headers expected by POST /bulk-import."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Download the bulk-import CSV template",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/invoices/bulk-import/template \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/invoices/bulk-import/template');"
          }
        ]
      }
    },
    "/api/v1/invoices/bulk-import/{job_id}/status": {
      "get": {
        "description": "Poll the status of a previously-queued bulk-import job.\n\nRequires any authenticated workspace member. Reads the job\nsnapshot from Redis under the `bulk_import:{job_id}` key (TTL\n1h). While the worker is still running it returns\n`{status: \"processing\"}`; once finished it returns the final\n`completed` or `failed` shape with row counts and any\nper-row errors. Job ids are not validated against the caller's\norganisation today \u2014 treat job ids as opaque secrets.",
        "operationId": "invoices.bulk_import_status",
        "parameters": [
          {
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "title": "Job Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkImportStatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Check the status of a bulk-import job",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/invoices/bulk-import/{job_id}/status \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/invoices/bulk-import/{job_id}/status');"
          }
        ]
      }
    },
    "/api/v1/invoices/export/csv": {
      "get": {
        "description": "Export the caller's invoices (up to 10,000 rows) as a single CSV download.\n\nRequires the `has_csv_export` plan feature (Starter+). Streams a\nCSV body with `Content-Disposition: attachment; filename=\"invoices.csv\"`.\nThe export is unfiltered and unsorted \u2014 for a paginated /\nfiltered view use `GET /invoices`. Intended for accountants\nimporting into bookkeeping software.",
        "operationId": "invoices.export_csv",
        "responses": {
          "200": {
            "content": {
              "text/csv": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "All invoices in the caller's organisation, serialised as CSV."
          },
          "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": "Plan does not include the CSV export feature."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Export invoices as CSV",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/invoices/export/csv \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/invoices/export/csv');"
          }
        ]
      }
    },
    "/api/v1/invoices/numbering/next": {
      "get": {
        "description": "Preview the next invoice number under the workspace's numbering pattern.\n\nRequires any authenticated workspace member. Loads the\norganisation's MongoDB-backed numbering config (`pattern` +\n`seq_padding`) and asks the numbering service to render the next\nsequential number \u2014 useful for showing the user what number their\nnext invoice will get without actually consuming it. Calling\n`POST /invoices` with no `invoice_number` reserves and consumes\nthe number atomically.",
        "operationId": "invoices.next_number",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NextNumberResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Reserve the next invoice number",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/invoices/numbering/next \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/invoices/numbering/next');"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}": {
      "delete": {
        "description": "Permanently delete an unsent invoice (only DRAFT or VALIDATED are deletable).\n\nRequires `admin` or `accountant`. Sent / queued / delivered /\nvoided invoices cannot be deleted \u2014 those return 409, since\ndeleting them would break the regulatory audit trail (use\n`POST /invoices/{id}/void` to issue a credit note instead). On\nsuccess the invoice + line items are removed and a `deleted`\naudit log entry is written. Returns **204 No Content**.",
        "operationId": "invoices.delete",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice is not in a deletable status (must be draft or validated)."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Delete a draft invoice",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X DELETE https://api.efakturuj.sk/api/v1/invoices/{invoice_id} \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.delete('/api/v1/invoices/{invoice_id}');"
          }
        ]
      },
      "get": {
        "description": "Return the full invoice (header + line items) for the given id.\n\nRequires any authenticated workspace member. The service scopes\naccess to the caller's organisation \u2014 fetching another tenant's\ninvoice returns 404 (not 403) to avoid leaking the existence of\nforeign records. Returns the same `InvoiceResponse` shape as\n`POST /invoices` and `PUT /invoices/{id}`.",
        "operationId": "invoices.get",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Fetch one invoice by id",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/invoices/{invoice_id} \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/invoices/{invoice_id}');"
          }
        ]
      },
      "put": {
        "description": "Replace the header and line items of an editable invoice with the supplied payload.\n\nRequires `admin` or `accountant`. Only invoices in editable\nstatuses (DRAFT / VALIDATED) can be updated \u2014 attempts on sent or\nvoided invoices return 409. The service performs a full replace\n(line items are deleted and re-created), recalculates totals, and\nwrites an `updated` audit log entry. Returns the refreshed invoice.",
        "operationId": "invoices.update",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice is no longer in a status that allows editing (e.g. already sent), or the updated invoice_number conflicts with an existing invoice in this organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid invoice payload."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Update a draft invoice",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X PUT https://api.efakturuj.sk/api/v1/invoices/{invoice_id} \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.put('/api/v1/invoices/{invoice_id}', data: {...});"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/approval": {
      "get": {
        "description": "Return the current approval record for an invoice (or null if none exists).\n\nRequires any authenticated workspace member. Useful for UI badges\nthat show whether an invoice is pending approval, who requested\nit, who reviewed it, and the outcome / rejection reason. The\n`approval` field is `null` when no `request-approval` call has\never been made on this invoice; otherwise it carries the latest\n`InvoiceApproval` snapshot.",
        "operationId": "invoices.get_approval",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApprovalStateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Fetch the approval state of an invoice",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/approval \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/invoices/{invoice_id}/approval');"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/approve": {
      "post": {
        "description": "Approve an invoice that was previously submitted via `POST /invoices/{id}/request-approval`.\n\nRequires both the `admin`/`approver` role *and* the\n`has_approval_workflow` plan feature \u2014 missing either returns 403.\nMarks the latest `InvoiceApproval` as APPROVED, stamps the\nreviewer + reviewed-at, and writes an `approval_granted` audit\nlog entry. Returns the approval id and final status.",
        "operationId": "invoices.approve",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApprovalActionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "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": "Caller lacks admin/approver role or plan lacks the approval feature."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "No pending approval exists for this invoice."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Approve a pending-approval invoice",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/approve \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/invoices/{invoice_id}/approve');"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/convert": {
      "post": {
        "description": "Promote a quotation or proforma document into a regular DRAFT invoice.\n\nRequires `admin` or `accountant`. The source document is left\nuntouched; a brand-new invoice (type 380) is created with the\nsame buyer / supplier / line items, a freshly-reserved invoice\nnumber from the workspace numbering pattern, and a link back to\nthe source via the audit log entry's `new_invoice_id` detail.\nCalling on a non-quote / non-proforma document returns 409.\nReturns the freshly created invoice as `InvoiceResponse`.",
        "operationId": "invoices.convert",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Source document does not exist or belongs to another organisation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Source document is not a convertible type (must be quotation or proforma)."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Convert a quote/proforma into an invoice",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/convert \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/invoices/{invoice_id}/convert');"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/mark-approved": {
      "post": {
        "description": "Self-approve an invoice without going through the team-approval workflow.\n\nRequires `admin` or `accountant`. Designed for solo users who\nissue and send invoices themselves on plans that don't enable\nthe multi-step approval feature. Only invoices in DRAFT or\nVALIDATED can be self-approved \u2014 calling on an already-approved,\nqueued, or sent invoice returns 409. On success the invoice\ntransitions to APPROVED and a `approval_granted` audit log entry\nis written with `channel: manual_self`.",
        "operationId": "invoices.mark_approved",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusTransitionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice is not in DRAFT or VALIDATED \u2014 cannot be self-approved."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Mark a pending-approval invoice approved",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/mark-approved \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/invoices/{invoice_id}/mark-approved');"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/mark-sent": {
      "post": {
        "description": "Manually mark an invoice as DELIVERED without routing through Peppol or FS.\n\nRequires `admin` or `accountant`. Intended for the pre-2027\nworkflow where Slovak B2B e-invoicing is optional and users still\ndeliver invoices by email / PDF / paper. The endpoint performs no\nUBL generation, no AP transmission, and no FS submission \u2014 it\njust flips the status to DELIVERED and writes a `sent_peppol`\naudit log entry with `channel: manual` so the bookkeeping trail\nis preserved.",
        "operationId": "invoices.mark_sent",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusTransitionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice is not in DRAFT, VALIDATED, or APPROVED."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Manually mark an invoice as sent",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/mark-sent \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/invoices/{invoice_id}/mark-sent');"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/pdf": {
      "get": {
        "description": "Render the invoice as a downloadable PDF using the organisation's design settings.\n\nRequires the `has_pdf_export` plan feature (Starter+). Generates\nthe PDF on-the-fly using the MongoDB-backed design settings\n(logo, colours, signature block) and serves it as\n`application/pdf` with a `Content-Disposition: attachment`\nheader naming the file after the invoice number. For an inline\nbrowser preview that doesn't trigger a download, use\n`GET /invoices/{id}/preview`.",
        "operationId": "invoices.get_pdf",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/pdf": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "PDF rendering of the invoice (download)."
          },
          "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": "Plan does not include the PDF export feature."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Download the invoice as PDF",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/pdf \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/invoices/{invoice_id}/pdf');"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/preview": {
      "get": {
        "description": "Render the invoice as a PDF for inline browser preview (no Content-Disposition: attachment).\n\nRequires any authenticated workspace member. Generates the PDF\non-the-fly using the organisation's MongoDB-backed design\nsettings (logo, colours, signature block). The response uses\n`Content-Disposition: inline` so browsers display the PDF in\na viewer rather than triggering a download. For an attachment-\nstyle download see `GET /invoices/{id}/pdf`. The call has no\nside effects.",
        "operationId": "invoices.preview",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/pdf": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "Inline PDF preview of the invoice (intended to render in a browser)."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Preview the invoice as PDF/HTML",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/preview \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/invoices/{invoice_id}/preview');"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/reject": {
      "post": {
        "description": "Reject a pending approval request with a mandatory free-text reason.\n\nRequires both the `admin`/`approver` role *and* the\n`has_approval_workflow` plan feature \u2014 missing either returns 403.\nThe reason is persisted on the `InvoiceApproval` row, the\ninvoice's approval moves to REJECTED, and an\n`approval_rejected` audit log entry is written that includes the\nreason for compliance trail purposes. Returns the approval id,\nfinal status, and echoed reason.",
        "operationId": "invoices.reject",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RejectBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApprovalActionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "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": "Caller lacks admin/approver role or plan lacks the approval feature."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "No pending approval exists for this invoice."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Reject a pending-approval invoice",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/reject \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/invoices/{invoice_id}/reject', data: {...});"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/request-approval": {
      "post": {
        "description": "Open a pending approval request on an invoice so an approver can review it.\n\nRequires the `has_approval_workflow` feature flag (Team plan and\nabove). The endpoint creates an `InvoiceApproval` record in\nPENDING status linked to the requesting user, and writes an\n`approval_requested` audit log entry. Approvers can then act via\n`POST /invoices/{id}/approve` or `POST /invoices/{id}/reject`.\nReturns the new approval id and status.",
        "operationId": "invoices.request_approval",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApprovalActionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "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": "Plan does not include the approval workflow feature."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Approval already requested or invoice is in an incompatible status."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Submit an invoice for approval",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/request-approval \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/invoices/{invoice_id}/request-approval');"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/send": {
      "post": {
        "description": "Validate the invoice and queue it for delivery via Peppol + Slovak FS (asynchronous).\n\nRequires `admin` or `accountant`. Only invoices in DRAFT,\nVALIDATED, or APPROVED status may be sent \u2014 other statuses return\n409. The endpoint runs the business-rule validator synchronously\nand returns 422 if it fails (so the caller can fix errors before\nqueuing). On success it transitions the invoice to QUEUED, writes\na `sent_peppol` audit log entry with PENDING result, and dispatches\ntwo Celery tasks (`send_invoice_via_peppol`, `send_fs_copy`) onto\nthe `critical` queue. Returns **202 Accepted** with the new status\n\u2014 delivery confirmation arrives later via webhooks / status polling.",
        "operationId": "invoices.send",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice is not in a sendable status (must be draft, validated, or approved)."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice failed business-rule validation \u2014 fix errors before sending."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Send the invoice via Peppol + FS",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST \\\n  https://api.efakturuj.sk/api/v1/invoices/<invoice-uuid>/send \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'\n# 202 Accepted \u2014 invoice is queued for Peppol + FS delivery.\n# Track final delivery via webhooks (invoice.delivered, invoice.rejected)\n# or by polling GET /invoices/{invoice_id}."
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk/api/v1',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\n\nfinal response = await dio.post('/invoices/$invoiceId/send');\n// 202 Accepted \u2014 response.data['status'] == 'queued'.\n// Subscribe a webhook to invoice.delivered / invoice.rejected\n// to receive the final outcome."
          },
          {
            "label": "Python",
            "lang": "Python",
            "source": "import httpx\n\nr = httpx.post(\n    f'https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/send',\n    headers={'X-Api-Key': '<YOUR_API_KEY>'},\n)\nr.raise_for_status()  # 202 Accepted\nprint(r.json())\n# {'invoice_id': '...', 'status': 'queued',\n#  'message': 'Invoice queued for delivery'}"
          },
          {
            "label": "TypeScript",
            "lang": "JavaScript",
            "source": "const r = await fetch(\n  `https://api.efakturuj.sk/api/v1/invoices/${invoiceId}/send`,\n  {\n    method: 'POST',\n    headers: { 'X-Api-Key': '<YOUR_API_KEY>' },\n  },\n);\nif (r.status !== 202) throw new Error(`HTTP ${r.status}`);\nconst { invoice_id, status } = await r.json();\n// status === 'queued' \u2014 listen for invoice.delivered webhook\n// for the final outcome."
          },
          {
            "label": "PHP",
            "lang": "PHP",
            "source": "<?php\n$client = new GuzzleHttp\\Client([\n    'base_uri' => 'https://api.efakturuj.sk/api/v1/',\n    'headers' => ['X-Api-Key' => '<YOUR_API_KEY>'],\n]);\n$response = $client->post('invoices/' . $invoiceId . '/send');\n// 202 Accepted \u2014 body: {invoice_id, status: 'queued', message}.\n$body = json_decode($response->getBody(), true);"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/ubl": {
      "get": {
        "description": "Return the invoice rendered as a Peppol BIS Billing 3.0 / UBL 2.1 XML document.\n\nRequires any authenticated workspace member. The response body is\nthe raw XML payload (not JSON-wrapped) with a\n`Content-Disposition: attachment` header so browsers download it\nusing the invoice number as the filename. The XML is generated\non-the-fly from the current invoice state \u2014 it is not validated\nhere (use `POST /invoices/{id}/validate` for that) and the call\nhas no side effects.",
        "operationId": "invoices.get_ubl",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/xml": {
                "schema": {
                  "format": "binary",
                  "type": "string"
                }
              }
            },
            "description": "UBL 2.1 XML document."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Download the invoice as UBL 2.1 XML",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/ubl \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/invoices/{invoice_id}/ubl');"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/validate": {
      "post": {
        "description": "Run the business-rule + UBL validation pipeline on a stored invoice.\n\nRequires any authenticated workspace member. Always runs the\nPython business-rule validator (mandatory fields, line totals,\nSlovak VAT rules, ZZZ rounding). When XSD/Schematron files are\ninstalled it also generates UBL 2.1 XML and runs it through the\nUBL XSD plus Peppol BIS3 + Slovak v1.3 Schematron checks. If the\ninvoice is in DRAFT and every check passes, it is promoted to\nVALIDATED so the UI badge reflects the result. The endpoint never\nsends the invoice \u2014 for delivery use `POST /invoices/{id}/send`.",
        "operationId": "invoices.validate",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationResult"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Validate the invoice's UBL XML",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/validate \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/invoices/{invoice_id}/validate');"
          }
        ]
      }
    },
    "/api/v1/invoices/{invoice_id}/void": {
      "post": {
        "description": "Void a sent/delivered invoice by issuing a corresponding credit note.\n\nRequires `admin` or `accountant`. The original invoice's audit\ntrail is preserved (never deleted) \u2014 instead a new invoice of\ntype 381 (credit note) is created mirroring the lines with\ninverted amounts and linked back to the original via\n`source_invoice_id`. The original invoice's `voided_by_id` and\n`voided_at` columns are also stamped. A `voided` audit log entry\nis written referencing the new credit note id. Returns the\nfreshly created credit note as `InvoiceResponse`.",
        "operationId": "invoices.void",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice does not exist or belongs to another organisation."
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice cannot be voided (e.g. already voided, or status is wrong), or the generated credit-note number conflicts with an existing invoice."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Issue a credit note voiding this invoice",
        "tags": [
          "invoices"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/invoices/{invoice_id}/void \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/invoices/{invoice_id}/void');"
          }
        ]
      }
    },
    "/api/v1/lookup/companies": {
      "get": {
        "description": "Fuzzy-search the Slovak business registry for companies matching `q`.\n\nAvailable to any authenticated workspace member. The service\nqueries the public RPO/registeruz indexes and returns up to 10\n`CompanySuggestion` hits (I\u010cO, legal name, optional address,\n`terminated` flag) suitable for the invoice-form autocomplete.\nA pure 8-digit I\u010cO in `q` is treated as an exact lookup; any\nother string runs as a fuzzy name search. Results are cached in\nRedis for 24h.",
        "operationId": "lookup.companies",
        "parameters": [
          {
            "description": "Free text \u2014 company name or 8-digit I\u010cO",
            "in": "query",
            "name": "q",
            "required": true,
            "schema": {
              "description": "Free text \u2014 company name or 8-digit I\u010cO",
              "maxLength": 100,
              "minLength": 2,
              "title": "Q",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanySearchResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Query string is missing or fails the 2..100 char length check."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Search Slovak companies by name",
        "tags": [
          "lookup"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/lookup/companies \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/lookup/companies');"
          }
        ]
      }
    },
    "/api/v1/lookup/company": {
      "get": {
        "description": "Resolve one Slovak company by its 8-digit I\u010cO across public registries.\n\nAvailable to any authenticated workspace member. The service\ncontacts RPO, registeruz, Finstat, and VIES in parallel and\nmerges whatever data each source returns into a single\n`CompanyLookupResponse` (legal name, addresses, DI\u010c/I\u010c DPH,\nlegal form, VAT-registration flag). The `sources` field on the\nresponse lists which registries actually contributed. Returns\n404 if no source recognises the I\u010cO, and 502 if every source is\nunreachable. Results are cached in Redis for 24h.",
        "operationId": "lookup.company",
        "parameters": [
          {
            "description": "8-digit Slovak I\u010cO",
            "in": "query",
            "name": "ico",
            "required": true,
            "schema": {
              "description": "8-digit Slovak I\u010cO",
              "maxLength": 8,
              "minLength": 8,
              "pattern": "^\\d{8}$",
              "title": "Ico",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyLookupResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "No company is registered under the supplied I\u010cO."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "I\u010cO is not exactly 8 digits."
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "All upstream registries (RPO, registeruz, Finstat, VIES) failed."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Lookup a Slovak company by I\u010cO (business id)",
        "tags": [
          "lookup"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/lookup/company \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/lookup/company');"
          }
        ]
      }
    },
    "/api/v1/oauth2/clients": {
      "post": {
        "description": "Provision a new OAuth2 client for the caller's organisation.\n\nRequires the `admin` role. Generates an opaque `client_id`\nprefixed with `efk_client_` and a high-entropy `client_secret`\nprefixed with `efk_secret_`, persists only the SHA-256 hash of\nthe secret, and returns both values together exactly once via\n`ClientCreateResponse`. Subsequent reads of the client only\nexpose the `client_id`, not the secret \u2014 store the secret\nimmediately. The client is created `is_active=True` with the\nrequested scopes and may be exchanged for access tokens at\n`POST /oauth2/token`.",
        "operationId": "oauth2.create_client",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClientCreateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "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": "Caller does not hold the `admin` role."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid client metadata (name too long, malformed scopes)."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Register an OAuth2 client application",
        "tags": [
          "oauth2"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/oauth2/clients \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/oauth2/clients', data: {...});"
          }
        ]
      }
    },
    "/api/v1/oauth2/token": {
      "post": {
        "description": "Exchange OAuth2 client credentials for a short-lived JWT access token.\n\nImplements the RFC 6749 \u00a74.4 client-credentials grant \u2014 the only\ngrant type this endpoint supports. The caller posts its\n`client_id` and `client_secret`; on success the response is an\n`OAuth2TokenResponse` containing an RS256-signed JWT valid for\n900 seconds (15 minutes) with `token_type: Bearer`. The token\nembeds the originating organisation, the registered scopes, and\nthe client's plan tier so downstream routes can authorise without\nextra database reads. No refresh tokens are issued \u2014 clients\nre-authenticate by calling `/token` again with their static\ncredentials. Authorization, password, and refresh-token grants\nare not supported and return 400.",
        "operationId": "oauth2.token",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TokenRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuth2TokenResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unsupported `grant_type` \u2014 only `client_credentials` is accepted."
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unknown client, wrong client_secret, or client has been deactivated."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Token request body is malformed."
          }
        },
        "summary": "OAuth2 token endpoint (RFC 6749)",
        "tags": [
          "oauth2"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/oauth2/token \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/oauth2/token', data: {...});"
          }
        ]
      }
    },
    "/api/v1/organisations/me": {
      "get": {
        "description": "Return details for the authenticated user's organisation.",
        "operationId": "get_current_organisation_api_v1_organisations_me_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganisationResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Get Current Organisation",
        "tags": [
          "organisations"
        ]
      },
      "put": {
        "description": "Update the authenticated user's organisation (admin only).\n\nOnly fields that are explicitly set (not None) are updated.\nAt least one field must be provided.\nIBAN values are encrypted before storage (AES-256-GCM).",
        "operationId": "update_current_organisation_api_v1_organisations_me_put",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrganisationUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganisationResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Update Current Organisation",
        "tags": [
          "organisations"
        ]
      }
    },
    "/api/v1/organisations/me/usage": {
      "get": {
        "description": "Return monthly invoice usage for the authenticated organisation.",
        "operationId": "get_current_usage_api_v1_organisations_me_usage_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganisationUsageResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Get Current Usage",
        "tags": [
          "organisations"
        ]
      }
    },
    "/api/v1/payments": {
      "post": {
        "description": "Record a single payment against an invoice.\n\nRequires an `admin` or `accountant` role. Persists the payment\n(amount, currency, date, method, reference, optional note) with\nthe caller as `recorded_by`, then recomputes the parent invoice's\n`payment_status` based on the new running total of payments\n(`UNPAID`, `PARTIALLY_PAID`, `PAID`, or `OVERPAID`). Partial\npayments and overpayments are both allowed. Returns the created\n`PaymentResponse`.",
        "operationId": "payments.create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PaymentCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid payment payload."
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Record a payment against an invoice",
        "tags": [
          "payments"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/payments \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/payments', data: {...});"
          }
        ]
      }
    },
    "/api/v1/payments/invoice/{invoice_id}": {
      "get": {
        "description": "Return every payment recorded against a given invoice.\n\nAvailable to any authenticated workspace member. Results are\nordered newest-first by `payment_date`, then `created_at` to\nbreak ties. The query is organisation-scoped \u2014 payments on\ninvoices that belong to a different organisation are silently\nomitted, so an unknown id returns an empty list rather than 404.",
        "operationId": "payments.list_for_invoice",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/PaymentResponse"
                  },
                  "title": "Response Payments.List For Invoice",
                  "type": "array"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "List all payments recorded against an invoice",
        "tags": [
          "payments"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/payments/invoice/{invoice_id} \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/payments/invoice/{invoice_id}');"
          }
        ]
      }
    },
    "/api/v1/payments/invoice/{invoice_id}/mark-paid": {
      "post": {
        "description": "Record a single payment for the exact remaining balance on an invoice.\n\nRequires an `admin` or `accountant` role. Convenience over\n`POST /payments` for the common \"mark invoice paid\" UI button:\nthe service computes `remaining = total_gross - sum(payments)`\nand inserts one bank-transfer payment for that amount dated\ntoday, with reference `mark-paid` and the caller as\n`recorded_by`. The invoice's `payment_status` flips to `PAID`.\nReturns 404 when the invoice does not exist or is already fully\npaid (i.e. `remaining <= 0`).",
        "operationId": "payments.mark_paid",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice not found, or already fully paid (nothing left to settle)."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Record a single payment that fully settles the invoice",
        "tags": [
          "payments"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/payments/invoice/{invoice_id}/mark-paid \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/payments/invoice/{invoice_id}/mark-paid');"
          }
        ]
      }
    },
    "/api/v1/payments/invoice/{invoice_id}/summary": {
      "get": {
        "description": "Return a settlement summary for an invoice: gross total, paid, remaining, status, payments.\n\nAvailable to any authenticated workspace member. Computes\n`total_paid` by summing every recorded `Payment.amount` for the\ninvoice and derives `remaining = total_gross - total_paid`. The\nresponse also bundles the full payment list so the UI can render\na single panel without a follow-up call. Returns 404 if the\ninvoice does not exist in the caller's organisation.",
        "operationId": "payments.invoice_summary",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoicePaymentSummary"
                }
              }
            },
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invoice not found in this organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Get the running total of payments + remaining balance for an invoice",
        "tags": [
          "payments"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X GET https://api.efakturuj.sk/api/v1/payments/invoice/{invoice_id}/summary \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.get('/api/v1/payments/invoice/{invoice_id}/summary');"
          }
        ]
      }
    },
    "/api/v1/payments/{payment_id}": {
      "delete": {
        "description": "Delete a payment record and recompute the invoice's payment status.\n\nRequires an `admin` or `accountant` role. Hard-deletes the row\n(payments are not append-only) and then recomputes the parent\ninvoice's `payment_status` from the remaining payments \u2014 for\nexample, removing a payment that fully settled an invoice flips\nthe status back to `PARTIALLY_PAID` or `UNPAID`. Returns 204\nNo Content on success.",
        "operationId": "payments.delete",
        "parameters": [
          {
            "in": "path",
            "name": "payment_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Payment Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Missing or invalid bearer token."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Payment not found in this organisation."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Delete a payment record",
        "tags": [
          "payments"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X DELETE https://api.efakturuj.sk/api/v1/payments/{payment_id} \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.delete('/api/v1/payments/{payment_id}');"
          }
        ]
      }
    },
    "/api/v1/settings": {
      "get": {
        "description": "Get organisation settings from MongoDB.",
        "operationId": "get_settings_endpoint_api_v1_settings_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Get Settings Endpoint",
        "tags": [
          "settings"
        ]
      },
      "put": {
        "description": "Update organisation settings.",
        "operationId": "update_settings_endpoint_api_v1_settings_put",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SettingsUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Update Settings Endpoint",
        "tags": [
          "settings"
        ]
      }
    },
    "/api/v1/settings/numbering": {
      "get": {
        "description": "Get numbering pattern, padding, and current sequence.",
        "operationId": "get_numbering_config_endpoint_api_v1_settings_numbering_get",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Get Numbering Config Endpoint",
        "tags": [
          "settings"
        ]
      },
      "put": {
        "description": "Update numbering pattern, optionally reset sequence.",
        "operationId": "update_numbering_config_endpoint_api_v1_settings_numbering_put",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NumberingConfigUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Update Numbering Config Endpoint",
        "tags": [
          "settings"
        ]
      }
    },
    "/api/v1/webhooks/fs/acknowledgement": {
      "post": {
        "description": "Receive an acknowledgement callback from Slovak Finan\u010dn\u00e1 spr\u00e1va (FS).\n\nCalled BY the Slovak tax authority once it has finished\nprocessing an invoice copy this organisation submitted to comply\nwith the 2027 mandatory e-invoice reporting regime \u2014 never by an\nend user. Authentication is enforced at the network layer (the\ndeployment terminates the FS shared-secret check at the reverse\nproxy in front of this handler). The handler looks up the\ninvoice by `fs_submission_id`; on `acknowledged` it transitions\nthe row to `FS_ACKNOWLEDGED`, sets `fs_acknowledged_at`, and\nrecords an `FS_ACKNOWLEDGED` audit entry. On `rejected` it\ntransitions to `REJECTED` with a `REJECTED` audit entry that\ncaptures the FS-supplied `rejection_reason`. Missing-invoice\ncallbacks are logged but still acknowledged so FS does not retry.",
        "operationId": "webhooks.fs_acknowledgement",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FSAcknowledgement"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FSAcknowledgementAck"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Acknowledgement body fails Pydantic validation."
          }
        },
        "summary": "Slovak Finan\u010dn\u00e1 spr\u00e1va invoice-acknowledgement callback",
        "tags": [
          "webhooks"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/webhooks/fs/acknowledgement \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/webhooks/fs/acknowledgement', data: {...});"
          }
        ]
      }
    },
    "/api/v1/webhooks/peppol/delivery-status": {
      "post": {
        "description": "Receive an Oxalis delivery-status callback for a previously sent invoice.\n\nCalled BY Oxalis once the AS4 transport layer has confirmed (or\nabandoned) delivery of an invoice this organisation sent \u2014 never\nby an end user. Authentication is enforced at the network layer\n(the route is reachable only from the internal Oxalis container).\nThe handler looks up the invoice by `peppol_message_id`; on a\nmatch it transitions the row to `DELIVERED` and records a\n`RECEIVED` audit entry. If no invoice matches the message id the\ncallback is acknowledged with a warning log (Oxalis must not\nkeep retrying because of a missing local row). Always returns\n200 with `status=acknowledged` so Oxalis treats the callback as\nsettled and stops retrying.",
        "operationId": "webhooks.peppol_delivery_status",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PeppolDeliveryNotification"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PeppolDeliveryStatusAck"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Notification body fails Pydantic validation."
          }
        },
        "summary": "Peppol AS4 outbound delivery-status callback",
        "tags": [
          "webhooks"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/webhooks/peppol/delivery-status \\\n  -H 'X-Api-Key: <YOUR_API_KEY>' \\\n  -H 'Content-Type: application/json' \\\n  -d '{...}'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/webhooks/peppol/delivery-status', data: {...});"
          }
        ]
      }
    },
    "/api/v1/webhooks/peppol/receive": {
      "post": {
        "description": "Receive an inbound UBL invoice forwarded by the Peppol Access Point.\n\nCalled BY the local Oxalis instance after an AS4 message has been\naccepted from a remote Peppol participant \u2014 never by an end user.\nAuthentication is enforced at the network layer (Oxalis terminates\nmTLS and is restricted to the internal network), so this handler\naccepts the payload directly. The request body is the raw UBL 2.1\nXML; the `X-Peppol-Message-Id` header (when present) is captured\nas the persistent identifier. Parsing uses an XXE-safe lxml\nparser. The handler creates an `invoices` row with\n`source='peppol'`, `status=DELIVERED`, the parsed lines, and\nwrites a `RECEIVED` entry to `audit_logs`. Returns the new\ninvoice id for the caller's own bookkeeping.",
        "operationId": "webhooks.peppol_receive",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PeppolReceiveAck"
                }
              }
            },
            "description": "Successful Response"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Body is not well-formed XML."
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Content-Type is neither XML nor application/octet-stream."
          }
        },
        "summary": "Peppol AS4 inbound document receiver",
        "tags": [
          "webhooks"
        ],
        "x-codeSamples": [
          {
            "label": "curl",
            "lang": "Shell",
            "source": "curl -X POST https://api.efakturuj.sk/api/v1/webhooks/peppol/receive \\\n  -H 'X-Api-Key: <YOUR_API_KEY>'"
          },
          {
            "label": "Dart",
            "lang": "Dart",
            "source": "import 'package:dio/dio.dart';\n\nfinal dio = Dio(BaseOptions(\n  baseUrl: 'https://api.efakturuj.sk',\n  headers: {'X-Api-Key': '<YOUR_API_KEY>'},\n));\nfinal response = await dio.post('/api/v1/webhooks/peppol/receive');"
          }
        ]
      }
    },
    "/api/v1/workspaces/{workspace_id}/members": {
      "get": {
        "description": "List all members of a workspace.",
        "operationId": "list_workspace_members_api_v1_workspaces__workspace_id__members_get",
        "parameters": [
          {
            "in": "path",
            "name": "workspace_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Workspace Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "List Workspace Members",
        "tags": [
          "workspaces"
        ]
      },
      "post": {
        "description": "Invite a user to a workspace by email. Admin only.",
        "operationId": "invite_workspace_member_api_v1_workspaces__workspace_id__members_post",
        "parameters": [
          {
            "in": "path",
            "name": "workspace_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Workspace Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InviteMemberRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Invite Workspace Member",
        "tags": [
          "workspaces"
        ]
      }
    },
    "/api/v1/workspaces/{workspace_id}/members/{user_id}": {
      "delete": {
        "description": "Remove a member from a workspace. Admin only.",
        "operationId": "remove_workspace_member_api_v1_workspaces__workspace_id__members__user_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "workspace_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Workspace Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "User Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Remove Workspace Member",
        "tags": [
          "workspaces"
        ]
      },
      "patch": {
        "description": "Update a workspace member's role. Admin only.",
        "operationId": "update_member_role_api_v1_workspaces__workspace_id__members__user_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "workspace_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "Workspace Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "user_id",
            "required": true,
            "schema": {
              "format": "uuid",
              "title": "User Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMemberRoleRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "BearerJWT": []
          }
        ],
        "summary": "Update Member Role",
        "tags": [
          "workspaces"
        ]
      }
    }
  },
  "servers": [
    {
      "description": "Production",
      "url": "https://api.efakturuj.sk/api/v1"
    }
  ],
  "tags": [
    {
      "description": "Sign in with email/password, refresh tokens, password recovery, and WebAuthn passkeys.",
      "name": "auth"
    },
    {
      "description": "Create, validate, send, and track Peppol invoices.",
      "name": "invoices"
    },
    {
      "description": "Manage business customers and their VAT identifiers.",
      "name": "customers"
    },
    {
      "description": "Record incoming payments against invoices.",
      "name": "payments"
    },
    {
      "description": "Subscribe HTTPS endpoints to receive event notifications (invoice sent, delivery confirmed, payment received).",
      "name": "webhooks"
    },
    {
      "description": "Peppol participant lookup \u2014 confirm a counterparty can receive Peppol invoices before sending.",
      "name": "lookup"
    },
    {
      "description": "Create and revoke long-lived API keys for server-to-server integrations.",
      "name": "api-keys"
    },
    {
      "description": "OAuth2 client-credentials flow for server-to-server integrations. Authorization-code flow for end-user-acting third-party apps is on the roadmap but not yet wired.",
      "name": "oauth2"
    }
  ]
}
