# Recibe los eventos de Stripe en tu punto de conexión de webhook

Recibe eventos de Stripe en tu punto de conexión de webhook para que la integración pueda activar reacciones automáticamente.

## Empieza aquí: instala las habilidades de agente

Stripe aconseja usar las habilidades oficiales para la integración en la API con las prácticas recomendadas. Sigue las instrucciones que se incluyen a continuación para aprender cómo.

**Consejo: Usa cURL, en lugar de herramientas de Fetch.** Las habilidades se detallan en archivos de marcado de&nbsp;10&nbsp;a&nbsp;20&nbsp;KB. Las herramientas de Fetch las resumen. `curl -sL` garantiza el contenido completo.

**Uso de `npx skills`**: comprueba si `npx` está instalado en el sistema. Si `npx` está disponible, ejecuta `npx skills add https://docs.stripe.com --list` para enumerar las habilidades disponibles y, a continuación, ejecuta `npx skills add https://docs.stripe.com --yes --skill <skill-name> <--skill other-skills>` para instalar habilidades individuales.

**En el caso de que `npx skills` no esté disponible**: puedes usar cURL para obtener el índice de las habilidades disponibles, lo que hacen y sus archivos de `https://docs.stripe.com/.well-known/skills/index.json`. Para obtener una habilidad y sus archivos relacionados, usa cURL y descárgalos de `https://docs.stripe.com/.well-known/skills/<filepath>`.

Para este artículo, recomendamos usar estas habilidades: `stripe-best-practices`

