Skip to main content

POST /api/webhooks/stripe

Endpoint para recibir y procesar webhooks de Stripe relacionados con suscripciones, pagos y eventos de facturación.
Este endpoint es exclusivamente para uso de Stripe. No debe ser llamado directamente por aplicaciones cliente.

Autenticación

No usa autenticación Bearer tradicional. Stripe autentica las solicitudes usando:
  • Header stripe-signature con la firma del webhook
  • Verificación mediante STRIPE_WEBHOOK_SECRET configurado en el servidor

Headers Requeridos

stripe-signature
string
required
Firma criptográfica generada por Stripe para verificar la autenticidad del webhook.
content-type
string
required
Debe ser application/json. Stripe envía el body en formato JSON.

Body

El body es un objeto de evento de Stripe con la siguiente estructura:
id
string
required
ID único del evento de Stripe (ej: evt_1234567890).
type
string
required
Tipo de evento. Eventos soportados:
  • checkout.session.completed - Pago de suscripción completado
  • customer.subscription.updated - Suscripción actualizada
  • customer.subscription.deleted - Suscripción cancelada
  • invoice.payment_succeeded - Pago mensual exitoso
  • invoice.payment_failed - Pago mensual fallido
data
object
required
Objeto que contiene los datos del evento según su tipo.

Eventos Procesados

checkout.session.completed

Se ejecuta cuando un usuario completa el pago exitosamente. Crea o actualiza la suscripción en la base de datos. Datos requeridos en metadata:
  • userId - UUID del usuario
  • plan - Plan contratado: BASIC, PRO, o ENTERPRISE
  • promotionCodeId (opcional) - ID del código promocional usado

customer.subscription.updated

Se ejecuta cuando una suscripción se actualiza (cambio de plan, renovación, etc.). Actualiza:
  • Plan actual
  • Precio
  • Estado de la suscripción
  • Fechas del período actual

customer.subscription.deleted

Se ejecuta cuando una suscripción es cancelada. Acciones:
  • Marca la suscripción como CANCELLED
  • Crea automáticamente una suscripción FREE para el usuario

invoice.payment_succeeded

Se ejecuta cuando un pago mensual es exitoso. Actualiza:
  • Fechas del período actual
  • Estado a ACTIVE

invoice.payment_failed

Se ejecuta cuando un pago falla. Actualiza:
  • Estado a PAST_DUE

Response

received
boolean
Siempre true si el webhook fue recibido.
warning
string
Mensaje de advertencia si el webhook secret no está configurado (solo en desarrollo).

Códigos de Estado

  • 200 - Webhook procesado exitosamente
  • 400 - Falta header stripe-signature o firma inválida
  • 500 - Error al procesar el webhook
curl --request POST \
  --url 'https://api.contafy.com/api/webhooks/stripe' \
  --header 'stripe-signature: t=1678886400,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd' \
  --header 'Content-Type: application/json' \
  --data '{
    "id": "evt_1234567890abcdef",
    "type": "checkout.session.completed",
    "data": {
      "object": {
        "id": "cs_test_1234567890",
        "mode": "subscription",
        "customer": "cus_1234567890",
        "subscription": "sub_1234567890",
        "metadata": {
          "userId": "123e4567-e89b-12d3-a456-426614174000",
          "plan": "PRO"
        }
      }
    }
  }'
{
  "received": true
}

Configuración

Para configurar este webhook en Stripe:
  1. Ve a Stripe Dashboard → Developers → Webhooks
  2. Haz clic en “Add endpoint”
  3. URL del endpoint: https://api.contafy.com/api/webhooks/stripe
  4. Selecciona los eventos a escuchar:
    • checkout.session.completed
    • customer.subscription.updated
    • customer.subscription.deleted
    • invoice.payment_succeeded
    • invoice.payment_failed
  5. Copia el “Signing secret” y configúralo como STRIPE_WEBHOOK_SECRET en las variables de entorno

Auditoría

Todos los eventos recibidos se registran en la tabla PaymentEvent con:
  • stripe_event_id - ID del evento
  • stripe_event_type - Tipo de evento
  • event_data - Datos completos del evento
  • processed_at - Fecha y hora de procesamiento
Esto permite auditoría y re-procesamiento de eventos si es necesario.

Build docs developers (and LLMs) love