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

# Cancelar orden

> Cancela una orden de agregador y, cuando el procesador de pago lo soporta, reembolsa el pago.

Cancela una orden creada previamente con [Inyectar orden](/es/api-reference/orders). Fire busca la orden por `account` y `order_uid`, actualiza la orden a `CANCELED` y devuelve la orden actualizada dentro del sobre estándar de la API.

Si el procesador de pago guardado soporta reembolsos (por ejemplo, Deuna), Fire intenta el reembolso y deja `payment_status` en `REFUNDED` cuando es exitoso. Para otros procesadores, Fire cancela el estado de pago y deja `payment_status` en `CANCELED`.

<ParamField header="Authorization" type="string" required>
  Token Bearer obtenido desde [POST /login](/es/api-reference/login). Formato: `Bearer <accessToken>`.
</ParamField>

<ParamField header="x-api-key" type="string" required>
  Tu API key de Fire.
</ParamField>

<ParamField header="x-client-channel" type="string" required>
  Debe ser `integration`. Identifica la petición como proveniente de una integración externa.
</ParamField>

<ParamField header="account" type="string" required>
  Identificador de la cuenta usado para encontrar la orden.
</ParamField>

<ParamField header="Content-Type" type="string" default="application/json">
  Usa `application/json` para el cuerpo de la petición.
</ParamField>

<ParamField path="order_uid" type="string" required>
  UID de la orden que se va a cancelar.
</ParamField>

<ParamField body="reason" type="string" required>
  Motivo de la cancelación o solicitud de reembolso.
</ParamField>

<ParamField body="payment_method_uid" type="string">
  Opcional. UID del método de pago usado para resolver credenciales de reembolso cuando necesitas apuntar a un método específico.
</ParamField>

<ParamField body="vendor_uid" type="string" required>
  UID del vendor usado para resolver credenciales de pago.
</ParamField>

<ParamField body="email" type="string">
  Email del cliente enviado al procesador de pago cuando aplica.
</ParamField>

<ParamField body="customer_uid" type="string">
  UID del cliente registrado. Si está presente, Fire trata el payload de reembolso como autenticado.
</ParamField>

<ParamField body="anonymous_customer_uid" type="string">
  UID del cliente anónimo. Se usa como identificador de usuario de pago cuando no existe `customer_uid`.
</ParamField>

<ParamField body="store_uid" type="string">
  UID de la tienda usado para resolver credenciales de pago específicas de la tienda.
</ParamField>

<ParamField body="media" type="string">
  Medio de venta usado para resolver credenciales. Valores soportados: `APP`, `WEB`.
</ParamField>

<ParamField body="cancellation_type" type="string">
  Opcional. ID del motivo de cancelación o código del catálogo. Cuando se envía, se persiste en la orden y se reporta al gateway de pago.
</ParamField>

<RequestExample>
  ```json Cancelación mínima theme={null}
  {
    "reason": "Duplicate charge",
    "vendor_uid": "vendor-uid-abc"
  }
  ```

  ```json Cancelación con tipo theme={null}
  {
    "reason": "Solicitud del cliente",
    "cancellation_type": "101",
    "vendor_uid": "vendor-uid-abc"
  }
  ```

  ```json Cancelación con cliente y canal theme={null}
  {
    "reason": "Customer cancellation",
    "cancellation_type": "101",
    "payment_method_uid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "vendor_uid": "vendor-uid-abc",
    "store_uid": "store-uid-xyz",
    "media": "WEB",
    "email": "customer@example.com",
    "customer_uid": "customer-uid-123"
  }
  ```
</RequestExample>

<ResponseField name="data" type="object">
  Orden actualizada. Los precios en `order_lines`, `totals` y `payment_methods` se devuelven como montos externos sin escalar.

  <Expandable title="data">
    <ResponseField name="uid" type="string">UID de la orden.</ResponseField>
    <ResponseField name="order_code" type="string | null">Código legible de la orden.</ResponseField>
    <ResponseField name="account_uid" type="string">Identificador de la cuenta.</ResponseField>
    <ResponseField name="vendor_uid" type="string | null">UID del vendor.</ResponseField>
    <ResponseField name="store_uid" type="string | null">UID de la tienda.</ResponseField>
    <ResponseField name="status" type="string">Estado final de la orden. Las cancelaciones exitosas devuelven `CANCELED`.</ResponseField>
    <ResponseField name="payment_status" type="string">Estado final del pago: `REFUNDED` o `CANCELED`.</ResponseField>
    <ResponseField name="cancellation_type" type="string | null">ID o código del tipo de cancelación enviado en el request, persistido en la orden. `null` si no se proporcionó.</ResponseField>
    <ResponseField name="order_lines" type="array | null">Líneas de la orden con precios sin escalar.</ResponseField>
    <ResponseField name="totals" type="array | null">Totales con precios sin escalar.</ResponseField>
    <ResponseField name="payment_methods" type="array | null">Métodos de pago con montos sin escalar.</ResponseField>
    <ResponseField name="metadata" type="object | null">Metadata de la orden.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="status" type="number">
  Código HTTP dentro del sobre de la API.
