<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Panche I.</title>
    <description>The latest articles on DEV Community by Panche I. (@panchei).</description>
    <link>https://dev.to/panchei</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4188367%2Fcaff6cd7-357c-42f6-bbea-fcba84d1f944.jpg</url>
      <title>DEV Community: Panche I.</title>
      <link>https://dev.to/panchei</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/panchei"/>
    <language>en</language>
    <item>
      <title>Stripe doesn't open accounts in 37 of the 85 countries we checked. Here are the legal ways to get paid anyway</title>
      <dc:creator>Panche I.</dc:creator>
      <pubDate>Fri, 06 Nov 2026 08:18:43 +0000</pubDate>
      <link>https://dev.to/panchei/stripe-doesnt-open-accounts-in-37-of-the-85-countries-we-checked-here-are-the-legal-ways-to-get-41i1</link>
      <guid>https://dev.to/panchei/stripe-doesnt-open-accounts-in-37-of-the-85-countries-we-checked-here-are-the-legal-ways-to-get-41i1</guid>
      <description>&lt;p&gt;Every week someone writes to us with the same message: "I have customers ready to pay by card, but Stripe won't let me open an account where I live."&lt;/p&gt;

&lt;p&gt;So we checked. On 6 October 2026 we went through 85 countries and compared them against Stripe's own list of supported countries.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;37 of 85:&lt;/strong&gt; Stripe does not open accounts at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5 more:&lt;/strong&gt; Stripe offers only a limited version, including India, Indonesia, Kenya, Nigeria and South Africa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;11 of the same 85:&lt;/strong&gt; PayPal cannot receive money either.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And once an account exists, Stripe support is clear: "You can't change the country of a Stripe account."&lt;/p&gt;

&lt;h2&gt;
  
  
  The legal options
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. A merchant of record.&lt;/strong&gt; The merchant of record is the legal seller of your product. It takes the card payment, handles the buyer's tax and pays you out to your bank, so Stripe never needs to support your country. Paddle, Lemon Squeezy, Polar, Creem, Dodo Payments and AgentaOS all work this way. The catch: check that the one you pick &lt;strong&gt;pays out to your country&lt;/strong&gt;, not just that it accepts your sign-up. Payout lists differ a lot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A US company (Stripe Atlas).&lt;/strong&gt; About $500 to start, a yearly Delaware tax from $400, a yearly IRS Form 5472, and usually an accountant. Takes weeks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. An EU company (e.g. Estonian e-Residency).&lt;/strong&gt; An accountant and VAT filings every month. Takes weeks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Bank transfer invoices.&lt;/strong&gt; Works for a few clients. No card checkout, no subscriptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three mistakes that get accounts closed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Opening Stripe in a country you don't live in.&lt;/strong&gt; Stripe checks ID, address and bank account, and the account country can't be changed later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buying a "verified Stripe account."&lt;/strong&gt; They are sold on LinkedIn and Telegram. Your money sits in someone else's account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reading a platform payout as Stripe access.&lt;/strong&gt; Bandcamp or X can pay you through Stripe. That does not let you sell your own product.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to start this week
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Look up your country: how payouts reach you and what they cost.&lt;/li&gt;
&lt;li&gt;Pick a merchant of record that pays out there and accepts what you sell. Paddle and Lemon Squeezy do not take services.&lt;/li&gt;
&lt;li&gt;Create your product with a one-time or monthly price and share the checkout link.&lt;/li&gt;
&lt;li&gt;Open a EUR or USD account at your bank for payouts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The full country check, with Stripe's list and sources, is here: &lt;a href="https://agentaos.ai/answers/stripe-not-available-in-my-country" rel="noopener noreferrer"&gt;https://agentaos.ai/answers/stripe-not-available-in-my-country&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Disclosure: I run AgentaOS, one of the merchants of record above. The page lists the others too.&lt;/p&gt;

&lt;p&gt;Which country are you selling from, and what did you end up using?&lt;/p&gt;

