> ## 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.

# Payment method registered

> Notice that a user registered their bank account and you can already charge it.

When a user registers their bank account on the [enrollment page](https://devs.tapipay.la/en/payment-portal/autopay-sdk.md), TapiPay notifies you with this webhook. It carries the account's `externalPaymentMethodId`, the same one [`GET /payment-methods`](https://devs.tapipay.la/en/resources/direct-debit#query-a-users-payment-methods) returns and [`POST /v2/debts/orders`](https://devs.tapipay.la/en/resources/payment-orders) accepts, so you do not need to query the API to start charging the user.

| `type` | When it arrives |
| - | - |
| `PAYMENT_METHOD_REGISTERED` | The user registered an account and it is active. |

> [!NOTE]
>
> This webhook has **the same contract as the [order payment](https://devs.tapipay.la/en/webhooks/order-payment.md)**: it does not carry `operationId` or `companyName`, and its idempotency key is `id`. What [Common fields](https://devs.tapipay.la/en/webhooks.md#common-fields) explains does not apply here, except for `hash`.

## When it arrives

It arrives every time the account registration succeeds:

* **New account**: the first time the user registers that account.
* **Repeated registration**: the user registers again an account that was already active.
* **Reactivation**: the user registers again an account that had been [deleted](https://devs.tapipay.la/en/resources/direct-debit.md#delete-a-payment-method).

In the last two cases the notice carries the **same `id`** and the same `registeredAt` as the new account one. It is the same account, so treat it as a resend.

For now the contract covers bank accounts (`BANK_ACCOUNT`). If you receive a notice with another payment method `type`, ignore it: the other types are not part of this contract yet.

It does not arrive if the registration fails, nor for accounts TapiPay loads outside the registration, for example in a migration.

## Configuration

It reaches the same URL as the [payment order](https://devs.tapipay.la/en/webhooks/order-payment.md) events: the one you set for orders during onboarding or, if you do not have one, your general URL.

The security mechanisms are the same as for the rest of the webhooks: see [Validating the request comes from TapiPay](https://devs.tapipay.la/en/webhooks/payment-notification.md#validating-the-request-comes-from-tapipay).

`POST` with `Content-Type: application/json`. The `notificationType` header carries the same value as `type`, so you can route without reading the body.

## The payload

| Field | Type | Present | Description |
| - | - | - | - |
| `type` | String | Always | `PAYMENT_METHOD_REGISTERED`. Use it to route. |
| `hash` | String \| null | Always | Verification hash. `null` if you have no public key configured. |
| `id` | String (uuid) | Always | Identifier of the notification. It is the same for every notice about the same account. **Use it as the idempotency key.** |
| `companyCode` | String | Always | Code of the company the account was registered with. |
| `externalClientId` | String | Always | Your identifier for the user. |
| `paymentMethod` | Object | Always | The registered account: `{ type, externalPaymentMethodId, isDefault, details }`. It never carries the account number or the CLABE. |
| `registeredAt` | String | Always | When the account was first registered, in ISO 8601 UTC. |

### `paymentMethod`

| Field | Type | Description |
| - | - | - |
| `type` | String | For now `BANK_ACCOUNT`. |
| `externalPaymentMethodId` | String (uuid) | Identifier of the account. Send it in `POST /v2/debts/orders` to charge this account. |
| `isDefault` | Boolean | `true` if it is the user's default account. See [Query a user's payment methods](https://devs.tapipay.la/en/resources/direct-debit.md#query-a-users-payment-methods). |
| `details` | Object | For now it always arrives empty (`{}`). |

> [!NOTE]
>
> It is the same `paymentMethod` object that arrives in the [order payment](https://devs.tapipay.la/en/webhooks/order-payment.md), with two more fields: `isDefault` and `details`.

## The hash

If you provided an RSA public key during onboarding, `hash` is encrypted with it. Decrypt it with your private key: it contains your integration username or, in version `v2` of the security, `{ "clientUsername", "operationId" }`. In `v2`, check that `operationId` matches the `id` in the body.

## Example

It belongs to an integration without a public key, which is why `hash` is `null`.

```json theme={null}
{
  "type": "PAYMENT_METHOD_REGISTERED",
  "hash": null,
  "id": "0b8f3c6e-7a21-5d94-b3e8-2c6f9a1d4e57",
  "companyCode": "MX-S-12345",
  "externalClientId": "CLI-00042",
  "paymentMethod": {
    "type": "BANK_ACCOUNT",
    "externalPaymentMethodId": "b7e4a0c2-9f13-4e6d-8a25-71c3d9e0b4f8",
    "isDefault": true,
    "details": {}
  },
  "registeredAt": "2026-10-23T14:03:11.000Z"
}
```

## Recommendations

* **Process each `id` only once.** Besides the retries when you do not respond, a repeated registration and a reactivation resend the same `id`. Store processed `id` values in persistent storage.
* **Store the `externalPaymentMethodId`** with your user: it is what you need to charge that account.
* **Do not use `isDefault` as the source of truth.** The default account can change later, for example if the user deletes an account. Before deciding which account to charge, query [`GET /payment-methods`](https://devs.tapipay.la/en/resources/direct-debit#query-a-users-payment-methods).
* **Ignore fields you do not know**: new fields can be added, also inside `details`.

The requirements for your endpoint (respond 2xx in under 5 seconds and be reachable from TapiPay's IPs) are the same as for the rest of the webhooks: see [Requirements for your endpoint](https://devs.tapipay.la/en/webhooks/payment-notification.md#requirements-for-your-endpoint).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.