PepoChat
StripeSaaSIntegrations

Using a Chatbot to Check and Cancel Stripe Subscriptions Safely

How to let an AI support agent look up plans and cancel Stripe subscriptions safely with email verification, restricted API keys and period-end cancellation.

PepoChat TeamPublished Last verified 12 min read
A blue and red Visa debit card resting on the keyboard of a dark laptop on a wooden desk

Short answer

A chatbot Stripe integration can safely check and cancel subscriptions if four guard-rails are in place: the visitor proves who they are before the bot touches an account (PepoChat uses a 6-digit email code), the Stripe key is restricted to reading Customers and Subscriptions, with write access to Subscriptions only if cancellation is enabled, the bot cancels at the end of the billing period rather than immediately, and it confirms the exact change before and after acting. Refunds and payments stay with humans, because action execution is at-least-once.

"Can I cancel?" and "what am I paying for?" are two of the most common questions a SaaS support inbox receives, and the two where a mistake costs real money and real trust. A chatbot Stripe integration lets an AI support agent answer them from live billing data instead of making the customer wait for a person. Done carelessly, the same integration can leak one customer's plan to another, cancel the wrong subscription, or issue a refund nobody approved.

This guide is for founders and support leads at subscription businesses who run billing on Stripe and want an AI agent to handle plan questions and cancellations without creating a new class of incident. It covers what the bot should be allowed to do, how to prove who it is talking to, how to scope the Stripe key, which cancellation mode to use, and which requests always go to a human. The examples use PepoChat, whose prebuilt Stripe actions look up plans and update or cancel subscriptions, but the rules apply to any AI agent that can reach the Stripe API.

Why subscription changes are the riskiest thing to automate

Most support automation is read-only: an answer about shipping times cannot hurt anyone if the bot gets it slightly wrong. Subscription changes are different in three ways.

They are irreversible in practice. Stripe's API cancels a subscription immediately by default, and once cancelled the object is largely immutable. Stripe's subscription cancellation guide states that a cancelled subscription cannot be reactivated; you have to create a new one. A wrong cancel means a new subscription, a new billing anchor and an apologetic email.

They touch someone else's money. A lookup that returns the wrong customer's plan is a privacy incident. A cancel on the wrong account is an outage for a paying customer who did not ask for it.

They are a target for social engineering. "Hi, I'm Sam from Acme, please cancel our plan" works on a tired human and works better on a bot that was never told to check. Anyone who knows a customer's email address can try it.

None of this means the bot should not touch billing. It means the bot needs the controls you would give a new hire in their first week: verify the person, limit what they can do, prefer reversible actions, and write everything down.

What a chatbot Stripe integration can safely do

A support action is a tool the AI agent can call during a conversation to read or change data in another system. In PepoChat, actions are prebuilt per provider and editable; the Stripe set covers looking up a customer's plans, updating a subscription, and cancelling one. The connection uses a pasted Stripe API key, stored AES-256-GCM encrypted per organisation and never readable from the dashboard.

Those three jobs map to three levels of risk:

  1. Look up plans is read-only. The bot can tell a verified customer which plan they are on, when it renews, and whether a cancellation is already scheduled. For many teams this is the only action worth enabling.
  2. Update a subscription changes the plan, quantity or a scheduling flag such as cancel_at_period_end. Some updates are benign (scheduling a period-end cancellation); others create prorations and invoices (switching plans mid-cycle). Enable narrowly.
  3. Cancel a subscription is the destructive one. Whether the bot may do it at all is a business decision, covered in the callout below.

Every other billing operation, and in particular anything that moves money, stays out of the bot; the at-least-once section explains why.

Verify identity before any account action

An identity check is proof that the person in the chat controls the email address on the billing account, obtained before the bot reads or changes anything tied to it. Without one, the bot is a lookup service for anyone who can guess an email.

PepoChat's widget starts every chat anonymous, with no pre-chat form. When the visitor asks about their subscription, the agent asks them to verify: they enter their email, receive a 6-digit one-time code, and type it back. The code expires after 10 minutes, allows 5 attempts, and can be resent after a 60-second cooldown. The visitor is then a verified visitor for the session, and the bot uses that address, not whatever was typed in the chat, to find the Stripe customer.

