Pagamenti Ricorrenti
Guida completa a subscription, addon seat-based, stati lifecycle, proration e calcolo rinnovi.
Pagamenti Ricorrenti e Subscription
Donutwork ti permette di gestire abbonamenti ricorrenti con un modello prevedibile:
- definisci il catalogo piani,
- associ il piano al cliente,
- gestisci il pricing a seat con gli addon,
- aggiorni il contratto nel tempo con operazioni lifecycle,
- mantieni la compatibilita con i flussi legacy gia in uso.
Questa pagina spiega il comportamento reale del sistema, con esempi pratici.
Cosa Contiene Una Subscription
Cadenza Rinnovo
Cicli a giorni o mesi (`renewal_days` / `renewal_months`) con data prossimo rinnovo (`next_renew`).
Gestione Trial
Periodo di prova opzionale prima del primo ciclo a pagamento.
Prezzi Seat + Addon
Il seat-based usa `addons[].quantity` (numero seat) e `addons[].price` (costo unitario seat).
Sconti e Imposte
Sconti addon, sconto globale, carryover credit e tasse sono applicati in ordine deterministico.
Come Viene Calcolato Il Prossimo Rinnovo
A ogni rinnovo, Donutwork calcola l'importo in questo ordine:
- Prezzo base del piano.
- Importi addon (
price * quantity) per addon con quantita attiva. - Sconto addon se configurato e non scaduto (
discount_until). - Sconto globale (
fixedopercentage, se attivo). - Credito carryover (
carryover_credit) da downgrade/proration precedenti. - Imposte del profilo fiscale associato.
Formula (semplificata)
net_subtotal = base + addons_dopo_sconti_addon
net_post_sconto_globale = net_subtotal - sconto_globale
net_due = max(0, net_post_sconto_globale - carryover_credit_usato)
vat_due = net_due * aliquota_iva
gross_due = net_due + vat_dueEsempio
- Piano base:
99.00 - Addon seat:
12.00x8seat =96.00 - Sconto addon 10% attivo => addon effettivo
86.40 - Subtotale netto =
185.40 - Sconto globale 15% =>
-27.81 - Credito carryover applicato:
20.00 - Netto dovuto =
137.59 - IVA 22% =
30.27 - Totale lordo =
167.86
Modello Seat-Based (Importante)
Il pricing a seat non usa uno schema separato. Nel modello attuale i seat sono addon:
- costo seat:
addons[].price - numero seat:
addons[].quantity - importo seat: incluso automaticamente nel rinnovo
Questo approccio e stabile e retrocompatibile con i flussi esistenti.
Stati Lifecycle (Significato Billing)
| Stato | Addebitabile | Significato |
|---|---|---|
active | Si | Fatturazione ricorrente normale. |
trialing | In genere no | Fase trial prima del primo rinnovo pagato. |
past_due | Condizionale | Stato di recupero dopo pagamento fallito. |
paused | No | Billing in pausa. Nessun addebito durante la pausa. |
cancel_pending | Nessun nuovo ciclo | Chiusura programmata a fine periodo (annullabile prima del boundary). |
cancelled | No | Subscription chiusa. |
Semantica Della Pausa
La pausa non genera arretrati automatici. Se un abbonamento viene riattivato dopo 2 mesi, i mesi in pausa non vengono addebitati retroattivamente. Il ciclo riparte dalla logica di resume.
Grafico Lifecycle
Operazioni Lifecycle Supportate
Tutte additive (nessuna rimozione route legacy):
| Operazione | Immediata | Fine Periodo | Proration | Note |
|---|---|---|---|---|
| Pause | Si | No | No | Sospende i rinnovi durante la pausa. |
| Resume | Si | No | No | resume_at opzionale per definire il nuovo boundary. |
| Change Plan | Si | Si | Opzionale | Supporta upgrade e downgrade. |
| Change Addons | Si | Si | Opzionale | Include aggiornamento quantita seat. |
| Cancel At Period End | Si (flag) | Effetto a boundary | No | Comportamento compatibile con legacy. |
| Undo Cancel At Period End | Si | No | No | Ripristina il piano attivo prima del boundary. |
| Next Renewal Preview | Read-only | N/A | N/A | Mostra breakdown completo del prossimo addebito. |
| Amendment History | N/A | N/A | N/A | Storico completo modifiche lifecycle. |
Esempi API
Pianificare Cambio Seat A Fine Periodo
{
"subscription": {
"action": "change_addons",
"when": "period_end",
"proration": false,
"addons": [
{
"name": "workspace_seat",
"quantity": 25,
"price": 12
}
]
}
}Anteprima Prossimo Rinnovo (estratto risposta)
{
"status": "success",
"data": {
"subscription_id": "sub_abc123",
"next_renewal": "2026-07-01",
"billable": true,
"pricing": {
"items": [
{ "service": "Subscription Base: Pro", "net": 99, "tax_rate": 22, "tax": 21.78, "total": 120.78 },
{ "service": "Addon: workspace_seat (Qty: 25)", "net": 300, "tax_rate": 22, "tax": 66, "total": 366 }
],
"net_due": 399,
"vat_due": 87.78,
"gross_due": 486.78
}
}
}FAQ API (Combinazioni Comuni)
Le combinazioni sotto fanno riferimento alle route Customer API documentate in /it/docs/api/customer#subscription-management.
Come posso fare l'upgrade di un piano?
Usa change-plan con applicazione immediata.
{
"lifecycle": {
"plan_id": "PLAN_ENTERPRISE_V3",
"when": "immediate",
"proration": true
}
}- Endpoint:
PUT /customers/{customerId}/subscriptions/{subscriptionId}/lifecycle/change-plan.json - Se il delta proration e positivo, viene tentato un addebito immediato.
- Se l'addebito immediato fallisce, la modifica non viene applicata.
Come posso fare il downgrade di un piano?
Usa sempre change-plan, puntando a un piano con prezzo inferiore.
{
"lifecycle": {
"plan_id": "PLAN_STARTER_V1",
"when": "immediate",
"proration": true
}
}- Endpoint:
PUT /customers/{customerId}/subscriptions/{subscriptionId}/lifecycle/change-plan.json - Con delta negativo, il sistema genera credito in
carryover_credit. - Il credito viene scalato sui rinnovi successivi prima di nuovi addebiti.
Come posso pianificare upgrade o downgrade dal prossimo rinnovo?
{
"lifecycle": {
"plan_id": "PLAN_PRO_V2",
"when": "period_end",
"proration": false
}
}- Endpoint:
PUT /customers/{customerId}/subscriptions/{subscriptionId}/lifecycle/change-plan.json - Nessun addebito immediato: la modifica si applica al boundary di rinnovo.
Come posso modificare la quantità degli addon (seat inclusi)?
{
"lifecycle": {
"addons": [
{ "element": "workspace_seat", "quantity": 25 }
],
"when": "immediate",
"proration": true
}
}- Endpoint:
PUT /customers/{customerId}/subscriptions/{subscriptionId}/lifecycle/change-addons.json - Nel modello seat-based, il numero seat e
addons[].quantity.
Come posso pianificare una modifica addon a fine periodo?
{
"lifecycle": {
"addons": [
{ "element": "workspace_seat", "quantity": 40 }
],
"when": "period_end",
"proration": false
}
}- Endpoint:
PUT /customers/{customerId}/subscriptions/{subscriptionId}/lifecycle/change-addons.json - Utile per cambi commerciali con decorrenza dal prossimo ciclo.
Come funziona pausa e ripresa dopo mesi?
- Metti in pausa:
PUT .../lifecycle/pause.json - Riprendi:
PUT .../lifecycle/resume.json(opzionaleresume_at)
Esempio reale:
- pausa il 1 maggio 2026
- riprendi il 1 luglio 2026
- non vengono addebitati retroattivamente maggio/giugno; il ciclo riparte dalla logica di resume.
Posso annullare una cancellazione gia impostata a fine periodo?
Sì:
- imposta cancellazione:
PUT .../lifecycle/cancel-at-period-end.json - annulla cancellazione:
PUT .../lifecycle/undo-cancel-at-period-end.json
Se annulli prima del boundary, la subscription torna operativa in stato active.
Come posso vedere prima l'impatto economico senza applicare modifiche?
Usa la preview lifecycle (no mutation):
{
"lifecycle": {
"action": "change_addons",
"addons": [
{ "element": "workspace_seat", "quantity": 30 }
]
}
}- Endpoint:
POST /customers/{customerId}/subscriptions/{subscriptionId}/lifecycle/preview.json - Risposta con
old_due,new_due,delta,direction.
Come gestisco retry sicuri lato integrazione?
Usa lifecycle.idempotency_key nelle chiamate mutative.
In caso di retry, eviti doppie applicazioni della stessa operazione.
Dove trovo lo storico completo delle modifiche?
Usa amendment history:
- Endpoint:
GET /customers/{customerId}/subscriptions/{subscriptionId}/amendments.json - Include azione, quando (
immediate/period_end), before/after, metadati proration.
Tabella rapida combinazioni
| Obiettivo | Endpoint | when | proration |
|---|---|---|---|
| Upgrade piano subito | .../change-plan.json | immediate | true |
| Downgrade piano subito | .../change-plan.json | immediate | true |
| Cambio piano da prossimo ciclo | .../change-plan.json | period_end | false |
| Aumento/diminuzione seat subito | .../change-addons.json | immediate | true |
| Cambio seat da prossimo ciclo | .../change-addons.json | period_end | false |
| Pausa servizio | .../pause.json | N/A | N/A |
| Ripresa servizio | .../resume.json | N/A | N/A |
| Cancella a fine periodo | .../cancel-at-period-end.json | boundary | N/A |
| Annulla cancellazione | .../undo-cancel-at-period-end.json | immediate | N/A |
| Simulazione impatto | .../preview.json | N/A | N/A |
| Storico modifiche | .../amendments.json | N/A | N/A |
Scenari Pratici
1) Pausa 2 Mesi, Poi Ripresa
- Pausa il 1 maggio 2026
- Riprendi il 1 luglio 2026
- Risultato: nessun addebito arretrato per maggio/giugno, rinnovo riallineato alla ripresa.
2) Upgrade Mid-Cycle
- Il cliente passa da 10 a 20 seat con modifica immediata.
- Delta proration positivo => addebito immediato di conguaglio.
3) Downgrade Mid-Cycle
- Il cliente riduce seat durante il periodo.
- Delta negativo => credito salvato in
carryover_credit. - Il credito viene consumato ai rinnovi successivi prima di nuovi addebiti.
4) Cancellazione In Attesa + Ripristino
- Cliente richiede cancellazione a fine periodo.
- Stato passa a
cancel_pending. - Se cambia idea prima del boundary,
undoriporta la subscription in stato attivo.
Backward Compatibility (No Break Changes)
I flussi panel/API legacy restano validi. Le nuove capability lifecycle sono opt-in.
| Area | Comportamento Legacy | Comportamento Attuale |
|---|---|---|
| Attach/detach subscription | Supportato | Ancora supportato |
| Route legacy update addon | Supportata | Ancora supportata |
| Campo status legacy | Presente | Ancora presente |
| Modello seat | Addon quantity | Stesso modello ufficiale |
| Integrazioni esistenti | Stabili | Adozione lifecycle progressiva |
Strategia Di Adozione
Se sei gia integrato con le route legacy, puoi lasciarle invariate e attivare gradualmente le route lifecycle dove ti servono pausa/resume, proration e storico amendment.
Checklist Consigliata
Modella I Seat Con Addon
Configura costo unitario seat sull'addon e aggiorna quantity per il numero seat.
Usa Scheduled Change
Per variazioni commerciali future, preferisci `period_end`.
Aumenta Trasparenza
Usa renewal preview e amendment history per supporto e audit.