Commitments and exit rules
A negotiated deal often says more than "this customer pays this much": the customer is committed for twelve months, must give three months' notice, or pays a fee to leave early. In Kontier these rules are written on the subscription itself, as the exit rules of a phase.
There is no separate agreement object. A commitment is part of the deal, so it lives where the deal lives: in the subscription's revisions, on the phase it applies to. A renegotiation that cuts the deal carries the rules forward or replaces them like any other part of a phase.
The exit block
Every phase can carry an exit object:
| Field | Shape | Meaning |
|---|---|---|
gate | none, warn or block | What the rule does to a cancellation inside the commitment. |
not_before | {"position": n}, optionally with subscription_id | The commitment: the subscription cannot be cancelled before phase n has ended. |
notice_duration | {"count": 3, "unit": "month"} | How much notice a cancellation must give. Units are day, week, month, year. |
fee | decimal string, e.g. "490.00" | An early-termination fee, in the subscription's currency. |
Positions are 0-based and refer to the phases of the live revision. Because
not_before points at a phase, not at a date, the commitment follows the
deal: if a pause moves the phase, the commitment moves with it.
The exit rules that apply are those of the phase in force at the instant the cancellation would take effect.
When a cancellation is refused
POST /v1/subscriptions/{id}/cancel evaluates the exit rules, and it is the only
operation that does. A cancellation is refused when the phase in force at the
cancellation instant has:
gate: "block", and- a
not_beforephase that has not ended by that instant, or whose end is not known yet (for example a phase that ends on an event that has not happened).
The refusal is 409 with code SUBSCRIPTION_EXIT_BLOCKED. It applies to every
form of cancel: when: {"kind": "now"}, and also when you plan one with
{"kind": "at", …} or {"kind": "period_end"}. A planned cancellation is
checked against its own instant, so you learn about the block when you plan it,
not when it would fire. A cancellation planned for an instant after the
committed phase has ended is accepted.
There is no override field on the cancel request. To end a blocked subscription
early, first change the deal: open a draft (cut or copy), change or remove the
phase's exit rules, publish, then cancel.
gate: "none" and gate: "warn" never refuse a cancellation; neither does a
phase without not_before. warn marks the rule for people reading the deal
(the quote document shows it); the API does not act on it.
Notice and fee are recorded, not enforced
notice_duration and fee are part of the deal: they are returned on the
revision and printed in the quote document the customer signs. The cancel
operation does not move a cancellation date to honour the notice, and it does not
charge the fee. Plan the cancellation for the right date yourself (when at),
and invoice a fee you are owed separately.
Co-terminated deals
not_before can point at a phase of another subscription, by adding its
subscription_id. This is how several subscriptions sold on one contract are
held to the same end: each says "not before phase 1 of subscription X has
ended", and a cancellation of any of them is refused until that phase is over.
Only the subscription you cancel is cancelled; the others are not affected.
Write the rules
The exit block is part of a phase, so it is written with the phase: in the whole
draft you send to PUT /v1/subscriptions/{id}/revisions/draft. That works for
revision 1 and for every later draft (open one with a cut or with
POST /v1/subscriptions/{id}/revisions/draft). To change the rules of one
phase, send the whole draft with the new exit on that phase. A phase that has
already started cannot change, so its exit rules cannot change either. The
change takes effect when the draft is published (or, for revision 1, when the
subscription is activated or its quote is signed).
A 12-month committed phase with three months' notice and a fee, then an open-ended continuation without a commitment:
cURL
"not_before": {"position": 0} on phase 0 means "not before this phase has
ended": the customer cannot leave during the first year. Phase 1 has no exit
block, so after the first year a cancellation is accepted.
A fixed term that ends the subscription instead of rolling on is a last phase
with then: "stop". When it closes, the subscription is cancelled with
cancellation_reason AGREEMENT_TERM_ENDED, which reporting can tell apart from
a customer leaving.
Changing the rules on many subscriptions
The subscription.transform operation of POST /v1/changes has a set_exit
kind (exit_gate, exit_not_before_position, exit_notice_count,
exit_notice_unit, exit_fee in its payload) that rewrites the exit rules of a
subscription from an instant on, now or at a scheduled time. See
Scheduled changes.
Trying to cancel inside the commitment
cURL
Response 409
Branch on code; detail is a sentence for people and its wording can change. To find out when the commitment ends, read the committed
phase's window.end in GET /v1/subscriptions/{id}/revisions/live?include=phases.
Through a quote
When the deal is sold with a quote, the exit rules are written on the draft revision the quote holds, with the same operations. The quote document shows the commitment, notice and fee to the buyer, and the signature publishes them with the rest of the deal.
Reference
| Topic | When you need it |
|---|---|
| Subscriptions | Revisions, phases, cancel and scheduled cancellation |
| Quotes | Selling a committed deal that needs a signature |
| Scheduled changes | Changing exit rules at a future instant |
| Errors | The problem document and how to branch on code |