> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Update Payment Method

> Update the payment method for an existing subscription. You can either add a new payment method or use an existing one from the customer's saved payment methods.

Update the payment method for a subscription. This endpoint supports both active subscriptions and subscriptions in `on_hold` state.

<Info>
  For subscriptions in `on_hold` state, updating the payment method automatically creates a charge for remaining dues, generates an invoice, and reactivates the subscription to `active` state upon successful payment.
</Info>

### Use Cases

* **Active subscriptions**: Update payment method when a card expires or customer wants to use a different payment method
* **On hold subscriptions**: Reactivate subscriptions that went on hold due to failed payments by updating the payment method
* **Payment method management**: Switch between saved payment methods or add new ones

<Info>
  To list existing payment methods for a customer, use the [List Payment Methods API](/api-reference/customers/get-customer-payment-methods). This helps you retrieve available payment method IDs when using `type: "existing"` to update a subscription's payment method.
</Info>

### Behavior for Active Subscriptions

When updating the payment method for an active subscription:

* The payment method is updated immediately
* No charge is created
* The subscription remains active
* Future renewals will use the new payment method

### Behavior for On Hold Subscriptions

When updating the payment method for a subscription in `on_hold` state:

1. A charge is automatically created for remaining dues
2. An invoice is generated for the charge
3. The payment is processed using the new payment method
4. Upon successful payment, the subscription is reactivated to `active` state
5. You'll receive webhook events: `payment.succeeded` followed by `subscription.active`

<Warning>
  If the payment fails after updating the payment method for an `on_hold` subscription, the subscription will remain in `on_hold` state. Monitor webhook events to track payment status.
</Warning>

### Webhook Events

When updating a payment method for an `on_hold` subscription, you'll receive the following webhook events:

1. **`payment.succeeded`** - The charge for remaining dues was successful
2. **`subscription.active`** - The subscription has been reactivated


## OpenAPI

````yaml post /subscriptions/{subscription_id}/update-payment-method
openapi: 3.1.0
info:
  title: public
  description: ''
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
  version: 1.102.0
servers:
  - url: https://test.dodopayments.com/
    description: Test Mode Server Host
  - url: https://live.dodopayments.com/
    description: Live Mode Server Host
security: []
tags:
  - name: Products
  - name: Payments
  - name: Subscriptions
  - name: Addons
  - name: Customers
  - name: Refunds
  - name: Disputes
  - name: Events
  - name: License Keys
  - name: Entitlements
  - name: Licenses
  - name: Discounts
  - name: Meters
  - name: Credit Entitlements
  - name: Credit Entitlement Balances
  - name: Outgoing Webhooks
  - name: Checkout
  - name: Webhook Events
