Skip to content
Create account
or
Sign in
The Stripe Docs logo
/
Ask AI
Create account
Sign in
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
Developer tools
Get started
Payments
Finance automation
Get started
Payments
Finance automation
Platforms and marketplaces
Money management
OverviewExplore all products
Start building
Start developing
Sample projects
About the APIs
    API tour
    Payment Intents API
    Setup Intents API
    Payment Methods
    Products and prices
    Older APIs
      Charges
      Sources
        Transition to the new APIs
        Card Sources
        Sources and customers
        ACH Direct Debit
        Connect platforms
        Best practices
        iOS
        Android
    Release phases
Build with LLMs
Use Stripe without code
Set up Stripe
Create an account
Web Dashboard
Mobile Dashboard
Migrate to Stripe
Manage fraud risk
Understand fraud
Radar fraud protection
Manage disputes
Verify identities
HomeGet startedAbout the APIsOlder APIsSources

Transition to the Payment Intents and Payment Methods APIs

Learn how to transition from the Sources and Tokens APIs to the Payment Methods API.

Copy page

The Payment Methods API replaces the existing Tokens and Sources APIs as the recommended way for integrations to collect and store payment information. It works with the Payment Intents API to create payments for a wide range of payment methods.

We plan to turn off Sources API support for local payment methods. If you currently handle any local payment methods using the Sources API, you must migrate them to the Payment Methods API. We’ll send email communication with more information about the end of support for the Sources and Tokens APIs.

While we don’t plan to turn off support for card payment methods, we still recommend that you migrate them to the Payment Methods and Payment Intents APIs. For more information about migrating card payment methods, see Migrating to the Payment Intents API.

Migrate local payment methods from the Sources API to the Payment Intents API

To migrate your integration for local payment methods, update your server and front end to use the PaymentIntents API. There are three typical integration options:

  • Redirect to Stripe Checkout for your payment flow.
  • Use the Stripe Payment Element on your own payment page.
  • Build your own form and use the Stripe JS SDK to complete the payment.

If you use Stripe Checkout or the Payment Element, you can add and manage most payment methods from the Stripe Dashboard without making code changes.

For specific information about integrating a local payment method using the Payment Methods API, see the instructions for that payment method in the payment methods documentation. The following table provides a high-level comparison of the different payment types.

Old integrationStripe CheckoutPayment ElementOwn form

Low complexity

Medium complexity

High complexity

Create a Source on the front end or on the serverCreate a Checkout Session on the serverCreate a PaymentIntent on the serverCreate a PaymentIntent on the server
Authorise payment by loading a widget or redirecting to a third partyNot neededPass the client secret to the front end and use the Stripe JS SDK to render a Payment Element to complete the paymentPass the client secret to the front end, use your own form to collect details from your customer, and complete the payment according to the payment method
Confirm the source is chargeable and charge the SourceNot neededNot neededNot needed
Confirm the Charge succeeded asynchronously with the charge.succeeded webhookConfirm the Checkout session succeeded with the payment_intent.succeeded webhookConfirm the PaymentIntent succeeded with the payment_intent.succeeded webhookConfirm the PaymentIntent succeeded with the payment_intent.succeeded webhook

Caution

A PaymentIntent object represents a payment in the new integration, and it creates a Charge when you confirm the payment on the front end. If you previously stored references to the Charge, you can continue to do so by fetching the Charge ID from the PaymentIntent after the customer completes the payment. However, we also recommend that you store the PaymentIntent ID.

Checking payment status

Previously, your integration should have checked both the status of the Source and the status of the Charge after each API call. You no longer need to check two statuses, you only need to check the status of the PaymentIntent or the Checkout Session after you confirm it on the front end.

payment_intent.statusMeaningSpecial instructions
succeededThe payment succeeded.Not applicable
requires_payment_methodThe payment failed.Not applicable
requires_actionThe customer hasn’t completed authorising the payment.If the customer doesn’t complete the payment within 48 hours, then the PaymentIntent transitions to requires_payment_method and you can retry the confirmation.

Always confirm the status of the PaymentIntent by fetching it on your server or listening for the webhooks on your server. Don’t rely solely on the user returning to the return_url that’s provided when you confirm the PaymentIntent.

Refunds

You can continue to call the Refunds API with a Charge that the PaymentIntent creates. The ID of the Charge is accessible on the latest_charge parameter.

Alternatively, you can provide the PaymentIntent ID to the Refunds API instead of the Charge.

Error handling

Previously, you had to handle errors on the Sources. With PaymentIntents, instead of checking for errors on a Source, you check for errors on the PaymentIntent when it’s created and after the customer has authorised the payment. Most errors on the PaymentIntent are of invalid_request_error type, returned in an invalid request.

