Refunds & Notifications Β· Article 6.1
When refunds happen: the Γβ_REFUND amendment branches
A refund in Clozo is always tied to a Γβ_REFUND amendment branch β partial (revised total smaller than deposit paid) or full (revised total at zero). The amendment is the legal trigger; the refund is the cash consequence.
Clozo doesn't have a "give the client some money back" button divorced from the contract. Every refund is the cash leg of a signed amendment that reduced the total below what the client already paid as deposit. This design is deliberate β refunds without a corresponding contract change are a tax-audit nightmare; tying every refund to a signed amendment ensures the legal documents (Stornorechnung, Berichtigung, Gutschrift) and the cash movement are always in sync.
Quick visual tour

Step 1: Refund request arrives. Don't panic - there's a clear path.

Step 2: Check eligibility on the decision tree. Most cases are valid.

Step 3: Press Refund. Stripe handles the actual money movement.

Step 4: Watch the coins fly back from your vault to the client.

Step 5: Issue a credit note. The accounting closes cleanly.
Step by step
Decide the refund amount.
It's not a number you type β it's the consequence of editing line items in an amendment. New total below deposit collected Γ’β β refund. New total at zero Γ’β β full deposit refunded.
Open the amendment wizard.
/proposals/{id}/amend. Reduce line items in Step 1 until the wizard's deposit-context banner shows "Refund: Γ’βΒ¬X".Set the reason on Step 2.
Minimum 30 characters (the longer minimum reflects that you're shrinking β make it explicit). The reason appears on the addendum, on the credit note narrative, and is part of the audit trail.
Send and wait for client to sign.
The amendment goes through the standard PIN-gated flow (article 7.4). On signing, the refund pipeline runs.
Watch the refund timeline.
A "Refund in progress" banner appears on the proposal page once signed. Stages: issued Γ’β β requested (Stripe accepted) Γ’β β settled (Stripe webhook confirmed) β see article 8.4.
After the client signs the Γβ_REFUND amendment, the proposal banner switches to "Refund in progress" with the credit note number and an expected window. The Documents dropdown gets the new docs (Storno, Berichtigung, Gutschrift). The credit note's refund_status drives the UI: requested Γ’β β "Refund in progress, expected in 3β5 business days"; failed Γ’β β "Refund failed" with retry / manual options; succeeded / manual Γ’β β "Refund completed on [date]".
Why this works this way
The refund flow is rooted in process_amendment_signed (backend/apps/proposals/amendment_postsign.py). At sign time, the function checks amendment.triggers_refund. If true, it computes refund_gross = deposit_paid Γ’Λβ revised_total (clamped at zero) and:
1. Creates a DepositInvoiceCorrection (Berichtigung der Anzahlungsrechnung) with correction_type=partial_refund or full_cancellation.
2. Creates a CreditNote (Gutschrift) with refund_status=pending, the gross/net/VAT amounts split via _split_refund_vat, and references to the original deposit invoice (number + date) per Art. 219 EU VAT Directive.
3. Calls _trigger_stripe_refund to attempt the cash leg via Stripe API on the freelancer's connected account.
Two different "trigger" sources produce a refund:
| Trigger | Branch | Docs created | Cash leg |
|---|---|---|---|
Amendment with revised_total < deposit_paid, original deposit paid via Stripe | Γβ_REFUND partial OR full | Storno + Berichtigung + Gutschrift (+ cancelled FinalInvoice on full) | Stripe refund (article 8.2) |
Amendment with revised_total < deposit_paid, original deposit paid via SEPA / out-of-band | Γβ_REFUND partial OR full | Same docs | Manual SEPA (article 8.3 + 8.9) |
There's no "refund the final payment" path because the final payment isn't a deposit β once Paid, the contract is settled. To partially refund a paid contract, you create an amendment that reduces the scope (ΓβΓ’Λβ), sign it; the proposal moves back to Awaiting final payment with a smaller balance, and any over-collected amount is handled via the post-sign pipeline as a Γβ_REFUND. The amendment is always the front door.
Note: as of 2026-05-07, direct deletion of an in_work proposal is also forbidden β the backend rejects DELETE with HTTP 409 in_work_requires_amendment. The amendment wizard's red 'Refund all' callout (Step 1) is the only UI path to refund a paid deposit; clicking it sets every line-item qty to 0, the wizard surfaces the Γβ_REFUND full branch, and on client signature this article's pipeline runs (per [D-125]).
Troubleshooting
Keep reading
Proposals & Invoices
The 4 delta branches: Ξ+, Ξβ, Ξ=0, Ξ_REFUND
Every signed amendment falls into one of four branches based on (a) the sign of the cost change and (b) whether the proposal was already paid. Each branch fires a different document chain. This is the central conceptual map for the entire amendment system.
Refunds & Notifications
Stripe automatic refund (Direct Charges via Connect)
When the original deposit was paid via Stripe, the refund is automatic. Clozo issues a Refund on the freelancer's connected account, watches for the `refund.updated` webhook, and flips the credit note to `succeeded` once Stripe confirms β typically within 3β5 business days for the cash to reach the client.
Refunds & Notifications
SEPA / out-of-band refund: when automation can't help
When the original deposit was paid via SEPA bank transfer (or any non-Stripe channel), Clozo can't refund automatically β Stripe API has nothing to refund. You issue the SEPA transfer manually from your bank, then click `Mark refunded` to update the credit note and notify the client.
Refunds & Notifications
Refund stages: issued β requested β succeeded (or manual)
The credit note moves through up to four states from creation to settled. Each state corresponds to a specific point in the refund lifecycle, with predictable UI badges and email triggers.