</description>
      <category>stripe</category>
      <category>payments</category>
      <category>saas</category>
      <category>startup</category>
    </item>
    <item>
      <title>Add payments to a Next.js app with two route handlers (merchant of record, tax handled)</title>
      <dc:creator>Panche I.</dc:creator>
      <pubDate>Mon, 26 Oct 2026 11:35:26 +0000</pubDate>
      <link>https://dev.to/panchei/add-payments-to-a-nextjs-app-with-two-route-handlers-merchant-of-record-tax-handled-2jhc</link>
      <guid>https://dev.to/panchei/add-payments-to-a-nextjs-app-with-two-route-handlers-merchant-of-record-tax-handled-2jhc</guid>
      <description>&lt;p&gt;Selling a SaaS plan or a digital product from a Next.js app usually means two jobs: taking the payment, and then handling VAT, sales tax and invoices for buyers in other countries. This post sets up both in two route handlers with &lt;code&gt;@agentaos/nextjs&lt;/code&gt;. AgentaOS is a merchant of record: it sells the product in its own name, charges the buyer's VAT or sales tax, issues the invoice and pays you out.&lt;/p&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a Next.js app with the App Router&lt;/li&gt;
&lt;li&gt;an AgentaOS account (test mode works from the first minute)&lt;/li&gt;
&lt;li&gt;a product created in the AgentaOS dashboard, and its link ID from the product page&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Install and set the keys
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @agentaos/nextjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the dashboard, create an API key under &lt;strong&gt;Developers → API keys&lt;/strong&gt; (&lt;code&gt;sk_test_...&lt;/code&gt; in test mode). Under &lt;strong&gt;Settings → Developers → Webhooks&lt;/strong&gt;, set the URL to &lt;code&gt;https://your-domain.com/api/webhooks/agentaos&lt;/code&gt; and copy the signing secret.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .env.local&lt;/span&gt;
&lt;span class="nv"&gt;AGENTAOS_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk_test_...
&lt;span class="nv"&gt;AGENTAOS_WEBHOOK_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;whsec_...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. The checkout route
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/checkout/route.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Checkout&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@agentaos/nextjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Checkout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;pro&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-pro-link-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;successUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://your-domain.com/thanks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getCurrentUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// your own session&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now a plain link starts a checkout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/checkout?product=pro"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Buy Pro&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things the route does for you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only slugs in &lt;code&gt;products&lt;/code&gt; can be bought. Someone editing the URL cannot buy a product you did not list.&lt;/li&gt;
&lt;li&gt;The buyer's email and the metadata come from your server through &lt;code&gt;customer()&lt;/code&gt;, never from the query string.&lt;/li&gt;
&lt;li&gt;The route adds the slug to the metadata as &lt;code&gt;product&lt;/code&gt;, so your webhook knows what was bought.&lt;/li&gt;
&lt;li&gt;It ignores prefetch requests. A &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; that scrolls into view, or a browser prefetch, does not open a checkout. With &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt;, set &lt;code&gt;prefetch={false}&lt;/code&gt; anyway.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In test mode, pay with &lt;code&gt;4242 4242 4242 4242&lt;/code&gt;, any future date and any CVC. The buyer comes back to &lt;code&gt;successUrl&lt;/code&gt; with &lt;code&gt;?sessionId=...&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The webhook route
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/api/webhooks/agentaos/route.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Webhooks&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@agentaos/nextjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Webhooks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;webhookSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AGENTAOS_WEBHOOK_SECRET&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;onCheckoutCompleted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Renewals arrive as checkout.session.completed too, without your metadata.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;grantAccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;onSubscriptionCanceled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;revokeAccessByEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerEmail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The route verifies an HMAC-SHA256 signature over the raw body and rejects anything older than 5 minutes. It refuses to start without a secret, so a missing environment variable fails at boot instead of accepting unsigned events. It needs no API key.&lt;/p&gt;

&lt;p&gt;There is one function per event: &lt;code&gt;onCheckoutCompleted&lt;/code&gt;, &lt;code&gt;onSubscriptionCreated&lt;/code&gt;, &lt;code&gt;onSubscriptionRenewed&lt;/code&gt;, &lt;code&gt;onSubscriptionUpdated&lt;/code&gt;, &lt;code&gt;onSubscriptionPaymentFailed&lt;/code&gt;, &lt;code&gt;onSubscriptionCanceled&lt;/code&gt;, &lt;code&gt;onDisputeCreated&lt;/code&gt;, &lt;code&gt;onDisputeClosed&lt;/code&gt;, plus &lt;code&gt;onEvent&lt;/code&gt; for everything. If your function throws, the route answers 500 and the event is delivered again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three things that trip people up
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Renewals look like checkouts.&lt;/strong&gt; A renewal or an upgrade charge also arrives as &lt;code&gt;checkout.session.completed&lt;/code&gt;, carrying a &lt;code&gt;subscriptionId&lt;/code&gt; instead of your metadata. Save the link from &lt;code&gt;subscriptionId&lt;/code&gt; to your user on the first event.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Events can arrive twice.&lt;/strong&gt; Grant access once per &lt;code&gt;event.data.sessionId&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metadata keys arrive in camelCase.&lt;/strong&gt; &lt;code&gt;user_id&lt;/code&gt; comes back as &lt;code&gt;userId&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Using Better Auth?
&lt;/h2&gt;

