Skip to main content

Migrate from Stripe Billing

Time: ~15 minutes to read | Difficulty: Intermediate TagadaPay is not a drop-in Stripe replacement, but the object model maps cleanly. The biggest win: payment flows let you route across multiple processors — something Stripe cannot do without re-architecting.

Object mapping

StripeTagadaPayNotes
Customer (cus_)Customer (cus_)tagada.customers.create
PaymentMethod (pm_)PaymentInstrument (inst_)Created via createFromToken — not attached directly
SetupIntentcore-js tokenize + createFromTokenNo separate SetupIntent object
PaymentIntent (pi_)Payment (pay_)tagada.payments.process
Price (price_)Price (price_)Lives inside a product variant
Product (prod_)Product (product_)tagada.products.create with recurring variant
Subscription (sub_)Subscription (sub_)tagada.subscriptions.create
InvoiceBuild from orders + payments + webhooks
BillingPortalBuild your own with headless SDK
stripe.webhooks.constructEventtagada.webhooks.constructEventSame ergonomics, sha256= HMAC

Code mapping

Create a customer

// Stripe
const customer = await stripe.customers.create({ email: 'user@saas.com' });

// TagadaPay
const customer = await tagada.customers.create({
  storeId: 'store_xxx',
  email: 'user@saas.com',
  firstName: 'Alex',
  lastName: 'Founder',
});

Save a card

// Stripe (browser)
const { paymentMethod } = await stripe.createPaymentMethod({ type: 'card', card: element });
await stripe.paymentMethods.attach(paymentMethod.id, { customer: customer.id });

// TagadaPay (browser → server)
// FRONTEND:
const { tagadaToken } = await tokenizeCard({ cardNumber, expiryDate, cvc });

// BACKEND:
const { paymentInstrument } = await tagada.paymentInstruments.createFromToken({
  tagadaToken, storeId, customerData: { email, firstName, lastName },
});

Charge + subscribe

// Stripe
const paymentIntent = await stripe.paymentIntents.create({
  amount: 1900, currency: 'eur', customer: customer.id,
  payment_method: paymentMethod.id, confirm: true,
});
const subscription = await stripe.subscriptions.create({
  customer: customer.id, items: [{ price: 'price_xxx' }],
});

// TagadaPay
const { payment } = await tagada.payments.process({
  amount: 1900, currency: 'EUR', storeId,
  paymentInstrumentId: paymentInstrument.id,
  customerId: customer.id, initiatedBy: 'customer',
  paymentFlowId: 'flow_xxx',
});
const { subscription } = await tagada.subscriptions.create({
  customerId: customer.id, priceId: 'price_xxx', storeId,
  currency: 'EUR', defaultPaymentInstrumentId: paymentInstrument.id,
  paymentId: payment.id,
});

Webhooks

// Stripe
const event = stripe.webhooks.constructEvent(rawBody, sig, secret);

// TagadaPay
const event = tagada.webhooks.constructEvent(rawBody, req.headers['x-tagadapay-signature'], secret);

Migration phases

Phase 1 — New subscriptions on TagadaPay

  • Keep existing Stripe subs running
  • Route new signups through TagadaPay (SaaS quick start)
  • Use a cascade payment flow: sandbox for dev → live TPA for production
  • Map Stripe webhook handlers to TagadaPay events:
Stripe eventTagadaPay event
invoice.paidsubscription/rebillSucceeded
invoice.payment_failedsubscription/rebillDeclined
customer.subscription.deletedsubscription/canceled
payment_intent.succeededpayment/succeeded

Phase 2 — Processor flexibility (TagadaPay advantage)

This is what Stripe cannot offer:
Stripe:  locked to Stripe
TagadaPay: sandbox → TPA → Stripe → Checkout.com (one vault)
Add processors to your payment flow as you grow. If one TPA is banned, switch the flow — cards stay vaulted.

Phase 3 — Migrate existing subscriptions

TagadaPay supports processor migration without re-vaulting:
await tagada.subscriptions.changeProcessor({
  subscriptionIds: ['sub_xxx'],
  processorId: 'processor_new',
});
For bulk card migration from Stripe, contact support — the vault model supports importing tokenized instruments in some configurations.

What Stripe has that TagadaPay doesn’t (yet)

FeatureWorkaround
Invoices / PDFBuild from payments + orders; email via your app
Usage/metered billingCustom metering in your app + payments.process
Customer billing portalBuild with headless SDK customer hooks
Subscription plan changesManual cancel + re-create (upgrade API coming)

Get started

SaaS Quick Start

Working example tested in production

Payment Flows

Multi-TPA routing — the reason to switch