Lifecycle ยท Article 2.13
Timeline events: every event type explained
The Timeline component on every proposal detail page records 21+ event types. This is the canonical list with descriptions and triggers, useful when auditing what happened on a proposal.
The Timeline is your audit trail. Every webhook, every click, every email send produces an event. We preserve them for the lifetime of the proposal (10 years for legal retention). When you're trying to figure out "wait, when did the client actually sign?" or "did the deposit invoice ever go out?", Timeline is the source of truth โ even when the UI badge or email confirmation gives you a different impression.
Why this works this way
Timeline events are stored in ProposalTimelineEvent model with fields: event_type (enum), created_by (User or null for client-initiated), data (JSON: IPs, amounts, signature evidence, etc.), created_at (UTC timestamp). They are append-only โ we never edit or delete an event. If a process is undone (e.g., status reverted), we record a new event explaining the undo, leaving the original intact.
### Reference: all event types
| Event | Trigger | Key metadata |
|---|---|---|
created | Proposal first saved | created_by user |
sent | Freelancer clicks Send | to_email, sent_from_ip |
viewed | Client first opens link with valid PIN | viewer_ip, user_agent |
signed | Client clicks Sign on public page | signer_name, signer_ip, ua, signed_at, consent |
pdf_generated | Async PDF render completes | doc_type (PRO/AGR/CON/DEP/INV/STR/DCR/CRN/REC), r2_key |
deposit_paid | Stripe webhook or manual mark | method, amount, payment_intent_id |
final_invoice_issued | Freelancer issues final invoice | invoice_number, total |
payment_received (final) | Stripe webhook or manual mark | method, amount |
completed | Freelancer marks completed | notes |
declined | Client declines on public page | decline_reason |
expired | 90-day cron job | days_since_sent |
archived | Freelancer archives | reason |
amendment_proposed | Amendment created | amendment_id, delta_total |
amendment_viewed | Client opens amendment link | viewer_ip |
amendment_signed | Client signs amendment | signer_name, ip, evidence_stack |
amendment_declined | Client declines amendment | decline_reason |
amendment_cancelled | Freelancer cancels amendment before signing | cancelled_by |
amendment_expired | Amendment 90-day expiry | โ |
refund_initiated | Refund flow triggered | credit_note_number, amount |
refund_completed | Stripe webhook or manual mark | method, completed_at |
Troubleshooting
Keep reading
Lifecycle
The proposal lifecycle, end to end
Every proposal goes through up to nine status transitions, with two actors (you and your client) handing off control along the way. This is the canonical map.
Lifecycle
Status: Signed โ legally binding, audit trail captured
The client clicked Sign. Clozo collects an eIDAS-compliant evidence stack, generates the signed Service Agreement PDF, fires confirmation emails to both parties, and queues the deposit invoice. The proposal is now a contract.