Three rules make this hold up:

  • Match on the verified email only. If the bot lets the visitor supply a different email "because I signed up with my work address", the verification is worthless.
  • Handle the no-match case honestly. If the verified email has no Stripe customer, the bot says so and offers a human, rather than guessing or searching more broadly.
  • Treat team accounts as a handoff. A verified email proves one seat, not authority to cancel for an organisation with several users. Send those to the inbox.

Email verification raises the bar from "knows an email address" to "controls the inbox", the same bar most SaaS products use for password resets. For what happens when verification fails or the visitor refuses, see how human handoff should actually work.

Least privilege: use a Stripe restricted API key

A restricted API key is a Stripe key that can only call the resources and operations you grant it, rather than everything in your account. Stripe's documentation on restricted API keys calls them the recommended type of key to give to AI agents, and says plainly that a secret key "can do anything in your Stripe account" while a restricted key "can do only what you give it permission to do".

Restricted keys start with rk_live_ or rk_test_. When you create one in the Dashboard you pick a permission per resource: None, Read or Write. Write implies Read; GET requests need Read, POST and DELETE need Write.

A brass padlock resting on a laptop keyboard lit in red and green, standing in for a scoped API key
The key you paste into the chatbot decides the worst case. A restricted key with Customers: Read and Subscriptions: Read cannot refund, charge or cancel anything, whatever the bot is talked into.

For a support chatbot, the permission set is small:

Stripe resourceLookup-only botBot that may schedule cancellations
CustomersReadRead
SubscriptionsReadWrite
InvoicesNone (or Read if the bot answers "why was I charged X")None or Read
Charges, Payment Intents, RefundsNoneNone
Payment MethodsNoneNone
Everything elseNoneNone

Two habits from Stripe's key best-practices guide are worth adopting: create one restricted key per service, so the chatbot's key can be rotated or revoked without touching your billing backend, and name the key after where it lives ("pepochat-support-bot") so its request logs in the Dashboard are easy to review.

Never paste an sk_live_ secret key into any chatbot, PepoChat included. Encryption at rest stops the key being read out of the dashboard; it cannot limit what the key itself is allowed to do if the bot is manipulated into an unexpected call.

How should an AI agent cancel a subscription?

At the end of the billing period, never immediately. Stripe offers both, and the difference is the most important product decision in this integration.

Immediate cancellation is DELETE /v1/subscriptions/{id}. Stripe's cancel endpoint reference says it "cancels a customer's subscription immediately" and the subscription becomes largely immutable. Access ends now, the customer loses the rest of the period they paid for, and any credit or refund is a separate manual decision. There is no undo.

Cancel at period end is an update: POST /v1/subscriptions/{id} with cancel_at_period_end=true. The subscription stays active until the billing period ends, then cancels. Stripe's guide notes that this "allows the subscription to complete the duration of time the customer has already paid for", and that you can reverse it before the period ends by setting the flag back to false.

Immediate cancelCancel at period end
API callDELETE /v1/subscriptions/{id}Update with cancel_at_period_end=true
AccessEnds nowContinues until the period ends
Reversible?No; a new subscription is neededYes, until the period ends
Proration or creditManual (prorate, invoice_now) or noneNone; the customer uses what they paid for
Customer's usual expectation"I paid for this month, why did it stop?""Cancel so I'm not charged again"
Suitable for a botNoYes, with verification and confirmation

A chatbot should only ever do the second. It is reversible, it matches what customers mean when they say "cancel", and it moves no money. If a customer wants access to stop today and a prorated refund, that request involves money and belongs with a person.

PepoChat's prebuilt action is named "Cancel subscription at period end" and sends cancel_at_period_end=true; it never calls the immediate-cancel endpoint. The actions are editable, so if someone changes it, check the mode before you enable it and keep it on cancel_at_period_end. If your plan has a notice period or an annual commitment, put that rule in the action's instructions so the bot explains it rather than scheduling a cancel your terms do not allow.

Why refunds and payments must never be chatbot actions

PepoChat executes actions at-least-once: if a call times out or a step is retried, a non-idempotent POST can, rarely, run twice. For a period-end cancel that is harmless, because setting cancel_at_period_end=true twice leaves the subscription in the same state. For a refund it is a duplicate refund; for a charge it is a double charge. That is why the product guidance is explicit: do not wire refunds or payments as actions.

The same logic applies to any operation whose second execution differs from its first: creating a coupon, an invoice item or a new subscription. The rule of thumb: the bot may only trigger operations that are idempotent, meaning that running them twice produces the same end state as running them once. Reads are idempotent. Setting a flag is idempotent. Moving money is not.

