How to connect Stripe to Discord roles

To give a Discord role when someone pays with Stripe, you need three pieces: a way to know the buyer’s Discord account, a webhook that listens for Stripe’s subscription events, and a bot that adds or removes the role through Discord’s API. You can build all three yourself, or use a bot like flatpass that runs the same setup on your own Stripe account.

  • The whole build, step by step
  • The edge cases that take the time
  • Or the ready-made option
  1. Buyer signs in with Discordidentify · guilds.join
  2. Stripe Checkoutsubscription mode · Discord ID attached
  3. Your webhooksignature checked · each event once
  4. Discord APIPUT …/members/{user}/roles/{role}
  5. Role addedand removed when it ends

Building it yourself

Five steps to a working first version.

Step 1: Know who the buyer is on Discord

Stripe knows an email address, not a Discord account, and the two often don’t match. So link them before checkout:

  • Send the buyer through Discord’s OAuth2 with the identify scope. You get their Discord user ID.
  • Add guilds.join if buyers may not be in your server yet. It lets your bot add them.
  • Put the Discord user ID on the Checkout Session as client_reference_idand on the subscription’s metadata, so every later event can find it.

Step 2: Create the Discord bot

  • Create an application in the Discord Developer Portal and add a bot to it.
  • Invite it to your server with Manage Roles, plus Create Instant Invite if it will add buyers to the server.
  • Drag the bot’s role above every role it sells, in Server Settings → Roles. Discord only lets a bot manage roles below its own, and it puts a new bot’s role at the bottom. It’s the most common reason a working integration quietly fails.

The bot doesn’t need to be online in Discord’s gateway to change roles. Its token works with Discord’s REST API, called from your webhook handler.

Step 3: Create the checkout

A Stripe Checkout Session in subscription mode, with the price for the role and the Discord user ID from step 1. Stripe hosts the page, so cards, Apple Pay and Google Pay come with it.

Turn on Stripe’s customer portal for cancelling and changing cards. Otherwise every cancellation is a message to you.

Step 4: Listen for Stripe’s events

A webhook endpoint on an always-on HTTPS server. Two rules before any logic:

  • Verify the signature on every request, with your endpoint’s signing secret and the raw request body.
  • Handle each event once. Stripe retries deliveries for up to three days and doesn’t guarantee their order. Record the event IDs you’ve processed, and read the subscription’s current status rather than trusting the order events arrive in.

Then map each event to what happens to the role:

Stripe eventThe role
checkout.​session.​completedAdd the role, and add the member to the server if needed.
customer.​subscription.​updatedKeep the role while the status is active, trialing or past_due; remove it on unpaid, canceled or paused.
customer.​subscription.​deletedRemove the role.
charge.​refundedYour call: most remove the role on a full refund and cancel the subscription.
charge.​dispute.​createdYour call: most remove the role until the dispute is decided.

Keeping the role through past_due matters: Stripe retries a failed renewal for days, and removing the role on the first failed charge punishes someone whose card simply expired.

Step 5: Change the role on Discord

Three calls, with your bot token:

Add a rolePUT /guilds/{guild}/members/{user}/roles/{role}

Remove a roleDELETE /guilds/{guild}/members/{user}/roles/{role}

Add to serverPUT /guilds/{guild}/members/{user}

Adding someone to the server takes the OAuth2 access token from step 1, and the role can go in the same call. Then handle what Discord sends back: 50013means the role is above the bot’s, so retrying won’t help; 10007means they aren’t in the server; 429 means wait for retry_after and try again.

The edge cases: where the time goes

The five steps make a working first version. These make one you can leave running.

Cancel at period end

A member who cancels has paid until the period ends. Remove the role when the subscription actually ends, not when they click Cancel.

Leaving and rejoining

Discord drops a member’s roles when they leave. If they come back while still paying, nothing gives the role back unless you listen for joins (the privileged Server Members intent) or give them a way to ask.

The role order changes

Someone drags the role you sell above the bot’s, and every grant of it fails from then on. You need to notice, and re-grant the members who paid in the meantime.

Missed events

Your server was down for longer than Stripe retries. Without a periodic check of Stripe against Discord, those members never get their role, or never lose it.

Several tiers

Map each price to a role, and swap roles when a member moves between tiers.

Your own records

Which member holds which subscription, so you can answer “I paid and have no role” without opening two dashboards.

What building it costs

Your time, for the first version and for the edge cases. An always-on HTTPS server for the webhook. Upkeep as Stripe’s and Discord’s APIs change. And no platform fee: only Stripe’s card processing. If you want full control or custom logic, it’s a good project.

Or use a bot that already does it

flatpass is this setup, already built, running on your own Stripe account.

  • Linking the Discord account. Members sign in with Discord before checkout, with guilds.join, so a buyer who isn’t in your server gets added.

  • The bot. Two permissions, Manage Roles and Create Invite. Never Administrator.

  • The checkout. Stripe Checkout on your own Stripe account, with cards, Apple Pay and Google Pay.

  • Webhook safety. Every Stripe event is signature-checked and processed once.

  • Failed renewals. The role stays while Stripe retries the card.

  • Cancellations. The role stays until the paid period ends. Members cancel in Stripe’s portal, from /membership.

  • Refunds. A full refund removes the role and ends the subscription; a partial one changes nothing.

  • Chargebacks. The role comes off when a dispute opens. It comes back if you win, and the subscription ends if you lose.

  • The role order. Your dashboard warns you, and members who paid in the meantime get their role once you fix it.

  • Leaving and rejoining. /membership, or the Open button on your invite page, puts the role back.

  • Your records. A member list with each member’s tier, status, renewal date and whether the role is on.

Not built yet: moving a member between tiers, and one-time payments. Free up to 15 paid members, then a flat monthly fee from $29, and 0% of your sales; Stripe’s card fee is the same either way. How it works for your members.

Common questions

How do I connect Stripe to Discord roles?

To give a Discord role when someone pays with Stripe, you need three pieces: a way to know the buyer’s Discord account, a webhook that listens for Stripe’s subscription events, and a bot that adds or removes the role through Discord’s API. You can build all three yourself, or use a bot like flatpass that runs the same setup on your own Stripe account.

Does Stripe have a Discord integration?

Not a built-in one. Stripe takes the payment, and something else has to change the Discord role: your own webhook and bot, or an app that does it for you.

Can I build it with n8n or Zapier?

Yes. The same pieces apply: the Discord account link before checkout, the Stripe events to handle, and the Discord calls. The edge cases don’t go away.

Do I need a server?

Yes, for the webhook. Stripe has to be able to reach it at any time over HTTPS.

Does the bot need to be online all the time?

Not to change roles: the API calls work with the bot’s token alone. Only to react to things happening in Discord, like a member rejoining.

Skip the build, keep your Stripe

Free up to 15 paid members · 0% of your sales · Your own Stripe account