&lt;p&gt;If your app signs users in with Better Auth, &lt;code&gt;@agentaos/better-auth&lt;/code&gt; does the checkout from the signed-in session instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;authClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agentaos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full guides: &lt;a href="https://docs.agentaos.ai/sdk/nextjs" rel="noopener noreferrer"&gt;Next.js route handlers&lt;/a&gt; and &lt;a href="https://docs.agentaos.ai/sdk/better-auth" rel="noopener noreferrer"&gt;Better Auth plugin&lt;/a&gt;. The packages are open source in &lt;a href="https://github.com/AgentaOS/agentaos" rel="noopener noreferrer"&gt;AgentaOS/agentaos&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>payments</category>
      <category>saas</category>
      <category>webdev</category>
    </item>
    <item>
      <title>All 50 Stripe decline codes in 5 buckets, with what to tell the buyer (2026)</title>
      <dc:creator>Panche I.</dc:creator>
      <pubDate>Tue, 20 Oct 2026 08:20:27 +0000</pubDate>
      <link>https://dev.to/panchei/all-50-stripe-decline-codes-in-5-buckets-with-what-to-tell-the-buyer-2026-43jl</link>
      <guid>https://dev.to/panchei/all-50-stripe-decline-codes-in-5-buckets-with-what-to-tell-the-buyer-2026-43jl</guid>
      <description>&lt;p&gt;A declined card is a sale you can still save, if the buyer knows what to do next. Most checkouts show "Your card was declined" for every case, so a typo in the CVC looks the same as a stolen card.&lt;/p&gt;

&lt;p&gt;Stripe tells you the reason in &lt;code&gt;decline_code&lt;/code&gt;. You get it on the card error (&lt;code&gt;err.decline_code&lt;/code&gt; when &lt;code&gt;err.type === 'card_error'&lt;/code&gt;) and on a PaymentIntent as &lt;code&gt;last_payment_error.decline_code&lt;/code&gt;. Stripe lists 50 codes. They fall into five buckets, and each bucket needs a different message.&lt;/p&gt;

&lt;p&gt;Codes checked against Stripe's decline codes docs on 18 October 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five buckets
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bucket&lt;/th&gt;
&lt;th&gt;Codes&lt;/th&gt;
&lt;th&gt;What to do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Buyer can fix it&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;Ask them to correct the number, CVC, date, address or PIN, or finish 3D Secure.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retry&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;A temporary error at the bank or network. Retry once.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Another card&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;No funds, a limit, or the card can't pay this. Ask for another card.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bank must say why&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;The issuer gave no reason. Only the buyer's bank can explain.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Show as generic&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Fraud, lost, stolen or block list. Never tell the buyer the real reason.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The last row matters most. Stripe's guidance for &lt;code&gt;fraudulent&lt;/code&gt;, &lt;code&gt;lost_card&lt;/code&gt;, &lt;code&gt;stolen_card&lt;/code&gt; and &lt;code&gt;merchant_blacklist&lt;/code&gt; is to show a generic decline, so you never tell a fraudster which check caught them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drop-in mapping
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BUCKET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authentication_required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authentication_not_handled&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;duplicate_transaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;incorrect_address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;incorrect_cvc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;incorrect_number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;incorrect_pin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;incorrect_zip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invalid_cvc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invalid_expiry_month&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invalid_expiry_year&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invalid_number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invalid_pin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline_pin_required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online_or_offline_pin_required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mobile_device_authentication_required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;approve_with_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;issuer_not_available&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;processing_error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reenter_transaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;try_again_later&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;otherCard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;card_not_supported&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;expired_card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;insufficient_funds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pin_try_exceeded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;testmode_decline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;withdrawal_count_limit_exceeded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;generic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fraudulent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lost_card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;merchant_blacklist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stolen_card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="c1"&gt;// everything else: the bank must say why&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MESSAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Some card details don&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;t match. Please check them and try again.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;We could not approve this payment. Please try again in a moment.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;otherCard&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This card can&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;t be used for this payment. Please use another card.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bank&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Your bank declined this payment. Please contact your bank or use another card.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;declineMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BUCKET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;MESSAGE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bank&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// never reveal fraud checks&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fix&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;retry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;otherCard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BUCKET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;MESSAGE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;MESSAGE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bank&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two refinements worth adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For &lt;code&gt;duplicate_transaction&lt;/code&gt;, tell the buyer to check their email first. The earlier payment may already have gone through.&lt;/li&gt;
&lt;li&gt;For &lt;code&gt;authentication_required&lt;/code&gt; on an off-session renewal, you can't show 3D Secure in the background. Email the customer a link to come back and confirm.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Test them before buyers do
&lt;/h2&gt;

