> Documentation index: [Saleor](/llms.txt) · [This section](/developer/llms.txt)
> Source: https://docs.saleor.io/developer/extending/webhooks/synchronous-events/stored-payment-method

# Stored payment method events

A stored payment method is a payment method that can be used later by customers without providing all payment details. Saleor has synchronous webhooks that allow delegating the stored payment methods management to payment apps.

<a id="key-concepts"></a>

## Key concepts

The `HANDLE_PAYMENTS` permission is required for the App to receive store payment method webhooks.

The usage of the webhook is strictly related to the usage of stored payment method. You can find more details about it in the [_Stored Payment Methods_](/developer/payments/stored-payments.md).

info

This feature is dedicated to [third-party](/api-reference/apps/enums/app-type-enum.md#thirdparty) apps.

<a id="list-stored-payment-methods"></a>

## List stored payment methods

`LIST_STORED_PAYMENT_METHODS`

A synchronous webhook is called when the user wants to fetch stored payment methods. Triggered when a customer requested a field [User.storedPaymentMethods](/api-reference/users/objects/user.md#stored-payment-methods), [checkout.storedPaymentMethods](/api-reference/checkout/objects/checkout.md#stored-payment-methods).

The webhook expects to return a list of payment methods that are assigned to the customer. The payment methods from the webhook response will be returned as a response for [User.storedPaymentMethods](/api-reference/users/objects/user.md#stored-payment-methods), [checkout.storedPaymentMethods](/api-reference/checkout/objects/checkout.md#stored-payment-methods) fields.

info

To reduce the number of HTTP requests triggered to the payment app, the response is cached on Saleor side. Saleor will trigger a new request when the cache expires or becomes invalid.

<a id="request"></a>

### Request

Saleor will send a [LIST\_STORED\_PAYMENT\_METHODS](/api-reference/webhooks/enums/webhook-event-type-sync-enum.md#list-stored-payment-methods) webhook by using the [ListStoredPaymentMethods](/api-reference/payments/objects/list-stored-payment-methods.md) subscription type or with a pre-defined payload in case of a missing subscription query.

You can find more details about building webhook subscription queries in [Subscription Webhook Payloads](/developer/extending/webhooks/subscription-webhook-payloads.md).

The example below shows a sample webhook subscription defined to list stored payment methods:

```graphql
subscription {
  event {
    ... on ListStoredPaymentMethods {
      user {
        id
      }
      channel {
        id
      }
    }
  }
}
```

The example below shows the pre-defined payload that will be used in the case when a subscription query is not provided:

```json
{
  "user_id": "VXNlcjoyOA==",
  "channel_slug": "main"
}
```

<a id="response"></a>

### Response

The app needs to return a list of stored payment methods that can be used by customer.

The response in this case should have the following structure:

```json
{
  "paymentMethods": [
    {
      "id": "<ID of stored payment method>",
      "supportedPaymentFlows": "<list of supported flows that can be performed with this payment method>",
      "type": "<type of the payment method. For example: Credit Card>",
      // "creditCardInfo": [Optional] credit card information if the payment method is a credit card.
      "creditCardInfo": {
        "brand": "<credit card brand>",
        "lastDigits": "<last digits>",
        "expMonth": "<expiration month>",
        "expYear": "<expiration year>",
        "firstDigits": "<[Optional] first digits>"
      },
      "name": "<[Optional] name of the payment method. For example: last 4 digits of credit card, obfuscated email>",
      "data": "<[Optional] JSON data that will be returned to client>"
    }
  ]
}
```

Below are the possible `supportedPaymentFlows` values and their explanations:

-   `INTERACTIVE` - When the user needs to be present to prove the ownership of the payment method (instead of, for example, a subscription-based payment which does not require user interaction).

warning

There is no default payment flow. If the `supportedPaymentFlows` list is empty, the payment method will not be returned.

<a id="delete-stored-payment-method-requested"></a>

## Delete stored payment method requested

`STORED_PAYMENT_METHOD_DELETE_REQUESTED`

A synchronous webhook [STORED\_PAYMENT\_METHOD\_DELETE\_REQUESTED](/api-reference/webhooks/enums/webhook-event-type-sync-enum.md#stored-payment-method-delete-requested) is called when the user requests the deletion of the stored payment method. User can request the deletion of the stored payment method by triggering the mutation [storedPaymentMethodRequestDelete](/api-reference/payments/mutations/stored-payment-method-request-delete.md). More details about the flow can be found in the [transactions overview](/developer/payments/overview.md).

<a id="request-1"></a>

### Request

The example below shows a sample webhook subscription defined for [STORED\_PAYMENT\_METHOD\_DELETE\_REQUESTED](/api-reference/webhooks/enums/webhook-event-type-sync-enum.md#stored-payment-method-delete-requested) webhook:

```graphql
subscription {
  event {
    ... on StoredPaymentMethodDeleteRequested {
      user {
        id
      }
      paymentMethodId
      channel {
        currencyCode
      }
    }
  }
}
```

The example below shows the pre-defined payload that will be used in the case when a subscription query is not provided:

```json
{
  "payment_method_id": "payment-method-id",
  "user_id": "VXNlcjoyOA==",
  "channel_slug": "main"
}
```

<a id="response-1"></a>

### Response

The app needs to return the status of the requested deletion.

The response in this case should have the following structure:

-   Response that reports successful delete action

```json
{
  "result": "SUCCESSFULLY_DELETED"
}
```

-   Response that reports failure to delete action

```json
{
  "result": "FAILED_TO_DELETE",
  "error": "Error message that will be passed to the frontend."
}
```

The `result` field is an enum value of [StoredPaymentMethodRequestDeleteResult](/api-reference/payments/enums/stored-payment-method-request-delete-result.md). In case of returning failure `result`, the `error` message will be attached to the [error](/api-reference/payments/objects/payment-method-request-delete-error.md) returned by [storedPaymentMethodRequestDelete](/api-reference/payments/mutations/stored-payment-method-request-delete.md) mutation.

<a id="initialize-payment-gateway-session"></a>

## Initialize payment gateway session

`PAYMENT_GATEWAY_INITIALIZE_TOKENIZATION_SESSION`

The synchronous [PAYMENT\_GATEWAY\_INITIALIZE\_TOKENIZATION\_SESSION](/api-reference/webhooks/enums/webhook-event-type-sync-enum.md#payment-gateway-initialize-tokenization-session) webhook is triggered when a customer requests the initialization of the payment gateway to tokenize a payment method. This webhook is activated by executing the [paymentGatewayInitializeTokenization](/api-reference/payments/mutations/payment-gateway-initialize-tokenization.md) mutation.

The webhook payload includes details about the [customer](/api-reference/payments/objects/payment-gateway-initialize-tokenization-session.md#user), [channel](/api-reference/payments/objects/payment-gateway-initialize-tokenization-session.md#channel), and [data](/api-reference/payments/objects/payment-gateway-initialize-tokenization-session.md#data). The [data](/api-reference/payments/mutations/payment-gateway-initialize-tokenization.md#data) field contains the JSON data provided as input in the [paymentGatewayInitializeTokenization](/api-reference/payments/mutations/payment-gateway-initialize-tokenization.md) mutation.

The response must adhere to the expected format and will be returned within the [paymentGatewayInitializeTokenization](/api-reference/payments/mutations/payment-gateway-initialize-tokenization.md) mutation.

<a id="request-2"></a>

### Request

Saleor will send a [PAYMENT\_GATEWAY\_INITIALIZE\_TOKENIZATION\_SESSION](/api-reference/webhooks/enums/webhook-event-type-sync-enum.md#payment-gateway-initialize-tokenization-session) webhook using the [PaymentGatewayInitializeTokenizationSession](/api-reference/payments/objects/payment-gateway-initialize-tokenization-session.md) subscription type or with a predefined payload in case of a missing subscription query.

For more details on building webhook subscription queries, refer to [Subscription Webhook Payloads](/developer/extending/webhooks/subscription-webhook-payloads.md).

The example below demonstrates a sample webhook subscription defined to handle the initialization of the payment gateway for tokenizing a payment method:

```graphql
subscription {
  event {
    ... on PaymentGatewayInitializeTokenizationSession {
      user {
        id
      }
      channel {
        id
      }
      data
    }
  }
}
```

The following example illustrates the predefined payload that will be used if a subscription query is not provided:

```json
{
  "user_id": "VXNlcjoyOA==",
  "channel_slug": "main",
  "data": { "data": "from-input" }
}
```

<a id="response-2"></a>

### Response

The application should return the status of the initialization and optionally `data` required to finalize the initialization on the client side.

-   Response indicating successful initialization:

```json
{
  "result": "SUCCESSFULLY_INITIALIZED",
  "data": { "data": "additional-data" }
}
```

-   Response indicating failed initialization:

```json
{
  "result": "FAILED_TO_INITIALIZE",
  "error": "Error message that will be passed to the frontend."
}
```

The `result` field is an enum value of [PaymentGatewayInitializeTokenizationResultEnum](/api-reference/payments/enums/payment-gateway-initialize-tokenization-result.md). In the event of returning a failure `result`, the `errors` message will be attached to the [error](/api-reference/payments/objects/payment-gateway-initialize-tokenization.md) returned by the [paymentGatewayInitializeTokenization](/api-reference/payments/mutations/payment-gateway-initialize-tokenization.md) mutation.

<a id="initialize-payment-method-tokenization"></a>

## Initialize payment method tokenization

`PAYMENT_METHOD_INITIALIZE_TOKENIZATION_SESSION`

The synchronous [PAYMENT\_METHOD\_INITIALIZE\_TOKENIZATION\_SESSION](/api-reference/webhooks/enums/webhook-event-type-sync-enum.md#payment-method-initialize-tokenization-session) webhook is triggered when a customer requests the tokenization of a payment method. This webhook is activated by executing the [paymentMethodInitializeTokenization](/api-reference/payments/mutations/payment-method-initialize-tokenization.md) mutation.

The webhook payload includes details about the [customer](/api-reference/payments/objects/payment-method-initialize-tokenization-session.md#user), [channel](/api-reference/payments/objects/payment-method-initialize-tokenization-session.md#channel), and [data](/api-reference/payments/objects/payment-method-initialize-tokenization-session.md#data). The [data](/api-reference/payments/objects/payment-method-initialize-tokenization-session.md#data) field contains the JSON data provided as input in the [paymentMethodInitializeTokenization](/api-reference/payments/mutations/payment-method-initialize-tokenization.md) mutation.

The response must conform to the expected format and will be returned within the [paymentMethodInitializeTokenization](/api-reference/payments/mutations/payment-method-initialize-tokenization.md) mutation.

<a id="request-3"></a>

### Request

Saleor will send a [PAYMENT\_METHOD\_INITIALIZE\_TOKENIZATION\_SESSION](/api-reference/webhooks/enums/webhook-event-type-sync-enum.md#payment-method-initialize-tokenization-session) webhook using the `PaymentMethodInitializeTokenizationSession` subscription type or with a predefined payload in case of a missing subscription query.

For detailed information on building webhook subscription queries, please refer to [Subscription Webhook Payloads](/developer/extending/webhooks/subscription-webhook-payloads.md).

The following example demonstrates a sample webhook subscription defined to handle the tokenization of a payment method:

```graphql
subscription {
  event {
    ... on PaymentMethodInitializeTokenizationSession {
      paymentFlowToSupport
      user {
        id
      }
      channel {
        id
      }
      data
    }
  }
}
```

The next example illustrates the predefined payload that will be used if a subscription query is not provided:

```json
{
  "user_id": "VXNlcjoyOA==",
  "channel_slug": "main",
  "data": { "data": "from-input" },
  "payment_flow_to_support": "interactive"
}
```

<a id="response-3"></a>

### Response

-   A response indicating successful tokenization should include the `result`, the `id` of the stored payment method, and optionally `data` to be passed to the client:

```json
{
  "result": "SUCCESSFULLY_TOKENIZED",
  "id": "payment-method-id",
  "data": { "data": "additional-data" }
}
```

-   A response indicating a required additional action should contain the expected `result`, the `id`, and optionally `data`:

```json
{
  "result": "ADDITIONAL_ACTION_REQUIRED",
  "id": "id",
  "data": { "data": "additional-data" }
}
```

-   A response indicating a pending tokenization:

```json
{
  "result": "PENDING",
  "data": { "data": "additional-data" }
}
```

-   A response indicating a failed tokenization:

```json
{
  "result": "FAILED_TO_TOKENIZE",
  "error": "Error message that will be passed to the frontend."
}
```

The `result` field is an enum value of [PaymentMethodTokenizationResultEnum](/api-reference/payments/enums/payment-method-tokenization-result.md). In case of a failure `result`, the `error` message will be attached to the [errors](/api-reference/payments/objects/payment-method-initialize-tokenization.md#errors) returned by the [paymentMethodInitializeTokenization](/api-reference/payments/mutations/payment-method-initialize-tokenization.md) mutation.

<a id="process-additional-actions-for-payment-method-tokenization"></a>

## Process additional actions for payment method tokenization

`PAYMENT_METHOD_PROCESS_TOKENIZATION_SESSION`

The synchronous [PAYMENT\_METHOD\_PROCESS\_TOKENIZATION\_SESSION](/api-reference/webhooks/enums/webhook-event-type-sync-enum.md#payment-method-process-tokenization-session) webhook is triggered when a customer requests to process additional actions required for tokenizing the payment method. This webhook is activated by executing the `paymentMethodProcessTokenization` mutation.

The webhook payload includes details about the [customer](/api-reference/users/objects/user.md), [channel](/api-reference/channels/objects/channel.md), and data. The `data` field contains the JSON data provided as input in the [paymentMethodProcessTokenization](/api-reference/payments/mutations/payment-method-process-tokenization.md) mutation.

The response must adhere to the expected format and will be returned within the [paymentMethodProcessTokenization](/api-reference/payments/mutations/payment-method-process-tokenization.md) mutation.

<a id="request-4"></a>

### Request

Saleor will send a [PAYMENT\_METHOD\_PROCESS\_TOKENIZATION\_SESSION](/api-reference/webhooks/enums/webhook-event-type-sync-enum.md#payment-method-process-tokenization-session) webhook using the [PaymentMethodProcessTokenizationSession](/api-reference/payments/objects/payment-method-process-tokenization-session.md) subscription type or with a predefined payload in case of a missing subscription query.

For detailed information on building webhook subscription queries, please refer to [Subscription Webhook Payloads](/developer/extending/webhooks/subscription-webhook-payloads.md).

The following example demonstrates a sample webhook subscription defined to handle the tokenization of a payment method:

```graphql
subscription {
  event {
    ... on PaymentMethodProcessTokenizationSession {
      id
      user {
        id
      }
      channel {
        id
      }
      data
    }
  }
}
```

The next example illustrates the predefined payload that will be used if a subscription query is not provided:

```json
{
  "user_id": "VXNlcjoyOA==",
  "channel_slug": "main",
  "data": { "data": "from-input" }
}
```

<a id="response-4"></a>

### Response

-   A response indicating successful tokenization should include the `result`, the `id` of the stored payment method, and optionally `data` to be passed to the client:

```json
{
  "result": "SUCCESSFULLY_TOKENIZED",
  "id": "payment-method-id",
  "data": { "data": "additional-data" }
}
```

-   A response indicating a required additional action should contain the expected `result`, an `id`, and optional `data`:

```json
{
  "result": "ADDITIONAL_ACTION_REQUIRED",
  "id": "payment-method-id",
  "data": { "data": "additional-data" }
}
```

-   A response indicating a pending tokenization:

```json
{
  "result": "PENDING",
  "data": { "data": "additional-data" }
}
```

-   A response indicating a failed tokenization:

```json
{
  "result": "FAILED_TO_TOKENIZE",
  "error": "Error message that will be passed to the frontend."
}
```

The `result` field is an enum value of [PaymentMethodTokenizationResultEnum](/api-reference/payments/enums/payment-method-tokenization-result.md). In case of a failure `result`, the `error` message will be attached to the [errors](/api-reference/payments/objects/payment-method-process-tokenization.md#errors) returned by the [paymentMethodProcessTokenization](/api-reference/payments/objects/payment-method-process-tokenization.md) mutation.
