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

# Payloads de Eventos de Webhook

> La estructura de cada payload de webhook — los campos de la envoltura, cómo el campo sequence ordena los eventos y cómo applicationId delimita cada evento.

Cada entrega de webhook lleva un cuerpo JSON con la misma estructura de envoltura, sin importar el tipo de evento. Esta página explica cada campo y los dos más importantes de manejar correctamente en tu integración: `sequence` y `applicationId`.

## La envoltura

```json theme={"dark"}
{
  "id": "event_01HXPA3M9R7DEF456",
  "type": "transfer.succeeded",
  "apiVersion": "v2",
  "originalCreateDate": "2026-08-07T14:05:30.000Z",
  "livemode": true,
  "sequence": 5,
  "data": {
    "id": "payout_d243ab2b1de4447d8a046d87fefe58cf",
    "type": "transfer",
    "applicationId": "application_1324354657",
    "customerId": "customer_f31121c389624d3697cbf3ea8830b7a4",
    "transferType": "oneTimeTransfer",
    "previousStatus": "processing",
    "previousStatusAt": "2026-08-07T14:02:15.000Z",
    "status": "succeeded",
    "statusAt": "2026-08-07T14:05:30.000Z",
    "cause": null
  }
}
```

| Campo                | Descripción                                                                                                                                                                                                                                                                                                |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                 | Identificador único del evento (prefijo `event_`). Estable a través de cada entrega y reenvío del mismo evento — úsalo como tu clave de idempotencia.                                                                                                                                                      |
| `type`               | El nombre del evento del [catálogo de eventos](/es/concepts/webhooks/event-catalog), p. ej. `customer.approved`.                                                                                                                                                                                           |
| `apiVersion`         | La versión del esquema del evento (actualmente `v2`). Es distinto del `apiVersion` con fecha que configuras en el endpoint de webhook.                                                                                                                                                                     |
| `originalCreateDate` | Marca de tiempo ISO 8601 de cuándo ocurrió originalmente el cambio de estado del recurso que desencadenó este evento. Nunca cambia, ni siquiera en los reenvíos — a diferencia del encabezado `Sphere-Timestamp`, que refleja cuándo se envió cada intento de entrega.                                     |
| `livemode`           | `true` para eventos de producción, `false` para eventos en modo de prueba.                                                                                                                                                                                                                                 |
| `sequence`           | Entero monotónicamente creciente que se usa para ordenar los eventos de un recurso. Consulta [más abajo](#el-campo-sequence).                                                                                                                                                                              |
| `data`               | El sujeto del evento: el ID del recurso, su `applicationId`, el estado anterior, el nuevo estado y un campo `cause` reservado para razones de fallo (actualmente siempre `null`). Los campos varían ligeramente según el recurso — consulta el [catálogo de eventos](/es/concepts/webhooks/event-catalog). |

El cuerpo es idéntico byte por byte a través de cada entrega y reenvío del mismo evento. Todo lo que varía por intento de entrega — el ID de entrega, el contador de intentos, la marca de tiempo, la firma — vive en su lugar en los [encabezados HTTP](/es/concepts/webhooks/verifying-signatures).

## Eventos, entregas e intentos

Tres registros distintos están detrás de cada webhook que te llega, y cada uno lleva su propio identificador y sus propias marcas de tiempo. Mantenerlos claros es la clave para reconciliar las distintas marcas de tiempo y la lógica de `sequence` que se explica a continuación.

| Registro               | Qué es                                                                                                      | Identificador                                                                                                 | Marcas de tiempo                                                                                                                                        | Dónde lo ves                                                                        |
| ---------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| **Evento**             | El hecho inmutable de que algo sucedió. Uno por ocurrencia, compartido por cada endpoint que lo recibe.     | `id` en el cuerpo (`event_...`)                                                                               | `originalCreateDate` — cuándo ocurrió originalmente el cambio de estado del recurso que desencadenó el evento. Nunca cambia, ni siquiera en un reenvío. | El cuerpo del payload; [`GET /v2/events`](/es/concepts/webhooks/events-and-replays) |
| **Entrega de evento**  | El enrutamiento de un evento a un endpoint. Dos endpoints suscritos producen dos entregas del mismo evento. | Encabezado `Sphere-Delivery-Id` (`eventDelivery_...`)                                                         | `deliveredAt` — cuándo tu endpoint confirmó con un `2xx`.                                                                                               | Los encabezados; el objeto `delivery` en la API de Eventos                          |
| **Intento de entrega** | Una única solicitud HTTP a tu endpoint — el envío original o un reenvío manual.                             | Contador `Sphere-Delivery-Attempt` y encabezado `Sphere-Delivery-Type`; `attempts[]` en el detalle del evento | Encabezado `Sphere-Timestamp` / `attemptedAt` — cuándo se envió esta solicitud en particular. Nuevo en cada intento.                                    | Los encabezados; [`GET /v2/events/{id}`](/es/concepts/webhooks/events-and-replays)  |

La división sigue una sola regla: todo lo intrínseco al **evento** — `id`, `type`, `sequence`, `originalCreateDate`, `data` — vive en el cuerpo y nunca cambia; todo lo que describe **esta solicitud HTTP en particular** — ID de entrega, número de intento, tipo de intento, marca de tiempo, firma — vive en los encabezados y se regenera en cada intento.

<Warning>
  Al ordenar el estado de negocio, confía en el evento, nunca en el intento. Un reenvío de un evento antiguo llega con un `Sphere-Timestamp` nuevo (por lo que pasa las verificaciones de tolerancia de firma), pero su `sequence` y `originalCreateDate` siguen reflejando cuándo ocurrió realmente el cambio de estado. Ordenar por `Sphere-Timestamp` haría que un evento antiguo reenviado pareciera más nuevo que los eventos que lo superaron — ordenar por `sequence` mantiene los reenvíos inofensivos.
</Warning>

## Los payloads llevan el cambio de estado, no el recurso completo

Los payloads de webhook contienen deliberadamente lo mínimo que necesitas para reaccionar: el ID del recurso y la transición de `previousStatus` a `status`. **No** contienen el objeto del recurso completo.

La mayoría de las reacciones — enrutar según el nuevo estado, actualizar la fila en tu propia base de datos, notificar a tu equipo de operaciones — funcionan solo con el payload. Cuando necesites el recurso completo (criterios de verificación completos, detalles de cuenta bancaria, montos de transferencia), recupéralo del endpoint `GET` del recurso:

```bash theme={"dark"}
# The payload told you payout_d243... succeeded; fetch the full object:
curl https://api.spherepay.co/v2/transfer/payout_d243ab2b1de4447d8a046d87fefe58cf \
  -H "Authorization: Bearer {{api_key}}"
```

<Tip>
  Debido a que el payload es mínimo e inmutable, un evento reenviado nunca lleva datos obsoletos que pretendan ser recientes — describe una transición que ocurrió en `originalCreateDate`. Si siempre haces un `GET` del recurso para obtener su estado actual antes de actuar sobre los efectos secundarios, los reenvíos son inofensivos.
</Tip>

## El campo `sequence`

`sequence` es un entero monotónicamente creciente **delimitado a una única instancia de recurso** — un contador por cliente, uno por transferencia, y así sucesivamente, identificado por `data.id`. Se asigna cuando se crea el evento y nunca cambia, por lo que refleja el orden real en que ocurrieron los cambios de estado incluso cuando las entregas llegan fuera de orden.

Debido a que el orden de entrega no está garantizado, usa `sequence` para protegerte contra actualizaciones obsoletas:

1. Almacena el `sequence` más alto que hayas procesado **por instancia de recurso** — por ejemplo, una columna `lastSphereSequence` en la fila del cliente en tu propia base de datos.
2. Cuando llegue un evento, compara su `sequence` con el valor almacenado para ese `data.id`.
3. Si `incoming.sequence <= stored.sequence`, el evento es obsoleto o un duplicado — confirma con un `2xx` y omite la actualización.
4. De lo contrario, aplica la actualización y almacena el nuevo `sequence`.

No necesitas un contador global en toda tu cuenta — solo seguimiento por entidad, ubicado junto al estado del recurso que ya mantienes.

<Note>
  No asumas que los valores de sequence que recibes son contiguos. Si tu endpoint se suscribe a un subconjunto de los eventos de un recurso, observarás brechas — usa la comparación de obsolescencia `<=` de arriba, nunca detección de brechas.
</Note>

### ¿Por qué tanto `sequence` como `originalCreateDate`?

Responden preguntas diferentes. `originalCreateDate` te dice **cuándo** ocurrió un cambio de estado — tiempo de reloj, útil para visualización, registros de auditoría y consultas por ventana de tiempo. Pero el tiempo de reloj es una clave de *ordenamiento* poco confiable: dos transiciones rápidas en el mismo recurso pueden caer tan cerca una de otra que sus marcas de tiempo colisionan, y una comparación de marcas de tiempo no tiene forma de romper el empate. `sequence` existe para hacer que el ordenamiento sea inequívoco — un entero estrictamente creciente por instancia de recurso, de modo que dos eventos cualesquiera del mismo recurso siempre tienen un orden definido, sin importar qué tan cerca ocurrieron.

Regla general: **ordena y deduplica por `sequence`; visualiza y audita por `originalCreateDate`.**

## El campo `applicationId`

Cada payload incluye `data.applicationId` — la aplicación de SpherePay a la que pertenece el evento. Los endpoints de webhook se registran por aplicación, y los eventos solo se entregan para recursos que pertenecen a la aplicación del endpoint.

Esto importa sobre todo cuando operas **múltiples aplicaciones de SpherePay que comparten una misma URL receptora de webhooks**. Registrar la misma URL bajo dos aplicaciones es perfectamente válido — pero tu handler entonces recibe eventos de ambas, y el endpoint de cada aplicación tiene su propio secreto de firma. Usa `applicationId` para enrutar cada evento al contexto de aplicación correcto en tu sistema (y para seleccionar el secreto correcto al verificar firmas).

<Tip>
  Puedes encontrar el ID de cada aplicación en la página de **Settings** del dashboard de integradores de SpherePay.
</Tip>