&lt;p&gt;Many codes have a Stripe test card. A few:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;insufficient_funds&lt;/code&gt;: 4000 0000 0000 9995&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;expired_card&lt;/code&gt;: 4000 0000 0000 0069&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;incorrect_cvc&lt;/code&gt;: 4000 0000 0000 0127&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;generic_decline&lt;/code&gt;: 4000 0000 0000 0002&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The full list
&lt;/h2&gt;

&lt;p&gt;All 50 codes, each with its meaning, what to do, a buyer message you can copy and its test card where one exists, are on one searchable page: &lt;a href="https://agentaos.ai/tools/stripe-decline-codes" rel="noopener noreferrer"&gt;Stripe decline codes 2026&lt;/a&gt;. The test cards for every scenario are at &lt;a href="https://agentaos.ai/tools/stripe-test-cards" rel="noopener noreferrer"&gt;Stripe test cards&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Disclosure: I build AgentaOS, a merchant of record. The pages above are free and need no account.&lt;/p&gt;

</description>
      <category>stripe</category>
      <category>payments</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Ten $100 sales on 7 merchants of record: what actually reaches your bank (Oct 2026)</title>
      <dc:creator>Panche I.</dc:creator>
      <pubDate>Mon, 19 Oct 2026 10:09:27 +0000</pubDate>
      <link>https://dev.to/panchei/ten-100-sales-on-7-merchants-of-record-what-actually-reaches-your-bank-oct-2026-53e6</link>
      <guid>https://dev.to/panchei/ten-100-sales-on-7-merchants-of-record-what-actually-reaches-your-bank-oct-2026-53e6</guid>
      <description>&lt;p&gt;Headline fees hide the extras. International cards, subscriptions and payouts all take a cut, and they stack differently on each provider. So we did the plain sum: ten $100 card sales from buyers in the provider's home market, paid out once. Every number comes from the provider's own pricing and docs pages, checked 6 to 19 October 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  What reaches your bank
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Per sale&lt;/th&gt;
&lt;th&gt;Lands from $1,000&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dodo Payments&lt;/td&gt;
&lt;td&gt;4% + $0.40&lt;/td&gt;
&lt;td&gt;$931 to $951&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creem&lt;/td&gt;
&lt;td&gt;3.9% + $0.40&lt;/td&gt;
&lt;td&gt;about $947&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lemon Squeezy&lt;/td&gt;
&lt;td&gt;5% + $0.50&lt;/td&gt;
&lt;td&gt;about $945&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paddle&lt;/td&gt;
&lt;td&gt;5% + $0.50&lt;/td&gt;
&lt;td&gt;$930 to $945&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AgentaOS&lt;/td&gt;
&lt;td&gt;4.5% + €0.50&lt;/td&gt;
&lt;td&gt;about €940 (on €1,000)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polar&lt;/td&gt;
&lt;td&gt;5% + $0.50 (Starter)&lt;/td&gt;
&lt;td&gt;about $940&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gumroad&lt;/td&gt;
&lt;td&gt;10% + $0.50, plus card fees&lt;/td&gt;
&lt;td&gt;about $863&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The gap between the best and worst is close to $90 on $1,000. Between the top six it is about $20.&lt;/p&gt;

