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

# Órdenes de trabajo en la Buyer API

> Crea, lista, filtra, reasigna y cierra órdenes de trabajo con la Buyer API de OpenWrench, incluidas acciones de estado, notas, etiquetas y tipos de problema.

Las órdenes de trabajo son el centro de la Buyer API. Esta guía cubre la superficie completa bajo `/v1/buyer/work_order/`: creación de órdenes de trabajo, consulta, acciones de estado del lado del comprador, el hilo de notas, las etiquetas y los tipos de problema.

Todos los ejemplos asumen estas variables de shell:

```bash theme={null}
export BASE="https://api.useopenwrench.com/api/external"
export KEY="<your-api-key>"        # X-API-KEY header
export SECRET="<shared-secret>"    # OW-KEY header
```

## El objeto orden de trabajo

Una orden de trabajo devuelta por la API lleva, entre otros campos:

| Campo                                                                | Notas                                                                                                                                                         |
| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                                                                 | Id numérico usado por todos los demás endpoints.                                                                                                              |
| `title`, `description`                                               | Qué hay que hacer. `descriptionNonFormatted` es la variante en texto plano.                                                                                   |
| `status`, `displayStatus`                                            | `status` es el estado fino de máquina (ver [el modelo de estados](#el-modelo-de-estados)); `displayStatus` es la etiqueta más gruesa que se muestra en la UI. |
| `locationId`, `assetId`, `subAssetIds`, `areaId`                     | Dónde ocurre el trabajo y sobre qué.                                                                                                                          |
| `problemTypeId`, `workCategoryId`, `spendCategoryId`, `woPriorityId` | Clasificación.                                                                                                                                                |
| `supplierFacilityId`, `supplierPrimaryContactEmail`                  | El proveedor asignado, una vez despachada.                                                                                                                    |
| `nte`, `price`, `currencyId`                                         | Monto not-to-exceed y precios.                                                                                                                                |
| `scheduledAt`, `estimatedCompletionDate`, `dueDate`, `completedAt`   | Fechas clave.                                                                                                                                                 |
| `notes`, `lastNote`, `lastNoteAddedBy`, `lastNoteAddedAt`            | El hilo de notas comprador-proveedor. `lastNoteAddedAt` está en milisegundos desde epoch.                                                                     |
| `associatedServiceCalls`, `lastServiceCall`                          | Visitas registradas por el proveedor. Ver [Llamadas de servicio](/es/buyer-api/service-calls).                                                                |
| `statusChanges`                                                      | Historial completo de estados.                                                                                                                                |
| `buyerAttachments`, `supplierAttachments`                            | Referencias a archivos. Ver [Archivos y adjuntos](/es/buyer-api/files-and-attachments).                                                                       |
| `isPM`, `plannedMaintenanceScheduleId`                               | Se establecen cuando la orden de trabajo fue generada desde un cronograma de PM.                                                                              |
| `walkThroughId`                                                      | Se establece cuando la orden de trabajo salió de un recorrido de encuesta de sitio.                                                                           |

## Crear una orden de trabajo

`POST /v1/buyer/work_order/work_orders` requiere más que los campos obvios. A diferencia de la mayoría de endpoints del comprador, **`buyerFacilityId`, `buyerCompanyId` y `createdBy` deben suministrarse en el cuerpo**; no se derivan de tu clave de API en este endpoint. Usa [`GET /v1/buyer/me`](/es/buyer-api/account-and-utilities) para consultar tus ids de empresa e instalación una vez y cachéalos.

Campos requeridos: `title`, `locationId`, `problemTypeId`, `buyerFacilityId`, `buyerCompanyId` y `createdBy` (el correo del contacto que crea).

```bash theme={null}
curl -X POST "$BASE/v1/buyer/work_order/work_orders" \
  -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Walk-in cooler not holding temperature",
    "description": "Temp reading 48F, product at risk.",
    "locationId": 1204,
    "assetId": 5511,
    "problemTypeId": 17,
    "woPriorityId": 3,
    "nte": 500,
    "buyerFacilityId": 88,
    "buyerCompanyId": 12,
    "createdBy": "ops@example.com",
    "supplierFacilityId": 3021
  }'
```

Comportamiento a conocer:

* **Estado inicial.** Si se omite `status`, el estado inicial se calcula a partir de la configuración de tu empresa. Las solicitudes de servicio típicamente empiezan en `PendingApproval`; las órdenes de trabajo por defecto en `Unassigned`. Si pasas un `status`, aún se resuelve contra la configuración de la empresa, así que el estado efectivo puede diferir del que enviaste.
* **Despachar al crear.** Pasar `supplierFacilityId` asigna el proveedor de inmediato. Un `supplierFacilityId`, `assetId` o `problemTypeId` desconocido se rechaza con `400`.
* **Subactivos.** `subAssetIds` es un arreglo opcional de ids de subactivos que se adjuntan junto al `assetId` principal. Los subactivos son activos creados con un `parentId`; ver [Activos](/es/buyer-api/assets-and-locations#activos).
* **Flag de aprobación.** El campo es `needApproval`, no `needsApproval`. El objeto de respuesta usa `needsApproval`; la solicitud de creación no.
* **Enlace a recorrido.** `walkThroughId` y `siteSurveyTaskTitleId` deben suministrarse juntos o no suministrarse. Ver [Recorridos de encuesta de sitio](/es/buyer-api/site-survey-walkthroughs).
* **Upserts.** Pasar un `id` actualiza esa orden de trabajo existente en lugar de crear una nueva.

## Listar, filtrar y contar

```bash theme={null}
# Órdenes de trabajo más recientes de una ubicación
curl -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  "$BASE/v1/buyer/work_order/work_orders?locationId=1204&limit=25&sort_by=createdAt&order=desc"

# Cuántas coinciden, sin traerlas
curl -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  "$BASE/v1/buyer/work_order/work_orders/count_by?locationId=1204"
```

Los endpoints de listado aceptan `offset`, `limit` (por defecto 10, máx. 25), `sort_by` y `order`. Cualquier otro parámetro de consulta se trata como un filtro de campo; separa un valor por coma para coincidir con cualquiera de varios (`status=Unassigned,PendingApproval`). Los filtros siempre se combinan con el alcance por inquilino derivado de tu clave, así que solo verás las órdenes de trabajo de tu empresa.

El listado y el conteo resuelven qué órdenes de trabajo coinciden en el índice de búsqueda de OpenWrench y luego cargan los registros completos desde la base de datos. Eso cambia algunos comportamientos:

* **Búsqueda de texto completo.** `search=` coincide con palabras (con coincidencia por prefijo y por raíz) en el título, la descripción, el nombre de la ubicación, las notas, las notas de check-in y check-out de las llamadas de servicio, y el nombre del tipo de problema. También coincide con números de referencia como el número de orden de trabajo, el número de PO y el número de serie del activo. Pon el valor entre comillas (`search="walk-in cooler"`) para exigir la frase exacta.
* **Los filtros de activo incluyen los subactivos.** `assetId=` y `assetIds=` coinciden con órdenes de trabajo cuyo activo principal *o* cualquiera de sus subactivos es el id dado.
* **Ordenamiento.** `sort_by` admite `createdAt`, `locationName`, `woPriority` (por el tiempo de resolución esperado de la prioridad) y `lastServiceCallServiceScheduledAt`. Cualquier otro valor, o la ausencia de `sort_by`, ordena por `createdAt` descendente.
* **Los filtros no indexados se ignoran.** `updatedAtStartDate`, `updatedAtEndDate`, `buyerFacilityId` y `walkthroughId` no están en el índice de búsqueda y ya no estrechan los resultados. Filtra en su lugar por ventanas de `statusChangedAt` u otras columnas indexadas.
* **Frescura.** Las actualizaciones del índice de búsqueda y de la réplica van un momento por detrás de las escrituras, así que una orden de trabajo creada hace milisegundos puede estar brevemente ausente de los resultados de listado y de los conteos.
* **Profundidad de paginación.** `offset + limit` no puede exceder la ventana de resultados de búsqueda de 10.000. Estrecha el filtro en lugar de paginar tan profundo.

El endpoint de conteo ejecuta la misma consulta del índice de búsqueda que el listado, así que un conteo siempre concuerda con el listado que describe.

Obtén una orden de trabajo con `GET /v1/buyer/work_order/work_orders/{id}`.

<Warning>
  **Usa el listado para consultar, no para vigilar cambios.** Si tu integración necesita saber cuándo se crean órdenes de trabajo, cambian de estado o reciben una nota nueva, registra un [webhook](/es/buyer-api/webhooks). Obtén por id la orden de trabajo nombrada en cada evento. Sondear el endpoint de listado según un cronograma es lento en cuentas grandes, gasta tu límite de tasa y aun así pierde los cambios entre sondeos. Reserva las llamadas de listado para consultas puntuales, la carga inicial única y una conciliación ocasional con filtros estrechos (ventana de `statusChangedAt`, `limit` pequeño).
</Warning>

## Reasignar un proveedor

`PATCH /v1/buyer/work_order/work_orders/{id}` es deliberadamente estrecho: **solo `supplierFacilityId` y `supplierPrimaryContactEmail` se leen del cuerpo**. Cualquier otro campo que envíes se ignora silenciosamente en lugar de rechazarse.

```bash theme={null}
curl -X PATCH "$BASE/v1/buyer/work_order/work_orders/9001" \
  -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "supplierFacilityId": 3055, "supplierPrimaryContactEmail": "dispatch@newsupplier.com" }'
```

Dos trampas:

* `supplierPrimaryContactEmail` solo aplica como parte de una reasignación. Enviarlo sin un cambio de instalación de proveedor hace que todo el patch sea un no-op: nada se persiste y se devuelve la orden de trabajo actual.
* Un id inexistente y una denegación de permiso devuelven la misma respuesta `400` unauthorized, así que no uses este endpoint para sondear si una orden de trabajo existe.

Para elegir el proveedor correcto de forma programática, consulta [Red de proveedores](/es/buyer-api/supplier-network), que cubre el endpoint jerarquizado de red privada.

## Acciones de estado del comprador

Cuatro endpoints dedicados mueven una orden de trabajo por las partes del ciclo de vida que son propiedad del comprador. Cada uno toma el mismo cuerpo: el `id` de la orden de trabajo y una `note` opcional que se añade al hilo junto con el cambio de estado.

| Endpoint                                             | Estado resultante          | Efectos secundarios                                                                                                                                                                    |
| ---------------------------------------------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST .../status_update/work_reviewed_and_completed` | `WorkReviewedAndCompleted` | Puede publicar la factura en borrador del proveedor (según la configuración del proveedor) y cumplir las solicitudes de compra enlazadas.                                              |
| `POST .../status_update/cancelled`                   | `CancelledWithReason`      | Se rechaza con `409` mientras un técnico tiene check-in activo, si tu empresa habilita el [bloqueo de cancelación](#bloqueo-de-cancelación-mientras-un-técnico-tiene-check-in-activo). |
| `POST .../status_update/work_unsatisfactory`         | `WorkUnsatisfactory`       | Envía la nota adjunta al proveedor.                                                                                                                                                    |
| `POST .../status_update/reopen`                      | Reabierta                  | Envía la nota adjunta.                                                                                                                                                                 |

```bash theme={null}
curl -X POST "$BASE/v1/buyer/work_order/work_orders/status_update/work_reviewed_and_completed" \
  -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "id": 9001,
    "note": {
      "text": "Verified on site, closing out.",
      "noteAddedBy": "ops@example.com",
      "noteAddedAt": "2026-08-21T09:00:00.000-07:00"
    }
  }'
```

Cada acción de estado devuelve la orden de trabajo actualizada en la envoltura estándar.

### Bloqueo de cancelación mientras un técnico tiene check-in activo

Las empresas pueden optar por un bloqueo de cancelación que mantiene abiertas las órdenes de trabajo mientras un técnico está en sitio. Con el bloqueo habilitado, OpenWrench rechaza cualquier cancelación con `409 Conflict` si un técnico tiene un check-in activo en cualquiera de las llamadas de servicio de la orden de trabajo. Esto cubre las visitas de la propia orden de trabajo y las visitas de sus órdenes de trabajo subcontratadas. OpenWrench bloquea de la misma forma la cancelación de un subcontrato cuyo estado se propaga a la orden de trabajo raíz, y no confirma nada en ninguna de las dos órdenes.

El bloqueo se configura por empresa compradora con dos ajustes:

| Ajuste                             | Predeterminado | Efecto                                                                                                                                                                 |
| ---------------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`                          | `false`        | Activa el bloqueo. Cuando está desactivado (el valor predeterminado), los check-ins nunca bloquean cancelaciones.                                                      |
| `checkInConsideredStaleAfterHours` | `24`           | Un check-in abierto más antiguo que este número de horas se trata como un check-out olvidado, no como trabajo en curso, y deja de bloquear la cancelación por sí solo. |

El mensaje de error `409` identifica al técnico con check-in por su correo cuando la visita lo registró:

```json theme={null}
{
  "message": "You can’t cancel this work order: technician tech@supplier.com is currently checked in."
}
```

Cuando tu integración recibe este `409`, espera a que el técnico haga check-out (o a que el check-in caduque) y reintenta, o pide al proveedor que termine la visita primero. El bloqueo forma parte de la configuración de órdenes de trabajo de tu empresa compradora en OpenWrench.

## El modelo de estados

Valores de `status` que verás y que establecerás a través de la API:

| Estado                                             | Propiedad de | Significado                                                                                                                                                                                                                |
| -------------------------------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Unassigned`                                       | Sistema      | Creada, sin proveedor asignado aún.                                                                                                                                                                                        |
| `PendingApproval`                                  | Comprador    | En espera de aprobación interna, o retornada aquí tras un rechazo del proveedor.                                                                                                                                           |
| `SupplierInitiatedPendingApproval`                 | Comprador    | Un proveedor abrió esta orden de trabajo por su cuenta; espera tu aprobación antes de que el proveedor quede confirmado en ella (se omite cuando tu empresa aprueba automáticamente el trabajo iniciado por el proveedor). |
| `ConfirmedByServiceProvider`                       | Proveedor    | El proveedor aceptó el trabajo.                                                                                                                                                                                            |
| `TechAssigned`, `TechScheduled`, `TechRescheduled` | Proveedor    | Llamada de servicio creada o (re)programada.                                                                                                                                                                               |
| `TechWorkingOnSite`                                | Proveedor    | Técnico hizo check-in.                                                                                                                                                                                                     |
| `PartsRequested`, `PartsOnOrder`, `PartsReceived`  | Proveedor    | Adquisición de partes en curso.                                                                                                                                                                                            |
| `WaitingForReview`                                 | Proveedor    | Trabajo terminado, en espera de tu revisión.                                                                                                                                                                               |
| `WorkReviewedAndCompleted`                         | Comprador    | Revisaste y cerraste el trabajo.                                                                                                                                                                                           |
| `WorkUnsatisfactory`                               | Comprador    | Rechazaste el trabajo completado.                                                                                                                                                                                          |
| `CancelledWithReason`                              | Comprador    | Cancelada.                                                                                                                                                                                                                 |

Las transiciones propiedad del proveedor llegan a través de la integración del propio proveedor o de las apps de OpenWrench; tu lado las observa mediante [webhooks](/es/buyer-api/webhooks) o por sondeo (`statusChangedAt`, `statusChanges`) y actúa sobre las que son propiedad del comprador.

## Notas

Las órdenes de trabajo llevan un hilo de notas comprador-proveedor compartido.

**Añade** con `PATCH /v1/buyer/work_order/work_orders/append_notes`. El cuerpo es `{ "id": <woId>, "note": { ... } }` donde la nota necesita `text` y `noteAddedBy`. El servidor sobrescribe `noteAddedAt` con su propio reloj, y el correo del autor se añade a la lista de suscriptores del comprador de la orden de trabajo para que reciba notificaciones posteriores.

```bash theme={null}
curl -X PATCH "$BASE/v1/buyer/work_order/work_orders/append_notes" \
  -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "id": 9001,
    "note": {
      "text": "Access code for the back door is 4417.",
      "noteAddedBy": "ops@example.com",
      "noteAddedAt": "2026-08-21T09:00:00.000-07:00"
    }
  }'
```

**Etiqueta a personas en una nota** añadiendo `taggedUsers` junto a `note`: una lista de correos electrónicos de contactos a los que @mencionar. OpenWrench incorpora cada correo en `note.elements` como un elemento `user`, la misma forma que las apps escriben para una @mención, así que no necesitas construir la estructura `elements` tú mismo. Los contactos etiquetados se añaden a la lista de suscriptores de la orden de trabajo si aún no están suscritos.

```bash theme={null}
curl -X PATCH "$BASE/v1/buyer/work_order/work_orders/append_notes" \
  -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "id": 9001,
    "note": {
      "text": "Access code for the back door is 4417.",
      "noteAddedBy": "ops@example.com",
      "noteAddedAt": "2026-08-21T09:00:00.000-07:00"
    },
    "taggedUsers": ["tech@supplier.com", "manager@example.com"]
  }'
