DEVELOPERS
Sandbox
The Sandbox customer object
Test-mode scenarios: create a customer, fail a payment, remove a card, run a cancel flow.
ATTRIBUTES
- object enum
- sandbox_customer
- customer object
Show child attributesHide child attributes
- object enum
- customer
- id string
NoChurn id, always present.
- stripe_customer_id string | null
Stripe customer id, when billed by Stripe.
- external_id string | null
The id of this customer in your app.
- stripe_account string | null
- livemode boolean
- email string | null
- company_domain string | null
Domain of the email when it is a company's (not a free, disposable or placeholder address): the customer's logo is GET /v1/logos/{company_domain}.
- name string | null
- locale string | null
- country string | null
- region string | null
State or province of the address.
- timezone string | null
IANA time zone used to reach the customer.
- timezone_source enum | null
api (sent by you, never overwritten), attribute, address, country_guess (main zone of a multi-zone country), ip_country, card_country, account (fallback).
- api
- attribute
- address
- country_guess
- ip_country
- card_country
- account
- attributes object
Custom attributes (M4/M6).
- churn_score integer | null
- churn_level enum | null
- low
- medium
- high
- flag object | null
FLAGGED: a prevention signal before the renewal. Cleared when a new card arrives.
Show child attributesHide child attributes
- reason enum
- card_removed
- card_expiring
-
- state enum
From billing: in_recovery = an open invoice with a failed attempt; churned = no live subscription.
- none
- trialing
- active
- in_recovery
- paused
- churned
- plan string | null
Plan of the main live subscription.
- mrr_cents integer
Monthly recurring revenue, in the minor unit of currency.
- lifetime_value_cents integer
Paid invoices seen by NoChurn (12 months of Stripe history, then all).
- currency string | null
Billing currency. Amounts are never converted.
- payment_method object | null
Default payment method (null when none).
-
From the last_active_at attribute your app sends.
-
Set by Pause all flows: no flow acts on this customer.
- identifiers array of objects
Every identifier a source gave for this customer, oldest first: how Stripe, your other tools, your app and support all reach this one customer (docs: customer matching).
Show child attributesHide child attributes
- kind enum
stripe (cus_), provider (a billing, store or support tool's id), external (your id, current or previous), email, nochurn (the cst_ id of a customer merged into this one, still accepted).
- stripe
- external
- provider
- nochurn
- provider string | null
The tool for stripe and provider ids (stripe, chargebee, app_store, intercom…).
- connection string | null
The billing connection (scn_ / bcn_) or support integration (itg_) the id belongs to.
- value string
- source enum
Who gave it: api, import, stripe, stripe_metadata, provider, support, manual, merge (moved by a merge).
- api
- stripe_metadata
- stripe
- manual
- provider
- support
- import
- merge
-
- risk object
With include[]=risk (list only): when the customer renews and why the score is what it is. Early signals (card removed…) are in flag.
Show child attributesHide child attributes
-
Soonest end of the current period of a paying subscription (active or past_due) still to come.
- cancel_at_period_end boolean | null
That subscription stops then instead of renewing. null without a renewal.
-
Factors that raised the last churn score, largest first (starting point and lowering factors left out).
-
-
- subscription object
Show child attributesHide child attributes
- object enum
- subscription
- id string
- customer string
- stripe_subscription_id string | null
- external_id string | null
- livemode boolean
- status enum
- incomplete
- incomplete_expired
- trialing
- active
- past_due
- canceled
- unpaid
- paused
- plan string | null
- amount_cents integer
- currency string | null
- interval string | null
- interval_count integer
- mrr_cents integer
- cancel_at_period_end boolean
-
- payment_method object
Metadata only. NoChurn never stores card numbers.
Show child attributesHide child attributes
- object enum
- payment_method
- id string
- customer string | null
- stripe_payment_method_id string | null
- livemode boolean
- type string
- brand string | null
- last4 string | null
- exp_month integer | null
- exp_year integer | null
- funding string | null
credit, debit, prepaid or unknown
- country string | null
- wallet string | null
apple_pay, google_pay, link…
- is_default boolean
-
- next string
Schema: SandboxCustomer
{
"object": "sandbox_customer",
"customer": {
"object": "customer",
"id": "cst_bunoEakFaTiPtdny",
"stripe_customer_id": null,
"external_id": "sandbox_204d2c04",
"stripe_account": null,
"livemode": false,
"email": "sandbox+204d2c04@example.com",
"company_domain": null,
"name": "Sandbox customer",
"locale": null,
"country": null,
"region": null,
"timezone": "Europe/Paris",
"timezone_source": "account",
"attributes": {
"signup_source": "ads"
},
"churn_score": null,
"churn_level": null,
"flag": null,
"state": "active",
"plan": "Team",
"mrr_cents": 4900,
"lifetime_value_cents": 0,
"currency": "usd",
"payment_method": {
"id": "npm_wv5NxAxFfWoidwEv",
"type": "card",
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2029,
"funding": "credit",
"wallet": null,
"risk_category": null,
"label": "Visa •••• 4242"
},
"last_seen_at": null,
"churned_at": null,
"flows_paused_at": null,
"signup_at": "2026-11-04T10:00:00.000Z",
"created_at": "2026-11-04T10:00:00.000Z",
"updated_at": "2026-11-04T10:00:00.000Z",
"identifiers": [
{
"kind": "email",
"provider": null,
"connection": null,
"value": "sandbox+204d2c04@example.com",
"source": "api",
"created_at": "2026-11-04T10:00:00.000Z"
},
{
"kind": "external",
"provider": null,
"connection": null,
"value": "sandbox_204d2c04",
"source": "api",
"created_at": "2026-11-04T10:00:00.000Z"
}
]
},
"subscription": {
"object": "subscription",
"id": "nsub_ee6FgdZrth7eEGKc",
"customer": "cst_bunoEakFaTiPtdny",
"stripe_subscription_id": null,
"external_id": "sandbox_sub_204d2c04",
"livemode": false,
"status": "active",
"plan": "Team",
"amount_cents": 4900,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"mrr_cents": 4900,
"current_period_end": "2026-11-09T10:00:00.000Z",
"cancel_at_period_end": false,
"canceled_at": null,
"paused_until": null,
"trial_end": null,
"created_at": "2026-11-04T10:00:00.000Z"
},
"payment_method": {
"object": "payment_method",
"id": "npm_wv5NxAxFfWoidwEv",
"customer": "cst_bunoEakFaTiPtdny",
"stripe_payment_method_id": null,
"livemode": false,
"type": "card",
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2029,
"funding": "credit",
"country": null,
"wallet": null,
"is_default": true,
"detached_at": null,
"created_at": "2026-11-04T10:00:00.000Z"
},
"next": "Play a scenario: POST /v1/sandbox/failed_payment, /card_removed or /cancel_flow_run with customer: sandbox_204d2c04."
} Sandbox: create a test customer
Test mode only. A customer with an active subscription billed by API (no Stripe call) renewing in renews_in_days (5), and a default test card (visa 4242). Writes sandbox.customer_created.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need write access. - AI apps (OAuth):
sandboxscope, test mode only.
BODY PARAMETERS
- external_id string
- email string
- name string
- locale string
- plan string
- amount integer
Cents.
- currency string
- interval enum
- month
- year
- attributes object
RETURNS
-
201created — the Sandbox customer object
ERRORS
-
403test_mode_only live mode
curl https://api.nochurn.sh/v1/sandbox/customers \
-H "Authorization: Bearer nc_test_…" \
-H "Content-Type: application/json" \
-d '{
"plan": "Team",
"attributes": {
"signup_source": "ads"
}
}'const res = await fetch("https://api.nochurn.sh/v1/sandbox/customers", {
method: "POST",
headers: {
Authorization: "Bearer nc_test_…",
"Content-Type": "application/json",
},
body: JSON.stringify({
"plan": "Team",
"attributes": {
"signup_source": "ads"
}
}),
});
const sandboxCustomer = await res.json();import requests
res = requests.post(
"https://api.nochurn.sh/v1/sandbox/customers",
headers={
"Authorization": "Bearer nc_test_…",
},
json={
"plan": "Team",
"attributes": {
"signup_source": "ads"
}
},
)
sandbox_customer = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/sandbox/customers")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
"plan" => "Team",
"attributes" => {
"signup_source" => "ads"
}
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
sandbox_customer = JSON.parse(res.body) {
"object": "sandbox_customer",
"customer": {
"object": "customer",
"id": "cst_bunoEakFaTiPtdny",
"stripe_customer_id": null,
"external_id": "sandbox_204d2c04",
"stripe_account": null,
"livemode": false,
"email": "sandbox+204d2c04@example.com",
"company_domain": null,
"name": "Sandbox customer",
"locale": null,
"country": null,
"region": null,
"timezone": "Europe/Paris",
"timezone_source": "account",
"attributes": {
"signup_source": "ads"
},
"churn_score": null,
"churn_level": null,
"flag": null,
"state": "active",
"plan": "Team",
"mrr_cents": 4900,
"lifetime_value_cents": 0,
"currency": "usd",
"payment_method": {
"id": "npm_wv5NxAxFfWoidwEv",
"type": "card",
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2029,
"funding": "credit",
"wallet": null,
"risk_category": null,
"label": "Visa •••• 4242"
},
"last_seen_at": null,
"churned_at": null,
"flows_paused_at": null,
"signup_at": "2026-11-04T10:00:00.000Z",
"created_at": "2026-11-04T10:00:00.000Z",
"updated_at": "2026-11-04T10:00:00.000Z",
"identifiers": [
{
"kind": "email",
"provider": null,
"connection": null,
"value": "sandbox+204d2c04@example.com",
"source": "api",
"created_at": "2026-11-04T10:00:00.000Z"
},
{
"kind": "external",
"provider": null,
"connection": null,
"value": "sandbox_204d2c04",
"source": "api",
"created_at": "2026-11-04T10:00:00.000Z"
}
]
},
"subscription": {
"object": "subscription",
"id": "nsub_ee6FgdZrth7eEGKc",
"customer": "cst_bunoEakFaTiPtdny",
"stripe_subscription_id": null,
"external_id": "sandbox_sub_204d2c04",
"livemode": false,
"status": "active",
"plan": "Team",
"amount_cents": 4900,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"mrr_cents": 4900,
"current_period_end": "2026-11-09T10:00:00.000Z",
"cancel_at_period_end": false,
"canceled_at": null,
"paused_until": null,
"trial_end": null,
"created_at": "2026-11-04T10:00:00.000Z"
},
"payment_method": {
"object": "payment_method",
"id": "npm_wv5NxAxFfWoidwEv",
"customer": "cst_bunoEakFaTiPtdny",
"stripe_payment_method_id": null,
"livemode": false,
"type": "card",
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2029,
"funding": "credit",
"country": null,
"wallet": null,
"is_default": true,
"detached_at": null,
"created_at": "2026-11-04T10:00:00.000Z"
},
"next": "Play a scenario: POST /v1/sandbox/failed_payment, /card_removed or /cancel_flow_run with customer: sandbox_204d2c04."
} Sandbox: simulate a failed payment
Test mode only. An open invoice and a failed payment, then the recovery flow like a failure sent by API: the day-0 email is written in the background (never sent to a real inbox). invoice_url is the card update page of your app (billing by API); without it the email waits for review without a card link.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need write access. - AI apps (OAuth):
sandboxscope, test mode only.
BODY PARAMETERS
-
cst_… or your own id.
- amount integer
- currency string
- decline_code string
RETURNS
-
201recovery run started — a SandboxFailedPayment
ERRORS
-
404customer_not_found unknown customer
curl https://api.nochurn.sh/v1/sandbox/failed_payment \
-H "Authorization: Bearer nc_test_…" \
-H "Content-Type: application/json" \
-d '{
"customer": "cst_bKA5uydA3TFbny8p",
"invoice_url": "https://app.example.com/billing"
}'const res = await fetch("https://api.nochurn.sh/v1/sandbox/failed_payment", {
method: "POST",
headers: {
Authorization: "Bearer nc_test_…",
"Content-Type": "application/json",
},
body: JSON.stringify({
"customer": "cst_bKA5uydA3TFbny8p",
"invoice_url": "https://app.example.com/billing"
}),
});
const sandboxFailedPayment = await res.json();import requests
res = requests.post(
"https://api.nochurn.sh/v1/sandbox/failed_payment",
headers={
"Authorization": "Bearer nc_test_…",
},
json={
"customer": "cst_bKA5uydA3TFbny8p",
"invoice_url": "https://app.example.com/billing"
},
)
sandbox_failed_payment = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/sandbox/failed_payment")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
"customer" => "cst_bKA5uydA3TFbny8p",
"invoice_url" => "https://app.example.com/billing"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
sandbox_failed_payment = JSON.parse(res.body) {
"object": "sandbox_failed_payment",
"customer": "cst_bKA5uydA3TFbny8p",
"invoice": {
"object": "invoice",
"id": "ninv_r3bxXGhL1pmwzzsq",
"customer": "cst_bKA5uydA3TFbny8p",
"subscription": "nsub_h4fGLF2jw3Fmj949",
"stripe_invoice_id": null,
"external_id": "sandbox_in_5c71a02c",
"livemode": false,
"number": null,
"status": "open",
"amount_due_cents": 4900,
"amount_paid_cents": 0,
"amount_remaining_cents": 4900,
"currency": "usd",
"attempt_count": 1,
"next_attempt_at": null,
"failure_code": null,
"decline_code": "insufficient_funds",
"hosted_invoice_url": "https://app.example.com/billing",
"paid_at": null,
"created_at": "2026-11-04T10:00:00.000Z"
},
"payment": {
"object": "payment",
"id": "npay_36FrWRqwQscjZzbo",
"livemode": false,
"customer": "cst_bKA5uydA3TFbny8p",
"subscription": "nsub_h4fGLF2jw3Fmj949",
"invoice": "ninv_r3bxXGhL1pmwzzsq",
"external_id": "sandbox_pay_5c71a02c",
"stripe_charge_id": null,
"status": "failed",
"amount_cents": 4900,
"currency": "usd",
"decline_code": "insufficient_funds",
"failure_code": null,
"occurred_at": "2026-11-04T10:00:00Z",
"created_at": "2026-11-04T10:00:00Z"
},
"recovery_run": {
"id": "run_mmJr34RXHjDV6MZi",
"state": "active",
"holdout": false,
"stop_reason": null
},
"skipped": null,
"next": "The day-0 email is written in the background (test mode: never sent to a real inbox). Check it with GET /v1/integration/verify."
} Sandbox: the customer removes their card before the renewal
Test mode only, on a sandbox card. Prevention signal card_removed: the customer is flagged, and the prevention flow writes its reminder when it is published in test mode.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need write access. - AI apps (OAuth):
sandboxscope, test mode only.
BODY PARAMETERS
RETURNS
-
201flagged — a SandboxCardRemoved
curl https://api.nochurn.sh/v1/sandbox/card_removed \
-H "Authorization: Bearer nc_test_…" \
-H "Content-Type: application/json" \
-d '{
"customer": "cst_m7f9kZH5XcRMAx7x"
}'const res = await fetch("https://api.nochurn.sh/v1/sandbox/card_removed", {
method: "POST",
headers: {
Authorization: "Bearer nc_test_…",
"Content-Type": "application/json",
},
body: JSON.stringify({
"customer": "cst_m7f9kZH5XcRMAx7x"
}),
});
const sandboxCardRemoved = await res.json();import requests
res = requests.post(
"https://api.nochurn.sh/v1/sandbox/card_removed",
headers={
"Authorization": "Bearer nc_test_…",
},
json={
"customer": "cst_m7f9kZH5XcRMAx7x"
},
)
sandbox_card_removed = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/sandbox/card_removed")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
"customer" => "cst_m7f9kZH5XcRMAx7x"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
sandbox_card_removed = JSON.parse(res.body) {
"object": "sandbox_card_removed",
"customer": {
"object": "customer",
"id": "cst_m7f9kZH5XcRMAx7x",
"stripe_customer_id": null,
"external_id": "sandbox_a096134f",
"stripe_account": null,
"livemode": false,
"email": "sandbox+a096134f@example.com",
"company_domain": null,
"name": "Sandbox customer",
"locale": null,
"country": null,
"region": null,
"timezone": "Europe/Paris",
"timezone_source": "account",
"attributes": {},
"churn_score": 60,
"churn_level": "medium",
"flag": {
"reason": "card_removed",
"flagged_at": "2026-11-04T10:00:00.000Z"
},
"state": "active",
"plan": "Pro",
"mrr_cents": 4900,
"lifetime_value_cents": 0,
"currency": "usd",
"payment_method": null,
"last_seen_at": null,
"churned_at": null,
"flows_paused_at": null,
"signup_at": "2026-11-04T10:00:00.000Z",
"created_at": "2026-11-04T10:00:00.000Z",
"updated_at": "2026-11-04T10:00:00.000Z",
"identifiers": [
{
"kind": "email",
"provider": null,
"connection": null,
"value": "sandbox+a096134f@example.com",
"source": "api",
"created_at": "2026-11-04T10:00:00.000Z"
},
{
"kind": "external",
"provider": null,
"connection": null,
"value": "sandbox_a096134f",
"source": "api",
"created_at": "2026-11-04T10:00:00.000Z"
}
]
},
"payment_method": {
"object": "payment_method",
"id": "npm_r3X9MXd9dt36G7ZR",
"customer": "cst_m7f9kZH5XcRMAx7x",
"stripe_payment_method_id": null,
"livemode": false,
"type": "card",
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2029,
"funding": "credit",
"country": null,
"wallet": null,
"is_default": false,
"detached_at": "2026-11-04T10:00:00.000Z",
"created_at": "2026-11-04T10:00:00.000Z"
},
"flagged": true,
"prevention_run": null
} Sandbox: play the cancel flow
Test mode only. Opens the cancel flow, answers a reason (the first one by default), refuses or accepts the offer, then cancels in one click (click to cancel). Billing by API: the cancellation reaches your app as billing.cancel_requested.
- Secret key (
nc_test_…ornc_live_…). Restricted keys need write access. - AI apps (OAuth):
sandboxscope, test mode only.
BODY PARAMETERS
- subscription string
Several live subscriptions: the one to play (default: the first listed).
- reason string
- accept_offer boolean
- locale string
RETURNS
-
201cancelled — a SandboxCancelFlowRun
curl https://api.nochurn.sh/v1/sandbox/cancel_flow_run \
-H "Authorization: Bearer nc_test_…" \
-H "Content-Type: application/json" \
-d '{
"customer": "cst_vyBRXyK4QwPYf9mu"
}'const res = await fetch("https://api.nochurn.sh/v1/sandbox/cancel_flow_run", {
method: "POST",
headers: {
Authorization: "Bearer nc_test_…",
"Content-Type": "application/json",
},
body: JSON.stringify({
"customer": "cst_vyBRXyK4QwPYf9mu"
}),
});
const sandboxCancelFlowRun = await res.json();import requests
res = requests.post(
"https://api.nochurn.sh/v1/sandbox/cancel_flow_run",
headers={
"Authorization": "Bearer nc_test_…",
},
json={
"customer": "cst_vyBRXyK4QwPYf9mu"
},
)
sandbox_cancel_flow_run = res.json()require "net/http"
require "json"
uri = URI("https://api.nochurn.sh/v1/sandbox/cancel_flow_run")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer nc_test_…"
req["Content-Type"] = "application/json"
req.body = {
"customer" => "cst_vyBRXyK4QwPYf9mu"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
sandbox_cancel_flow_run = JSON.parse(res.body) {
"object": "sandbox_cancel_flow_run",
"session": {
"object": "cancel_session",
"id": "ses_E4ydMSMHe2opxRar",
"livemode": false,
"step": "done",
"outcome": "cancelled",
"locale": "en",
"holdout": false,
"published": false,
"customer": {
"id": "cst_vyBRXyK4QwPYf9mu",
"stripe_customer_id": null,
"external_id": "sandbox_474b675f"
},
"subscription": {
"id": "nsub_G5GU7sVoHJFgxgQc",
"plan": "Pro",
"status": "active",
"amount_cents": 4900,
"currency": "usd",
"interval": "month",
"interval_count": 1,
"current_period_end": "2026-11-09T10:00:00Z",
"cancel_at_period_end": false
},
"subscriptions": [],
"reasons": [
{
"key": "too_expensive",
"label": "It's too expensive",
"free_text": false
},
{
"key": "missing_feature",
"label": "A feature is missing",
"free_text": false
},
{
"key": "not_using",
"label": "I don't use it enough",
"free_text": false
},
{
"key": "switching",
"label": "I'm switching to another tool",
"free_text": false
},
{
"key": "temporary",
"label": "I only need a break",
"free_text": false
},
{
"key": "project_finished",
"label": "My project is finished",
"free_text": false
},
{
"key": "other",
"label": "Something else",
"free_text": true
}
],
"offer": null,
"talk_url": null,
"texts": {
"review_ask": "Would you leave a short review on {{platform}}? No reward, just your honest opinion.",
"review_cta": "Leave a review",
"title": "Before you go",
"reason_prompt": "Why are you cancelling?",
"other_placeholder": "Tell us more (optional)",
"offer_title": "One last thing",
"accept": "Accept the offer",
"decline": "No thanks, continue",
"feedback_prompt": "Anything we could have done better?",
"feedback_submit": "Continue",
"confirm_title": "Cancel your subscription?",
"confirm_body": "You keep access until the end of the paid period.",
"cancel_now": "Cancel my subscription",
"saved_title": "Thanks for staying!",
"cancelled_title": "Your subscription is cancelled",
"cancelled_body": "You keep access until the end of the paid period.",
"offer_discount": "{{percent}}% off for {{months}} months",
"offer_pause": "Pause for {{months}} months, free",
"offer_downgrade": "Switch to {{plan}}",
"offer_talk": "Talk to the team",
"choose_subscription_title": "Which subscription?",
"choose_subscription_body": "You have several subscriptions. Choose the one you want to cancel.",
"choose_subscription_select": "Continue with this one",
"cancel_this_one": "Cancel this one",
"renews_on": "Renews on {{date}}"
},
"feedback_enabled": true,
"feedback": {
"enabled": true,
"required": false
},
"theme": {
"object": "cancel_flow_theme",
"preset": "light",
"format": "modal",
"tokens": {
"bg": "#f5f6fa",
"surface": "#ffffff",
"text": "#1c1e4a",
"muted": "#686b85",
"accent": "#4637d9",
"accent_text": "#ffffff",
"border": "#e3e5ec",
"danger": "#c2410c",
"font": "system-ui, sans-serif",
"font_size": 15,
"radius": 12,
"radius_control": 8,
"overlay": 0.5,
"max_width": 480,
"shadow": "md",
"spacing": "regular",
"border_width": 1,
"border_style": "solid",
"font_scale": 1.25,
"font_weight_title": 600
},
"font_url": null,
"brand": "logo",
"logo_url": null,
"app_name": "Account 1",
"end_screen": {
"style": "celebrate",
"auto_close_seconds": 6
},
"custom_css": "",
"cancel_button_check": "ok",
"classes": [
"nc-modal",
"nc-title",
"nc-reason",
"nc-offer",
"nc-btn-primary",
"nc-btn-cancel",
"nc-footer"
]
},
"cancel_url_now": null,
"cancel_status": "requested",
"cancel_effective_at": "2026-11-09T10:00:00Z",
"result": null,
"access_until": "2026-11-09T10:00:00Z",
"confirmation_email_sent": false,
"review": null,
"expires_at": "2026-11-05T10:00:00Z",
"created_at": "2026-11-04T10:00:00Z"
}
}