&lt;h2&gt;
  
  
  The extras that change the answer
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;International cards:&lt;/strong&gt; Dodo, Lemon Squeezy, Polar and AgentaOS add 1.5%. Paddle does not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscriptions:&lt;/strong&gt; Dodo and Lemon Squeezy add 0.5% on recurring payments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payouts:&lt;/strong&gt; Creem charges $7 or 1%, whichever is higher. Lemon Squeezy is free in the US and 1% elsewhere. Dodo charges $5 below $1,000. Polar passes on Stripe's payout fees ($2 a month plus 0.25% + $0.25 per payout). Paddle is free by SEPA or ACH.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FastSpring&lt;/strong&gt; does not publish a rate; you get a quote from sales.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to choose
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;If most buyers are outside the provider's home market, add the international surcharge before comparing.&lt;/li&gt;
&lt;li&gt;If you sell subscriptions, add the subscription surcharge.&lt;/li&gt;
&lt;li&gt;If your payouts are small, the fixed payout fee matters more than half a percent.&lt;/li&gt;
&lt;li&gt;Check the provider pays out to your country. Several do not reach the Balkans, Pakistan or parts of Africa.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The data
&lt;/h2&gt;

&lt;p&gt;The full table, with every extra and a link to each provider's price page, is at &lt;a href="https://agentaos.ai/merchant-of-record-fees" rel="noopener noreferrer"&gt;Merchant of Record fees, side by side&lt;/a&gt;, with a free CSV. Reuse it with a credit. If a number is wrong, tell me and I will fix it.&lt;/p&gt;

&lt;p&gt;Disclosure: I build AgentaOS, one of the providers in the table. It is not the cheapest per sale; Creem and Dodo are.&lt;/p&gt;

</description>
      <category>saas</category>
      <category>payments</category>
      <category>indiehackers</category>
      <category>startup</category>
    </item>
    <item>
      <title>Stripe isn't available in 37 of 85 countries we checked. Here is who pays out there (2026 data)</title>
      <dc:creator>Panche I.</dc:creator>
      <pubDate>Sat, 17 Oct 2026 14:19:30 +0000</pubDate>
      <link>https://dev.to/panchei/stripe-isnt-available-in-37-of-85-countries-we-checked-here-is-who-pays-out-there-2026-data-lpd</link>
      <guid>https://dev.to/panchei/stripe-isnt-available-in-37-of-85-countries-we-checked-here-is-who-pays-out-there-2026-data-lpd</guid>
      <description>&lt;p&gt;We checked 85 countries against the public country lists of 9 payment providers: Stripe, PayPal, Paddle, Lemon Squeezy, Polar, Creem, Dodo Payments, Gumroad and Wise. Every cell has a note taken from that provider's own list, and the check date is in the file (6 Oct 2026).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stripe does not support 37 of the 85.&lt;/strong&gt; That includes Serbia, North Macedonia, Albania, Bosnia and Herzegovina, Kosovo, Montenegro, Moldova, Ukraine, Georgia, Turkey, Egypt, Morocco, Pakistan, Bangladesh, Nepal, Sri Lanka, Vietnam, the Philippines, South Korea, Taiwan, Argentina, Chile, Colombia, Peru and Uruguay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who pays out in those 37 countries
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Yes&lt;/th&gt;
&lt;th&gt;Limited&lt;/th&gt;
&lt;th&gt;No&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Paddle&lt;/td&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dodo Payments&lt;/td&gt;
&lt;td&gt;31&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creem&lt;/td&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lemon Squeezy&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polar&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gumroad&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PayPal&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wise&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;"Limited" usually means PayPal payouts only, or an account that can send but not hold money. Paddle's "yes" means the country is not on Paddle's unsupported list; Paddle still reviews every business.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means if you are in one of them
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A merchant of record is the usual route.&lt;/strong&gt; It sells to your customer in its own name, handles VAT and sales tax, and pays you out. You do not need a Stripe account or a company abroad.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the payout, not the checkout.&lt;/strong&gt; Most providers can charge a card anywhere. The question is whether they can send money to a bank in your country, in which currency, and with what minimum.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare the real cost.&lt;/strong&gt; Per-sale fees range from about 3.9% to 10% plus fixed fees, and some add currency conversion and payout fees on top.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The data
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CSV and notes: &lt;a href="https://huggingface.co/datasets/agentaos/payment-provider-country-coverage-2026" rel="noopener noreferrer"&gt;Hugging Face&lt;/a&gt; and &lt;a href="https://www.kaggle.com/panchei" rel="noopener noreferrer"&gt;Kaggle&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Free to reuse with a credit. If a cell is wrong, tell me and I will fix it in the next monthly check.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disclosure: I build &lt;a href="https://agentaos.ai/answers/stripe-not-available-in-my-country" rel="noopener noreferrer"&gt;AgentaOS&lt;/a&gt;, a merchant of record that pays out to banks in these countries. The table above includes our competitors as they are; several of them cover more countries than people expect.&lt;/p&gt;

