Contract Lifecycle
The ProfessionalContract status machine: from open to terminated, the three status-update endpoints, and the termination PDF attachment paths.
TL;DR
Status machine
A contract moves through these statuses:
open
Contract created, not yet filled. The professional hasn't started completing it.
filling
Contract is being filled by the professional. Digital signature pending.
in_approval
Contract submitted for approval. Waiting for the business to approve.
approved
Contract is active and valid. This is the steady state.
termination_requested
Termination has been requested. Waiting for the distrato PDF to be attached.
terminated
Contract is ended. The termination PDF is attached and the contract is closed.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /professional-contracts | List all contracts for the current business. |
| POST | /professional-contracts | Create a new contract. |
| GET | /professional-contracts/{id} | Get a single contract. |
| PATCH | /professional-contracts/{id} | Update contract data (mutable fields only). |
| PATCH | /professional-contracts/{id}/update-status | Transition contract status. Supports termination PDF attachment. |
| PATCH | /professional-contracts/update-status | Body-based variant — contract id in the request body. |
| PATCH | /professional-contracts/{id}/in-approval | Deprecated — transition to in_approval status. |
| PATCH | /professional-contracts/{id}/cancellation-request | Deprecated — request contract cancellation. |
| DELETE | /professional-contracts/{id} | Deprecated — soft-delete a contract. |
Lifecycle flow
Creating a contract
A contract is typically created via a BusinessRequest (new_contract or new_contract_pdf). The system creates the contract and links it to the request.
Status transitions
open → filling
The professional starts filling the contract. Automatic transition when the contract data is partially submitted.
filling → in_approval
Contract is submitted for approval. The business reviews and approves or rejects.
in_approval → approved
Business approves the contract. The contract is now active.
approved → termination_requested
Termination is requested via BusinessRequest (terminate_contract) or direct status update. The contract enters the termination flow.
termination_requested → terminated
The distrato PDF is attached and the contract is terminated. The column is locked once set.
Termination PDF attachment paths
The distrato PDF can be attached in three ways:
- On create with
data.pdf_url— contract goes directly from approved → terminated (skips termination_requested). Use when the signed PDF is already available. - On status update to closed — pass a top-level
termination_pdf_urlin the status-update payload. The URL is written after the contract transitions to terminated. - On direct contract status update to terminated — pass
termination_pdf_urlin the payload. Same lock + precondition rules apply.
termination_pdf_url errors with 422 TerminationPdfUrlAlreadySet.
Gotchas
- The deprecated
/in-approvaland/cancellation-requestendpoints should not be used for new integrations. - The body-based
/professional-contracts/update-statusrequirescontract_idin the request body. - The
dataJSON field on a BusinessRequest is immutable pastdraft/openstatus. - Termination PDF paths write only to the contract column, not to the BusinessRequest
data.