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

# Webhooks en la Buyer API

> Recibe en tu propio endpoint los eventos de orden de trabajo creada, cambio de estado y nueva nota, en lugar de sondear la Buyer API de OpenWrench.

Los webhooks envían tres eventos de orden de trabajo a un endpoint HTTPS de tu propiedad: se creó una orden de trabajo, cambió su estado o se le añadió una nota. Cada entrega te dice qué orden de trabajo cambió y qué ocurrió. Tu integración luego obtiene la orden de trabajo a través de la API. Eso convierte a los webhooks en el disparador natural de una integración de despacho: reacciona a `workorder.create` y `workorder.status_update` en el momento en que ocurren, y conserva el [sondeo](/es/buyer-api/work-orders#juntándolo-todo) solo como respaldo de conciliación.

## Configurar un endpoint

Los endpoints se registran por empresa compradora y cubren todas sus ubicaciones e instalaciones. Todavía no hay una API de autoservicio para esto: escribe a [support@useopenwrench.com](mailto:support@useopenwrench.com) con

* la URL HTTPS que debe recibir las entregas,
* cuáles de los tres eventos quieres (`workorder.create`, `workorder.status_update`, `workorder.new_note`), y
* si el endpoint es de pruebas o de producción.

Soporte registra el endpoint en la pasarela de webhooks de OpenWrench y te devuelve el secreto de firma que usarás para [verificar las entregas](#verificar-las-entregas). Puedes registrar varios endpoints, por ejemplo una URL por tipo de evento, o la misma URL para los tres.

## Eventos

| `event_type`              | Se dispara cuando                                                      |
| ------------------------- | ---------------------------------------------------------------------- |
| `workorder.create`        | Se crea una orden de trabajo en tu empresa.                            |
| `workorder.status_update` | El `status` de una orden de trabajo cambia de valor.                   |
| `workorder.new_note`      | Se añade una nota al hilo comprador–proveedor de una orden de trabajo. |

Algunos detalles de cada uno:

* **`workorder.create`** se dispara en cada creación, sin importar quién la haga: tu propio `POST /v1/buyer/work_order/work_orders`, un usuario en las apps web o móviles de OpenWrench, un cronograma de mantenimiento preventivo, un recorrido de encuesta de sitio, o un proveedor que abre una orden de trabajo en una de tus ubicaciones (`SupplierInitiatedPendingApproval`). El payload lleva el estado inicial, así que puedes distinguir una solicitud de servicio pendiente de aprobación de una orden de trabajo despachada al crearse.
* **`workorder.status_update`** se dispara en cada transición del [modelo de estados](/es/buyer-api/work-orders#el-modelo-de-estados), para estados propiedad de cualquiera de los dos lados. Las ediciones que no tocan `status` (un cambio de prioridad, una nueva fecha estimada de finalización, una reasignación mientras la orden sigue pendiente de confirmación) no emiten uno. Cuando una orden de trabajo pasa de un proveedor a otro puedes recibir una actualización intermedia cuyo `newStatus` es `Rejected`, que cierra la asignación anterior, seguida de la actualización con el estado nuevo.
* **`workorder.new_note`** se dispara para las notas del hilo raíz comprador–proveedor de cualquiera de los dos lados, incluidas las notas publicadas por tu propia integración, las publicaciones masivas de fotos y la nota adjunta a una acción de estado. Las notas internas de los proveedores y los hilos de subcontratación nunca emiten eventos.

Recibes eventos por los cambios que hace tu propia integración. Si replicas órdenes de trabajo en otro sistema, lleva un registro de las escrituras que hiciste y omite los eventos correspondientes, o trata cada evento como una señal para volver a obtener y comparar.

## Payload de la entrega

Cada entrega es un `POST` HTTP con cuerpo JSON. El cuerpo tiene dos campos: `event_type` y `data`.

### Eventos de creación y de estado

```json theme={null}
{
  "event_type": "workorder.status_update",
  "data": {
    "workOrderId": 9001,
    "location": "Store 1204 - Denver",
    "oldStatus": "TechScheduled",
    "newStatus": "WaitingForReview",
    "changedBy": "Sam Rivera",
    "changedAt": "2026-08-21T09:05:22.000-07:00"
  }
}
```

| Campo         | Notas                                                                                           |
| ------------- | ----------------------------------------------------------------------------------------------- |
| `workOrderId` | El `id` numérico de la orden de trabajo. Úsalo con `GET /v1/buyer/work_order/work_orders/{id}`. |
| `location`    | El nombre para mostrar de la ubicación.                                                         |
| `oldStatus`   | El estado anterior. Ausente en `workorder.create`.                                              |
| `newStatus`   | El estado actual, o el estado inicial en `workorder.create`.                                    |
| `changedBy`   | Nombre para mostrar de la persona o el sistema que hizo el cambio.                              |
| `changedAt`   | Marca de tiempo ISO 8601 con desfase horario.                                                   |

`workorder.create` usa la misma forma de `data` sin `oldStatus`.

### Eventos de nota

```json theme={null}
{
  "event_type": "workorder.new_note",
  "data": {
    "workOrderId": 9001,
    "newNote": "Access code for the back door is 4417.",
    "addedBy": "Sam Rivera",
    "addedAt": "2026-08-21T09:05:22.000-07:00"
  }
}
```

| Campo            | Notas                                                                                      |
| ---------------- | ------------------------------------------------------------------------------------------ |
| `workOrderId`    | El `id` numérico de la orden de trabajo.                                                   |
| `newNote`        | El texto de la nota. Vacío en las notas que solo llevan foto.                              |
| `photo`, `video` | URL del medio adjunto a la nota, cuando existe.                                            |
| `photos`         | Presente en las publicaciones masivas de fotos: todas las URL de fotos del lote, en orden. |
| `addedBy`        | Nombre para mostrar del autor.                                                             |
| `addedAt`        | Marca de tiempo ISO 8601 con desfase horario.                                              |

El payload no incluye el resto del hilo. Léelo con `GET /v1/buyer/work_order/work_order_notes/{woId}` si necesitas contexto.

## Verificar las entregas

Cada entrega va firmada. La pasarela calcula un HMAC sobre el cuerpo crudo de la petición con el secreto de firma de tu endpoint y lo envía en una cabecera de firma. Cuando soporte registra tu endpoint te entrega el secreto, el nombre de la cabecera y el algoritmo de hash. Verifica la firma contra los bytes crudos del cuerpo antes de parsearlo, y rechaza cualquier cosa que no coincida. Como el secreto es por endpoint, rotarlo es una solicitud a soporte: pide un secreto nuevo, despliégalo y luego pide a soporte que cambie el endpoint.

## Respuesta, reintentos y duplicados

* **Confirma rápido.** Devuelve un `2xx` en cuanto hayas almacenado el evento, y haz el trabajo posterior (obtener la orden de trabajo, actualizar tu sistema) de forma asíncrona. Una respuesta distinta de `2xx` o un tiempo de espera agotado cuentan como entrega fallida.
* **Las entregas fallidas se reintentan** desde la pasarela con un esquema de espera creciente. Haz que tu manejador sea idempotente para que un reintento tras un éxito parcial no cause daño.
* **Las entregas son al menos una vez.** El mismo evento puede llegar más de una vez incluso sin un fallo de tu lado. Deduplica con `event_type` más `workOrderId` más `changedAt` (o `addedAt` para las notas).
* **El orden no está garantizado.** Dos eventos de la misma orden de trabajo pueden llegar desordenados. No derives el estado de la secuencia de eventos; obtén la orden de trabajo y confía en su `status`.
* **Los eventos antiguos se descartan, no se entregan tarde.** Un evento que no se haya pasado a la pasarela dentro de las tres horas siguientes al cambio se descarta. Tras una interrupción del lado de OpenWrench, o si tu endpoint estuvo caído más tiempo que la ventana de reintentos, concilia sondeando `GET /v1/buyer/work_order/work_orders?statusChangedAt=...` para el periodo que te perdiste.

## Reaccionar a un evento

El manejador recomendado es pequeño: verificar, almacenar, confirmar y luego obtener.

```bash theme={null}
# Obtener la orden de trabajo indicada en el evento
curl -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  "$BASE/v1/buyer/work_order/work_orders/9001"
```

Las lecturas de la API externa se sirven desde una réplica de lectura, así que una orden de trabajo creada hace un instante puede volver vacía brevemente. Reintenta la obtención tras un segundo antes de darla por inexistente. La obtención cuenta contra el [límite de tasa](/es/buyer-api/introduction#límites-de-tasa), así que agrupa las ráfagas de eventos de la misma orden de trabajo en una sola obtención.

## Juntándolo todo

Una integración de despacho impulsada por webhooks:

1. Registra un endpoint para `workorder.create` y `workorder.status_update` (añade `workorder.new_note` si replicas la conversación).
2. En `workorder.create`, obtén la orden de trabajo y crea el registro correspondiente en tu sistema. Si despachas desde tu lado, haz `PATCH` del `supplierFacilityId` como se describe en [Órdenes de trabajo](/es/buyer-api/work-orders#reasignar-un-proveedor).
3. En `workorder.status_update`, obtén la orden de trabajo. Cuando `newStatus` sea `WaitingForReview`, ejecuta tu flujo de revisión y publica `work_reviewed_and_completed` o `work_unsatisfactory`.
4. Ejecuta un sondeo periódico sobre `statusChangedAt` como red de seguridad para cualquier cosa que la ruta de webhooks haya perdido.