</description>
      <category>stripe</category>
      <category>saas</category>
      <category>payments</category>
      <category>opendata</category>
    </item>
    <item>
      <title>How to let an AI agent set up payments (and who files the VAT)</title>
      <dc:creator>Panche I.</dc:creator>
      <pubDate>Sat, 17 Oct 2026 10:29:19 +0000</pubDate>
      <link>https://dev.to/panchei/how-to-let-an-ai-agent-set-up-payments-and-who-files-the-vat-5728</link>
      <guid>https://dev.to/panchei/how-to-let-an-ai-agent-set-up-payments-and-who-files-the-vat-5728</guid>
      <description>&lt;p&gt;Your AI agent can write a checkout integration in ten minutes. What it can't do is register for VAT in the EU, collect sales tax in US states, and file the returns every quarter. That part is why most "let the agent add payments" demos stop at test mode.&lt;/p&gt;

&lt;p&gt;This post is about the missing piece: a &lt;strong&gt;merchant of record&lt;/strong&gt;, and how to wire one to Claude, ChatGPT or Cursor over MCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a merchant of record does
&lt;/h2&gt;

&lt;p&gt;A merchant of record (MoR) is the legal seller on every sale. Your customer buys from the MoR, the MoR pays you out. Because it's the seller, the tax registrations, invoices and chargebacks are its job, not yours. Paddle, Lemon Squeezy, Polar, Creem and AgentaOS all work this way; Stripe on its own doesn't (you stay the seller and file the tax).&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;merchant of record for AI agents&lt;/strong&gt; is the same thing, except your agent can operate it: create the products, the checkout links and the subscriptions, while the MoR does the selling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is who in an agent sale
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Who&lt;/th&gt;
&lt;th&gt;Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The agent&lt;/td&gt;
&lt;td&gt;Claude, ChatGPT, Cursor&lt;/td&gt;
&lt;td&gt;Creates products and checkouts through a connection you approved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;td&gt;The verified business&lt;/td&gt;
&lt;td&gt;Passes the ID check, gets the payout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The MoR&lt;/td&gt;
&lt;td&gt;e.g. AgentaOS&lt;/td&gt;
&lt;td&gt;Legal seller on the receipt, charges and files VAT/sales tax, handles disputes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The agent is never the seller. It acts for a verified business.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wiring it up (MCP)
&lt;/h2&gt;

&lt;p&gt;With AgentaOS the hosted MCP server is &lt;code&gt;https://mcp.agentaos.ai/mcp&lt;/code&gt; (OAuth, no API key to paste):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Claude.ai / ChatGPT / Cursor:&lt;/strong&gt; add it as a remote MCP connector and approve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code:&lt;/strong&gt; &lt;code&gt;/mcp&lt;/code&gt;, pick &lt;code&gt;agentaos&lt;/code&gt;, Authenticate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No MCP?&lt;/strong&gt; &lt;code&gt;npm install -g agentaos&lt;/code&gt; for the CLI, or &lt;code&gt;@agentaos/pay&lt;/code&gt; in your server code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then ask: &lt;em&gt;"Add a €29/month Pro plan to my app and give me a checkout link."&lt;/em&gt; The agent creates the product once, returns a hosted checkout link, and you test it with &lt;code&gt;4242 4242 4242 4242&lt;/code&gt;. Real money starts after verification; the same links then take it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rules I'd give any agent before it touches payments
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Never unlock access on the success redirect.&lt;/strong&gt; Unlock on a verified webhook, or after your server confirms the session status is &lt;code&gt;completed&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create the product once, not per buyer.&lt;/strong&gt; A product is your catalogue; a checkout session is one buyer's attempt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logged-in users get a server-created checkout&lt;/strong&gt; with your user id in metadata, never the shared payment link.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never retry a create after an error.&lt;/strong&gt; Check the state first; a timeout isn't a failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Card numbers never pass through the agent.&lt;/strong&gt; Buyers type them on the hosted checkout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legal and tax details come from the human.&lt;/strong&gt; The agent asks; it never guesses a registration number or accepts a declaration for you.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What it costs
&lt;/h2&gt;