paths:
  /subscriptions/{subscription_id}/update-payment-method:
    post:
      tags:
        - Subscriptions
      operationId: update
      parameters:
        - name: subscription_id
          in: path
          description: Subscription Id
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdatePaymentMethodReq'
        required: true
      responses:
        '200':
          description: Payment method updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdatePaymentMethodResponse'
        '422':
          description: Invalid Request Object or Parameters
        '500':
          description: Something went wrong :(
      security:
        - API_KEY: []
      x-codeSamples:
        - lang: JavaScript
          source: >-
            import DodoPayments from 'dodopayments';


            const client = new DodoPayments({
              bearerToken: process.env['DODO_PAYMENTS_API_KEY'], // This is the default and can be omitted
            });


            const response = await
            client.subscriptions.updatePaymentMethod('subscription_id', {
              payment_method: { type: 'new' },
            });


            console.log(response.payment_id);
        - lang: Python
          source: |-
            import os
            from dodopayments import DodoPayments

            client = DodoPayments(
                bearer_token=os.environ.get("DODO_PAYMENTS_API_KEY"),  # This is the default and can be omitted
            )
            response = client.subscriptions.update_payment_method(
                subscription_id="subscription_id",
                payment_method={
                    "type": "new"
                },
            )
            print(response.payment_id)
        - lang: Go
          source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/dodopayments/dodopayments-go\"\n\t\"github.com/dodopayments/dodopayments-go/option\"\n)\n\nfunc main() {\n\tclient := dodopayments.NewClient(\n\t\toption.WithBearerToken(\"My Bearer Token\"),\n\t)\n\tresponse, err := client.Subscriptions.UpdatePaymentMethod(\n\t\tcontext.TODO(),\n\t\t\"subscription_id\",\n\t\tdodopayments.SubscriptionUpdatePaymentMethodParams{\n\t\t\tPaymentMethod: dodopayments.SubscriptionUpdatePaymentMethodParamsPaymentMethodNew{\n\t\t\t\tType: dodopayments.F(dodopayments.SubscriptionUpdatePaymentMethodParamsPaymentMethodNewTypeNew),\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", response.PaymentID)\n}\n"
        - lang: Java
          source: >-
            package com.dodopayments.api.example;


            import com.dodopayments.api.client.DodoPaymentsClient;

            import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient;

            import
            com.dodopayments.api.models.subscriptions.SubscriptionUpdatePaymentMethodParams;

            import
            com.dodopayments.api.models.subscriptions.SubscriptionUpdatePaymentMethodResponse;


            public final class Main {
                private Main() {}

                public static void main(String[] args) {
                    DodoPaymentsClient client = DodoPaymentsOkHttpClient.fromEnv();

                    SubscriptionUpdatePaymentMethodParams params = SubscriptionUpdatePaymentMethodParams.builder()
                        .subscriptionId("subscription_id")
                        .paymentMethod(SubscriptionUpdatePaymentMethodParams.PaymentMethod.New.builder().build())
                        .build();
                    SubscriptionUpdatePaymentMethodResponse response = client.subscriptions().updatePaymentMethod(params);
                }
            }
        - lang: Kotlin
          source: >-
            package com.dodopayments.api.example


            import com.dodopayments.api.client.DodoPaymentsClient

            import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient

            import
            com.dodopayments.api.models.subscriptions.SubscriptionUpdatePaymentMethodParams

            import
            com.dodopayments.api.models.subscriptions.SubscriptionUpdatePaymentMethodResponse


            fun main() {
                val client: DodoPaymentsClient = DodoPaymentsOkHttpClient.fromEnv()

                val params: SubscriptionUpdatePaymentMethodParams = SubscriptionUpdatePaymentMethodParams.builder()
                    .subscriptionId("subscription_id")
                    .paymentMethod(SubscriptionUpdatePaymentMethodParams.PaymentMethod.New.builder().build())
                    .build()
                val response: SubscriptionUpdatePaymentMethodResponse = client.subscriptions().updatePaymentMethod(params)
            }
        - lang: Ruby
          source: >-
            require "dodopayments"


            dodo_payments = Dodopayments::Client.new(
              bearer_token: "My Bearer Token",
              environment: "test_mode" # defaults to "live_mode"
            )


            response =
            dodo_payments.subscriptions.update_payment_method("subscription_id",
            payment_method: {type: :new})


            puts(response)
        - lang: PHP
          source: |-
            <?php

            require_once dirname(__DIR__) . '/vendor/autoload.php';

            use Dodopayments\Client;
            use Dodopayments\Core\Exceptions\APIException;
            use Dodopayments\Payments\PaymentMethodTypes;

            $client = new Client(
              bearerToken: getenv('DODO_PAYMENTS_API_KEY') ?: 'My Bearer Token',
              environment: 'test_mode',
            );

            try {
              $response = $client->subscriptions->updatePaymentMethod(
                'subscription_id',
                paymentMethod: [
                  'type' => 'new',
                  'allowedPaymentMethodTypes' => [PaymentMethodTypes::ACH],
                  'returnURL' => 'return_url',
                ],
              );

              var_dump($response);
            } catch (APIException $e) {
              echo $e->getMessage();
            }
        - lang: C#
          source: >-
            using System;

            using DodoPayments.Client;

            using DodoPayments.Client.Models.Payments;

            using DodoPayments.Client.Models.Subscriptions;


            DodoPaymentsClient client = new();


            SubscriptionUpdatePaymentMethodParams parameters = new()

            {
                SubscriptionID = "subscription_id",
                PaymentMethod = new New()
                {
                    AllowedPaymentMethodTypes =
                    [
                        PaymentMethodTypes.Ach
                    ],
                    ReturnUrl = "return_url",
                },
            };


            var response = await
            client.Subscriptions.UpdatePaymentMethod(parameters);


            Console.WriteLine(response);