</ResponseField>

<ResponseField name="traceId" type="string">
  Identificador de traza para soporte y diagnóstico.
</ResponseField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "uid": "550e8400-e29b-41d4-a716-446655440000",
      "order_code": "ORD-2026-001234",
      "account_uid": "acc-uid-12345",
      "vendor_uid": "vendor-uid-abc",
      "store_uid": "store-uid-xyz",
      "status": "CANCELED",
      "payment_status": "REFUNDED",
      "cancellation_type": "101",
      "order_lines": [],
      "totals": [],
      "payment_methods": [],
      "metadata": {},
      "created_at": "2026-03-30T12:00:00.000Z",
      "updated_at": "2026-03-30T12:05:00.000Z",
      "deleted_at": null
    },
    "status": 200,
    "method": "POST",
    "pathname": "/api/v4/integrations/sales/aggregator/orders/550e8400-e29b-41d4-a716-446655440000/refund",
    "duration": 120,
    "traceId": "abc123",
    "isArray": false
  }
  ```

  ```json 422 theme={null}
  {
    "status": 422,
    "errors": {
      "status": "422",
      "code": "invalid_type",
      "title": "Validation error",
      "detail": "reason is required"
    }
  }
  ```

  ```json 404 theme={null}
  {
    "status": 404,
    "errors": {
      "status": "404",
      "code": "not_found",
      "title": "Not found",
      "detail": "Order not found"
    }
  }
  ```

  ```json 400 theme={null}
  {
    "status": 400,
    "errors": {
      "status": "400",
      "code": "custom",
      "title": "Error",
      "detail": "Payment methods not found"
    },
    "message": "Payment methods not found",
    "code": 0,
    "moreInfo": "https://docs.artisn.io/api/errors"
  }
  ```
</ResponseExample>

## Reglas de procesamiento

* Cuando se envía, `payment_method_uid` ayuda a resolver credenciales, pero Fire evalúa los métodos de pago guardados en la orden.
* Para reembolsos con Deuna, la orden debe incluir `metadata.order_token`; si no existe, Fire devuelve `400`.
* Después de guardar la orden actualizada, Fire devuelve precios transformados para consumo externo.
* Fire notifica la cancelación downstream después de guardar la orden.

## Comportamiento posterior a la cancelación

<Warning>
  Un `200` significa que **la orden** quedó cancelada. **No** significa que el documento fiscal ya esté anulado: esa parte es asíncrona y puede seguir en curso, o fallar, después de que respondimos.
</Warning>

### La anulación fiscal es asíncrona

Cuando la orden tenía un documento fiscal emitido, Fire solicita su anulación al proveedor y deja el documento en `cancelling`. El estado final llega **por webhook del proveedor**, no en la respuesta de este endpoint.

| Estado del documento | Qué significa                                                                       |
| -------------------- | ----------------------------------------------------------------------------------- |
| `cancelling`         | Anulación solicitada, esperando confirmación del proveedor. Estado **transitorio**. |
| `cancelled`          | Anulado y confirmado. Circuito completo.                                            |
| `rejected`           | El fisco rechazó la anulación. El documento sigue vigente.                          |

Si el webhook del proveedor nunca llega, el documento **queda en `cancelling` indefinidamente**: no hay reintento automático que lo destrabe. Para un integrador que necesita certeza fiscal, esperar el `200` de este endpoint no alcanza — hay que consultar el estado del documento después.

### Los montos no se ponen en cero

La orden cancelada **conserva sus totales y sus métodos de pago con los importes originales**. `order_lines`, `totals` y `payment_methods` vuelven con los mismos valores que antes de cancelar; lo que cambia es `status` y `payment_status`.

Esto es deliberado: la orden es el registro de lo que pasó, no de lo que quedó vigente. Si conciliás montos contra órdenes canceladas, vas a encontrar que **cuadran perfecto** — porque se cobró exactamente lo que se vendió antes de anular. La conciliación correcta para una orden cancelada no es "¿coinciden los montos?" sino "¿se revirtió cada eslabón?".

### La anulación es total, nunca parcial

No existe la anulación por líneas ni por importe: se cancela la orden entera o no se cancela. Por eso el request no lleva montos ni lista de ítems. Si necesitás revertir solo una parte, la operación es cancelar y volver a inyectar.

### Qué verificar del lado del cliente

* **No asumas que el documento fiscal quedó anulado** por recibir `200`. Consultá su estado si necesitás certeza.
* **`payment_status` distingue dos desenlaces distintos**: `REFUNDED` (el procesador devolvió la plata) y `CANCELED` (se anuló el cobro sin devolución). No son equivalentes para una conciliación.
* **El evento downstream sale después de guardar la orden**, no después de que se confirme la anulación fiscal. Llega antes de que el circuito esté cerrado.