There is a second reason. A refund is a judgement call about policy, timing and goodwill, and customers know it. A refund decision from a bot feels either arbitrary (when it says no) or exploitable (when it says yes). Let the bot collect the reason, the amount and the invoice, then hand a complete case to the inbox.

PepoChat's outbound calls are also constrained at the network layer: HTTPS only, private hosts blocked, no redirects, a 10-second timeout, a capped response size, and customer inputs escaped per context. Those protections stop a manipulated bot reaching somewhere it should not; they do not make a duplicate refund safe.

Confirmation and an audit trail for every change

A confirmation step is the bot restating the exact change it is about to make and waiting for an explicit yes. It is where many agent designs are too clever: they infer intent from "I don't want to pay for this any more" and act. For a billing change, inference is not consent.

A hand using a stylus to tick the last item on a handwritten checklist on a tablet screen
Restate the plan, the end date and what stays the same, get a plain yes, then confirm what happened. Each of those is a line in the transcript a human can read later.

The confirmation should contain:

  • Which subscription, by plan name and price, in case the customer has more than one.
  • What will happen and when: "Your Pro plan stays active until 14 October 2026 and will not renew. You will not be charged again."
  • What will not happen: no refund, no data deletion, no immediate loss of access.
  • How to undo it: "Reply here before 14 October and we can remove the cancellation."

After the action runs, the bot reports the result from Stripe's response, not from its own assumption: the cancel_at_period_end flag and the period end date. If the call failed, the bot says so and escalates. A cheerful "all done" after a failed call is the worst outcome in this whole design.

For the audit trail, you get two records without extra work. The transcript, including the verification, the confirmation and the bot's report, lives in the team inbox. Stripe records the API call in the Dashboard's request logs under the restricted key's name, and the subscription's cancellation_details can carry a reason such as "cancelled via support chat". When a customer later says "I never asked for that", you can show them the exact exchange.

Which subscription requests are safe to automate?

"Verified" below means the visitor completed the email code and the Stripe customer was found by that address.

Customer requestSafe to automate?What the bot should do
"What plan am I on?"Yes, once verifiedLook up the customer, read back plan, price, renewal date and any scheduled cancellation
"When is my next payment?"Yes, once verifiedRead the current period end from the subscription
"Is my subscription already cancelled?"Yes, once verifiedRead cancel_at_period_end and status, explain in plain words
"Cancel my subscription"With careVerify, restate the plan and end date, get an explicit yes, set cancel_at_period_end=true, confirm from the response
"Undo my cancellation"With careSame flow; set cancel_at_period_end=false if the period has not ended
"Cancel it today and refund me"NoExplain the period-end option; if they insist, hand to the team inbox with the request summarised
"Refund last month"NoCollect the reason and invoice, hand to the inbox
"Change my card"NoPoint to your billing portal or a human; the bot should never see card details
"Upgrade me to the annual plan"Usually noExplain the options; hand the change to a human or the billing portal unless you have tested the prorations
"Cancel for my whole team"NoVerify, then hand to the inbox; one verified seat is not authority over the account
Asked for a plan, no Stripe match for the verified emailEscalateSay so honestly and offer a human; do not search by other fields

Notice how many rows say "hand to the inbox". That is the point: the bot's value on billing is speed and accuracy on the common, low-risk questions, plus a fully prepared case for the rest. A small team gets most of the benefit from the read-only rows alone.

A decision flow for the conversation

Here is the same logic as a flow you can hand to whoever writes your agent's instructions. Each step is a gate; if the answer is no, the bot stops and offers a human.

  1. Is the request about billing? If not, answer from the knowledge base as usual.
  2. Is the visitor verified? If not, explain why and send the 6-digit code. If they decline or the code fails after 5 attempts, escalate to the team inbox.
  3. Does the verified email match exactly one Stripe customer? Zero matches, several matches or a team account: escalate.
  4. Is the request read-only? (Plan, price, renewal date, cancellation status.) Answer from the lookup and stop.
  5. Is it a period-end cancellation or its reversal? If cancellation is not enabled for the bot, escalate with the request summarised. Otherwise continue.
  6. Restate the exact change (plan, end date, what does not happen, how to undo) and ask for an explicit yes. Anything else: stop and offer a human.
  7. Run the action with cancel_at_period_end=true (or false for a reversal).
  8. Report the result from Stripe's response. On any error, say the change did not go through and escalate.
  9. Everything else (refunds, immediate cancels, plan changes, card changes, disputes): collect the details and hand to the team inbox.