When you migrate your integration, keep in mind that PaymentIntent error codes can differ from the corresponding error codes for Sources.

Webhooks

If you previously listened to Source events, you might need to update your integration to listen to new event types. The following table shows some examples.

Old webhookNew webhook on CheckoutNew webhook on PaymentIntentsSpecial instructions
source.chargeableNot applicableNot applicable
source.failedNot applicableNot applicable
source.canceledNot applicableNot applicable
charge.succeededcheckout.session.completedpayment_intent.succeededThe charge.succeeded webhook is also sent, so you don’t have to update your integration to listen to the new webhook.
charge.failedNot applicable - The customer can re-attempt the payment on the same Checkout Session until it expires, at which point you receive a checkout.session.expired event.payment_intent.payment_failedThe charge.failed webhook is also sent, so you don’t have to update your integration to listen to the new webhook.
charge.dispute.createdcharge.dispute.createdcharge.dispute.created

Transitioning to the Payment Methods API

The main difference between the Payment Methods and Sources APIs is that Sources describes the transaction state through the status property. That means that each Source object must transition to a chargeable state before you can use it for a payment. By contrast, a PaymentMethod is stateless, relying on the PaymentIntent object to represent payment state.

Note

The following table isn’t a comprehensive list of payment methods. If you integrate other payment methods with the Sources API, migrate them to the Payment Methods API as well.

FlowsIntegrate Payment Method with Payment Intents APITokens or Sources with Charges API
CardsCard paymentsSupported on Tokens; Not recommended on Sources
ACH Direct DebitUS bank account direct debitsSupported on Tokens Not supported on Sources
ACH Credit TransferUSD Bank TransfersDeprecated
AlipayAlipay paymentsDeprecated
BancontactBancontact paymentsDeprecated
EPSEPS paymentsDeprecated
giropaygiropay paymentsDeprecated
iDEALiDEAL paymentsDeprecated
KlarnaKlarna paymentsDeprecated
MultibancoMultibanco paymentsDeprecated Beta
Przelewy24Przelewy24 paymentsDeprecated
SEPA Credit TransferEUR Bank TransfersDeprecated
SEPA Direct DebitSingle Euro Payments Area direct debitsDeprecated
SofortSofort paymentsDeprecated
WeChat PayWeChat Pay paymentsDeprecated

After you choose the API to integrate with, use the guide to payment methods to help you determine the right payment method types you need to support.

This guide includes detailed descriptions of each payment method and describes the differences in the customer-facing flows, along with the geographic regions where they’re most relevant. You can enable any payment method available to you within the Dashboard. Activation is generally instantaneous and doesn’t require additional contracts.

Compatibility with legacy reusable payment methods

If you previously processed any of the following reusable payment methods using Sources, the existing saved sources don’t migrate automatically:

  • Alipay
  • Bacs Direct Debit
  • SEPA Direct Debit

To preserve your existing customers’ saved payment methods, you must convert those sources to payment methods using a data migration tool in the Stripe Dashboard. For instructions on how to convert them, see the support page.

Compatibility with legacy card objects

If you previously collected card customer payment details with Stripe using cards or Sources, you can start using the Payment Methods API immediately without migrating any payment information.

Compatible payment instruments that have been saved to a Customer are usable in any API that accepts a PaymentMethod object. For example, you can use a saved card as a PaymentMethod when creating a PaymentIntent:

Command Line
cURL
curl https://api.stripe.com/v1/payment_intents \ -u "
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:"
\ -d "payment_method_types[]"=card \ -d amount=1099 \ -d currency=usd \ -d customer=
{{CUSTOMER_ID}}
\ -d payment_method=
{{CARD_ID}}

Remember to provide the customer ID that your compatible payment instrument is saved to when attaching the object to a PaymentIntent.

You can retrieve all saved compatible payment instruments through the Payment Methods API.

{ "id": "card_1EBXBSDuWL9wT9brGOaALeD2", "object": "card", "address_city": "San Francisco", "address_country": "US", "address_line1": "1234 Fake Street", "address_line1_check": null, "address_line2": null, "address_state": null, "address_zip": null,
{ "id": "card_1EBXBSDuWL9wT9brGOaALeD2", "object": "payment_method", "billing_details": { "address": { "city": "San Francisco", "country": "US", "line1": "1234 Fake Street", "line2": null, "postal_code": null,

With this compatibility, no new objects are created; the Payment Methods API provides a different view of the same underlying object. For example, updates to a compatible payment instrument through the Payment Methods API is visible through the Sources API, and vice versa.

See also

  • Guide to payment methods
  • Connect payments
  • Payment Methods API reference
Was this page helpful?
YesNo
Need help? Contact Support.
Join our early access programme.
Check out our changelog.
Questions? Contact Sales.
LLM? Read llms.txt.
Powered by Markdoc