&lt;p&gt;MoRs charge more per sale than a raw processor because they carry the tax work. Typical 2026 rates: Creem 3.9% + $0.40, Dodo 4% + $0.40, AgentaOS 4.5% + €0.50 (4% + €0.40 on Pro), Paddle and Lemon Squeezy 5% + $0.50. A side-by-side table with sources and payout fees is here: &lt;a href="https://agentaos.ai/merchant-of-record-fees" rel="noopener noreferrer"&gt;Merchant of Record fees 2026&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: I build AgentaOS. The open-source SDK, CLI and MCP server are on &lt;a href="https://github.com/AgentaOS/agentaos" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. Longer version, with what the agent can and can't do: &lt;a href="https://agentaos.ai/merchant-of-record-for-ai-agents" rel="noopener noreferrer"&gt;Merchant of Record for AI agents&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>payments</category>
      <category>saas</category>
    </item>
    <item>
      <title>Add payments to your app from Claude Code in one prompt</title>
      <dc:creator>Panche I.</dc:creator>
      <pubDate>Fri, 16 Oct 2026 08:55:52 +0000</pubDate>
      <link>https://dev.to/panchei/add-payments-to-your-app-from-claude-code-in-one-prompt-1gom</link>
      <guid>https://dev.to/panchei/add-payments-to-your-app-from-claude-code-in-one-prompt-1gom</guid>
      <description>&lt;p&gt;I grew up in North Macedonia, where Stripe still doesn't work. If you build software somewhere like that, getting paid by customers abroad usually means opening a company in another country, finding a bank there, and then dealing with VAT and sales tax in every market you sell to.&lt;/p&gt;

&lt;p&gt;A merchant of record removes most of that: it becomes the official seller of your product, takes the card or subscription payment, charges the right tax, sends the invoice, handles chargebacks and pays you out. I built one, AgentaOS, and this post shows the part I think is most useful for developers: setting payments up from your coding agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Install the plugin (Claude Code)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude plugins marketplace add AgentaOS/agentaos
claude plugins &lt;span class="nb"&gt;install &lt;/span&gt;agentaos@agentaos
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open &lt;code&gt;/mcp&lt;/code&gt; in Claude Code and sign in with your AgentaOS account. There is no API key to paste.&lt;/p&gt;

&lt;p&gt;Using Cursor, ChatGPT or another MCP client instead? Add the hosted server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agentaos"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.agentaos.ai/mcp"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Ask in plain words
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Add a €29/month Pro plan and give me a checkout link.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent creates the product and the price and returns a checkout link you can put behind your upgrade button. Other things it can do from the same chat:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create discount codes and check which ones are used&lt;/li&gt;
&lt;li&gt;list payments, subscriptions and customers&lt;/li&gt;
&lt;li&gt;change a customer's plan or give them credit&lt;/li&gt;
&lt;li&gt;send a receipt&lt;/li&gt;
&lt;li&gt;show the statements you attest to before submitting business verification&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. What happens when someone pays
&lt;/h2&gt;

&lt;p&gt;The customer pays by card, one-time or monthly. Because AgentaOS is the seller, the right VAT or sales tax is charged, the invoice is issued in our name, chargebacks are ours to handle, and you get paid out to your bank twice a month. You don't need a company to start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Free to start: €0 a month and 4.5% + €0.50 per card sale. If you want to compare it with Paddle, Lemon Squeezy, Polar and others, I keep a fees table with the source for every number: &lt;a href="https://agentaos.ai/merchant-of-record-fees" rel="noopener noreferrer"&gt;https://agentaos.ai/merchant-of-record-fees&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Setup docs: &lt;a href="https://docs.agentaos.ai/mcp/setup" rel="noopener noreferrer"&gt;https://docs.agentaos.ai/mcp/setup&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Source (CLI, SDK, MCP server): &lt;a href="https://github.com/AgentaOS/agentaos" rel="noopener noreferrer"&gt;https://github.com/AgentaOS/agentaos&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;More on the Claude Code flow: &lt;a href="https://agentaos.ai/add-payments-with-claude-code" rel="noopener noreferrer"&gt;https://agentaos.ai/add-payments-with-claude-code&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd like to hear from anyone selling from outside the US and EU: what does your payment setup look like today?&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>payments</category>
      <category>saas</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
