Easy Labs
PaymentsMigration

Migrate from Stripe to Easy Payments

Mechanical mapping from Stripe's API to Easy Labs' Payments product.

This page is the mechanical method-and-event mapping between the Stripe Node SDK and @easylabs/node. Field names mostly carry over; the larger conceptual shift is that Easy Labs collapses Stripe's PaymentIntent / Charge / SetupIntent split into a single Transfer lifecycle. See Object model differences at the bottom.

API surface mapping

StripeEasy LabsNotes
stripe.customers.create({ email, name })easy.createCustomer({ first_name, last_name, email })First/last name are required and split into separate fields.
stripe.customers.retrieve(id)easy.getCustomer(id)Identical.
stripe.customers.update(id, …)easy.updateCustomer(id, partial)Identical.
stripe.customers.list({ limit })easy.getCustomers({ limit, offset })Pagination is offset-based, not cursor-based.
stripe.customers.listPaymentMethods(id)easy.getCustomerPaymentInstruments(id)Returns Payment Instruments instead of PaymentMethods.
stripe.paymentMethods.create({ type: "card" })Use mountEmbeddedCheckout (@easylabs/browser) or <EmbeddedCheckout> (@easylabs/react); the iframe tokenizes and creates the Payment Instrument.No raw card → token call on the server.
stripe.paymentMethods.retrieve(id)Available implicitly via easy.getCustomerPaymentInstruments(customerId).find(i => i.id === pmId)No standalone get-by-id endpoint.
stripe.paymentMethods.update(id, …)easy.updatePaymentInstrument(id, partial)Includes enabled, address, tags.
stripe.paymentIntents.create({ amount, … })easy.createTransfer({ amount, currency, source })No two-step intent → confirm. Authorization + capture happen in one call against a Payment Instrument.
stripe.paymentIntents.confirm(id)n/aImplicit; createTransfer is the equivalent of "create + confirm".
stripe.charges.create({ … })easy.createTransfer({ amount, currency, source })Renamed; same contract.
stripe.charges.retrieve(id)easy.getTransfer(id)Identical.
stripe.charges.list({ limit })easy.getTransfers({ limit, offset })Pagination differences as above.
stripe.refunds.create({ charge, amount })easy.createRefund(transferId, { refund_amount })Reversal is itself a Transfer with type: "REVERSAL".
stripe.disputes.retrieve(id)easy.getDispute(id)Identical.
stripe.disputes.list()easy.getDisputes({ limit, offset })Pagination differences.
stripe.disputes.update(id, { metadata })easy.updateDispute(id, tags)Tags are the only mutable surface; evidence upload is dashboard-only today.
stripe.checkout.sessions.create({ … })easy.createEmbeddedCheckoutSession({ … })success_url / cancel_url / line_items shapes carry over. Add payment_methods: ["card"] (or "crypto").
stripe.checkout.sessions.retrieve(id)easy.getEmbeddedCheckoutSession(id)Identical.
stripe.products.create(…) / .update / .listeasy.createProduct / .updateProduct / .getProductsIdentical surface.
stripe.prices.create(…) / .update / .listeasy.createPrice / .updatePrice / .getPricesunit_amount is in the smallest currency unit, same as Stripe.
stripe.subscriptions.create({ customer, items })easy.createSubscription({ identity_id, items, instrument_id })customeridentity_id. Funding source must be passed explicitly.
stripe.subscriptions.cancel(id)easy.cancelSubscription(id, { at_period_end: true })Default cancels immediately; opt into period-end via flag.
stripe.invoices.create(…)easy.createInvoice(…)Field names differ; see invoice reference.
stripe.webhookEndpoints.create(…)easy.registerWebhookEndpoint({ url, events })Returns the signing secret once; persist immediately.
stripe.webhooks.constructEvent(body, sig, sec)EasyWebhooks.constructEvent(rawBody, sig, secret)Identical signature. Header is x-easy-webhook-signature.

Webhook event mapping

Stripe eventEasy Labs eventNotes
payment_intent.succeededpayment.updated (state SUCCEEDED)Easy Labs collapses intent + charge events into one payment.* stream.
payment_intent.payment_failedpayment.updated (state FAILED)failure_code + failure_message are populated on the Transfer.
charge.succeededpayment.created / payment.updatedThe single Transfer lifecycle covers both.
charge.refundedrefund.updated (state SUCCEEDED)The reversal is its own Transfer event.
charge.refund.updatedrefund.updatedIdentical semantics.
charge.dispute.createddispute.createdIdentical.
charge.dispute.closeddispute.updated (terminal status)Watch for status transitioning to WON / LOST.
checkout.session.completedcheckout.session.completedIdentical name.
customer.subscription.createdsubscription.createdIdentical.
customer.subscription.updatedsubscription.updatedIdentical.
customer.subscription.deletedsubscription.deletedIdentical.
customer.subscription.pausedsubscription.pausedIdentical.
customer.subscription.resumedsubscription.resumedIdentical.
customer.subscription.trial_will_endsubscription.trial_will_endIdentical.
invoice.createdinvoice.createdIdentical.
invoice.finalizedinvoice.finalizedIdentical.
invoice.paidinvoice.paidIdentical.
invoice.payment_failedinvoice.payment_failedIdentical.
customer.createdidentity.created"Identity" is the underlying processor entity for Customer.
customer.updatedidentity.updatedIdentical semantics.

Object model differences

  • No PaymentIntent. Stripe separates "intent to charge" from "actual charge"; Easy Labs has one Transfer lifecycle that covers both (PENDING → SUCCEEDED | FAILED). If you used PaymentIntent.id to correlate before/after capture, switch to Transfer.id.
  • Identity vs. Customer. Internally Easy Labs calls customers "identities" (you'll see identity_id on Subscriptions, identity on Orders, and identity.* webhook events). The SDK surface still uses customer everywhere — identity_id is the field name on payloads.
  • Payment Instruments are saved by default. A successful checkout always produces a re-usable Payment Instrument. There is no separate SetupIntent for "save card without charging" — instead, create a small auth + void or save during a real first payment.
  • Order is a first-class object. Stripe doesn't have one — it conflates "the transaction" with "the line items." Easy Labs separates Order (line items, totals, customer details) from Transfer (money movement), so refunds happen against the Transfer but fulfillment data lives on the Order.
  • Pagination is offset-based. No starting_after / ending_before cursors. Pass limit + offset.
  • Webhook signature header. Stripe uses Stripe-Signature with a t=…,v1=… payload; Easy Labs uses x-easy-webhook-signature: sha256=<hex> over the raw body. The Node verifier handles this for you (EasyWebhooks.constructEvent).

On this page