```

Reglas de `taggedUsers`:

* Los correos se recortan y se pasan a minúsculas antes de compararse. Una nota puede mencionar como máximo a 25 usuarios.
* Los correos duplicados en la lista, y los usuarios ya etiquetados en `note.elements`, se omiten en lugar de mencionarse dos veces.
* Una entrada que no sea un correo electrónico válido, o una lista de más de 25 correos, se rechaza con un `400` de tipo `invalidInputDataException`. No se persiste nada.
* Una lista vacía se ignora. Enviar `taggedUsers` sin un objeto `note` se rechaza con `400`.

**Añade fotos en bloque** con `PATCH /v1/buyer/work_order/work_orders/append_notes/bulk`. Úsalo cuando tengas un lote de fotos que publicar (el conjunto de antes/después de un técnico, por ejemplo): los suscriptores reciben una única notificación agrupada en lugar de una notificación por foto. El cuerpo es `{ "id": <woId>, "notes": [ ... ] }` con de 1 a 25 notas, y cada nota debe llevar una URL en `photo` y ningún otro contenido: `text` debe estar vacío y `video`, `audio`, `otherFile` y `elements` deben estar ausentes. Repetir la misma URL de foto dentro de una solicitud se rechaza con `400`. El servidor marca cada nota del lote con el mismo `noteAddedAt` y conserva el orden en que las enviaste.

```bash theme={null}
curl -X PATCH "$BASE/v1/buyer/work_order/work_orders/append_notes/bulk" \
  -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "id": 9001,
    "notes": [
      { "text": "", "photo": "https://cdn.example.com/wo-9001/before.jpg" },
      { "text": "", "photo": "https://cdn.example.com/wo-9001/after.jpg" }
    ]
  }'
