Subscriptions
Give the reason for cancelling
Records the customer’s reason and returns the save offers it earns: at most two, each
with a server-issued offer_id and a preview of the next order date and amount. The
amount is null when the platform cannot state it in advance. Monetary offers are left
out while the customer is within the merchant’s cooldown, on any of their subscriptions.
The reason is given once: the same reason again returns the same offers, another is
refused with 409 (reason_already_given). A session past its 30 minutes returns
409 (session_expired). While the cancel flow is off, the reason is recorded and no
offer is shown. Returns 422 for a reason the flow does not show.
POST
/
api
/
checkout
/
v2026-04
/
subscriptions
/
{subscription_token}
/
cancellation-sessions
/
{id}
/
reason
Give the reason for cancelling
curl --request POST \
--url https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"reason_code": "too_expensive"
}
'import requests
url = "https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason"
payload = { "reason_code": "too_expensive" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({reason_code: 'too_expensive'})
};
fetch('https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'reason_code' => 'too_expensive'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason"
payload := strings.NewReader("{\n \"reason_code\": \"too_expensive\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"reason_code\": \"too_expensive\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason_code\": \"too_expensive\"\n}"
response = http.request(request)
puts response.read_body{
"cancellation_session": {
"id": "0199c6a4-5b2e-7d41-9f3a-2c8e1b7d4a60",
"outcome": "open",
"cancel_now_allowed": true,
"expires_at": "2026-10-10T15:30:00Z",
"retention_flow_version": 3,
"reasons": [
{
"code": "too_expensive",
"labels": {
"en": "Too expensive"
}
},
{
"code": "taking_a_break",
"labels": {}
}
],
"reason_code": "too_expensive",
"reason_text": null,
"offers": [
{
"offer_id": "rof_4kq9Zt2LmX8vB1nR7cWy",
"type": "discount",
"terms": {
"percentage": 20,
"duration": "once"
},
"saves": true,
"preview": {
"next_bill_date": "2026-11-03",
"next_order_total": "27.0",
"currency": "USD"
}
}
],
"accepted_offer_id": null
},
"meta": {
"request_id": "6d2f8a4c-3e1b-4c97-a5d0-9b4e2f7c1a38",
"timestamp": "2026-10-10T15:00:00Z"
}
}{
"message": "<string>"
}{
"error_message": "<string>",
"errors": "<string>",
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"code": "<string>",
"payment_uuid": "<string>",
"error_details": [
{
"code": "<string>",
"field": "<string>",
"payment": "not_attempted",
"message": "<string>"
}
],
"coded_recovery": true
}
}{
"error_message": "<string>",
"errors": "<string>",
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"code": "<string>",
"payment_uuid": "<string>",
"error_details": [
{
"code": "<string>",
"field": "<string>",
"payment": "not_attempted",
"message": "<string>"
}
],
"coded_recovery": true
}
}{
"error_message": "<string>",
"errors": "<string>",
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"code": "<string>",
"payment_uuid": "<string>",
"error_details": [
{
"code": "<string>",
"field": "<string>",
"payment": "not_attempted",
"message": "<string>"
}
],
"coded_recovery": true
}
}{
"error_message": "<string>",
"errors": "<string>",
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"code": "<string>",
"payment_uuid": "<string>",
"error_details": [
{
"code": "<string>",
"field": "<string>",
"payment": "not_attempted",
"message": "<string>"
}
],
"coded_recovery": true
}
}Authorizations
Bearer token authentication
Path Parameters
Subscription token
Cancellation session id
Body
application/json
⌘I
Give the reason for cancelling
curl --request POST \
--url https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"reason_code": "too_expensive"
}
'import requests
url = "https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason"
payload = { "reason_code": "too_expensive" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({reason_code: 'too_expensive'})
};
fetch('https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'reason_code' => 'too_expensive'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason"
payload := strings.NewReader("{\n \"reason_code\": \"too_expensive\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"reason_code\": \"too_expensive\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fluid.app/api/checkout/v2026-04/subscriptions/{subscription_token}/cancellation-sessions/{id}/reason")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason_code\": \"too_expensive\"\n}"
response = http.request(request)
puts response.read_body{
"cancellation_session": {
"id": "0199c6a4-5b2e-7d41-9f3a-2c8e1b7d4a60",
"outcome": "open",
"cancel_now_allowed": true,
"expires_at": "2026-10-10T15:30:00Z",
"retention_flow_version": 3,
"reasons": [
{
"code": "too_expensive",
"labels": {
"en": "Too expensive"
}
},
{
"code": "taking_a_break",
"labels": {}
}
],
"reason_code": "too_expensive",
"reason_text": null,
"offers": [
{
"offer_id": "rof_4kq9Zt2LmX8vB1nR7cWy",
"type": "discount",
"terms": {
"percentage": 20,
"duration": "once"
},
"saves": true,
"preview": {
"next_bill_date": "2026-11-03",
"next_order_total": "27.0",
"currency": "USD"
}
}
],
"accepted_offer_id": null
},
"meta": {
"request_id": "6d2f8a4c-3e1b-4c97-a5d0-9b4e2f7c1a38",
"timestamp": "2026-10-10T15:00:00Z"
}
}{
"message": "<string>"
}{
"error_message": "<string>",
"errors": "<string>",
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"code": "<string>",
"payment_uuid": "<string>",
"error_details": [
{
"code": "<string>",
"field": "<string>",
"payment": "not_attempted",
"message": "<string>"
}
],
"coded_recovery": true
}
}{
"error_message": "<string>",
"errors": "<string>",
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"code": "<string>",
"payment_uuid": "<string>",
"error_details": [
{
"code": "<string>",
"field": "<string>",
"payment": "not_attempted",
"message": "<string>"
}
],
"coded_recovery": true
}
}{
"error_message": "<string>",
"errors": "<string>",
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"code": "<string>",
"payment_uuid": "<string>",
"error_details": [
{
"code": "<string>",
"field": "<string>",
"payment": "not_attempted",
"message": "<string>"
}
],
"coded_recovery": true
}
}{
"error_message": "<string>",
"errors": "<string>",
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"code": "<string>",
"payment_uuid": "<string>",
"error_details": [
{
"code": "<string>",
"field": "<string>",
"payment": "not_attempted",
"message": "<string>"
}
],
"coded_recovery": true
}
}