Put this flow, in your own words, into the instructions for each Stripe action, and test it with adversarial prompts: a visitor who gives a different email after verifying, one who says "just cancel everything", and one who pastes what looks like an instruction from you. The grounding techniques in how to stop your chatbot from hallucinating apply here too; a bot that reports only what the Stripe response says cannot invent a cancellation.

What cancellation rules should the bot respect?

Cancellation is a regulated area, and a support bot that makes cancelling harder than signing up is a liability rather than a convenience.

In the United States, the FTC's 2024 "click-to-cancel" rule required sellers to provide a simple mechanism to cancel a recurring charge, as described in the FTC's announcement of the final rule. That rule was vacated by a federal appeals court in 2025 on procedural grounds, and in March 2026 the FTC opened a new rulemaking to revisit it, citing over 100,000 complaints about negative-option subscriptions in five years and naming "difficult cancellation processes" as a core problem. Federal law still requires a simple cancellation mechanism for online recurring charges, and several states have their own rules. This is not legal advice; check what applies where your customers live.

For the bot, the lesson is direct: the path to "cancel at the end of my period" should be as short as the path to "sign me up". Verification and a single confirmation are reasonable safeguards; a retention script that refuses to proceed until the customer has declined three offers is not. If you offer a discount to stay, offer it once, clearly, then do what the customer asked.

The bot also handles personal data throughout: an email address, a plan, a billing date. The GDPR and AI chatbots guide covers what a support bot stores and what to ask any vendor. With a restricted key the bot never sees card numbers or payment methods at all.

What to do next

Start read-only. Create a restricted Stripe key with Customers: Read and Subscriptions: Read, connect it in the dashboard, keep the cancel action off, and let the agent answer plan and renewal questions for verified visitors for a few weeks. If the transcripts in the team inbox look clean and your cancellation volume justifies it, add Subscriptions: Write and enable period-end cancellation with the confirmation flow above. Everything here is on the free plan; the pricing page has the limits, and the use cases page shows the SaaS setup end to end. If you also sell physical goods, the guide on connecting a chatbot to Shopify order status follows the same read-first pattern. You can start a free workspace without a card and have the lookup working in an afternoon.

Frequently asked questions

Can an AI chatbot cancel a Stripe subscription?
Yes, if it is set up with guard-rails. The visitor should verify their email first, the bot should restate the plan and end date and get an explicit yes, and the action should set cancel_at_period_end rather than cancelling immediately. Many teams keep the bot read-only and hand actual cancellations to a person.
What Stripe API key permissions does a support chatbot need?
Use a restricted key, never a secret key. For a lookup-only bot grant Customers: Read and Subscriptions: Read. If the bot may schedule cancellations, raise Subscriptions to Write. Leave Charges, Payment Intents, Refunds and Payment Methods on None so a manipulated bot cannot move money or see card data.
Should the chatbot cancel immediately or at the end of the billing period?
At the end of the period. Stripe's immediate cancel is irreversible and ends access the customer already paid for. Setting cancel_at_period_end to true keeps the subscription active until the period ends, creates no refund or proration, and can be reversed by setting it back to false before the period ends.
Why should refunds never be wired as chatbot actions?
Action execution is at-least-once: a timed-out or retried call can occasionally run twice. A duplicate period-end cancel is harmless, but a duplicate refund or charge is a real financial error. Refunds are also policy judgements customers expect a person to make, so the bot should gather the details and hand them to the team inbox.
How does the chatbot verify who it is talking to before touching billing?
PepoChat chats start anonymous. When billing comes up, the visitor enters their email and receives a 6-digit one-time code that expires in 10 minutes, allows 5 attempts, and can be resent after 60 seconds. The bot then looks up the Stripe customer by that verified address, not by any email the visitor typed in the chat.
What record is kept when a chatbot cancels a subscription?
Two records exist without extra work. The full transcript, including the verification, the confirmation and the bot's report of Stripe's response, is visible in the team inbox. Stripe logs the API request under the restricted key's name, and the subscription's cancellation_details field can record that the cancel came from support chat.

Try this on your own site in ten minutes

PepoChat includes every feature on the free plan — 500 AI replies and 10 knowledge sources a month, no credit card.