{"openapi":"3.0.3","info":{"title":"eContract API","version":"1.0.0","description":"REST API of eContract, the e-signature platform: create and send contracts, follow signing,\ndownload signed PDFs and audit trails. AI agents can also use the remote MCP server at\n`https://api.econtract.online/mcp`.\n\n## Authentication\nSend `Authorization: Bearer <credential>` with an API key (`cl_live_…`, created under\nDashboard → API Keys) or an OAuth 2.1 access token (`eco_at_…`). Each operation lists the scope\nit needs (`x-econtract-scope`). This reference lists the public endpoints and everything API keys\nand OAuth tokens can call; the web app uses further session-only endpoints that are not part of the\npublic API. Signing and declining are always done by a person.\n\n## Rate limits\nPer API key or OAuth grant: 60 requests/minute, 1,000/hour, 10,000/day. Responses carry\n`X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` (seconds until the minute\nwindow resets); `429` adds `Retry-After`.\n\nGuides: https://developers.econtract.online","contact":{"name":"eContract","url":"https://econtract.online","email":"contact@econtract.online"}},"servers":[{"url":"https://api.econtract.online","description":"Production"}],"externalDocs":{"description":"eContract developer guides","url":"https://developers.econtract.online"},"security":[{"bearerAuth":[]},{"oauth2":[]}],"tags":[{"name":"activities","description":"Contract activity log."},{"name":"ai","description":"AI text extraction and contract analysis (`ai:use`)."},{"name":"auth","description":"Login and the current principal (`GET /api/v1/auth/me` works with API keys and OAuth tokens)."},{"name":"contracts","description":"Create, send, track and void contracts; signing links, signed PDF and audit trail."},{"name":"files","description":"File upload and download."},{"name":"guides","description":"Public guides."},{"name":"otp","description":"One-time passwords for signer identity checks."},{"name":"Public Verify","description":"Public verification of signed PDFs."},{"name":"signers","description":"Signers of a contract and the external signer address book."},{"name":"signing","description":"Signer-facing signing flow (token based, used by the signing page)."},{"name":"system-templates","description":"Public system template catalogue."},{"name":"templates","description":"Contract templates and generating contracts from them."},{"name":"tokens","description":"Signing token validation."},{"name":"verify","description":"Public verification of signed PDFs and contracts."},{"name":"webhooks","description":"Webhook endpoints, delivery log and retries (workspace admin or owner)."},{"name":"workflows","description":"Signing workflow state and events."}],"paths":{"/api/v1/ai/analyze-contract":{"post":{"operationId":"AnalysisController_analyzeContract","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyzeContractRequest"}}}},"responses":{"200":{"description":""}},"tags":["ai"],"x-econtract-auth":"machine","x-econtract-scope":"ai:use","security":[{"bearerAuth":[]},{"oauth2":["ai:use"]}]}},"/api/v1/ai/contract-prefill":{"post":{"operationId":"PrefillController_contractPrefill","summary":"Extract contract prefill data from an uploaded file","responses":{"200":{"description":"Prefill data extracted successfully"},"400":{"description":"Invalid request or unsupported file type"},"403":{"description":"Rate limit or cost limit exceeded"},"404":{"description":"File not found in storage"}},"tags":["ai"],"x-econtract-auth":"machine","x-econtract-scope":"ai:use","security":[{"bearerAuth":[]},{"oauth2":["ai:use"]}]}},"/api/v1/ai/extract-text":{"post":{"operationId":"ExtractionController_extractText","summary":"Extract text from a PDF file","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"PDF file to extract text from (max 50MB)"}},"required":["file"]}}}},"responses":{"200":{"description":"Text extracted successfully"},"400":{"description":"Invalid file or extraction error"},"413":{"description":"File too large"}},"tags":["ai"],"x-econtract-auth":"machine","x-econtract-scope":"ai:use","security":[{"bearerAuth":[]},{"oauth2":["ai:use"]}]}},"/api/v1/auth/accept-invite":{"post":{"operationId":"AuthController_acceptInvite","summary":"Accept workspace invitation","responses":{"200":{"description":""}},"tags":["auth"],"x-econtract-auth":"public","security":[]}},"/api/v1/auth/forgot-password":{"post":{"operationId":"AuthController_forgotPassword","summary":"Request password reset","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordDto"}}}},"responses":{"200":{"description":""}},"tags":["auth"],"x-econtract-auth":"public","security":[]}},"/api/v1/auth/login":{"post":{"operationId":"AuthController_login","summary":"User login","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginDto"}}}},"responses":{"200":{"description":"Login successful"}},"tags":["auth"],"x-econtract-auth":"public","security":[]}},"/api/v1/auth/me":{"get":{"operationId":"AuthController_me","summary":"Get current user profile","responses":{"200":{"description":""}},"tags":["auth"],"x-econtract-auth":"machine","security":[{"bearerAuth":[]},{"oauth2":[]}]}},"/api/v1/auth/register":{"post":{"operationId":"AuthController_register","summary":"Register a new user","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterDto"}}}},"responses":{"201":{"description":"User registered"},"429":{"description":"USAGE_LIMIT_REACHED: too many signups from this IP today"}},"tags":["auth"],"x-econtract-auth":"public","security":[]}},"/api/v1/auth/register/google":{"post":{"operationId":"AuthController_registerGoogle","responses":{"201":{"description":""}},"tags":["auth"],"x-econtract-auth":"public","security":[]}},"/api/v1/auth/register/microsoft":{"post":{"operationId":"AuthController_registerMicrosoft","responses":{"201":{"description":""}},"tags":["auth"],"x-econtract-auth":"public","security":[]}},"/api/v1/auth/resend-verification":{"post":{"operationId":"AuthController_resendVerification","summary":"Resend verification email","responses":{"200":{"description":""}},"tags":["auth"],"x-econtract-auth":"public","security":[]}},"/api/v1/auth/reset-password":{"post":{"operationId":"AuthController_resetPassword","summary":"Reset password with token","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordDto"}}}},"responses":{"200":{"description":""}},"tags":["auth"],"x-econtract-auth":"public","security":[]}},"/api/v1/auth/verify-email":{"post":{"operationId":"AuthController_verifyEmail","summary":"Verify email address","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyEmailDto"}}}},"responses":{"200":{"description":""}},"tags":["auth"],"x-econtract-auth":"public","security":[]}},"/api/v1/contract-templates":{"post":{"operationId":"TemplateController_create","summary":"Create template","responses":{"201":{"description":"Template created successfully"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:write","security":[{"bearerAuth":[]},{"oauth2":["templates:write"]}]},"get":{"operationId":"TemplateController_findAll","summary":"List templates","parameters":[{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"type","required":true,"in":"query","schema":{"type":"string"}},{"name":"category","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Templates retrieved successfully"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:read","security":[{"bearerAuth":[]},{"oauth2":["templates:read"]}]}},"/api/v1/contract-templates/{id}":{"get":{"operationId":"TemplateController_findById","summary":"Get template by ID","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Template retrieved successfully"},"404":{"description":"Template not found"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:read","security":[{"bearerAuth":[]},{"oauth2":["templates:read"]}]},"put":{"operationId":"TemplateController_update","summary":"Update template","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Template updated successfully"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:write","security":[{"bearerAuth":[]},{"oauth2":["templates:write"]}]},"delete":{"operationId":"TemplateController_archive","summary":"Archive template","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Template archived successfully"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:delete","security":[{"bearerAuth":[]},{"oauth2":["templates:delete"]}]}},"/api/v1/contract-templates/{id}/extract-variables":{"post":{"operationId":"TemplateController_extractVariables","summary":"Extract variables from template file","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:write","security":[{"bearerAuth":[]},{"oauth2":["templates:write"]}]}},"/api/v1/contract-templates/{id}/generate":{"post":{"operationId":"TemplateController_generate","summary":"Generate contract from template","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateFromTemplateDto"}}}},"responses":{"201":{"description":"Contract created from template"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contract-templates/{id}/preview":{"post":{"operationId":"TemplateController_preview","summary":"Preview template with values","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:read","security":[{"bearerAuth":[]},{"oauth2":["templates:read"]}]}},"/api/v1/contract-templates/categories":{"get":{"operationId":"TemplateController_getCategories","summary":"List template categories","responses":{"200":{"description":""}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:read","security":[{"bearerAuth":[]},{"oauth2":["templates:read"]}]}},"/api/v1/contracts":{"post":{"operationId":"ContractsController_create","summary":"Create contract","parameters":[{"name":"Idempotency-Key","in":"header","description":"Up to 255 characters. Retries with the same key and body replay the first result (header Idempotent-Replayed: true) for 24 h.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContractDto"}}}},"responses":{"201":{"description":"Contract created successfully"},"400":{"description":"Invalid request"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]},"get":{"operationId":"ContractsController_findAll","summary":"List contracts","parameters":[{"name":"page","required":false,"in":"query","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Values above 100 are capped","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"status","required":false,"in":"query","schema":{"enum":["draft","pending","in_signing","completed","voided","expired"],"type":"string"}},{"name":"search","required":false,"in":"query","description":"Matches code, title or description","schema":{"type":"string"}},{"name":"createdBy","required":false,"in":"query","description":"Creator user id","schema":{"type":"string"}},{"name":"fromDate","required":false,"in":"query","description":"Created at or after (ISO 8601)","schema":{"type":"string"}},{"name":"toDate","required":false,"in":"query","description":"Created at or before (ISO 8601)","schema":{"type":"string"}}],"responses":{"200":{"description":"Contracts retrieved successfully"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]}},"/api/v1/contracts/{contractId}/activities":{"get":{"operationId":"ActivitiesController_findByContractId","summary":"List activities for a contract","parameters":[{"name":"contractId","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["activities"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]}},"/api/v1/contracts/{contractId}/activities/verify-chain":{"get":{"operationId":"ActivitiesController_verifyChain","summary":"Verify activity chain integrity","parameters":[{"name":"contractId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["activities"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]}},"/api/v1/contracts/{contractId}/signers":{"post":{"operationId":"SignersController_addSigner","summary":"Add signer to contract","parameters":[{"name":"contractId","required":true,"in":"path","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddSignerDto"}}}},"responses":{"201":{"description":"Signer added successfully"},"400":{"description":"Invalid request or duplicate signer"}},"tags":["signers"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]},"get":{"operationId":"SignersController_findByContractId","summary":"List signers for contract","parameters":[{"name":"contractId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Signers retrieved successfully"}},"tags":["signers"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]}},"/api/v1/contracts/{contractId}/signers/{id}":{"get":{"operationId":"SignersController_findById","summary":"Get signer by ID","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Signer retrieved successfully"},"404":{"description":"Signer not found"}},"tags":["signers"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]},"delete":{"operationId":"SignersController_removeSigner","summary":"Remove signer from contract","parameters":[{"name":"contractId","required":true,"in":"path","schema":{"type":"string"}},{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Signer removed successfully"},"400":{"description":"Cannot remove signed signer"},"404":{"description":"Signer not found"}},"tags":["signers"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/{id}":{"get":{"operationId":"ContractsController_findById","summary":"Get contract by ID","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"includeSigners","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Contract retrieved successfully"},"404":{"description":"Contract not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]},"put":{"operationId":"ContractsController_update","summary":"Update contract (draft only)","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContractDto"}}}},"responses":{"200":{"description":"Contract updated successfully"},"400":{"description":"Cannot update non-draft contract"},"404":{"description":"Contract not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]},"delete":{"operationId":"ContractsController_delete","summary":"Delete contract (draft only)","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Contract deleted successfully"},"400":{"description":"Cannot delete non-draft contract"},"404":{"description":"Contract not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:delete","security":[{"bearerAuth":[]},{"oauth2":["contracts:delete"]}]}},"/api/v1/contracts/{id}/accept-ai-suggestions":{"post":{"operationId":"ContractsController_acceptAISuggestions","summary":"Accept AI suggestions and update contract title/description","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptAISuggestionsDto"}}}},"responses":{"200":{"description":"AI suggestions accepted"},"400":{"description":"Contract is not in draft state"},"404":{"description":"Contract not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/{id}/ai-suggestions":{"post":{"operationId":"ContractsController_getAISuggestions","summary":"[Deprecated] AI suggestions — delegates to file-driven prefill","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AISuggestRequestDto"}}}},"responses":{"200":{"description":"Prefill data extracted from source file"},"400":{"description":"Prefill failed or not available"},"404":{"description":"Contract or file not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/{id}/audit-trail":{"get":{"operationId":"ContractsController_auditTrail","summary":"Audit trail: signers, events, hash-chain check and document hash","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditTrailResponseDto"}}}}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]}},"/api/v1/contracts/{id}/document":{"get":{"operationId":"ContractsController_document","summary":"Download the contract PDF","description":"version=signed (409 DOCUMENT_NOT_SIGNED until completed), version=original (404 ORIGINAL_NOT_AVAILABLE when not retained), default: signed when completed else the current file. Headers X-Document-Version and X-Document-Sha256.","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"version","required":false,"in":"query","description":"Default: signed when completed, else the current file","schema":{"enum":["signed","original"],"type":"string"}},{"name":"fileId","required":false,"in":"query","description":"Contract file id (multi-file contracts; default: the primary file)","schema":{"type":"string"}}],"responses":{"200":{"description":"PDF bytes"},"404":{"description":"Contract / file not found, or ORIGINAL_NOT_AVAILABLE"},"409":{"description":"DOCUMENT_NOT_SIGNED or DOCUMENT_NOT_READY"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]}},"/api/v1/contracts/{id}/files":{"get":{"operationId":"ContractsController_listFiles","summary":"List contract files","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Files retrieved successfully"},"404":{"description":"Contract not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]},"post":{"operationId":"ContractsController_addFile","summary":"Add file to contract (draft only)","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddContractFileDto"}}}},"responses":{"201":{"description":"File added successfully"},"400":{"description":"Cannot add file to non-draft contract"},"404":{"description":"Contract not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/{id}/files/{fileId}":{"delete":{"operationId":"ContractsController_removeFile","summary":"Remove file from contract (draft only)","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"fileId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"File removed successfully"},"400":{"description":"Cannot remove file from non-draft contract"},"404":{"description":"Contract or file not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/{id}/files/{fileId}/retry-conversion":{"post":{"operationId":"ContractsController_retryConversion","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"fileId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/{id}/prefill":{"post":{"operationId":"ContractsController_getContractPrefill","summary":"File-driven contract prefill — extract title, summary, signers from source document","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContractPrefillRequestDto"}}}},"responses":{"200":{"description":"Prefill data extracted from source file"},"400":{"description":"Prefill failed or not available"},"404":{"description":"Contract or file not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/{id}/resend-signing-request":{"post":{"operationId":"ContractsController_resendSigningRequest","summary":"Resend signing request notifications to pending signers","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Up to 255 characters. Retries with the same key and body replay the first result (header Idempotent-Replayed: true) for 24 h.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendSigningRequestDto"}}}},"responses":{"200":{"description":"Signing requests resent successfully"},"400":{"description":"Contract is not in signing state"},"404":{"description":"Contract not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/{id}/resolve-candidates":{"post":{"operationId":"ContractsController_resolveCandidates","summary":"Resolve signer candidates against internal users and external signers","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveSignerCandidatesRequestDto"}}}},"responses":{"200":{"description":"Candidates resolved successfully"},"400":{"description":"Invalid request"},"404":{"description":"Contract not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/{id}/signing-links":{"post":{"operationId":"ContractsController_signingLinks","summary":"Get signing links for the signers (no email is sent)","description":"Mints a fresh token for every external signer who has not signed or declined (older links stay valid). Internal signers get the dashboard link. 409 unless the contract is pending or in signing.","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Up to 255 characters. Retries with the same key and body replay the first result (header Idempotent-Replayed: true) for 24 h.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SigningLinksResponseDto"}}}},"409":{"description":"CONTRACT_NOT_IN_SIGNING"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/{id}/submit":{"post":{"operationId":"ContractsController_submit","summary":"Submit contract for signing","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Up to 255 characters. Retries with the same key and body replay the first result (header Idempotent-Replayed: true) for 24 h.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitContractDto"}}}},"responses":{"200":{"description":"Contract submitted successfully"},"400":{"description":"Invalid contract state"},"404":{"description":"Contract not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/{id}/void":{"post":{"operationId":"ContractsController_void","summary":"Void contract","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","description":"Up to 255 characters. Retries with the same key and body replay the first result (header Idempotent-Replayed: true) for 24 h.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoidContractDto"}}}},"responses":{"200":{"description":"Contract voided successfully"},"400":{"description":"Cannot void contract"},"404":{"description":"Contract not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/ai/feature-flags":{"get":{"operationId":"ContractsController_getAIFeatureFlags","summary":"Get AI feature flags for the current tenant/plan","responses":{"200":{"description":"Feature flags retrieved"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]}},"/api/v1/contracts/code/{code}":{"get":{"operationId":"ContractsController_findByCode","summary":"Get contract by code","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Contract retrieved successfully"},"404":{"description":"Contract not found"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]}},"/api/v1/contracts/send":{"post":{"operationId":"ContractsController_send","summary":"Create and send contract in one call (JSON with base64/URL files, or multipart upload)","parameters":[{"name":"Idempotency-Key","in":"header","description":"Up to 255 characters. Retries with the same key and body replay the first result (header Idempotent-Replayed: true) for 24 h.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SendContractDto"},{"type":"object","properties":{"files":{"type":"array","items":{"type":"string","format":"binary"},"description":"PDF or DOCX files (max 10, max 50MB each)"},"metadata":{"type":"string","description":"Stringified JSON SendContractDto (without files)"}}}]}},"multipart/form-data":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SendContractDto"},{"type":"object","properties":{"files":{"type":"array","items":{"type":"string","format":"binary"},"description":"PDF or DOCX files (max 10, max 50MB each)"},"metadata":{"type":"string","description":"Stringified JSON SendContractDto (without files)"}}}]}}}},"responses":{"202":{"description":"Contract created and queued for processing"},"400":{"description":"Invalid request (missing file, signers, or invalid email)"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:write","security":[{"bearerAuth":[]},{"oauth2":["contracts:write"]}]}},"/api/v1/contracts/stats":{"get":{"operationId":"ContractsController_getStats","summary":"Get contract statistics","parameters":[{"name":"userId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Statistics retrieved successfully"}},"tags":["contracts"],"x-econtract-auth":"machine","x-econtract-scope":"contracts:read","security":[{"bearerAuth":[]},{"oauth2":["contracts:read"]}]}},"/api/v1/external-signers":{"post":{"operationId":"SignersController_create","summary":"Create external signer","responses":{"201":{"description":"External signer created successfully"},"409":{"description":"Email already exists"}},"tags":["signers"],"x-econtract-auth":"machine","x-econtract-scope":"signing:write","security":[{"bearerAuth":[]},{"oauth2":["signing:write"]}]},"get":{"operationId":"SignersController_findAll","summary":"List external signers","responses":{"200":{"description":"External signers retrieved successfully"}},"tags":["signers"],"x-econtract-auth":"machine","x-econtract-scope":"signing:read","security":[{"bearerAuth":[]},{"oauth2":["signing:read"]}]}},"/api/v1/external-signers/{id}":{"get":{"operationId":"SignersController_findById","summary":"Get external signer by ID","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"External signer retrieved successfully"},"404":{"description":"External signer not found"}},"tags":["signers"],"x-econtract-auth":"machine","x-econtract-scope":"signing:read","security":[{"bearerAuth":[]},{"oauth2":["signing:read"]}]},"put":{"operationId":"SignersController_update","summary":"Update external signer","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"External signer updated successfully"},"404":{"description":"External signer not found"}},"tags":["signers"],"x-econtract-auth":"machine","x-econtract-scope":"signing:write","security":[{"bearerAuth":[]},{"oauth2":["signing:write"]}]},"delete":{"operationId":"SignersController_delete","summary":"Delete external signer","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"External signer deleted successfully"},"404":{"description":"External signer not found"}},"tags":["signers"],"x-econtract-auth":"machine","x-econtract-scope":"signing:write","security":[{"bearerAuth":[]},{"oauth2":["signing:write"]}]}},"/api/v1/external-signers/audit-trail":{"get":{"operationId":"SigningController_getAuditTrail","summary":"Get contract audit trail via signing token","parameters":[{"name":"token","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["signing"],"x-econtract-auth":"public","security":[]}},"/api/v1/external-signers/contract-file":{"get":{"operationId":"SigningController_getContractFile","summary":"Download contract file via signing token","parameters":[{"name":"token","required":true,"in":"query","schema":{"type":"string"}},{"name":"fileId","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"File stream returned"},"404":{"description":"Token or file not found"}},"tags":["signing"],"x-econtract-auth":"public","security":[]}},"/api/v1/external-signers/decline":{"post":{"operationId":"SigningController_declineContract","summary":"Decline contract as external signer","responses":{"200":{"description":"Contract declined successfully"},"404":{"description":"Token not found"}},"tags":["signing"],"x-econtract-auth":"public","security":[]}},"/api/v1/external-signers/sign":{"post":{"operationId":"SigningController_signContract","summary":"Sign contract as external signer","responses":{"200":{"description":"Contract signed successfully"},"400":{"description":"OTP not verified or invalid state"},"404":{"description":"Token not found"}},"tags":["signing"],"x-econtract-auth":"public","security":[]}},"/api/v1/external-signers/verify":{"post":{"operationId":"SigningController_verifyToken","summary":"Verify signing token and get contract info","responses":{"200":{"description":"Token verified, contract info returned"},"404":{"description":"Token not found or invalid"}},"tags":["signing"],"x-econtract-auth":"public","security":[]}},"/api/v1/external-signers/verify-chain":{"get":{"operationId":"SigningController_verifyChain","summary":"Verify contract integrity chain via signing token","parameters":[{"name":"token","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["signing"],"x-econtract-auth":"public","security":[]}},"/api/v1/files/{fileKey}":{"get":{"operationId":"FilesController_downloadFile","summary":"Download file (streaming)","parameters":[{"name":"fileKey","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"File stream"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:read","security":[{"bearerAuth":[]},{"oauth2":["files:read"]}]},"delete":{"operationId":"FilesController_deleteFile","summary":"Delete file","parameters":[{"name":"fileKey","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"File deleted"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:delete","security":[{"bearerAuth":[]},{"oauth2":["files:delete"]}]}},"/api/v1/files/{fileKey}/metadata":{"get":{"operationId":"FilesController_getFileMetadata","summary":"Get file metadata","parameters":[{"name":"fileKey","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"File metadata"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:read","security":[{"bearerAuth":[]},{"oauth2":["files:read"]}]}},"/api/v1/files/{fileKey}/url":{"get":{"operationId":"FilesController_getDownloadUrl","summary":"Get presigned download URL","parameters":[{"name":"fileKey","required":true,"in":"path","schema":{"type":"string"}},{"name":"expiryMinutes","required":true,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":"Download URL generated"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:read","security":[{"bearerAuth":[]},{"oauth2":["files:read"]}]}},"/api/v1/files/download":{"get":{"operationId":"FilesController_downloadFileByKey","summary":"Download file by key query param (streaming)","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"File stream"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:read","security":[{"bearerAuth":[]},{"oauth2":["files:read"]}]}},"/api/v1/files/metadata":{"get":{"operationId":"FilesController_getFileMetadataByKey","summary":"Get file metadata by query param","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"File metadata"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:read","security":[{"bearerAuth":[]},{"oauth2":["files:read"]}]}},"/api/v1/files/upload":{"post":{"operationId":"FilesController_uploadFile","summary":"Upload file directly (max 50MB)","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"},"fileName":{"type":"string"},"fileType":{"type":"string"},"entityType":{"type":"string"},"entityId":{"type":"string"}}}}}},"responses":{"201":{"description":""}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:write","security":[{"bearerAuth":[]},{"oauth2":["files:write"]}]}},"/api/v1/files/upload/multipart/{uploadId}":{"delete":{"operationId":"FilesController_abortMultipartUpload","summary":"Abort multipart upload","parameters":[{"name":"uploadId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Multipart upload aborted"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:write","security":[{"bearerAuth":[]},{"oauth2":["files:write"]}]}},"/api/v1/files/upload/multipart/complete":{"post":{"operationId":"FilesController_completeMultipartUpload","summary":"Complete multipart upload","responses":{"200":{"description":"Multipart upload completed"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:write","security":[{"bearerAuth":[]},{"oauth2":["files:write"]}]}},"/api/v1/files/upload/multipart/initiate":{"post":{"operationId":"FilesController_initiateMultipartUpload","summary":"Initiate multipart upload for large files","responses":{"200":{"description":"Multipart upload initiated"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:write","security":[{"bearerAuth":[]},{"oauth2":["files:write"]}]}},"/api/v1/files/upload/multipart/part-url":{"post":{"operationId":"FilesController_getPartUploadUrl","summary":"Get presigned URL for uploading a part","responses":{"200":{"description":"Part upload URL generated"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:write","security":[{"bearerAuth":[]},{"oauth2":["files:write"]}]}},"/api/v1/files/upload/url":{"post":{"operationId":"FilesController_getUploadUrl","summary":"Get presigned upload URL for client-side upload","responses":{"200":{"description":"Upload URL generated"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:write","security":[{"bearerAuth":[]},{"oauth2":["files:write"]}]}},"/api/v1/files/url":{"get":{"operationId":"FilesController_getDownloadUrlByKey","summary":"Get presigned download URL by query param","parameters":[{"name":"key","required":true,"in":"query","schema":{"type":"string"}},{"name":"expiryMinutes","required":true,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":"Download URL generated"}},"tags":["files"],"x-econtract-auth":"machine","x-econtract-scope":"files:read","security":[{"bearerAuth":[]},{"oauth2":["files:read"]}]}},"/api/v1/guides":{"get":{"operationId":"GuidesController_findAll","summary":"List guides","parameters":[{"name":"locale","required":true,"in":"query","schema":{"type":"string"}},{"name":"category","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":""}},"tags":["guides"],"x-econtract-auth":"public","security":[]}},"/api/v1/guides/{slug}":{"get":{"operationId":"GuidesController_findBySlug","summary":"Get guide by slug","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["guides"],"x-econtract-auth":"public","security":[]}},"/api/v1/guides/categories":{"get":{"operationId":"GuidesController_getCategories","summary":"List guide categories","parameters":[{"name":"locale","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["guides"],"x-econtract-auth":"public","security":[]}},"/api/v1/otp/send":{"post":{"operationId":"OtpController_sendOtp","summary":"Send OTP to signer email","responses":{"200":{"description":"OTP sent successfully"},"400":{"description":"Invalid request"},"429":{"description":"Rate limited"}},"tags":["otp"],"x-econtract-auth":"public","security":[]}},"/api/v1/otp/verify":{"post":{"operationId":"OtpController_verifyOtp","summary":"Verify OTP code","responses":{"200":{"description":"OTP verification result"},"400":{"description":"Invalid OTP or max attempts exceeded"}},"tags":["otp"],"x-econtract-auth":"public","security":[]}},"/api/v1/signing-tokens/{token}/status":{"get":{"operationId":"TokensController_getTokenStatus","summary":"Get signing token status (including OTP verification)","parameters":[{"name":"token","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Token status retrieved"},"404":{"description":"Token not found"}},"tags":["tokens"],"x-econtract-auth":"machine","x-econtract-scope":"signing:read","security":[{"bearerAuth":[]},{"oauth2":["signing:read"]}]}},"/api/v1/signing-tokens/validate":{"post":{"operationId":"TokensController_validate","summary":"Validate signing token","responses":{"200":{"description":"Token is valid"},"401":{"description":"Token is invalid or expired"},"404":{"description":"Token not found"}},"tags":["tokens"],"x-econtract-auth":"public","security":[]}},"/api/v1/system-templates":{"get":{"operationId":"TemplatesController_findAll","summary":"List system templates","parameters":[{"name":"category","required":true,"in":"query","schema":{"type":"string"}},{"name":"locale","required":true,"in":"query","schema":{"type":"string"}},{"name":"country","required":true,"in":"query","schema":{"type":"string"}},{"name":"search","required":true,"in":"query","schema":{"type":"string"}},{"name":"active","required":true,"in":"query","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"number"}},{"name":"limit","required":true,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":""}},"tags":["system-templates"],"x-econtract-auth":"public","security":[]}},"/api/v1/system-templates/{slug}":{"get":{"operationId":"TemplatesController_findBySlug","summary":"Get template by slug","parameters":[{"name":"slug","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["system-templates"],"x-econtract-auth":"public","security":[]}},"/api/v1/system-templates/categories":{"get":{"operationId":"TemplatesController_getCategories","summary":"List template categories","parameters":[{"name":"locale","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["system-templates"],"x-econtract-auth":"public","security":[]}},"/api/v1/templates":{"get":{"operationId":"TemplatesController_findAll","summary":"List all templates","responses":{"200":{"description":"Templates retrieved successfully"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:read","security":[{"bearerAuth":[]},{"oauth2":["templates:read"]}]},"post":{"operationId":"TemplatesController_create","summary":"Create new template","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateDto"}}}},"responses":{"201":{"description":"Template created successfully"},"409":{"description":"Template code already exists"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:write","security":[{"bearerAuth":[]},{"oauth2":["templates:write"]}]}},"/api/v1/templates/{id}":{"get":{"operationId":"TemplatesController_findById","summary":"Get template by ID","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Template retrieved successfully"},"404":{"description":"Template not found"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:read","security":[{"bearerAuth":[]},{"oauth2":["templates:read"]}]},"put":{"operationId":"TemplatesController_update","summary":"Update template","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTemplateDto"}}}},"responses":{"200":{"description":"Template updated successfully"},"404":{"description":"Template not found"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:write","security":[{"bearerAuth":[]},{"oauth2":["templates:write"]}]},"delete":{"operationId":"TemplatesController_delete","summary":"Delete template","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Template deleted successfully"},"404":{"description":"Template not found"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:delete","security":[{"bearerAuth":[]},{"oauth2":["templates:delete"]}]}},"/api/v1/templates/code/{code}":{"get":{"operationId":"TemplatesController_findByCode","summary":"Get template by code","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Template retrieved successfully"},"404":{"description":"Template not found"}},"tags":["templates"],"x-econtract-auth":"machine","x-econtract-scope":"templates:read","security":[{"bearerAuth":[]},{"oauth2":["templates:read"]}]}},"/api/v1/verify/contract/{code}":{"get":{"operationId":"VerifyController_verifyByContract","summary":"Verify signatures for a contract by code","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}},{"name":"tenant","required":true,"in":"query","description":"Workspace code","schema":{"type":"string"}}],"responses":{"200":{"description":"Verification results"},"404":{"description":"Contract not found"}},"tags":["verify"],"x-econtract-auth":"public","security":[]}},"/api/v1/verify/pdf":{"post":{"operationId":"VerifyController_verifyPdf","summary":"Verify digital signatures in an uploaded PDF","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"Verification results"},"400":{"description":"Invalid file"},"429":{"description":"Too many requests"}},"tags":["verify"],"x-econtract-auth":"public","security":[]}},"/api/v1/webhooks":{"post":{"operationId":"WebhooksController_createWebhook","summary":"Create a webhook","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookDto"}}}},"responses":{"201":{"description":""}},"tags":["webhooks"],"x-econtract-auth":"machine","x-econtract-scope":"webhooks:write","security":[{"bearerAuth":[]},{"oauth2":["webhooks:write"]}]},"get":{"operationId":"WebhooksController_listWebhooks","summary":"List webhooks for workspace","responses":{"200":{"description":""}},"tags":["webhooks"],"x-econtract-auth":"machine","x-econtract-scope":"webhooks:read","security":[{"bearerAuth":[]},{"oauth2":["webhooks:read"]}]}},"/api/v1/webhooks/{id}":{"get":{"operationId":"WebhooksController_getWebhook","summary":"Get webhook detail with recent deliveries","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["webhooks"],"x-econtract-auth":"machine","x-econtract-scope":"webhooks:read","security":[{"bearerAuth":[]},{"oauth2":["webhooks:read"]}]},"patch":{"operationId":"WebhooksController_updateWebhook","summary":"Update a webhook","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookDto"}}}},"responses":{"200":{"description":""}},"tags":["webhooks"],"x-econtract-auth":"machine","x-econtract-scope":"webhooks:write","security":[{"bearerAuth":[]},{"oauth2":["webhooks:write"]}]},"delete":{"operationId":"WebhooksController_deleteWebhook","summary":"Delete a webhook","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["webhooks"],"x-econtract-auth":"machine","x-econtract-scope":"webhooks:write","security":[{"bearerAuth":[]},{"oauth2":["webhooks:write"]}]}},"/api/v1/webhooks/{id}/deliveries":{"get":{"operationId":"WebhooksController_listDeliveries","summary":"List webhook deliveries with pagination","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["webhooks"],"x-econtract-auth":"machine","x-econtract-scope":"webhooks:read","security":[{"bearerAuth":[]},{"oauth2":["webhooks:read"]}]}},"/api/v1/webhooks/{id}/test":{"post":{"operationId":"WebhooksController_testWebhook","summary":"Send test webhook event","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["webhooks"],"x-econtract-auth":"machine","x-econtract-scope":"webhooks:write","security":[{"bearerAuth":[]},{"oauth2":["webhooks:write"]}]}},"/api/v1/webhooks/deliveries/{deliveryId}/retry":{"post":{"operationId":"WebhooksController_retryDelivery","summary":"Retry a failed delivery","parameters":[{"name":"deliveryId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["webhooks"],"x-econtract-auth":"machine","x-econtract-scope":"webhooks:write","security":[{"bearerAuth":[]},{"oauth2":["webhooks:write"]}]}},"/api/v1/workflows/events/{contractId}":{"get":{"operationId":"WorkflowsController_getWorkflowEvents","summary":"Get workflow events for a contract","parameters":[{"name":"contractId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["workflows"],"x-econtract-auth":"machine","x-econtract-scope":"workflow:read","security":[{"bearerAuth":[]},{"oauth2":["workflow:read"]}]}},"/api/v1/workflows/state/{contractId}":{"get":{"operationId":"WorkflowsController_getWorkflowState","summary":"Get workflow state for a contract","parameters":[{"name":"contractId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["workflows"],"x-econtract-auth":"machine","x-econtract-scope":"workflow:read","security":[{"bearerAuth":[]},{"oauth2":["workflow:read"]}]}},"/verify-pdf":{"post":{"operationId":"PublicVerifyController_verifyPdf","summary":"Verify digital signatures in a PDF document","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"Verification results"},"400":{"description":"Invalid file or no signatures"},"429":{"description":"Rate limit exceeded"}},"tags":["Public Verify"],"x-econtract-auth":"public","security":[]}}},"components":{"schemas":{"AcceptAISuggestionsDto":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"}}},"AddContractFileDto":{"type":"object","properties":{}},"AddSignerDto":{"type":"object","properties":{"signerType":{"type":"string","enum":["internal","external"],"description":"internal = workspace user, external = anyone by email (default external)"},"signerId":{"type":"string","description":"Tenant user id (required for internal signers)"},"externalSignerId":{"type":"string","description":"External signer (address book) id"},"email":{"type":"string","description":"Signer email (required)","example":"ceo@partner.vn"},"name":{"type":"string","example":"Tran Thi B"},"signOrder":{"type":"number","description":"Position in sequential signing (1-based)","example":1},"metadata":{"type":"object","additionalProperties":true}}},"AISuggestRequestDto":{"type":"object","properties":{}},"AnalyzeContractRequest":{"type":"object","properties":{}},"AuditTrailChainDto":{"type":"object","properties":{"valid":{"type":"boolean","description":"Hash chain of the contract activities verifies"},"checkedAt":{"type":"string"},"totalEvents":{"type":"number"},"chainedEvents":{"type":"number"},"verifiedEvents":{"type":"number"},"unchainedEvents":{"type":"number"},"brokenAt":{"type":"number","description":"1-based position of the first broken link"}},"required":["valid","checkedAt"]},"AuditTrailContractDto":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"},"status":{"type":"string"},"createdAt":{"type":"string"},"completedAt":{"type":"object","nullable":true}},"required":["id","code","title","status","createdAt","completedAt"]},"AuditTrailEventDto":{"type":"object","properties":{"type":{"type":"string","description":"Activity action (created, submitted, signed, ...) or workflow event (signer_notified, signer_viewed, signer_signed, ...)"},"source":{"type":"string","enum":["activity","workflow"],"description":"activity = hash-chained contract activity; workflow = signing workflow event"},"actorName":{"type":"object","nullable":true},"actorEmail":{"type":"object","nullable":true},"at":{"type":"string"},"ip":{"type":"object","nullable":true},"userAgent":{"type":"object","nullable":true},"details":{"type":"object","nullable":true,"additionalProperties":true}},"required":["type","source","actorName","actorEmail","at","ip","userAgent","details"]},"AuditTrailResponseDto":{"type":"object","properties":{"contract":{"$ref":"#/components/schemas/AuditTrailContractDto"},"signers":{"type":"array","items":{"$ref":"#/components/schemas/AuditTrailSignerDto"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/AuditTrailEventDto"}},"chain":{"$ref":"#/components/schemas/AuditTrailChainDto"},"documentSha256":{"type":"object","nullable":true,"description":"SHA-256 of the document GET /contracts/:id/document returns by default"},"documentVersion":{"type":"string","nullable":true,"enum":["signed","current"]}},"required":["contract","signers","events","chain","documentSha256","documentVersion"]},"AuditTrailSignerDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"object","nullable":true},"email":{"type":"string"},"signerType":{"type":"string","enum":["internal","external"]},"status":{"type":"string"},"signOrder":{"type":"number"},"notifiedAt":{"type":"object","nullable":true},"viewedAt":{"type":"object","nullable":true},"signedAt":{"type":"object","nullable":true},"rejectedAt":{"type":"object","nullable":true},"rejectionReason":{"type":"object","nullable":true},"ipAddress":{"type":"object","nullable":true}},"required":["id","name","email","signerType","status","signOrder"]},"ContractPrefillRequestDto":{"type":"object","properties":{}},"CreateContractDto":{"type":"object","properties":{"title":{"type":"string","example":"Service Agreement - Q2 2026"},"description":{"type":"string"},"fileKey":{"type":"string","description":"Key of a file uploaded with POST /files/upload"},"fileName":{"type":"string"},"fileSize":{"type":"number"},"fileHash":{"type":"string"},"fileType":{"type":"string","enum":["pdf","docx"]},"signingOrderType":{"type":"string","enum":["sequential","parallel"],"default":"sequential"},"expiresInDays":{"type":"number","description":"Days until the contract expires (default 90)","example":30},"metadata":{"type":"object","additionalProperties":true}},"required":["title"]},"CreateTemplateDto":{"type":"object","properties":{}},"CreateWebhookDto":{"type":"object","properties":{}},"ForgotPasswordDto":{"type":"object","properties":{}},"GenerateFromTemplateDto":{"type":"object","properties":{"values":{"type":"object","additionalProperties":{"type":"string"},"example":{"companyName":"Acme Corp"}},"title":{"type":"string","example":"Service Agreement - Acme"},"description":{"type":"string"},"signingOrderType":{"type":"string","enum":["sequential","parallel"],"default":"sequential"},"expiresInDays":{"type":"number","example":30}},"required":["values","title"]},"LoginDto":{"type":"object","properties":{}},"RegisterDto":{"type":"object","properties":{}},"ResendSigningRequestDto":{"type":"object","properties":{"signerId":{"type":"string","description":"Only this signer (default: every pending signer)"}}},"ResetPasswordDto":{"type":"object","properties":{}},"ResolveSignerCandidatesRequestDto":{"type":"object","properties":{}},"SendContractDto":{"type":"object","properties":{"title":{"type":"string","example":"Service Agreement - Q2 2026"},"description":{"type":"string"},"signingOrderType":{"type":"string","enum":["sequential","parallel"],"default":"sequential"},"signers":{"description":"At least one signer","type":"array","items":{"$ref":"#/components/schemas/AddSignerDto"}},"sendNotifications":{"type":"boolean","default":true,"description":"Legacy switch; prefer delivery. false = no invitation emails"},"delivery":{"type":"string","enum":["email","link","both"],"default":"email","description":"email/both: invitation emails; link: no emails, get links from POST /contracts/:id/signing-links"},"files":{"maxItems":10,"description":"JSON uploads: base64 content or https URL (multipart requests use the files field instead)","type":"array","items":{"$ref":"#/components/schemas/SendContractFileDto"}},"fileKey":{"type":"string","description":"Key of a previously uploaded file"},"fileName":{"type":"string"},"fileSize":{"type":"number"},"fileHash":{"type":"string"},"templateId":{"type":"string","description":"Generate the document from this template"},"templateValues":{"type":"object","additionalProperties":{"type":"string"},"description":"Required with templateId"},"expiresInDays":{"type":"number","default":90,"example":30},"metadata":{"type":"object","additionalProperties":true},"useAiTitle":{"type":"boolean"},"useAiDescription":{"type":"boolean"}},"required":["title","signers"]},"SendContractFileDto":{"type":"object","properties":{"filename":{"type":"string","description":"File name ending in .pdf or .docx (required with contentBase64)","example":"nda.pdf"},"contentBase64":{"type":"string","description":"Base64 file content (max 50 MB decoded). Use either contentBase64 or url."},"contentType":{"type":"string","enum":["application/pdf","application/vnd.openxmlformats-officedocument.wordprocessingml.document"]},"url":{"type":"string","description":"https URL to fetch the file from (public host, no redirects, 30 s, 50 MB)","example":"https://example.com/nda.pdf"}}},"SigningLinkDto":{"type":"object","properties":{"signerId":{"type":"string"},"name":{"type":"object","nullable":true},"email":{"type":"string"},"signerType":{"type":"string","enum":["internal","external"]},"status":{"type":"string","enum":["pending","notified","viewed","signed","rejected","expired"]},"signingUrl":{"type":"object","nullable":true,"description":"External: /sign/<token>; internal: dashboard link; null once signed/declined"},"expiresAt":{"type":"object","nullable":true,"description":"Token expiry (external signers)"}},"required":["signerId","name","email","signerType","status","signingUrl","expiresAt"]},"SigningLinksResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SigningLinkDto"}}},"required":["data"]},"SubmitContractDto":{"type":"object","properties":{"sendNotifications":{"type":"boolean","default":true,"description":"false = no invitation emails (distribute links yourself)"}}},"UpdateContractDto":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"},"fileKey":{"type":"string"},"fileName":{"type":"string"},"fileSize":{"type":"number"},"fileHash":{"type":"string"},"fileType":{"type":"string","enum":["pdf","docx"]},"signingOrderType":{"type":"string","enum":["sequential","parallel"]},"expiresAt":{"type":"string","description":"ISO 8601 date-time","example":"2026-12-31T00:00:00.000Z"},"metadata":{"type":"object","additionalProperties":true,"description":"Replaces the metadata object (e.g. signatureConfig)"}}},"UpdateTemplateDto":{"type":"object","properties":{}},"UpdateWebhookDto":{"type":"object","properties":{}},"VerifyEmailDto":{"type":"object","properties":{}},"VoidContractDto":{"type":"object","properties":{"reason":{"type":"string","example":"Terms changed"}}}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key `cl_live_…` or OAuth access token `eco_at_…` in `Authorization: Bearer`. Public operations (`x-econtract-auth: public`) need no credential."},"oauth2":{"type":"oauth2","description":"OAuth 2.1 authorization code flow with PKCE (S256 only). Discovery: https://api.econtract.online/.well-known/oauth-authorization-server. Clients register with a Client ID Metadata Document or dynamic client registration (https://api.econtract.online/oauth/register). Ask for resource=https://api.econtract.online to call this API. See https://developers.econtract.online/docs/oauth.","flows":{"authorizationCode":{"authorizationUrl":"https://api.econtract.online/oauth/authorize","tokenUrl":"https://api.econtract.online/oauth/token","refreshUrl":"https://api.econtract.online/oauth/token","scopes":{"contracts:read":"View contracts, their status, signed documents and audit trails","contracts:write":"Create, send, update and void contracts, and issue signing links","contracts:delete":"Delete contracts","templates:read":"View contract templates","templates:write":"Create and update contract templates","templates:delete":"Delete contract templates","signing:read":"View signing sessions and signer data","signing:write":"Manage signing sessions (never signs on your behalf)","workflow:read":"View workflow status","workflow:write":"Run workflow actions","files:read":"Download files","files:write":"Upload and update files","files:delete":"Delete files","webhooks:read":"View webhooks and their delivery logs","webhooks:write":"Create, update, test and delete webhooks","ai:use":"Use AI features such as contract analysis","offline_access":"Stay connected when you are not using the app (refresh tokens)"}}}}}}}