components:
  schemas:
    UpdatePaymentMethodReq:
      oneOf:
        - type: object
          title: New
          required:
            - type
          properties:
            allowed_payment_method_types:
              type:
                - array
                - 'null'
              items:
                $ref: '#/components/schemas/PaymentMethodTypes'
              description: >-
                List of payment methods allowed during checkout.


                Customers will **never** see payment methods that are **not** in
                this list.

                However, adding a method here **does not guarantee** customers
                will see it.

                Availability still depends on other factors (e.g., customer
                location, merchant settings).
              uniqueItems: true
            return_url:
              type:
                - string
                - 'null'
            type:
              type: string
              enum:
                - new
              x-stainless-const: true
        - type: object
          title: Existing
          required:
            - payment_method_id
            - type
          properties:
            payment_method_id:
              type: string
            type:
              type: string
              enum:
                - existing
              x-stainless-const: true
      discriminator:
        propertyName: type
    UpdatePaymentMethodResponse:
      type: object
      properties:
        client_secret:
          type:
            - string
            - 'null'
        expires_on:
          type:
            - string
            - 'null'
          format: date-time
        payment_id:
          type:
            - string
            - 'null'
        payment_link:
          type:
            - string
            - 'null'
    PaymentMethodTypes:
      type: string
      description: |-
        All supported payment method types (from Hyperswitch).

        Used for disabled-payment-methods filtering and validation.
      enum:
        - ach
        - affirm
        - afterpay_clearpay
        - alfamart
        - ali_pay
        - ali_pay_hk
        - alma
        - amazon_pay
        - apple_pay
        - atome
        - bacs
        - bancontact_card
        - becs
        - benefit
        - bizum
        - blik
        - boleto
        - bca_bank_transfer
        - bni_va
        - bri_va
        - card_redirect
        - cimb_va
        - classic
        - credit
        - crypto_currency
        - cashapp
        - dana
        - danamon_va
        - debit
        - duit_now
        - efecty
        - eft
        - eps
        - fps
        - evoucher
        - giropay
        - givex
        - google_pay
        - go_pay
        - gcash
        - ideal
        - interac
        - indomaret
        - klarna
        - kakao_pay
        - local_bank_redirect
        - mandiri_va
        - knet
        - mb_way
        - mobile_pay
        - momo
        - momo_atm
        - multibanco
        - online_banking_thailand
        - online_banking_czech_republic
        - online_banking_finland
        - online_banking_fpx
        - online_banking_poland
        - online_banking_slovakia
        - oxxo
        - pago_efectivo
        - permata_bank_transfer
        - open_banking_uk
        - pay_bright
        - paypal
        - paze
        - pix
        - pay_safe_card
        - przelewy24
        - prompt_pay
        - pse
        - red_compra
        - red_pagos
        - samsung_pay
        - sepa
        - sepa_bank_transfer
        - sofort
        - sunbit
        - swish
        - touch_n_go
        - trustly
        - twint
        - upi_collect
        - upi_intent
        - vipps
        - viet_qr
        - venmo
        - walley
        - we_chat_pay
        - seven_eleven
        - lawson
        - mini_stop
        - family_mart
        - seicomart
        - pay_easy
        - local_bank_transfer
        - mifinity
        - open_banking_pis
        - direct_carrier_billing
        - instant_bank_transfer
        - billie
        - zip
        - revolut_pay
        - naver_pay
        - payco
  securitySchemes:
    API_KEY:
      type: http
      scheme: bearer

````