A valid request URL is required to generate request examples{
"cancellation": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reason": "too_expensive",
"comment": "<string>",
"offer_shown": "",
"offer_taken": "",
"at_period_end": true,
"confirmed_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z"
},
"offer": {
"kind": "downgrade",
"headline": "<string>",
"plan": {},
"price": {},
"months": 123,
"resumes_at": "2023-11-07T05:31:56Z",
"coupon": {}
},
"access_until": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}Record why this team is leaving
Writes the answer down and answers with the save offer, if there is one. Owner-only.
This call reaches no payment gateway at all, and that is the point of it being its own request. The reason somebody types is the single most valuable thing on the screen and they will never type it again — they close the tab the moment the subscription is gone. The act at the gateway, by contrast, is retryable forever. So the fragile half is recorded here, where no timeout, refusal or outage of a gateway’s can cost it, and the act is /confirm below.
reason is required and must be one of the values GET returns. comment is free text and optional.
The response carries at most one offer, chosen from what the tenant configured and what the gateway can actually perform — a screen that answers “I am leaving” with three counter-offers is a negotiation and reads as one. offer is null when nothing addresses the reason: switching and missing_feature are deliberately never answered with a discount.
Calling this twice while one cancellation is open answers the same record, so a double-clicked button does not produce two.
A valid request URL is required to generate request examples{
"cancellation": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"subscription_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reason": "too_expensive",
"comment": "<string>",
"offer_shown": "",
"offer_taken": "",
"at_period_end": true,
"confirmed_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z"
},
"offer": {
"kind": "downgrade",
"headline": "<string>",
"plan": {},
"price": {},
"months": 123,
"resumes_at": "2023-11-07T05:31:56Z",
"coupon": {}
},
"access_until": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}Authorizations
A contact session token, uk_ct_…. Belongs to one of the developer's own users, and reads only that user's data.
Headers
The customer this call is acting inside — the same arrangement as X-Organization-Id, one plane down. Switching customers is navigation, not a mutation: nothing is stored, you send a different header, and the membership JOIN behind it decides what you may do there. An id you are not a member of matches no row and answers 404. Absent, the contact's oldest membership answers.
Body
Response
The record, the offer to make, and the date access ends.
One person's answer to "why are you leaving", and what happened next.
It is recorded before any gateway is asked anything, so a record exists whether or not the cancellation was ever carried out — and a record nobody carried out is the only churn signal that arrives while the customer is still a customer.
Show child attributes
Show child attributes
The one offer worth making to somebody who just gave this reason, or null.
At most one: a screen that answers "I am leaving" with three counter-offers is a negotiation and reads as one. The extra fields depend on kind — downgrade carries plan and price, pause carries months and resumes_at, discount carries coupon.
Show child attributes
Show child attributes