```

**Lee** con `GET /v1/buyer/work_order/work_order_notes/{woId}`. Esto devuelve solo el hilo raíz comprador-proveedor (los hilos de contratista e internos son separados), y la lectura marca las notas como leídas para tu contacto. Una lectura denegada devuelve una lista vacía en lugar de un error.

## Etiquetas

Las etiquetas son marcadores ligeros que tu equipo define en la app de OpenWrench (un nombre más un color opcional). A través de la API puedes leer el catálogo y reemplazar las etiquetas aplicadas a una orden de trabajo. La creación y edición de las etiquetas en sí permanece en la app.

**Explora el catálogo** con `GET /v1/buyer/work_order/work_order_labels`, u obtén una con `GET /v1/buyer/work_order/work_order_labels/{id}`. El listado está limitado a las etiquetas de tu empresa y paginado a 10 por página por defecto. Acepta filtros `search` y `label` sobre el texto de la etiqueta. Pasa `no_pagination=true` para traer el catálogo completo en una sola llamada (el ordenamiento sigue aplicando).

```bash theme={null}
curl -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  "$BASE/v1/buyer/work_order/work_order_labels?no_pagination=true"
```

**Reemplaza las etiquetas de una orden de trabajo** con `PUT /v1/buyer/work_order/work_orders/{woId}/labels`. El cuerpo es `{ "ids": [...] }` y es un reemplazo completo: las etiquetas no listadas se eliminan, y un array vacío las borra todas. La respuesta lista los mapeos de etiquetas ahora activos en la orden de trabajo.

```bash theme={null}
curl -X PUT "$BASE/v1/buyer/work_order/work_orders/9001/labels" \
  -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  -H "Content-Type: application/json" \
  -d '{ "ids": [4, 12] }'
