Dunning
A dunning policy is the staged sequence of actions Kontorion takes after an invoice goes past its due_date. Each policy is an ordered list of steps; each step has a days_after_due offset, an action (send_email, grace, suspend, cancel), and - for send_email - an email_event identifier that downstream notification handlers route on. A scheduled background runner picks up overdue invoices, walks their policy, and either escalates or recovers based on payment status.
Step actions
| Action | Effect |
|---|---|
send_email | Publishes a dunning.step.email event with the configured email_event payload - your notification service renders + sends the message |
grace | Publishes dunning.step.grace and moves the subscription's DunningStage to GRACED. The subscription itself stays in DUNNING; no access change yet |
suspend | Publishes dunning.step.suspend, moves the DunningStage to SUSPENDED (revoke access). Subscription is still in DUNNING until cancelled |
cancel | Publishes dunning.step.cancel, transitions the subscription to CANCELLED (terminal) |
send_email requires a non-empty email_event value (the validator rejects empty). The other actions don't take a payload.
Step ordering
Steps are validated to be monotonically increasing by days_after_due - each step must have a strictly larger offset than the previous, and all values must be ≥ 1. Same-day steps are explicitly rejected at create/update time.
days_after_due is measured from the invoice's due date, not from the previous step's execution time. A step with days_after_due: 14 always fires on day 14 past due, regardless of when earlier steps ran.
Policy shape
Code
| Field | Notes |
|---|---|
name | Required, free-form |
is_active | When false the runner skips this policy |
plan_id | null for the org-level default; set for a per-plan override |
steps | Required, at least one - see Step ordering |
Configuration
The org has a single default dunning policy at /v1/dunning-policy (singular). Use PUT to upsert it; the body carries the name and the ordered steps. The first call creates it (201 Created); subsequent calls update it (200 OK).
Code
days_after_due must be at least 1 per step (validated server-side).
Per-plan overrides live at /v1/plans/{planId}/dunning-policy; same PUT/DELETE shape.
Per-plan override (one per plan, takes precedence over the org default for subscriptions on that plan):
- Subscriptions - state transitions driven by dunning
- Payments - the retry layer dunning sits on top of
- Webhooks - event types emitted by the runner