---
title: "Payment Failed"
method: POST
path: "payment.failed"
tags: ["Payments"]
---

# Payment Failed

`POST payment.failed` (webhook)

Sent when a payment is failed

Required permissions:
 - `payment:basic:read`
 - `plan:basic:read`
 - `access_pass:basic:read`
 - `member:email:read`
 - `member:basic:read`
 - `member:phone:read`
 - `promo_code:basic:read`
 - `shipment:basic:read`
 - `payment:dispute:read`
 - `payment:resolution_center_case:read`
 - `webhook_receive:payments`

## Headers

- `webhook-id` string, required — A unique identifier for this webhook request
- `webhook-signature` string, required — The signature of the webhook request with the webhook version prepended
- `webhook-timestamp` string, required — The timestamp in seconds since the Unix epoch that the webhook was sent at on the server

## Payload

- object
  - `account_id` string, nullable — The account ID that this webhook event is associated with
  - `api_version` 'v1', required — The API version for this webhook
  - `api_version_date` string, nullable, required — The dated API version (Api-Version-Date) the payload is serialized to
  - `data` Payment, required
    - `account_id` string, nullable, required — The account that received the payment, prefixed `biz_`.
    - `amount_after_fees` Money, required
      - `amount` string, required — The amount in major units, as an exact decimal string — `"10.00"` is ten dollars. A string so no float rounds it in transit.
      - `currency` string, required — Three-letter ISO 4217 currency code, lowercase.
      - `decimals` integer, required — How many decimal places the amount CARRIES — the precision the charge itself runs at.
      - `display_decimals` integer, required — How many decimal places to SHOW. Usually equal to `decimals`, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is `2` and `0`. Format the number in your own locale using this.
    - `auto_refunded` boolean, required — True when Whop refunded the payment automatically, for example on a dispute alert.
    - `billing_address` PaymentAddress, required
      - `city` string, nullable, required — The city.
      - `country` string, nullable, required — The ISO 3166-1 alpha-2 country code.
      - `line1` string, nullable, required — The first street address line.
      - `line2` string, nullable, required — The second street address line.
      - `name` string, nullable, required — The name on the address.
      - `postal_code` string, nullable, required — The postal or ZIP code.
      - `state` string, nullable, required — The state, province or region.
    - `billing_reason` 'subscription_create' | 'subscription_cycle' | 'subscription_update' | 'one_time' | 'manual' | 'subscription', required — The reason why a specific payment was billed
    - `checkout_configuration_id` string, nullable, required — The checkout configuration the buyer paid through, prefixed `ch_`, or null.
    - `client_secret` string, nullable, required — The credential a buyer's surface presents to poll this payment and set its return URL. Only on payments created from a confirmation token, and always null in list responses — retrieve the payment for it.
    - `created_at` string, required — When the payment was created, as an ISO 8601 timestamp.
    - `currency` 'usd' | 'sgd' | 'inr' | 'aud' | 'brl' | 'cad' | 'dkk' | 'eur' | 'nok' | 'gbp' | 'sek' | 'chf' | 'hkd' | 'huf' | 'jpy' | 'mxn' | 'myr' | 'pln' | 'czk' | 'nzd' | 'aed' | 'eth' | 'ape' | 'cop' | 'ron' | 'thb' | 'bgn' | 'idr' | 'dop' | 'php' | 'try' | 'krw' | 'twd' | 'vnd' | 'pkr' | 'clp' | 'uyu' | 'ars' | 'zar' | 'dzd' | 'tnd' | 'mad' | 'kes' | 'kwd' | 'jod' | 'all' | 'xcd' | 'amd' | 'bsd' | 'bhd' | 'bob' | 'bam' | 'khr' | 'crc' | 'xof' | 'egp' | 'etb' | 'gmd' | 'ghs' | 'gtq' | 'gyd' | 'ils' | 'jmd' | 'mop' | 'mga' | 'mur' | 'mdl' | 'mnt' | 'nad' | 'ngn' | 'mkd' | 'omr' | 'pyg' | 'pen' | 'qar' | 'rwf' | 'sar' | 'rsd' | 'lkr' | 'tzs' | 'ttd' | 'uzs' | 'rub' | 'btc' | 'cny' | 'usdt' | 'kzt' | 'awg' | 'whop_usd' | 'xau', required — The available currencies on the platform
    - `customer_phone` string, nullable, required — The phone number the buyer gave at checkout, when one was collected.
    - `decline_code` 'insufficient_funds' | 'lost_card' | 'stolen_card' | 'expired_card' | 'suspected_fraud' | 'invalid_card_number' | 'invalid_cvc' | 'invalid_cvc_or_expiration' | 'incorrect_pin' | 'authentication_required' | 'card_not_supported' | 'currency_not_supported' | 'duplicate_transaction' | 'generic_decline' | 'invalid_account' | 'invalid_amount' | 'processing_error' | 'restricted_card' | 'card_velocity_exceeded' | 'contact_issuer' | 'bank_declined' | 'regulatory_blocked' | 'transaction_not_permitted' | 'transaction_stopped' | 'card_type_not_supported' | 'issuer_not_found' | 'closed_account' | 'issuer_unavailable' | 'invalid_zip' | 'invalid_expiry_month' | 'invalid_expiry_year' | 'invalid_expiry' | 'invalid_transaction' | 'cannot_authorize' | 'pin_required' | 'pin_try_exceeded' | 'provider_declined' | 'high_risk' | 'test_mode_decline' | 'merchant_blacklist' | 'reenter_transaction' | 'invalid_pin' | 'pin_required_as' | 'withdrawal_count_limit_exceeded' | 'invalid_country' | 'issuer_error' | 'invalid_card_holder_name' | 'no_accounts' | 'transaction_cancelled' | 'three_d_secure_success' | 'three_d_secure_canceled' | 'three_d_secure_invalid_card_number' | 'three_d_secure_generic_error' | 'three_d_secure_timeout' | 'three_d_secure_failed' | 'three_d_secure_card_not_enrolled' | 'three_d_secure_fraud' | 'three_d_secure_too_many_attempts' | 'three_d_secure_rejected_by_bank' | 'three_d_secure_reported_lost_or_stolen' | 'blocked_by_cardholder' | 'test_mode_test_card' | 'try_again_later' | 'transaction_not_allowed' | 'bank_insufficient_funds' | 'bank_account_not_found' | 'bank_account_closed' | 'bank_account_frozen' | 'bank_invalid_routing_number' | 'bank_non_transaction_account' | 'bank_authorization_revoked' | 'bank_payment_stopped' | 'bank_not_authorized' | 'bank_account_holder_deceased' | 'bank_duplicate' | 'bank_amount_error' | 'bank_regulatory_blocked' | 'bank_details_invalid' | 'bank_processing_error' | 'bank_generic_decline' | 'sepa_invalid_iban' | 'sepa_no_mandate' | 'sepa_mandate_data_invalid' | 'sepa_disputed' | 'sepa_refused_by_customer' | 'sepa_generic_decline', required — The reason a payment was declined.
    - `dispute_alerted_at` string, nullable, required — When an issuer warned that this payment will be disputed, or null.
    - `failure_message` string, nullable, required — Why the most recent attempt failed, in plain words, or null.
    - `financing_installments_count` number, nullable, required — For installment methods, how many payments the charge splits into.
    - `id` string, required — Payment ID, prefixed `pay_`.
    - `last_payment_attempt_at` string, nullable, required — When the most recent charge attempt ran, or null.
    - `member_id` string, nullable, required — The buyer's member record on the account, prefixed `mber_`. Null without the member:basic:read permission.
    - `membership_id` string, nullable, required — The membership this payment is billed against, prefixed `mem_`. Null for one-off purchases or without the member:basic:read permission.
    - `metadata` object, nullable, required — Your own key-value data attached when the payment was created.
    - `needs_tracking` boolean, nullable, required — True when funds are held until the order ships and no tracking number has been added yet. Null without the shipment:basic:read permission.
    - `next_payment_attempt_at` string, nullable, required — When the next automatic retry is scheduled, or null.
    - `paid_at` string, nullable, required — When the money was collected, or null while it has not been.
    - `payment_instrument` PaymentInstrument, required
      - `card` PaymentInstrumentCard, required
        - `brand` string, required — The network identifier (`visa`, `amex`, …), matching `card.networks` entries and saved card payment methods.
        - `last4` string, nullable, required — The card's last four digits, when captured.
      - `display_name` string, required — Buyer-facing instrument name — "Visa •••• 4242" when the card surfaced, else the method's own name ("Klarna").
      - `icons` PaymentMethodIcons, required
        - `card` PaymentMethodIconVariants, required
          - `dark` PaymentMethodIconFiles, required
            - `png_1x` string, required — Raster fallback at the shape's native size.
            - `png_2x` string, required — Raster fallback at double density.
            - `png_4x` string, required — Raster fallback at quadruple density.
            - `svg` string, required — The vector file. Prefer this everywhere SVG renders.
          - `light` PaymentMethodIconFiles, required
            - `png_1x` string, required — Raster fallback at the shape's native size.
            - `png_2x` string, required — Raster fallback at double density.
            - `png_4x` string, required — Raster fallback at quadruple density.
            - `svg` string, required — The vector file. Prefer this everywhere SVG renders.
        - `square` PaymentMethodIconVariants, required
          - `dark` PaymentMethodIconFiles, required
            - `png_1x` string, required — Raster fallback at the shape's native size.
            - `png_2x` string, required — Raster fallback at double density.
            - `png_4x` string, required — Raster fallback at quadruple density.
            - `svg` string, required — The vector file. Prefer this everywhere SVG renders.
          - `light` PaymentMethodIconFiles, required
            - `png_1x` string, required — Raster fallback at the shape's native size.
            - `png_2x` string, required — Raster fallback at double density.
            - `png_4x` string, required — Raster fallback at quadruple density.
            - `svg` string, required — The vector file. Prefer this everywhere SVG renders.
      - `installment_count` number, nullable, required — Installment methods only: how many payments the charge splits into. Data, not copy — compose and translate the label client-side.
      - `payment_method_type` string, required — The payment method type identifier, e.g. `card`, `klarna`, `apple_pay`.
    - `payment_method_id` string, nullable, required — The stored payment method that was charged, prefixed `payt_`. Null when the method was not saved.
    - `payment_method_type` 'acss_debit' | 'addi' | 'affirm' | 'afterpay_clearpay' | 'alipay' | 'alma' | 'amazon_pay' | 'apple' | 'apple_pay' | 'au_bank_transfer' | 'au_becs_debit' | 'bacs_debit' | 'bancolombia' | 'bancontact' | 'bank_wire' | 'billie' | 'bizum' | 'blik' | 'boleto' | 'bre_b' | 'ca_bank_transfer' | 'capchase_pay' | 'card' | 'card_installments_three' | 'card_installments_six' | 'card_installments_twelve' | 'cashapp' | 'claritypay' | 'coinbase' | 'crypto' | 'custom' | 'customer_balance' | 'demo_pay' | 'efecty' | 'eps' | 'eu_bank_transfer' | 'fpx' | 'flex_pay' | 'gb_bank_transfer' | 'gcash' | 'giropay' | 'google_pay' | 'gopay' | 'grabpay' | 'id_bank_transfer' | 'ideal' | 'interac' | 'kakao_pay' | 'klarna' | 'klarna_pay_now' | 'konbini' | 'kr_card' | 'kr_market' | 'kriya' | 'kueski' | 'link' | 'mb_way' | 'm_pesa' | 'mercado_pago' | 'mobilepay' | 'modo' | 'mondu' | 'multibanco' | 'naver_pay' | 'nequi' | 'netbanking' | 'ng_bank' | 'ng_bank_transfer' | 'ng_card' | 'ng_market' | 'ng_ussd' | 'ng_wallet' | 'nz_bank_account' | 'oney' | 'oney_3x' | 'oney_4x' | 'oxxo' | 'p24' | 'pago_efectivo' | 'pse' | 'pay_by_bank' | 'payco' | 'paynow' | 'paypal' | 'paypay' | 'payto' | 'pix' | 'platform_balance' | 'promptpay' | 'qris' | 'rapipago' | 'rechnung' | 'revolut_pay' | 'samsung_pay' | 'satispay' | 'scalapay' | 'sencillito' | 'sepa_debit' | 'sequra' | 'servipag' | 'sezzle' | 'shop_pay' | 'shopeepay' | 'sofort' | 'south_korea_market' | 'spei' | 'splitit' | 'sunbit' | 'swish' | 'tamara' | 'twint' | 'upi' | 'us_bank_account' | 'us_bank_transfer' | 'venmo' | 'vipps' | 'webpay' | 'wechat_pay' | 'yape' | 'zip' | 'coinflow' | 'unknown', required — The different types of payment methods that can be used.
    - `payments_failed` number, required — How many charge attempts have failed on this payment.
    - `plan_id` string, nullable, required — The plan that was charged, prefixed `plan_`.
    - `product_id` string, nullable, required — The product the plan belongs to, prefixed `prod_`. Null for a plan with no product.
    - `promo_code_id` string, nullable, required — The promo code applied at checkout, prefixed `promo_`, or null.
    - `refundable` boolean, required — True when the payment is `paid`, not yet fully refunded, and its processor supports refunds.
    - `refunded_amount` Money, required
      - `amount` string, required — The amount in major units, as an exact decimal string — `"10.00"` is ten dollars. A string so no float rounds it in transit.
      - `currency` string, required — Three-letter ISO 4217 currency code, lowercase.
      - `decimals` integer, required — How many decimal places the amount CARRIES — the precision the charge itself runs at.
      - `display_decimals` integer, required — How many decimal places to SHOW. Usually equal to `decimals`, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is `2` and `0`. Format the number in your own locale using this.
    - `refunded_at` string, nullable, required — When the payment was refunded, or null.
    - `retryable` boolean, required — True when the payment is `open` and Whop can attempt the charge again — see `POST /payments/{id}/retry`.
    - `risk_score` number, nullable, required — Whop's fraud risk score from 0 (lowest) to 100 (highest), or null when the payment was not scored.
    - `risk_signals` object, nullable, required — The factors behind `risk_score`, grouped by category, or null.
    - `settlement_time_at` string, nullable, required — When the funds post to the account's available balance, at midnight UTC. The `ledger_account.funds_available` webhook carries the same value. Null until the payment is paid, and always null in list responses — retrieve the payment for it.
    - `shipment_id` string, nullable, required — The shipment fulfilling this payment, prefixed `ship_`. Null when nothing ships or without the shipment:basic:read permission.
    - `shipping_address` PaymentAddress, required
      - `city` string, nullable, required — The city.
      - `country` string, nullable, required — The ISO 3166-1 alpha-2 country code.
      - `line1` string, nullable, required — The first street address line.
      - `line2` string, nullable, required — The second street address line.
      - `name` string, nullable, required — The name on the address.
      - `postal_code` string, nullable, required — The postal or ZIP code.
      - `state` string, nullable, required — The state, province or region.
    - `status` 'draft' | 'open' | 'authorized' | 'paid' | 'pending' | 'uncollectible' | 'unresolved' | 'void', required — The status of a receipt
    - `substatus` 'succeeded' | 'requires_capture' | 'pending' | 'failed' | 'past_due' | 'canceled' | 'price_too_low' | 'uncollectible' | 'refunded' | 'auto_refunded' | 'partially_refunded' | 'dispute_warning' | 'dispute_needs_response' | 'dispute_warning_needs_response' | 'resolution_needs_response' | 'dispute_under_review' | 'dispute_warning_under_review' | 'resolution_under_review' | 'dispute_won' | 'dispute_warning_closed' | 'resolution_won' | 'dispute_lost' | 'dispute_closed' | 'resolution_lost' | 'drafted' | 'incomplete' | 'unresolved' | 'open_dispute' | 'open_resolution', required — The friendly status of a payment. This is a derived status that provides a human-readable summary of the payment state, combining the underlying status and substatus fields.
    - `subtotal` Money, required
      - `amount` string, required — The amount in major units, as an exact decimal string — `"10.00"` is ten dollars. A string so no float rounds it in transit.
      - `currency` string, required — Three-letter ISO 4217 currency code, lowercase.
      - `decimals` integer, required — How many decimal places the amount CARRIES — the precision the charge itself runs at.
      - `display_decimals` integer, required — How many decimal places to SHOW. Usually equal to `decimals`, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is `2` and `0`. Format the number in your own locale using this.
    - `tax_amount` Money, required
      - `amount` string, required — The amount in major units, as an exact decimal string — `"10.00"` is ten dollars. A string so no float rounds it in transit.
      - `currency` string, required — Three-letter ISO 4217 currency code, lowercase.
      - `decimals` integer, required — How many decimal places the amount CARRIES — the precision the charge itself runs at.
      - `display_decimals` integer, required — How many decimal places to SHOW. Usually equal to `decimals`, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is `2` and `0`. Format the number in your own locale using this.
    - `tax_behavior` 'exclusive' | 'inclusive' | 'unspecified' | 'unable_to_collect', required — The type of tax inclusivity applied to the receipt, for determining whether the tax is included in the final price, or paid on top.
    - `tax_refunded_amount` Money, required
      - `amount` string, required — The amount in major units, as an exact decimal string — `"10.00"` is ten dollars. A string so no float rounds it in transit.
      - `currency` string, required — Three-letter ISO 4217 currency code, lowercase.
      - `decimals` integer, required — How many decimal places the amount CARRIES — the precision the charge itself runs at.
      - `display_decimals` integer, required — How many decimal places to SHOW. Usually equal to `decimals`, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is `2` and `0`. Format the number in your own locale using this.
    - `three_ds_verified` boolean, required — True when the buyer completed 3D Secure for this payment.
    - `total` Money, required
      - `amount` string, required — The amount in major units, as an exact decimal string — `"10.00"` is ten dollars. A string so no float rounds it in transit.
      - `currency` string, required — Three-letter ISO 4217 currency code, lowercase.
      - `decimals` integer, required — How many decimal places the amount CARRIES — the precision the charge itself runs at.
      - `display_decimals` integer, required — How many decimal places to SHOW. Usually equal to `decimals`, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is `2` and `0`. Format the number in your own locale using this.
    - `updated_at` string, required — When the payment last changed, as an ISO 8601 timestamp.
    - `usd_total` Money, required
      - `amount` string, required — The amount in major units, as an exact decimal string — `"10.00"` is ten dollars. A string so no float rounds it in transit.
      - `currency` string, required — Three-letter ISO 4217 currency code, lowercase.
      - `decimals` integer, required — How many decimal places the amount CARRIES — the precision the charge itself runs at.
      - `display_decimals` integer, required — How many decimal places to SHOW. Usually equal to `decimals`, and deliberately not always: COP is charged in centavos but written in whole pesos, so it is `2` and `0`. Format the number in your own locale using this.
    - `user` UserSummary, required
      - `id` string, required — User ID, prefixed `user_`.
      - `name` string, nullable, required — Display name.
      - `profile_picture` UserProfilePicture, required
        - `url` string, required — Avatar image URL. Always present — a generated placeholder when the user set no picture.
      - `username` string, required — Public username.
    - `verification_checks` PaymentVerificationChecks, required
      - `address_line1` string, nullable, required — Whether the billing street address the customer entered matched the issuer's records.
      - `card_holder_name` string, nullable, required — Whether the cardholder name matched the issuer's records.
      - `card_security_code` string, nullable, required — Whether the CVV / CVC matched the card.
      - `zip_code` string, nullable, required — Whether the billing postal code matched the issuer's records.
    - `voidable` boolean, required — True when the payment is `open` on a past-due membership and its processor supports voiding — see `POST /payments/{id}/void`.
  - `id` string, required — A unique ID for every single webhook request
  - `previous_attributes` object — For some `.updated` events, the old values of the payload fields that changed, keyed by field name. Omitted when no capture is available for the event
  - `timestamp` string, date-time, required — The timestamp in ISO 8601 format that the webhook was sent at on the server
  - `type` 'payment.failed', required — The webhook event type

## Acknowledgement `200`

Return a 200 status to indicate that the data was received successfully

---

[API](https://skmtc.dev/whop/apis/whop-api.md) · [All operations](https://skmtc.dev/whop/apis/whop-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/whop/whop-api/revisions/8473fa1d1f47/schema)