```

Comportamiento a conocer:

* Un `ids` ausente o que no sea un array, o un id que no sea un número entero, se rechaza con `400`.
* Cada id debe ser una etiqueta viva de tu propio catálogo. Los ids desconocidos o de otro inquilino responden `400` con los ids problemáticos listados.
* La escritura requiere permiso de escritura de órdenes de trabajo. Un id de orden de trabajo desconocido, eliminado o ajeno responde el mismo `400` que una escritura denegada, no un `404`.

## Tipos de problema

`GET /v1/buyer/work_order/problem_types` lista los tipos de problema configurados para tu empresa. Cachea esto: necesitas un `problemTypeId` válido para cada orden de trabajo que crees, y el endpoint jerarquizado de proveedores también toma uno.

```bash theme={null}
curl -H "X-API-KEY: $KEY" -H "OW-KEY: $SECRET" \
  "$BASE/v1/buyer/work_order/problem_types"
```

## Juntándolo todo

Una integración de despacho típica:

1. Cachea `me`, tipos de problema y ubicaciones al arrancar.
2. Crea la orden de trabajo con `supplierFacilityId` establecido (o créala sin asignar, luego jerarquiza proveedores y haz `PATCH` de la asignación).
3. Sigue el progreso del proveedor mediante [webhooks](/es/buyer-api/webhooks) (`workorder.status_update`), obteniendo cada orden de trabajo por id cuando llegue un evento. Mantén `GET /work_orders?statusChangedAt=...` como una pasada de conciliación poco frecuente, no como la señal principal.
4. Cuando el proveedor alcance `WaitingForReview`, verifica el trabajo (ver [Llamadas de servicio](/es/buyer-api/service-calls) para la evidencia de la visita) y publica `work_reviewed_and_completed`, o `work_unsatisfactory` con una nota.
5. Concilia el lado monetario mediante [Cotizaciones y propuestas](/es/buyer-api/quotes-and-proposals) y [Facturas](/es/buyer-api/invoices).
