{"openapi":"3.1.0","info":{"title":"FluxFina API","version":"1.0.0","description":"First-party REST API for the FluxFina web app and Flutter mobile client. See `docs/api/README.md` for the auth flow."},"servers":[{"url":"/","description":"Same-origin (web)"}],"components":{"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}}},"required":["code","message"]}},"required":["error"]},"ClientDTO":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":["string","null"]},"billingAddress":{"type":["string","null"]},"phone":{"type":["string","null"]},"taxId":{"type":["string","null"]},"notes":{"type":["string","null"]},"emailContacts":{"type":["array","null"],"items":{"type":"object","properties":{"email":{"type":"string","format":"email"},"label":{"type":"string","maxLength":200}},"required":["email"]}},"archivedAt":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","email","billingAddress","phone","taxId","notes","emailContacts","archivedAt","createdAt","updatedAt"]},"AttachmentDTO":{"type":"object","properties":{"id":{"type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"sizeBytes":{"type":"number"},"uploadedByUserId":{"type":"string"},"createdAt":{"type":"string"},"downloadUrl":{"type":"string"}},"required":["id","filename","mimeType","sizeBytes","uploadedByUserId","createdAt","downloadUrl"]},"InvoiceDTO":{"type":"object","properties":{"id":{"type":"string"},"clientId":{"type":["string","null"]},"status":{"type":"string"},"displayStatus":{"type":"string"},"invoiceNumber":{"type":["string","null"]},"publicToken":{"type":["string","null"]},"issueDate":{"type":["string","null"]},"dueDate":{"type":["string","null"]},"notes":{"type":["string","null"]},"terms":{"type":["string","null"]},"finalizedAt":{"type":["string","null"]},"voidedAt":{"type":["string","null"]},"voidReason":{"type":["string","null"]},"sendFailedAt":{"type":["string","null"]},"sendFailureReason":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"lines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"description":{"type":"string"},"quantity":{"type":"number"},"unitPrice":{"type":"number"},"taxRateId":{"type":["string","null"]},"amount":{"type":"number"},"taxAmount":{"type":"number"}},"required":["id","description","quantity","unitPrice","taxRateId","amount","taxAmount"]}},"totals":{"type":"object","properties":{"subtotal":{"type":"number"},"taxTotal":{"type":"number"},"total":{"type":"number"},"amountPaid":{"type":"number"},"amountDue":{"type":"number"}},"required":["subtotal","taxTotal","total","amountPaid","amountDue"]},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/AttachmentDTO"}}},"required":["id","clientId","status","displayStatus","invoiceNumber","publicToken","issueDate","dueDate","notes","terms","finalizedAt","voidedAt","voidReason","sendFailedAt","sendFailureReason","createdAt","updatedAt","lines","totals","attachments"]},"PaymentDTO":{"type":"object","properties":{"id":{"type":"string"},"invoiceId":{"type":"string"},"amount":{"type":"number"},"paidAt":{"type":"string"},"method":{"type":["string","null"]},"note":{"type":["string","null"]},"createdAt":{"type":"string"}},"required":["id","invoiceId","amount","paidAt","method","note","createdAt"]},"QuoteDTO":{"type":"object","properties":{"id":{"type":"string"},"clientId":{"type":"string"},"status":{"type":"string"},"displayStatus":{"type":"string"},"quoteNumber":{"type":["string","null"]},"publicToken":{"type":["string","null"]},"issueDate":{"type":["string","null"]},"validUntil":{"type":["string","null"]},"notes":{"type":["string","null"]},"terms":{"type":["string","null"]},"finalizedAt":{"type":["string","null"]},"sendFailedAt":{"type":["string","null"]},"sendFailureReason":{"type":["string","null"]},"respondedAt":{"type":["string","null"]},"respondedByName":{"type":["string","null"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"lines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"description":{"type":"string"},"quantity":{"type":"number"},"unitPrice":{"type":"number"},"taxRateId":{"type":["string","null"]},"position":{"type":"number"}},"required":["id","description","quantity","unitPrice","taxRateId","position"]}},"totals":{"type":"object","properties":{"subtotal":{"type":"number"},"taxTotal":{"type":"number"},"total":{"type":"number"}},"required":["subtotal","taxTotal","total"]},"attachments":{"type":"array","items":{"type":"object","properties":{"attachmentId":{"type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"},"sizeBytes":{"type":"number"},"downloadUrl":{"type":["string","null"]}},"required":["attachmentId","filename","mimeType","sizeBytes","downloadUrl"]}}},"required":["id","clientId","status","displayStatus","quoteNumber","publicToken","issueDate","validUntil","notes","terms","finalizedAt","sendFailedAt","sendFailureReason","respondedAt","respondedByName","createdAt","updatedAt","lines","totals","attachments"]},"TaxRateDTO":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"basisPoints":{"type":"number"},"isDefault":{"type":"boolean"},"isActive":{"type":"boolean"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","basisPoints","isDefault","isActive","createdAt","updatedAt"]},"MemberDTO":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","enum":["owner","admin","member"]}},"required":["id","name","email","role"]},"InvitationDTO":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","enum":["owner","admin","member"]},"status":{"type":"string"},"expiresAt":{"type":"string"},"createdAt":{"type":"string"},"acceptUrl":{"type":"string"},"emailSent":{"type":"boolean","description":"Only when an invitation is created: false if it exists but its email could not be sent."}},"required":["id","email","role","status","expiresAt","createdAt","acceptUrl"]},"OrganizationSettingsDTO":{"type":"object","properties":{"businessAddress":{"type":["string","null"]},"phone":{"type":["string","null"]},"taxId":{"type":["string","null"]},"currency":{"type":"string"},"logoUrl":{"type":["string","null"]},"timeZone":{"type":"string"},"invoiceNumberFormat":{"type":"object","properties":{"prefix":{"type":"string"},"padding":{"type":"integer"},"includeYear":{"type":"boolean"}},"required":["prefix","padding","includeYear"]},"quoteNumberFormat":{"type":"object","properties":{"prefix":{"type":"string"},"padding":{"type":"integer"},"includeYear":{"type":"boolean"}},"required":["prefix","padding","includeYear"]},"orderNumberFormat":{"type":"object","properties":{"prefix":{"type":"string"},"padding":{"type":"integer"},"includeYear":{"type":"boolean"}},"required":["prefix","padding","includeYear"]},"autoSendOnQuoteAcceptance":{"type":"boolean"},"customerEmailDisplayName":{"type":["string","null"]},"customerEmailReplyTo":{"type":["string","null"]}},"required":["businessAddress","phone","taxId","currency","logoUrl","timeZone","invoiceNumberFormat","quoteNumberFormat","orderNumberFormat","autoSendOnQuoteAcceptance","customerEmailDisplayName","customerEmailReplyTo"]},"RecurringProfileDTO":{"type":"object","properties":{"id":{"type":"string"},"clientId":{"type":"string"},"cadence":{"type":"string","enum":["hourly","daily","weekly","monthly","quarterly","yearly"]},"startDate":{"type":"string"},"nextRunAt":{"type":"string"},"endCondition":{},"occurrences":{"type":"integer"},"autoSend":{"type":"boolean"},"pausedAt":{"type":["string","null"]},"endedAt":{"type":["string","null"]},"templateDocument":{},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","clientId","cadence","startDate","nextRunAt","occurrences","autoSend","pausedAt","endedAt","createdAt","updatedAt"]}},"parameters":{},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"session-token"}}},"paths":{"/api/v1/clients":{"get":{"summary":"List clients","tags":["Clients"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"q","in":"query"},{"schema":{"type":["boolean","null"]},"required":false,"name":"includeArchived","in":"query"}],"responses":{"200":{"description":"Clients page","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ClientDTO"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]}},"required":["nextCursor"]}},"required":["data","meta"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a client","tags":["Clients"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"email":{"type":"string","format":"email"},"billingAddress":{"type":"string","maxLength":2000},"phone":{"type":"string","maxLength":50},"taxId":{"type":"string","maxLength":2000},"notes":{"type":"string","maxLength":2000},"emailContacts":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string","format":"email"},"label":{"type":"string","maxLength":200}},"required":["email"]},"maxItems":50}},"required":["name"]}}}},"responses":{"201":{"description":"Created client","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ClientDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/clients/{id}":{"get":{"summary":"Get a client","tags":["Clients"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Client","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ClientDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update a client","tags":["Clients"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"email":{"type":["string","null"],"format":"email"},"billingAddress":{"type":["string","null"],"maxLength":2000},"phone":{"type":["string","null"],"maxLength":50},"taxId":{"type":["string","null"],"maxLength":2000},"notes":{"type":["string","null"],"maxLength":2000},"emailContacts":{"type":["array","null"],"items":{"type":"object","properties":{"email":{"type":"string","format":"email"},"label":{"type":"string","maxLength":200}},"required":["email"]},"maxItems":50}}}}}},"responses":{"200":{"description":"Updated client","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ClientDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Archive a client","tags":["Clients"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Archived."},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/invoices":{"get":{"summary":"List invoices","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"clientId","in":"query"}],"responses":{"200":{"description":"Invoices page","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceDTO"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]}},"required":["nextCursor"]}},"required":["data","meta"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a draft invoice","tags":["Invoices"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"clientId":{"type":"string","minLength":1}},"required":["clientId"]}}}},"responses":{"201":{"description":"Created draft","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InvoiceDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/invoices/{id}":{"get":{"summary":"Get an invoice","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Invoice","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InvoiceDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Save draft invoice changes","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"clientId":{"type":"string","minLength":1},"issueDate":{"type":["string","null"],"pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"dueDate":{"type":["string","null"],"pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"notes":{"type":["string","null"],"maxLength":10000},"terms":{"type":["string","null"],"maxLength":10000},"lines":{"type":"array","items":{"type":"object","properties":{"description":{"type":"string","maxLength":500},"quantity":{"type":"number","minimum":0,"maximum":1000000},"unitPrice":{"type":"integer","minimum":-2147483647,"maximum":2147483647},"taxRateId":{"type":["string","null"],"maxLength":128}},"required":["description","quantity","unitPrice","taxRateId"]},"maxItems":500}},"required":["clientId","issueDate","dueDate","notes","terms","lines"]}}}},"responses":{"200":{"description":"Updated invoice","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InvoiceDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a draft invoice","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted."},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/invoices/{id}/finalize":{"post":{"summary":"Finalize a draft invoice","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Finalized invoice","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InvoiceDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/invoices/{id}/send":{"post":{"summary":"Send a finalized invoice by email","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Sent invoice","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InvoiceDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/invoices/{id}/void":{"post":{"summary":"Void a finalized invoice","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":10000}},"required":["reason"]}}}},"responses":{"200":{"description":"Voided invoice","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InvoiceDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/invoices/{id}/duplicate":{"post":{"summary":"Duplicate an invoice into a new draft","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"201":{"description":"New draft","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InvoiceDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/invoices/{id}/payments":{"get":{"summary":"List invoice payments","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Payments","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PaymentDTO"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]}},"required":["nextCursor"]}},"required":["data","meta"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Record a payment","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"type":"integer","exclusiveMinimum":0,"maximum":2147483647},"paidAt":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"method":{"type":"string","enum":["bank_transfer","card","cash","cheque","other"]},"note":{"type":["string","null"],"maxLength":10000}},"required":["amount","paidAt","method"]}}}},"responses":{"201":{"description":"Payment + refreshed invoice","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"payment":{"$ref":"#/components/schemas/PaymentDTO"},"invoice":{"$ref":"#/components/schemas/InvoiceDTO"}},"required":["payment","invoice"]}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/invoices/{id}/attachments":{"get":{"summary":"List invoice attachments","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Attachments","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AttachmentDTO"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]}},"required":["nextCursor"]}},"required":["data","meta"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Upload an attachment (multipart)","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string"}},"required":["file"]}}}},"responses":{"201":{"description":"Uploaded attachment","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AttachmentDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Payload too large.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Unsupported media type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/invoices/{id}/attachments/{attachmentId}":{"delete":{"summary":"Delete an attachment","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"attachmentId","in":"path"}],"responses":{"204":{"description":"Deleted."},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/invoices/{id}/attachments/{attachmentId}/download":{"get":{"summary":"Download an attachment","tags":["Invoices"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"attachmentId","in":"path"}],"responses":{"200":{"description":"Binary attachment bytes.","content":{"application/octet-stream":{"schema":{"type":"string"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/quotes":{"get":{"summary":"List quotes","tags":["Quotes"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Quotes page","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/QuoteDTO"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]}},"required":["nextCursor"]}},"required":["data","meta"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a draft quote","tags":["Quotes"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"clientId":{"type":"string","minLength":1}},"required":["clientId"]}}}},"responses":{"201":{"description":"Created draft","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/QuoteDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/quotes/{id}":{"get":{"summary":"Get a quote","tags":["Quotes"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Quote","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/QuoteDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Save draft quote changes","tags":["Quotes"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"clientId":{"type":"string","minLength":1},"issueDate":{"type":["string","null"],"pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"validUntil":{"type":["string","null"],"pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"notes":{"type":["string","null"]},"terms":{"type":["string","null"]},"lines":{"type":"array","items":{"type":"object","properties":{"description":{"type":"string","maxLength":500},"quantity":{"type":"number","minimum":0},"unitPrice":{"type":"integer"},"taxRateId":{"type":["string","null"]}},"required":["description","quantity","unitPrice","taxRateId"]}}},"required":["clientId","issueDate","validUntil","notes","terms","lines"]}}}},"responses":{"200":{"description":"Updated quote","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/QuoteDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a draft quote","tags":["Quotes"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted."},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/quotes/{id}/finalize":{"post":{"summary":"Finalize a draft quote","tags":["Quotes"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Finalized quote","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/QuoteDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/quotes/{id}/send":{"post":{"summary":"Send a finalized quote by email","tags":["Quotes"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Sent quote","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/QuoteDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/quotes/{id}/respond":{"post":{"summary":"Record an accept/decline response","tags":["Quotes"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"decision":{"type":"string","enum":["accept","decline"]},"name":{"type":["string","null"],"maxLength":200}},"required":["decision"]}}}},"responses":{"200":{"description":"Updated quote","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/QuoteDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/quotes/{id}/attachments":{"get":{"summary":"List quote attachments","tags":["Quotes"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Attachments","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AttachmentDTO"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]}},"required":["nextCursor"]}},"required":["data","meta"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Upload a quote attachment (multipart)","tags":["Quotes"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string"}},"required":["file"]}}}},"responses":{"201":{"description":"Uploaded attachment","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AttachmentDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Payload too large.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Unsupported media type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/quotes/{id}/attachments/{attachmentId}":{"delete":{"summary":"Delete a quote attachment","tags":["Quotes"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"attachmentId","in":"path"}],"responses":{"204":{"description":"Deleted."},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/quotes/{id}/attachments/{attachmentId}/download":{"get":{"summary":"Download a quote attachment","tags":["Quotes"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"attachmentId","in":"path"}],"responses":{"200":{"description":"Binary attachment bytes.","content":{"application/octet-stream":{"schema":{"type":"string"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/tax-rates":{"get":{"summary":"List active tax rates","tags":["Tax rates"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Tax rates","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TaxRateDTO"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]}},"required":["nextCursor"]}},"required":["data","meta"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a tax rate","tags":["Tax rates"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"basisPoints":{"type":"integer","minimum":0,"maximum":10000}},"required":["name","basisPoints"]}}}},"responses":{"201":{"description":"Tax rate","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TaxRateDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/tax-rates/{id}":{"get":{"summary":"Get a tax rate","tags":["Tax rates"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Tax rate","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TaxRateDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Edit a tax rate","tags":["Tax rates"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"basisPoints":{"type":"integer","minimum":0,"maximum":10000}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TaxRateDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Deactivate a tax rate","tags":["Tax rates"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deactivated."},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/tax-rates/{id}/set-default":{"post":{"summary":"Mark a tax rate as default","tags":["Tax rates"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TaxRateDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/team/members":{"get":{"summary":"List members","tags":["Team"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Members","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MemberDTO"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]}},"required":["nextCursor"]}},"required":["data","meta"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/team/invitations":{"get":{"summary":"List pending invitations","tags":["Team"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Invitations","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InvitationDTO"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]}},"required":["nextCursor"]}},"required":["data","meta"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Send an invitation","tags":["Team"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["member","admin"]}},"required":["email","role"]}}}},"responses":{"201":{"description":"Invitation","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InvitationDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/team/invitations/{id}":{"delete":{"summary":"Cancel an invitation","tags":["Team"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Cancelled."},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/organization/settings":{"get":{"summary":"Read organization settings","tags":["Organization"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Settings","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/OrganizationSettingsDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update organization settings","tags":["Organization"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"businessAddress":{"type":["string","null"],"maxLength":1000},"phone":{"type":["string","null"],"maxLength":50},"taxId":{"type":["string","null"],"maxLength":1000},"currency":{"type":"string","minLength":3,"maxLength":3},"timeZone":{"type":"string","minLength":1,"maxLength":60},"invoiceNumberFormat":{"type":"object","properties":{"prefix":{"type":"string","maxLength":20},"padding":{"type":"integer","minimum":1,"maximum":10},"includeYear":{"type":"boolean"}},"required":["prefix","padding","includeYear"]},"quoteNumberFormat":{"type":"object","properties":{"prefix":{"type":"string","maxLength":20},"padding":{"type":"integer","minimum":1,"maximum":10},"includeYear":{"type":"boolean"}},"required":["prefix","padding","includeYear"]},"orderNumberFormat":{"type":"object","properties":{"prefix":{"type":"string","maxLength":20},"padding":{"type":"integer","minimum":1,"maximum":10},"includeYear":{"type":"boolean"}},"required":["prefix","padding","includeYear"]},"autoSendOnQuoteAcceptance":{"type":"boolean"},"customerEmailDisplayName":{"type":["string","null"],"maxLength":1000},"customerEmailReplyTo":{"anyOf":[{"type":"string","maxLength":320,"format":"email"},{"type":"null"},{"type":"string","enum":[""]}]}}}}}},"responses":{"200":{"description":"Updated settings","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/OrganizationSettingsDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/payments/connect":{"post":{"summary":"Start or continue Stripe Connect onboarding","tags":["Payments"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Hosted onboarding link","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/recurring-profiles":{"get":{"summary":"List recurring profiles","tags":["Recurring"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Recurring profiles","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/RecurringProfileDTO"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]}},"required":["nextCursor"]}},"required":["data","meta"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a recurring profile","tags":["Recurring"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"clientId":{"type":"string","minLength":1},"kind":{"type":"string","enum":["invoice","quote"],"default":"invoice"},"cadence":{"type":"string","enum":["hourly","daily","weekly","monthly","quarterly","yearly"]},"startDate":{"type":"string","format":"date"},"nextRunAt":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}(T([01]\\d|2[0-3]):00)?$"},"endCondition":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["never"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["onDate"]},"endDate":{"type":"string","format":"date"}},"required":["type","endDate"]},{"type":"object","properties":{"type":{"type":"string","enum":["afterOccurrences"]},"count":{"type":"integer","exclusiveMinimum":0}},"required":["type","count"]}],"default":{"type":"never"}},"autoSend":{"type":"boolean","default":false},"templateDocument":{"type":"object","properties":{"logo":{"type":"string","maxLength":4096},"logoWidth":{"type":"number","minimum":0,"maximum":1000000},"title":{"type":"string","maxLength":80},"companyName":{"type":"string","maxLength":256},"companyAddress":{"type":"string","maxLength":256},"companyAddress2":{"type":"string","maxLength":256},"companyCountry":{"type":"string","maxLength":256},"companyPhone":{"type":"string","maxLength":256},"billTo":{"type":"string","maxLength":80},"clientName":{"type":"string","maxLength":256},"clientAddress":{"type":"string","maxLength":256},"clientAddress2":{"type":"string","maxLength":256},"clientCountry":{"type":"string","maxLength":256},"clientPhone":{"type":"string","maxLength":256},"invoiceTitleLabel":{"type":"string","maxLength":80},"invoiceTitle":{"type":"string","maxLength":256},"invoiceDateLabel":{"type":"string","maxLength":80},"invoiceDate":{"type":"string","maxLength":256},"paymentTermsLabel":{"type":"string","maxLength":80},"paymentTermsStart":{"type":"string","maxLength":256},"paymentTermsEnd":{"type":"string","maxLength":256},"invoiceDueDateLabel":{"type":"string","maxLength":80},"invoiceDueDate":{"type":"string","maxLength":256},"customFields":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","maxLength":80},"value":{"type":"string","maxLength":256}},"required":["label","value"],"additionalProperties":false},"maxItems":200},"productLineDescription":{"type":"string","maxLength":80},"productLineQuantity":{"type":"string","maxLength":80},"productLineQuantityRate":{"type":"string","maxLength":80},"productLineQuantityAmount":{"type":"string","maxLength":80},"productLines":{"type":"array","items":{"type":"object","properties":{"description":{"type":"string","maxLength":10000},"quantity":{"type":"string","maxLength":256},"rate":{"type":"string","maxLength":256},"taxRateId":{"type":["string","null"]}},"required":["description","quantity","rate"],"additionalProperties":false},"maxItems":200},"subTotalLabel":{"type":"string","maxLength":80},"totalLabel":{"type":"string","maxLength":80},"adjustments":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["discount","tax","shipping","custom"]},"mode":{"type":"string","enum":["currency","percent"]},"label":{"type":"string","maxLength":80},"amount":{"type":"string","maxLength":256}},"required":["kind","mode","amount"],"additionalProperties":false},"maxItems":200},"notesLabel":{"type":"string","maxLength":80},"notes":{"type":"string","maxLength":10000},"termLabel":{"type":"string","maxLength":80},"term":{"type":"string","maxLength":10000}},"required":["logo","logoWidth","title","companyName","companyAddress","companyAddress2","companyCountry","billTo","clientName","clientAddress","clientAddress2","clientCountry","invoiceTitleLabel","invoiceTitle","invoiceDateLabel","invoiceDate","paymentTermsLabel","paymentTermsStart","paymentTermsEnd","invoiceDueDateLabel","invoiceDueDate","customFields","productLineDescription","productLineQuantity","productLineQuantityRate","productLineQuantityAmount","productLines","subTotalLabel","totalLabel","adjustments","notesLabel","notes","termLabel","term"],"additionalProperties":false}},"required":["clientId","cadence","startDate","templateDocument"]}}}},"responses":{"201":{"description":"Created recurring profile","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RecurringProfileDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/recurring-profiles/{id}":{"get":{"summary":"Get a recurring profile","tags":["Recurring"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Recurring profile","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RecurringProfileDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update a recurring profile","tags":["Recurring"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"cadence":{"type":"string","enum":["hourly","daily","weekly","monthly","quarterly","yearly"]},"startDate":{"type":"string","format":"date"},"endCondition":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["never"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["onDate"]},"endDate":{"type":"string","format":"date"}},"required":["type","endDate"]},{"type":"object","properties":{"type":{"type":"string","enum":["afterOccurrences"]},"count":{"type":"integer","exclusiveMinimum":0}},"required":["type","count"]}]},"autoSend":{"type":"boolean"},"templateDocument":{"type":"object","properties":{"logo":{"type":"string","maxLength":4096},"logoWidth":{"type":"number","minimum":0,"maximum":1000000},"title":{"type":"string","maxLength":80},"companyName":{"type":"string","maxLength":256},"companyAddress":{"type":"string","maxLength":256},"companyAddress2":{"type":"string","maxLength":256},"companyCountry":{"type":"string","maxLength":256},"companyPhone":{"type":"string","maxLength":256},"billTo":{"type":"string","maxLength":80},"clientName":{"type":"string","maxLength":256},"clientAddress":{"type":"string","maxLength":256},"clientAddress2":{"type":"string","maxLength":256},"clientCountry":{"type":"string","maxLength":256},"clientPhone":{"type":"string","maxLength":256},"invoiceTitleLabel":{"type":"string","maxLength":80},"invoiceTitle":{"type":"string","maxLength":256},"invoiceDateLabel":{"type":"string","maxLength":80},"invoiceDate":{"type":"string","maxLength":256},"paymentTermsLabel":{"type":"string","maxLength":80},"paymentTermsStart":{"type":"string","maxLength":256},"paymentTermsEnd":{"type":"string","maxLength":256},"invoiceDueDateLabel":{"type":"string","maxLength":80},"invoiceDueDate":{"type":"string","maxLength":256},"customFields":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","maxLength":80},"value":{"type":"string","maxLength":256}},"required":["label","value"],"additionalProperties":false},"maxItems":200},"productLineDescription":{"type":"string","maxLength":80},"productLineQuantity":{"type":"string","maxLength":80},"productLineQuantityRate":{"type":"string","maxLength":80},"productLineQuantityAmount":{"type":"string","maxLength":80},"productLines":{"type":"array","items":{"type":"object","properties":{"description":{"type":"string","maxLength":10000},"quantity":{"type":"string","maxLength":256},"rate":{"type":"string","maxLength":256},"taxRateId":{"type":["string","null"]}},"required":["description","quantity","rate"],"additionalProperties":false},"maxItems":200},"subTotalLabel":{"type":"string","maxLength":80},"totalLabel":{"type":"string","maxLength":80},"adjustments":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["discount","tax","shipping","custom"]},"mode":{"type":"string","enum":["currency","percent"]},"label":{"type":"string","maxLength":80},"amount":{"type":"string","maxLength":256}},"required":["kind","mode","amount"],"additionalProperties":false},"maxItems":200},"notesLabel":{"type":"string","maxLength":80},"notes":{"type":"string","maxLength":10000},"termLabel":{"type":"string","maxLength":80},"term":{"type":"string","maxLength":10000}},"required":["logo","logoWidth","title","companyName","companyAddress","companyAddress2","companyCountry","billTo","clientName","clientAddress","clientAddress2","clientCountry","invoiceTitleLabel","invoiceTitle","invoiceDateLabel","invoiceDate","paymentTermsLabel","paymentTermsStart","paymentTermsEnd","invoiceDueDateLabel","invoiceDueDate","customFields","productLineDescription","productLineQuantity","productLineQuantityRate","productLineQuantityAmount","productLines","subTotalLabel","totalLabel","adjustments","notesLabel","notes","termLabel","term"],"additionalProperties":false}}}}}},"responses":{"200":{"description":"Updated recurring profile","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RecurringProfileDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a recurring profile (only when no invoices exist)","tags":["Recurring"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"Deleted."},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/recurring-profiles/{id}/pause":{"post":{"summary":"Pause a recurring profile","tags":["Recurring"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Paused profile","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RecurringProfileDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/recurring-profiles/{id}/resume":{"post":{"summary":"Resume a recurring profile (no backfill of missed cycles)","tags":["Recurring"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Resumed profile","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RecurringProfileDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/recurring-profiles/{id}/stop":{"post":{"summary":"Stop a recurring profile (terminal)","tags":["Recurring"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Stopped profile","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/RecurringProfileDTO"}},"required":["data"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/recurring-profiles/{id}/invoices":{"get":{"summary":"List invoices generated by a recurring profile","tags":["Recurring"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"Invoices generated by the profile","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceDTO"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"]}},"required":["nextCursor"]}},"required":["data","meta"]}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient permissions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid state transition.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{}}