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

# Failed card payment

> A card payment your user started from the portal was declined.

Fires when a **card payment started by your end user** is declined.

<Warning>
  **This event's `type` is `CARD_PAYMENT_STATUS`, not `CARD_PAYMENT_FAILED`.** The name is generic on purpose, so it can be reused later for confirmations and other states. Today the only case that emits it is the declined payment, so `status` is always `"FAILED"`.
</Warning>

<Tip>
  Route on `type` and then branch on `status`. That way your handler keeps working the day this same `type` starts carrying other states.
</Tip>

|                     |                         |
| ------------------- | ----------------------- |
| **`type`**          | `CARD_PAYMENT_STATUS`   |
| **`status`**        | Today always `"FAILED"` |
| **Idempotency key** | `operationId`           |

## The payload

| Field                                | Type           | Present     | Description                                                                                   |
| ------------------------------------ | -------------- | ----------- | --------------------------------------------------------------------------------------------- |
| `type`                               | String         | Always      | Always `"CARD_PAYMENT_STATUS"`.                                                               |
| `operationId`                        | String         | Always      | Identifier of the payment operation.                                                          |
| `status`                             | String         | Always      | Today always `"FAILED"`.                                                                      |
| `amount`                             | Number \| null | Always      | Payment amount. The key is always there; the value is `null` if the event does not report it. |
| `companyCode`                        | String \| null | Always      | Company code. Same rule as `amount`.                                                          |
| `companyName`                        | String \| null | Always      | Company name. Same rule as `amount`.                                                          |
| `additionalData`                     | Object         | Conditional | Provider error detail. **Dropped entirely** when it would be empty.                           |
| `additionalData.errorDetail.code`    | String         | Conditional | Provider error code.                                                                          |
| `additionalData.errorDetail.message` | String         | Conditional | Provider error message.                                                                       |
| `hash`                               | String \| null | Always      | Verification hash. `null` if you have no public key configured.                               |

<Note>
  The error detail is **nested** under `additionalData.errorDetail`, one level deeper than in [failed card autopay](/en/webhooks/failed-card-autopay), where it sits directly in `additionalData`. It is the only shape difference between the two card events.
</Note>

<Warning>
  `additionalData` is **dropped entirely** when there is no detail to send: when `sendErrorInfo` is off in your configuration, and also when it is on but the event carries no provider detail.
</Warning>

```javascript theme={null}
// Correct: handles both optional levels
const code = notification.additionalData?.errorDetail?.code ?? null;
```

## Examples

<CodeGroup>
  ```json With error detail theme={null}
  {
    "type": "CARD_PAYMENT_STATUS",
    "operationId": "b7c8d9e0-1122-3344-5566-7788990011aa",
    "status": "FAILED",
    "amount": 12000,
    "companyCode": "MX-S-12345",
    "companyName": "ACME",
    "additionalData": {
      "errorDetail": {
        "code": "CARD_DECLINED",
        "message": "Card declined by the issuer"
      }
    },
    "hash": "encrypted-base64-string"
  }
  ```

  ```json No detail and no amount reported theme={null}
  {
    "type": "CARD_PAYMENT_STATUS",
    "operationId": "b7c8d9e0-1122-3344-5566-7788990011aa",
    "status": "FAILED",
    "amount": null,
    "companyCode": "MX-S-12345",
    "companyName": "ACME",
    "hash": null
  }
  ```
</CodeGroup>

<Card title="Common fields, hash and idempotency" icon="bookmark" href="/en/webhooks">
  What every webhook in this family shares.
</Card>