> #### Envía eventos a tu cuenta AWS o suscripción Azure
> 
> Puedes enviar eventos directamente a [Amazon EventBridge](https://docs.stripe.com/event-destinations/eventbridge.md) o [Azure Event Grid](https://docs.stripe.com/event-destinations/eventgrid.md) como destinos de eventos.

Crea un destino de evento para recibir eventos en un punto de conexión de webhook HTTPS. Después de registrar el punto de conexión de webhook, Stripe puede enviar datos de eventos en tiempo real al punto de conexión de webhook de tu aplicación cuando se produzcan [eventos](https://docs.stripe.com/event-destinations.md#events-overview) en tu cuenta de Stripe. Stripe utiliza HTTPS para enviar eventos de webhook a tu aplicación como una carga JSON que incluye un [objeto Event](https://docs.stripe.com/api/events.md).

Recibir eventos webhook te ayuda a responder a eventos asincrónicos, como cuando el banco de un cliente confirma un pago, un cliente disputa un cargo, o un pago recurrente se realiza correctamente.

## Empezar

Para empezar a recibir eventos de webhook en tu aplicación, sigue estos pasos:

1. Crea un controlador de punto de conexión de webhook para recibir solicitudes POST de datos de eventos.
1. Prueba el controlador del punto de conexión de tu webhook a nivel local con la CLI de Stripe.
1. Crea un nuevo [destino de evento](https://docs.stripe.com/event-destinations.md) para tu punto de conexión de webhooks.
1. Protege tu punto de conexión de webhook.

Puedes registrarte y crear un punto de conexión para manejar varios tipos de eventos diferentes a la vez, o bien configurar puntos de conexión individuales para eventos específicos.

## Comportamientos de tipo de evento no admitidos para destinos de eventos de una organización

Stripe envía la mayoría de los tipos de eventos de forma asincrónica, pero espera una respuesta para algunos tipos de eventos. En estos casos, Stripe se comporta de forma diferente en función de si responde o no el destino del evento.

Si el destino de tu evento recibe eventos de la [Organización](https://docs.stripe.com/get-started/account/orgs.md), aquellos que requieren una respuesta tienen las siguientes limitaciones:

- No puedes suscribirte a `issuing_authorization.request` para los destinos de la organización. En su lugar, configura un [punto de conexión de webhook](https://docs.stripe.com/webhooks.md#example-endpoint) en una cuenta de Stripe dentro de la organización para suscribirte a este tipo de evento. Usa `issuing_authorization.request` para autorizar solicitudes de compra en tiempo real.
- Los destinos de la organización que reciben `checkout_sessions.completed` no pueden [gestionar el comportamiento](https://docs.stripe.com/checkout/fulfillment.md#redirect-hosted-checkout) de redireccionamiento cuando insertas [Procesos de compra](https://docs.stripe.com/payments/checkout.md) directamente en tu sitio web o rediriges a los clientes a una página de pago alojada en Stripe. Para influir en el comportamiento de redireccionamiento de procesos de compra, procesa este tipo de eventos con un [punto de conexión](https://docs.stripe.com/webhooks.md#example-endpoint) webhook configurado en una cuenta de Stripe dentro de la organización.
- Los destinos de la organización que responden sin éxito a un evento `invoice.created` no pueden influir en la [finalización automática de facturas cuando se usa cobro automático](https://docs.stripe.com/billing/subscriptions/webhooks.md#understand). Debes procesar este tipo de evento con un [punto de conexión webhook](https://docs.stripe.com/webhooks.md#example-endpoint) configurado en una cuenta de Stripe dentro de la organización para activar la finalización automática de facturas.

## Crea un controlador

Configura una función de punto de conexión HTTP o HTTPS que pueda aceptar solicitudes de webhooks con un método POST. Si todavía estás desarrollando tu función de punto de conexión en una máquina local, puedes usar HTTP. Una vez que sea de acceso público, la función de punto de conexión de tu webhook debe usar HTTPS.

Configura tu función de punto de conexión para que:

- Maneje las solicitudes POST con una carga JSON que consista en un [objeto Event](https://docs.stripe.com/api/events/object.md).
- En el caso de los administradores de eventos de la [organización](https://docs.stripe.com/get-started/account/orgs.md), inspecciona el valor `context` para determinar qué cuenta de una organización generó el evento y, luego, establece el encabezado `Stripe-Context` correspondiente al valor `context`.
- Devuelve de inmediato un código de estado correcto (`2xx`) antes de que alguna lógica compleja pueda provocar un error de tiempo de espera agotado. Por ejemplo, debes devolver una respuesta `200` antes de registrar la factura del cliente como pagada en tu sistema contable.

> - Usa nuestro [generador de puntos de conexión webhook](https://docs.stripe.com/webhooks/quickstart.md) para crear una función de punto de conexión webhook en tu lenguaje de programación.
- Usa la referencia de la API Stripe para identificar los [objetos Event](https://docs.stripe.com/api/v2/core/events/event-types.md) u [objetos Event instantáneos](https://docs.stripe.com/api/events/object.md) que tu servicio de webhooks debe procesar.

#### Punto de conexión de ejemplo

Este fragmento de código es una función de webhook configurada para verificar los eventos recibidos de una cuenta de Stripe, controlar los eventos y devolver respuestas `200`. Refiérete al controlador de eventos [con instantánea](https://docs.stripe.com/event-destinations.md#events-overview) cuando uses recursos de la API v1 y refiérete al controlador de eventos [breves](https://docs.stripe.com/event-destinations.md#events-overview) cuando uses recursos de la API v2.

#### Controlador de eventos con instantánea

Al crear un controlador de eventos con instantánea, usa la definición del objeto API en el momento del evento para la lógica. Para ello, accede a los campos `data.object` del evento. También puedes recuperar el recurso API de la API de Stripe para acceder a la definición de objeto más reciente y actualizada.

#### Ruby

```ruby
require 'json'
require 'stripe'

client = Stripe::StripeClient.new(ENV.fetch('STRIPE_API_KEY'))

# Replace this endpoint secret with your unique endpoint secret key
# If you're testing with the CLI, run 'stripe listen' to find the secret key
# If you defined your endpoint using the API or the Dashboard, check your webhook settings for your endpoint secret: https://dashboard.stripe.com/webhooks
endpoint_secret = 'whsec_...';

# Using Sinatra
post '/webhook' do
  payload = request.body.read
  event = nil

  begin
    event = Stripe::Event.construct_from(
      JSON.parse(payload, symbolize_names: true)
    )
  rescue JSON::ParserError => e
    # Invalid payload
    status 400
    return
  end

  # Check that you have configured webhook signing
  if endpoint_secret
    # Retrieve the event by verifying the signature using the raw body and the endpoint secret
    signature = request.env['HTTP_STRIPE_SIGNATURE'];
    begin
      event = Stripe::Webhook.construct_event(
        payload, signature, endpoint_secret
      )
    rescue Stripe::SignatureVerificationError => e
      puts "⚠️  Webhook signature verification failed. #{e.message}"
      status 400
    end
  end

  # Handle the event
  case event.type
  when 'payment_intent.succeeded'
    payment_intent = event.data.object # contains a Stripe::PaymentIntent
    # Then define and call a method to handle the successful payment intent.
    # handle_payment_intent_succeeded(payment_intent)
  when 'payment_method.attached'
    payment_method = event.data.object # contains a Stripe::PaymentMethod
    # Then define and call a method to handle the successful attachment of a PaymentMethod.
    # handle_payment_method_attached(payment_method)
  # ... handle other event types
  else
    puts "Unhandled event type: #{event.type}"
  end

  status 200
end
```

#### Controlador de eventos ligeros (Clover+)

Cuando crees un controlador de eventos ligeros, utiliza el método `fetchRelatedObject()` para recuperar la última versión del objeto asociado al evento. Los eventos pueden contener [datos adicionales](https://docs.stripe.com/event-destinations.md#fetch-data) que solo puedes recuperar a través del método de instancia `.fetchEvent()` en `EventNotification`. La forma exacta de esos datos depende del `type` del Evento.

Los tipos de eventos deben estar disponibles en el momento del lanzamiento para generar clases en esa versión del SDK. Para gestionar eventos en los que el SDK no tiene clases, utiliza la clase `UnknownEventNotification`.

#### Python

```python
import os
from stripe import StripeClient
from stripe.events import UnknownEventNotification

from flask import Flask, request, jsonify

app = Flask(__name__)
api_key = os.environ.get("STRIPE_API_KEY", "")
webhook_secret = os.environ.get("WEBHOOK_SECRET", "")

client = StripeClient(api_key)

@app.route("/webhook", methods=["POST"])
def webhook():
    webhook_body = request.data
    sig_header = request.headers.get("Stripe-Signature")

    try:
        event_notif = client.parse_event_notification(
            webhook_body, sig_header, webhook_secret
        )

        # type checkers will narrow the type based on the `type` property
        if event_notif.type == "v1.billing.meter.error_report_triggered":
            # in this block, event_notification is typed as
            # a V1BillingMeterErrorReportTriggeredEventNotification

            # there's basic info about the related object in the notification
            print(f"Meter w/ id {event_notif.related_object.id} had a problem")

            # or you can fetch the full object form the API for more details
            meter = event_notif.fetch_related_object()
            print(
                f"Meter {meter.display_name} ({meter.id}) had a problem"
            )

            # And you can always fetch the full event:
            event = event_notif.fetch_event()
            print(f"More info: {event.data.developer_message_summary}")

        elif event_notif.type == "v1.billing.meter.no_meter_found":
            # in this block, event_notification is typed as
            # a V1BillingMeterNoMeterFoundEventNotification

            # that class doesn't define `fetch_related_object` because the event
            # has no related object.
            # so this line would correctly give a type error:
            # meter = event_notif.fetch_related_object()

            # but fetching the event always works:
            event = event_notif.fetch_event()
            print(
                f"Err! No meter found: {event.data.developer_message_summary}"
            )

        # Events that were introduced after this SDK version release are
        # represented as `UnknownEventNotification`s.
        # They're valid, the SDK just doesn't have corresponding classes for them.
        # You must match on the "type" property instead.
        elif isinstance(event_notif, UnknownEventNotification):
            # these lines are optional, but will give you more accurate typing in this block
            from typing import cast

            event_notif = cast(UnknownEventNotification, event_notif)

            # continue matching on the type property
            # from this point on, the `related_object` property _may_ be None
            # (depending on the event type)
            if event_notif.type == "some.new.event":
                # if this event type has a related object, you can fetch it
                obj = event_notif.fetch_related_object()
                # otherwise, `obj` will just be `None`
                print(f"Related object: {obj}")

                # you can still fetch the full event, but it will be untyped
                event = event_notif.fetch_event()
                print(f"New event: {event.data}")  # type: ignore

        return jsonify(success=True), 200
    except Exception as e:
        return jsonify(error=str(e)), 400
```

#### Controlador de eventos ligeros (Acacia o Basil)

Al crear un controlador de eventos breves, usa el método `fetchRelatedObject()` para recuperar la última versión del objeto asociado con el evento. Los eventos breves pueden contener [datos contextuales adicionales](https://docs.stripe.com/event-destinations.md#fetch-data) que solo se pueden recuperar con la API. Usa la llamada `retrieve()` con la ID de evento breve para acceder a estos campos de carga adicionales.

#### Python

```python
import os
from stripe import StripeClient
from stripe.events import V1BillingMeterErrorReportTriggeredEvent

from flask import Flask, request, jsonify

app = Flask(__name__)
api_key = os.environ.get('STRIPE_API_KEY')
webhook_secret = os.environ.get('WEBHOOK_SECRET')

client = StripeClient(api_key)

@app.route('/webhook', methods=['POST'])
def webhook():
    webhook_body = request.data
    sig_header = request.headers.get('Stripe-Signature')

try:
    thin_event = client.parse_thin_event(webhook_body, sig_header, webhook_secret)

    # Fetch the event data to understand the failure
    event = client.v2.core.events.retrieve(thin_event.id)
    if isinstance(event, V1BillingMeterErrorReportTriggeredEvent):
        meter = event.fetch_related_object()
        meter_id = meter.id

        # Record the failures and alert your team
        # Add your logic here

    return jsonify(success=True), 200
except Exception as e:
    return jsonify(error=str(e)), 400

if __name__ == '__main__':
    app.run(port=4242)
```

#### Uso de `context`

#### Eventos instantáneos

Este fragmento de código es una función de webhooks configurada para verificar los eventos recibidos, detectar la cuenta de origen, si corresponde, gestionar el evento y devolver una respuesta `200`.

#### Ruby

```ruby
require 'json'

client = Stripe::StripeClient.new('sk_...')

# Using Sinatra
post '/webhook' do
  payload = request.body.read
  event = nil

  begin
    event = Stripe::Event.construct_from(
      JSON.parse(payload, symbolize_names: true)
    )
  rescue JSON::ParserError => e
    # Invalid payload
    status 400
    return
  end

  # Extract the context
  context = event.context

  # Define your API key variables (ideally loaded securely)
  ACCOUNT_123_API_KEY = "sk_test_123"
  ACCOUNT_456_API_KEY = "sk_test_456"

  account_api_keys = {
    "account_123" => ACCOUNT_123_API_KEY,
    "account_456" => ACCOUNT_456_API_KEY
  }

  api_key = account_api_keys[context]

  if api_key.nil?
    puts "No API key found for context: #{context}"
    status 400
    return
  end

  # Handle the event
  case event.type
  when 'customer.created'
    customer = event.data.object

    begin

      latest_customer = client.v1.customers.retrieve(customer.id, {api_key: api_key})
      handle_customer_created(latest_customer, context)
    rescue => e
      puts "Error retrieving customer: #{e.message}"
      status 500
      return
    end

  when 'payment_method.attached'
    payment_method = event.data.object

    begin
      latest_payment_method = client.v1.payment_methods.retrieve(payment_method.id, {api_key: api_key})
      handle_payment_method_attached(latest_payment_method, context)
    rescue => e
      puts "Error retrieving payment method: #{e.message}"
      status 500
      return
    end

  else
    puts "Unhandled event type: #{event.type}"
  end

  status 200
end
```

#### Controlador de eventos ligeros (Clover+)

Utiliza la propiedad `context` de `EventNotification` para identificar la cuenta de eventos dentro de tu [organización](https://docs.stripe.com/get-started/account/orgs.md). Debes definir el [encabezado de Stripe Context](https://docs.stripe.com/context.md) de forma manual para todas las llamadas API, excepto `.fetchRelatedObject()` y `.fetchEvent()`, que lo hacen por ti de forma automática.

#### Python

```python
org_api_key = os.environ.get("STRIPE_API_KEY")
webhook_secret = os.environ.get("WEBHOOK_SECRET")
client = StripeClient(org_api_key)

# inside your webhook handler
event_notification = client.parse_event_notification(payload, sig_header, webhook_secret)

# uses `context` automatically
event_notification.fetch_event()

# pass context manually for other API requests
client.v1.invoices.list(stripe_context=event_notification.context)
```

#### Controlador de eventos ligeros (Acacia o Basil)

Este fragmento de código es una función de webhook configurada para recibir eventos ligeros en una organización, verificar la firma, determinar la cuenta de origen con el campo `context` y usar la tecla API de esa cuenta para llamadas API posteriores.

#### Python

```python
import os
from flask import Flask, request, jsonify
from stripe import StripeClient
from stripe.events import V1BillingMeterErrorReportTriggeredEvent

app = Flask(__name__)

org_api_key = os.environ.get("STRIPE_API_KEY")
webhook_secret = os.environ.get("WEBHOOK_SECRET")
client = StripeClient(org_api_key)

account_api_keys = {
    "account_123": os.environ.get("ACCOUNT_123_API_KEY"),
    "account_456": os.environ.get("ACCOUNT_456_API_KEY"),
}

@app.route("/webhook", methods=["POST"])
def webhook():
    payload = request.data
    sig_header = request.headers.get("Stripe-Signature")

    try:
        thin_event = client.parse_thin_event(payload, sig_header, webhook_secret)

        # Retrieve the event using the org client to inspect context
        event = client.v2.core.events.retrieve(thin_event.id)

        context = getattr(event, "context", None)
        if not context:
            return jsonify(error="Missing context"), 400

        account_key = account_api_keys.get(context)
        if not account_key:
            return jsonify(error="Unknown context"), 400

        account_client = StripeClient(account_key)
        full_event = account_client.v2.core.events.retrieve(thin_event.id)

        if isinstance(full_event, V1BillingMeterErrorReportTriggeredEvent):
            meter = full_event.fetch_related_object()
            meter_id = meter.id
            # Record the failures and alert your team
            # Add your logic here

        return jsonify(success=True), 200
    except Exception as e:
        return jsonify(error=str(e)), 400

if __name__ == "__main__":
    app.run(port=4242)
```

## Prueba tu controlador

Antes de pasar a modo activo la función de punto de conexión de webhook, te recomendamos que pruebes la integración de tu aplicación. Para hacerlo, debes configurar un oyente local para que envíe eventos a tu máquina local, y enviar eventos de prueba. Debes usar la [CLI](https://docs.stripe.com/stripe-cli.md) para las pruebas.

#### Reenviar eventos a un punto de conexión local

Para reenviar eventos a tu punto de conexión local, ejecuta el siguiente comando con la [CLI](https://docs.stripe.com/stripe-cli.md) y configura un oyente local. La marca `--forward-to` envía todos los [eventos de Stripe](https://docs.stripe.com/cli/trigger#trigger-event) en un [entorno de prueba](https://docs.stripe.com/sandboxes.md) a tu punto de conexión local de webhook. Usa los comandos de CLI adecuados que se indican a continuación en función de si utilizas eventos [breves](https://docs.stripe.com/event-destinations.md#events-overview) o eventos con instantánea.

#### Reenvía eventos con instantánea

Usa el siguiente comando para reenviar [eventos con instantánea](https://docs.stripe.com/event-destinations.md#events-overview) al oyente local.

```bash
stripe listen --forward-to localhost:4242/webhook
```

#### Reenvía eventos breves

Usa el siguiente comando para reenviar [eventos breves](https://docs.stripe.com/event-destinations.md#events-overview) al oyente local.

```bash
$ stripe listen --forward-thin-to localhost:4242/webhook --thin-events "*"
```

> También puedes ejecutar `stripe listen` para ver eventos en [Stripe Shell](https://docs.stripe.com/workbench/shell.md), aunque no podrás reenviar eventos desde el shell a tu punto de conexión local.

Algunas configuraciones útiles para ayudarte a realizar pruebas con tu oyente local son las siguientes:

- Para deshabilitar la verificación del certificado HTTPS, utiliza la marca opcional `--skip-verify`.
- Para reenviar solo eventos específicos, usa la marca opcional `--events` y especifica una lista de eventos separados por comas.

#### Reenvía eventos con instantánea específicos

Usa el siguiente comando para reenviar eventos con instantánea específicos al oyente local.

```bash
stripe listen --events payment_intent.created,customer.created,payment_intent.succeeded,checkout.session.completed,payment_intent.payment_failed \
  --forward-to localhost:4242/webhook
```

#### Reenvía eventos breves específicos

Usa el siguiente comando para reenviar eventos breves específicos al oyente local.

```bash
stripe listen --thin-events v1.billing.meter.error_report_triggered,v1.billing.meter.no_meter_found \
  --forward-thin-to localhost:4242/webhook
```

- Para reenviar eventos a tu punto de conexión de webhook local desde el punto de conexión de webhook público que ya registraste en Stripe, usa la marca opcional `--load-from-webhooks-api`. Esta acción carga tu punto de conexión registrado, analiza la ruta y sus eventos registrados y, por último, agrega la ruta a tu punto de conexión de webhook local en `--forward-to path`.

#### Reenvía eventos con instantánea desde un punto de conexión de webhook público

Usa el siguiente comando para reenviar eventos con instantánea desde un punto de conexión de webhook público al oyente local.

```bash
stripe listen --load-from-webhooks-api --forward-to localhost:4242/webhook
```

#### Reenvía eventos breves desde un punto de conexión de webhook público

Usa el siguiente comando para reenviar eventos breves desde un punto de conexión de webhook público al oyente local.

```bash
stripe listen --load-from-webhooks-api --forward-thin-to localhost:4242/webhook
```

- Para comprobar las firmas de webhook, utiliza el `{{WEBHOOK_SIGNING_SECRET}}` de la salida inicial del comando de escucha.

```output
Ready! Your webhook signing secret is '{{WEBHOOK_SIGNING_SECRET}}' (^C to quit)
```

#### Cómo activar eventos de prueba

Para enviar eventos de prueba, activa un tipo de evento al que esté suscrito el destino de tu evento. Para ello, crea manualmente un objeto en el Dashboard de Stripe. Cómo activar eventos con [Stripe para VS Code](https://docs.stripe.com/stripe-vscode.md).

#### Activar un evento de instantánea

Puedes usar el siguiente comando en [Stripe Shell](https://docs.stripe.com/workbench/shell.md) o [Stripe CLI](https://docs.stripe.com/stripe-cli.md). Este ejemplo activa un evento `payment_intent.succeeded`:

```bash
stripe trigger payment_intent.succeeded
Running fixture for: payment_intent
Trigger succeeded! Check dashboard for event details.
```

#### Activar un evento breve

Puedes usar el siguiente comando en la [CLI de Stripe](https://docs.stripe.com/stripe-cli.md). Este ejemplo activa un evento `v1.billing.meter.error_report_triggered`:

```bash
stripe trigger v1.billing.meter.error_report_triggered
Setting up fixture for: list_billing_meters
Running fixture for: list_billing_meters
Setting up fixture for: billing_meter
Running fixture for: billing_meter
Setting up fixture for: list_billing_meters_after_creation
Running fixture for: list_billing_meters_after_creation
Setting up fixture for: billing_meter_event_session
Running fixture for: billing_meter_event_session
Setting up fixture for: create_billing_meter_event_stream
Running fixture for: create_billing_meter_event_stream
Trigger succeeded! Check dashboard for event details.
```

## Registra tu punto de conexión

Después de probar la función de punto de conexión del webhook, usa la [API](https://docs.stripe.com/api/v2/event-destinations.md) o la pestaña **Webhooks** en Workbench para registrar la URL accesible del punto de conexión del webhook de forma que Stripe sepa dónde entregar los eventos. Puedes registrar hasta 16&nbsp;puntos de conexión de webhook con Stripe. Los puntos de conexión de webhook registrados deben ser URL **HTTPS** de acceso público.

#### Formato de URL del webhook

El formato de la URL para registrar un punto de conexión del webhook es el siguiente:

```
https://<your-website>/<your-webhook-endpoint>
```

Por ejemplo, si tu dominio es `https://mycompanysite.com` y la ruta a tu punto de conexión de webhook es `@app.route('/stripe_webhooks', methods=['POST'])`, especifica `https://mycompanysite.com/stripe_webhooks` como la **URL del punto de conexión**.

#### Crea un destino de evento para el punto de conexión del webhook

Crea un destino de evento usando Workbench en el Dashboard o mediante programación con la [API](https://docs.stripe.com/api/v2/event-destinations.md). Puedes registrar hasta 16&nbsp;destinos de eventos en cada cuenta de Stripe.

#### Dashboard

Para crear un nuevo punto de conexión de webhook en el Dashboard, haz lo siguiente:

1. Abre la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) en Workbench.
1. Haz clic en **Crea un destino de evento**.
1. Selecciona desde dónde deseas recibir eventos. Stripe admite dos tipos de configuraciones: **Tu cuenta** y [Cuentas conectadas](https://docs.stripe.com/connect.md). Selecciona **Cuenta** para escuchar los eventos de tu propia cuenta. Si creaste una [aplicación de Connect](https://docs.stripe.com/connect.md) y quieres escuchar eventos de tus cuentas conectadas, selecciona **Cuentas conectadas**.

> #### Escucha los eventos de un punto de conexión de webhook de la organización
> 
> Si creas un punto de conexión de webhook en una [cuenta de organización](https://docs.stripe.com/get-started/account/orgs.md), selecciona **Cuentas** para escuchar los eventos de las cuentas de tu organización. Si tienes [plataformas de Connect](https://docs.stripe.com/connect.md) como miembros de tus organizaciones y quieres escuchar los eventos de las cuentas conectadas de todas las plataformas, selecciona **Cuentas conectadas**.

1. Selecciona la versión de API para el [objeto Events](https://docs.stripe.com/api/events.md) que quieres consumir.
1. Selecciona los [tipos de eventos](https://docs.stripe.com/api/events/types.md) que quieras enviar a un punto de conexión de webhook.
1. Selecciona **Continuar** y, luego, **Punto de conexión del webhook** como el tipo de destino.
1. Haz clic en **Continuar** y, luego, proporciona la **URL del punto de conexión** y una descripción opcional del webhook.

#### API

Puedes crear un nuevo destino de evento que te notifique cuando se active un error de validación de [cobro por consumo](https://docs.stripe.com/billing/subscriptions/usage-based.md) con la [API](https://docs.stripe.com/api/v2/event-destinations.md).

Si creaste una [solicitud Connect](https://docs.stripe.com/connect.md) y quieres escuchar tus cuentas conectadas, usa el parámetro [events_from](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-events_from) y establece su valor en `@accounts`. Para los destinos de eventos de la [organización](https://docs.stripe.com/get-started/account/orgs.md), usa `@organization_members` destinado a los eventos de cuentas de tu organización o `@organization_members/@accounts` para los eventos de cuentas conectadas de toda tu organización.

```curl
curl -X POST https://api.stripe.com/v2/core/event_destinations \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-03-25.preview" \
  --json '{
    "name": "My event destination",
    "description": "This is my event destination, I like it a lot",
    "type": "webhook_endpoint",
    "event_payload": "thin",
    "enabled_events": [
        "v1.billing.meter.error_report_triggered"
    ],
    "webhook_endpoint": {
        "url": "https://example.com/my/webhook/endpoint"
    }
  }'
```

> [Workbench](https://docs.stripe.com/workbench.md) reemplaza el [Dashboard para desarrolladores] (/development/dashboard) existente. Si todavía estás usando el Dashboard para desarrolladores, consulta cómo [crear un nuevo punto de conexión de webhooks](https://docs.stripe.com/development/dashboard/webhooks.md).

## Protege tu punto de conexión

Después de confirmar que tu punto de conexión funciona como se esperaba, asegúralo con las [prácticas recomendadas de webhooks](https://docs.stripe.com/webhooks.md#best-practices).

Para proteger tu integración, asegúrate de que tu controlador verifique que todas las solicitudes de webhook sean generadas por Stripe. Puedes verificar las firmas de webhooks con nuestras bibliotecas oficiales o hacerlo de forma manual.

#### Haz la verificación con las bibliotecas oficiales (recomendada)

### Haz la verificación manual de las firmas de webhook con las bibliotecas oficiales

Recomendamos utilizar nuestras bibliotecas oficiales para verificar las firmas. Para realizar la verificación, proporciona la carga del evento, el encabezado `Stripe-Signature` y el secreto del punto de conexión. Si la verificación falla, verás un error.

Si recibes un error de verificación de firma, lee nuestra guía sobre [solución de problemas](https://docs.stripe.com/webhooks/signature.md).

> Stripe requiere que el cuerpo sin formato de la solicitud realice la verificación de la firma. Si estás usando un framework, asegúrate de que no manipule el cuerpo sin formato. Cualquier manipulación al cuerpo sin formato de la solicitud hará que la verificación falle.

#### Ruby

```ruby

# Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
# Find your keys at https://dashboard.stripe.com/apikeys.
client = Stripe::StripeClient.new('<<YOUR_SECRET_KEY>>')

require 'stripe'
require 'sinatra'

# If you are testing your webhook locally with the Stripe CLI you
# can find the endpoint's secret by running `stripe listen`
# Otherwise, find your endpoint's secret in your webhook settings in
# the Developer Dashboardendpoint_secret = 'whsec_...'

# Using the Sinatra framework
set :port, 4242

post '/my/webhook/url' do
  payload = request.body.readsig_header = request.env['HTTP_STRIPE_SIGNATURE']
  event = nil

  beginevent = Stripe::Webhook.construct_event(
      payload, sig_header, endpoint_secret
    )
  rescue JSON::ParserError => e
    # Invalid payload
    puts "Error parsing payload: #{e.message}"
    status 400
    return
  rescue Stripe::SignatureVerificationError => e# Invalid signature
    puts "Error verifying webhook signature: #{e.message}"
    status 400
    return
  end

  # Handle the event
  case event.type
  when 'payment_intent.succeeded'
    payment_intent = event.data.object # contains a Stripe::PaymentIntent
    puts 'PaymentIntent was successful!'
  when 'payment_method.attached'
    payment_method = event.data.object # contains a Stripe::PaymentMethod
    puts 'PaymentMethod was attached to a Customer!'
  # ... handle other event types
  else
    puts "Unhandled event type: #{event.type}"
  end

  status 200
end
```

#### Haz la verificación en forma manual

### Haz la verificación manual de las firmas de webhook

Si bien te recomendamos que uses nuestra biblioteca oficial para verificar firmas de eventos de webhook, puedes crear una solución personalizada siguiendo las indicaciones de esta sección.

El encabezado `Stripe-Signature` incluido en cada evento firmado contiene una marca de tiempo y una o más firmas que debes verificar. La marca de tiempo tiene el prefijo `t=`, y cada firma tiene un *esquema* como prefijo. Los esquemas comienzan con `v`, seguido de un número entero. Actualmente, el único esquema de firma en modo activo válido es `v1`. Para ayudar con las pruebas, Stripe envía una firma adicional con un esquema `v0` falso, para eventos en modo de prueba.

```
Stripe-Signature:
t=1492774577,
v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd,
v0=6ffbb59b2300aae63f272406069a9788598b792a944a07aba816edb039989a39
```

> Propocionamos nuevas líneas para obtener mayor claridad, pero un encabezado `Stripe-Signature` real va en una sola línea.

Stripe genera firmas usando un código de autenticación de mensajes basado en hash ([HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)) con [SHA-256](https://en.wikipedia.org/wiki/SHA-2). Para evitar los [ataques de degradación](https://en.wikipedia.org/wiki/Downgrade_attack), ignora todos los esquemas que no sean `v1`.

Puedes tener más de una firma con el mismo par esquema-secreto cuando [cambias el secreto de un punto de conexión](https://docs.stripe.com/webhooks.md#roll-endpoint-secrets) y mantienes activo el secreto anterior por un plazo máximo de 24&nbsp;horas. Durante este plazo, tu punto de conexión tendrá varios secretos activos, y Stripe generará una firma para cada uno de ellos.

Si deseas crear una solución manual para verificar firmas, debes completar los siguientes pasos:

#### Paso 1: extrae la marca de tiempo y las firmas del encabezado

Divide el encabezado con el carácter `,` como separador para obtener una lista de elementos. Luego, divide cada elemento con el carácter `=` como separador para obtener un par de prefijo y valor.

El valor del prefijo `t` corresponde a la marca de tiempo, mientras que `v1` corresponde a la firma (o firmas). Puedes descartar el resto de los elementos.

#### Paso 2: Prepara la cadena `signed_payload`

La cadena `signed_payload` se crea concatenando:

- La marca de tiempo (como cadena)
- El carácter `.`
- La carga JSON real (es decir, el cuerpo de la solicitud)

#### Paso 3: determina la firma prevista

Calcula un HMAC con la función hash SHA256. Usa el secreto de la firma del punto de conexión como la clave, y la cadena `signed_payload` como el mensaje.

#### Paso 4: Compara las firmas

Compara la firma (o firmas) en el encabezado con la firma prevista. Para una correspondencia de igualdad, calcula la diferencia entre la marca de tiempo actual y la recibida, y luego decide si la diferencia está dentro de tu tolerancia.

Para protegerte contra ataques de sincronización, usa una comparación de cadenas de tiempo constante para comparar la firma esperada con cada una de las firmas recibidas.

## Depura las integraciones de webhooks

Pueden ocurrir varios tipos de problemas al entregar eventos al punto de conexión de tu webhook:

- Es posible que Stripe no pueda enviar un evento al punto de conexión de tu webhook.
- El punto de conexión de tu webhook podría tener un problema de SSL.
- Tu conectividad de red es intermitente.
- El punto de conexión de tu webhook no está recibiendo los eventos que esperas recibir.

### Ver las entregas de eventos

Para ver las entregas de eventos, selecciona el punto de conexión del webhook en **Webhooks** y, a continuación, selecciona la pestaña **Eventos**. La pestaña **Eventos** contiene una lista de eventos y muestra si tienen el estado `Delivered`, `Pending` o `Failed`. Haz clic en un evento para ver los metadatos, que incluyen el código de estado HTTP de los intentos de entrega anteriores y la hora de las entregas futuras pendientes.

También puedes usar la [CLI de Stripe](https://docs.stripe.com/stripe-cli.md) para [escuchar eventos](https://docs.stripe.com/webhooks.md#test-webhook) directamente en tu terminal.

### Corrige los códigos de estado HTTP

Cuando un evento muestra un código de estado `200`, indica una entrega correcta al punto de conexión de webhook. También puedes recibir un código de estado que no sea `200`. En la siguiente tabla, encontrarás una lista de códigos de estado HTTP comunes y soluciones recomendadas.

| Estado de webhook pendiente        | Descripción                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | Corregir                                                                                                                                         |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| (Error al establecer conexión) ERR | No podemos establecer conexión con el servidor de destino.                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Asegúrate de que tu dominio de host sea de acceso público en Internet.                                                                           |
| (`302`) ERR (u otro estado `3xx`)  | El servidor de destino intentó redirigir la solicitud a otra ubicación. Consideramos las respuestas de redireccionamiento a las solicitudes de webhook como errores.                                                                                                                                                                                                                                                                                                                                             | Establece el destino del punto de conexión del webhook en la URL resuelta por el redireccionamiento.                                             |
| (`400`) ERR (u otro estado `4xx`)  | El servidor de destino no puede procesar la solicitud o no lo hará. Esta circunstancia puede darse cuando el servidor detecta un error (`400`), cuando la URL de destino tiene restricciones de acceso (`401`, `403`) o cuando la URL de destino no existe (`404`).                                                                                                                                                                                                                                              | - Asegúrate de que tu punto de conexión sea de acceso público en Internet.
  - Asegúrate de que tu punto de conexión acepte un método POST HTTP. |
| (`500`) ERR (u otro estado `5xx`)  | El servidor de destino encontró un error mientras se procesaba la solicitud.                                                                                                                                                                                                                                                                                                                                                                                                                                     | Revisa los registros de tu aplicación para comprender por qué devuelve un error `500`.                                                           |
| (Error TLS) ERR                    | No pudimos establecer una conexión segura con el servidor de destino. Estos errores suelen deberse a los problemas con el certificado SSL/TLS o un certificado intermedio en la cadena de certificados del servidor de destino. Stripe requiere una versión `v1.2` de *TLS* (TLS refers to the process of securely transmitting data between the client—the app or browser that your customer is using—and your server. This was originally performed using the SSL (Secure Sockets Layer) protocol) o superior. | Realiza una [prueba de servidor SSL](https://www.ssllabs.com/ssltest/) para encontrar problemas que puedan causar este error.                    |
| (Se agotó el tiempo de espera) ERR | El servidor de destino tardó demasiado en responder a la solicitud de webhook.                                                                                                                                                                                                                                                                                                                                                                                                                                   | Asegúrate de aplazar la lógica compleja y devuelve una respuesta correcta de inmediato en tu código de manejo de webhooks.                       |

## Comportamientos de entrega de eventos

Esta sección te ayuda a comprender los diferentes comportamientos que puedes esperar en cuanto a la forma en que Stripe envía eventos a tu punto de conexión de webhook.

### Reintentos automáticos

Stripe intenta entregar eventos en tu destino durante un máximo de tres&nbsp;días con un retroceso exponencial en modo activo. Consulta cuándo se hará el siguiente reintento, si corresponde, en la pestaña **Entregas de eventos** de tu destino de eventos. Reintentamos las entregas de eventos creadas en un entorno de prueba tres veces en el transcurso de unas pocas horas. Si tu destino se deshabilitó o se eliminó cuando realizamos un reintento, no permitiremos próximos reintentos. Sin embargo, si deshabilitas y, luego, vuelves a habilitar el destino del evento antes de que podamos reintentarlo, aún verás reintentos futuros.

### Reintentos manuales

Hay dos maneras de reintentar eventos manualmente:

- En el Dashboard de Stripe, haz click en **Reenviar** cuando estés viendo un evento específico. Esto funciona hasta 15 días después de la creación del evento.
- Con la [CLI de Stripe](https://docs.stripe.com/cli/events/resend), ejecuta el comando `stripe events resend <event_id> --webhook-endpoint=<endpoint_id>`. Esto funciona hasta 30 días después de la creación del evento.

Reenviar manualmente un evento que tuvo fallos de entrega previos a un punto de conexión webhook no descarta el [comportamiento automático de reintentos](https://docs.stripe.com/webhooks.md#automatic-retries) de Stripe, aunque este de como resultado un código de estado `2xx`. Aprende cómo[procesar eventos de webhook no entregados](https://docs.stripe.com/webhooks/process-undelivered-events.md) a fin de detener futuros intentos.

### Pedido de eventos

Stripe no garantiza la entrega de eventos en el orden en que se generaron. Por ejemplo, crear una suscripción puede generar los siguientes eventos:

- `customer.subscription.created`
- `invoice.created`
- `invoice.paid`
- `charge.created` (si hay un cargo)

Asegúrate de que el destino de tu evento no dependa de recibir los eventos en un orden específico. Prepárate para administrar la entrega de manera adecuada. También puedes usar la API para recuperar los objetos faltantes. Por ejemplo, puedes recuperar los objetos Invoice, Charge y Subscription con la información de `invoice.paid` si recibes este evento primero.

### Control de versiones de la API

La versión de la API en la configuración de tu cuenta cuando ocurre el evento dicta la versión de la API y, por lo tanto, la estructura de un [Event](https://docs.stripe.com/api/events.md) enviado a tu destino. Por ejemplo, si tu cuenta está configurada en una versión anterior de la API, como 2015-02-16, y cambias la versión de la API para una solicitud específica con [control de versiones](https://docs.stripe.com/api.md#versioning), el objeto [Event](https://docs.stripe.com/api/events.md) generado y enviado a tu destino se seguirá basando en la versión de la API 2015-02-16. No puedes cambiar los objetos [Event](https://docs.stripe.com/api/events.md) después de la creación. Por ejemplo, si actualizas un cargo, el evento original del cargo no variará. Por lo tanto, las actualizaciones posteriores de la versión de la API de tu cuenta no alteran los objetos [Event](https://docs.stripe.com/api/events.md) existentes de forma retroactiva. La recuperación de un [Event](https://docs.stripe.com/api/events.md) anterior llamando a `/v1/events` con una versión más nueva de la API tampoco influye en la estructura del evento recibido. Puedes definir destinos de eventos de prueba para tu versión de API predeterminada o para la última versión de API. El [Event](https://docs.stripe.com/api/events.md) enviado al destino se estructura para la versión especificada del destino del evento.

## Prácticas recomendadas para usar webhooks

Revisa estas prácticas recomendadas para asegurarte de que tus puntos de conexión de webhook sigan siendo seguros y funcionen bien con tu integración.

### Maneja los eventos duplicados

Los puntos de conexión de webhooks ocasionalmente pueden recibir el mismo evento más de una vez. Para protegerte contra los recibos de eventos duplicados, puedes registrar los [ID de evento](https://docs.stripe.com/api/events/object.md#event_object-id) que procesaste y luego no procesar los eventos ya registrados.

En algunos casos, se generan y envían dos objetos Event separados. Para identificar estos duplicados, utiliza la ID del objeto en `data.object` junto con el `event.type`.

### Escucha únicamente los tipos de eventos que tu integración requiere

Configura tus puntos de conexión de webhook para recibir solo los tipos de evento que necesita tu integración. Si escuchas otros eventos (o todos los eventos), se producirá una saturación indebida en tu servidor que no recomendamos.

Puedes [modificar los eventos](https://docs.stripe.com/api/webhook_endpoints/update.md#update_webhook_endpoint-enabled_events) que recibe un punto de conexión de webhook en el Dashboard o con la API.

### Administra eventos de forma asíncrona

Configura el controlador para procesar los eventos entrantes con una cola asincrónica. Es posible que tengas problemas de escalabilidad si decides procesar los eventos de forma sincrónica. Cualquier aumento importante en las entregas de webhooks (por ejemplo, durante el comienzo del mes, cuando se renuevan todas las suscripciones) podría sobrecargar a los hosts de los puntos de conexión.

Las colas asincrónicas te permiten procesar los eventos simultáneos a una velocidad que el sistema puede admitir.

### Ruta de webhook exenta de la protección CSRF

Si usas Rails, Django u otro framework web, tu sitio podría comprobar automáticamente si cada solicitud POST contiene un *token CSRF*. Esta es una funcionalidad de seguridad importante que ayuda a protegerte a ti y a tus usuarios contra intentos de [falsificación de solicitudes en sitios cruzados](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_\(CSRF\)). No obstante, esta medida de seguridad también puede impedir que tu sitio procese eventos legítimos. De ser así, quizá sea necesario que la ruta de webhooks quede exenta de la protección CSRF.

#### Rails

```ruby
class StripeController < ApplicationController
  # If your controller accepts requests other than Stripe webhooks,
  # you'll probably want to use `protect_from_forgery` to add CSRF
  # protection for your application. But don't forget to exempt
  # your webhook route!
  protect_from_forgery except: :webhook

  def webhook
    # Process webhook data in `params`
  end
end
```

### Recibe eventos con un servidor HTTPS

Si usas una URL HTTPS para tu punto de conexión de webhooks (obligatorio en modo activo), Stripe validará que la conexión con tu servidor sea segura antes de enviar tus datos de webhook. Para que esto funcione, tu servidor debe estar configurado correctamente de manera de admitir HTTPS con un certificado de servidor válido. Los webhooks de Stripe solo admiten versiones v1.2 y v1.3 de *TLS* (TLS refers to the process of securely transmitting data between the client—the app or browser that your customer is using—and your server. This was originally performed using the SSL (Secure Sockets Layer) protocol).

### Cambia los secretos de firma del punto de conexión periódicamente

El secreto utilizado para verificar que los eventos provienen de Stripe se puede modificar en la pestaña **Webhooks** de Workbench. Para mantenerlos seguros, te recomendamos que cambies los secretos periódicamente o cuando sospeches que un secreto está en peligro.

Para cambiar un secreto:

1. Haz clic en cada punto de conexión de la pestaña **Webhooks** de Workbech para el que desees aplicar el secreto.
1. Ve al menú de contenido adicional (⋯) y haz clic en **Cambiar secreto**. Puedes elegir que el secreto actual venza de inmediato o postergar su vencimiento hasta 24&nbsp;horas para tener tiempo de actualizar el código de verificación en tu servidor. Durante este lapso, habrá varios secretos activos para el punto de conexión. Stripe genera una firma por secreto hasta su vencimiento.

### Verifica que los eventos provengan de Stripe

Sin verificación, un atacante podría enviar eventos de webhook falsos a tu punto de conexión para desencadenar acciones como completar pedidos, conceder acceso a cuentas o modificar registros. Verifica siempre que los eventos de webhook proceden de Stripe antes de realizar cualquier acción.

Usa estas dos protecciones:

- **Lista de IP permitidas**: Stripe envía eventos de webhook desde una lista definida de [direcciones IP](https://docs.stripe.com/ips.md). Configura tu servidor o firewall para que solo acepte solicitudes de webhook procedentes de estas direcciones.
- **Verificación de firma**: Stripe firma cada evento de webhook incluida una firma en el encabezado `Stripe-Signature`. Verifica esta firma con nuestras [bibliotecas oficiales](https://docs.stripe.com/webhooks.md#verify-official-libraries) o [manualmente](https://docs.stripe.com/webhooks.md#verify-manually) para confirmar que el evento no haya sido enviado o modificado por un tercero.

En la siguiente sección se describe cómo verificar las firmas de webhooks:

1. Recupera el secreto de tu punto de conexión.
1. Verifica la firma.

#### Cómo recuperar el secreto de tu punto de conexión

Utilice Workbench y vaya a la pestaña **Webhooks** para ver todos sus puntos de conexión. Seleccione un punto de conexión del que desee obtener el secreto y haga clic en **Hacer clic para revelar**.

Stripe genera un secreto único para cada punto de conexión. Si usas el mismo punto de conexión para las [claves de API de prueba y activas](https://docs.stripe.com/keys.md#test-live-modes), el secreto será diferente para cada una. Además, si usas varios puntos de conexión, deberás obtener un secreto para cada uno en el que quieras verificar las firmas. Después de esta configuración, Stripe comenzará a firmar cada webhook que envía al punto de conexión.

### Cómo prevenir ataques de reproducción

Un [ataque de reproducción](https://en.wikipedia.org/wiki/Replay_attack) se produce cuando un atacante intercepta una carga válida y su firma, y luego la vuelve a transmitir. Para mitigar estos ataques, Stripe incluye una marca de tiempo en el encabezado `Stripe-Signature`. Dado que esta marca de tiempo forma parte de la carga firmada, también se verifica mediante la firma, por lo que un atacante no puede cambiar la marca de tiempo sin invalidar la firma. Si la firma es válida, pero la marca de tiempo es demasiado antigua, puedes hacer que tu aplicación rechace la carga.

De manera predeterminada, nuestras bibliotecas tienen una tolerancia de 5 minutos entre la marca de tiempo y la hora actual. Proporciona un parámetro adicional al verificar las firmas para modificar esta tolerancia. Usa el protocolo de tiempo de redes ([NTP](https://en.wikipedia.org/wiki/Network_Time_Protocol)) para garantizar que el clock de tu servidor sea preciso y esté sincronizado con la hora de los servidores de Stripe.

> No uses un valor de tolerancia `0`. El uso de un valor de tolerancia `0` deshabilita por completo la comprobación reciente.

Stripe genera la marca de tiempo y la firma cada vez que enviamos un evento a tu punto de conexión. Si Stripe reintenta un evento (por ejemplo, porque el punto de conexión envió un código de estado que no es `2xx`), se generan una firma y una marca de tiempo nuevas para el nuevo intento de entrega.

### Devuelve rápidamente una respuesta 2xx

Tu [punto de conexión](https://docs.stripe.com/webhooks.md#example-endpoint) debe devolver de inmediato un código de estado correcto (`2xx`) antes de que alguna lógica compleja pueda provocar un error de tiempo de espera agotado. Por ejemplo, debes devolver una respuesta `200` antes de registrar la factura del cliente como pagada en tu sistema contable.

## See also

- [Envia eventos a Amazon EventBridge](https://docs.stripe.com/event-destinations/eventbridge.md)
- [Enviar eventos a Azure Event Grid](https://docs.stripe.com/event-destinations/eventgrid.md)
- [Lista de tipos de eventos ligeros](https://docs.stripe.com/api/v2/core/events/event-types.md)
- [Lista de tipos de eventos con instantánea](https://docs.stripe.com/api/events/.md)
- [Generador interactivo de puntos de conexión de webhooks](https://docs.stripe.com/webhooks/quickstart.md)
