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

# Extorno de una venta CARD aprobada

> Extorno explícito CARD y consulta de resultados; QR no admite extornos ni devoluciones.

`POST /reversals` aplica **solo a CARD** y solicita el extorno total de una venta aprobada. Conserva el `operationNumber` original.

## Cancelación y extorno

| Flujo | Uso | Verificación |
| - | - | - |
| `POST /cancel` | Solicitar cancelar una autorización activa. | Su respuesta informa el resultado de la cancelación. Ante fallo o incertidumbre, consulta el cobro original. |
| `POST /reversals` | Solicitar un extorno independiente de una venta CARD aprobada. | `GET /reversals/{operationNumber}` cuando el resultado no esté confirmado. |

En **QR**, únicamente cancelas o inhabilitas el código generado. Ni `/cancel` ni refund devuelven un monto pagado; `/reversals` no aplica. Si aparece `transaction.state: "AUTORIZADO"` en una consulta `200/00` después de solicitar cancelación, conserva el pago aprobado y registra la discrepancia para revisión.

Una cancelación fallida permite evaluar el extorno cuando `GET /payments/{operationNumber}` confirma el cobro CARD como `transaction.state: "AUTORIZADO"` en una consulta `200/00`. Usa el `operationNumber` de esa venta; el error de cancelación no genera un extorno automático.

## Requisitos por método

| Método | Requisito |
| - | - |
| CARD | Venta encontrada con `transaction.state: "AUTORIZADO"` y cobro vigente. Presenta la tarjeta cuando la solicite el PinPAD. |
| QR | No aplica este flujo: solo puedes cancelar o inhabilitar el código, sin devolver un monto pagado. |

Antes del POST, verifica que no exista un extorno completado o en curso. No dupliques la solicitud mientras falte resolución.

## Solicitud

Envía al mismo host y puerto de la autorización:

```http theme={"system"}
POST /reversals
Content-Type: application/json
Connection: close
```

```json theme={"system"}
{
  "operationNumber": "44992528"
}
```

| Campo | Tipo | Obligatorio | Uso |
| - | - | - | - |
| `operationNumber` | String | Sí | Referencia original aceptada en la autorización; consulta [Parámetros](/procesamiento-fisico/alignet-transit/parametros-de-envio). |

No envíes monto, moneda, método ni datos de tarjeta. El extorno es total.

```bash theme={"system"}
curl --header "Connection: close" --request POST "http://<IP_DEL_PINPAD>:<PUERTO>/reversals" \
  --header "Content-Type: application/json" \
  --max-time 110 \
  --data '{"operationNumber":"44992528"}'
```

Si el resultado no está confirmado o se pierde la respuesta, consulta el extorno:

```bash theme={"system"}
curl --header "Connection: close" -i "http://<IP_DEL_PINPAD>:<PUERTO>/reversals/44992528"
```

Todas las respuestas incluyen `Connection: close` y `Cache-Control: no-store`. Abre una conexión por petición. HTTP `202` añade `Retry-After: 2`; espera dos segundos antes de consultar el extorno.

## Respuestas del POST

| HTTP | Resultado documentado | Acción |
| - | - | - |
| `200` | `REVERSED` con `00`, `16` o `17` | Registrar extorno confirmado o éxito equivalente. |
| `200` | `DENIED` con `14`, `15`, `18`, `19`, `20`, `01`, `03` u otro código SDK | No registrar éxito; conservar código y mensaje. No reintentar automáticamente. |
| `202` | `SEARCHING`, `PROCESSING` o `PENDING`; códigos `SEARCHING`, `WAITING_RESULT` o `P22` | Respetar `Retry-After: 2` y consultar; no duplicar. |
| `400` | `BAD_REQUEST` | Corregir el cuerpo. No es un rechazo financiero. |
| `404` | `NOT_FOUND` | Verificar referencia y terminal; no confirma ausencia de cobro. |
| `409` | `POS_BUSY` | Esperar a que termine la operación activa antes de reintentar la solicitud no aceptada. |
| `502` | `UNKNOWN`, cuerpo compacto con `message`; sin `resultCode` | Búsqueda ambigua o control de tiempo agotado. Revisar con Alignet; no registrar éxito ni reenviar automáticamente. |
| `503` | `POS_NOT_AVAILABLE` | Restablecer disponibilidad y consultar antes de decidir otro envío. |

La forma normal conserva `operationNumber`, `status`, `resultCode`, `resultMessage`, `authorizationCode` y `completedAt` (fecha ISO 8601 UTC o `null` si no aplica). Ejemplo de extorno aprobado; no representa una prueba ejecutada:

```json theme={"system"}
{
  "operationNumber": "44992528",
  "status": "REVERSED",
  "resultCode": "00",
  "resultMessage": "Extorno aprobado",
  "authorizationCode": "123456",
  "completedAt": "2026-08-27T20:30:00Z"
}
```

El código aislado no basta: el éxito exige `REVERSED` con `00`, `16` o `17`. Conserva los códigos SDK sin normalizaciones adicionales. El cuerpo compacto de `UNKNOWN` utiliza `message`, no `resultMessage`.

Forma compacta de HTTP `502` (esquema, no evidencia de prueba):

```json theme={"system"}
{
  "operationNumber": "string",
  "status": "UNKNOWN",
  "message": "string"
}
```

## Consulta del extorno explícito

| HTTP de `GET /reversals/{operationNumber}` | Significado | Acción |
| - | - | - |
| `200` | `REVERSED`, `DENIED` o `ERROR` guardado. | Reconocer éxito solo con `REVERSED` y `00`, `16` o `17`. |
| `202` | Extorno en curso. | Respetar `Retry-After: 2` y continuar consultando. |
| `404` | No existe solicitud registrada o la venta original no fue encontrada. | Verificar terminal y referencia; no deducir un resultado financiero. |
| `400` | `ERROR/BAD_REQUEST`: segmento vacío o inválido. | Corregir la referencia en la ruta. |
| `502` | `UNKNOWN`: la solicitud terminó con error. | Revisar si se ejecutó el extorno con Alignet; no registrar éxito. |

`GET /reversals/{operationNumber}` consulta el estado **local** guardado por la app. El cobro y el extorno son resultados independientes. Encontrar `transaction.state: "AUTORIZADO"` en `GET /payments/{operationNumber}` no confirma ni descarta el extorno; consulta este último en `/reversals/{operationNumber}`.

## Estados del extorno

| Estado | Interpretación |
| - | - |
| `SEARCHING` | Se está buscando la venta original. Sigue consultando el extorno. |
| `PROCESSING`, `PENDING` | Extorno en proceso o espera HTTP agotada; continuar consultando. |
| `REVERSED` con `00`, `16` o `17` | Extorno confirmado o éxito equivalente. |
| `DENIED` | Solicitud denegada; no registres extorno exitoso. |
| `UNKNOWN` | La solicitud terminó con HTTP `502`, pero no se sabe si se ejecutó el extorno. Revisa el caso con Alignet. |
| `ERROR` | Evaluar HTTP, código y mensaje; no equivale a extorno. |

`DENIED`, `ERROR` y `UNKNOWN` no confirman un extorno exitoso. `UNKNOWN` no debe tratarse como un pendiente de cobro con HTTP `202`.

## Recuperación e idempotencia

* Ante timeout o desconexión, consulta la misma referencia: el timeout no determina el resultado financiero.
* Si el mismo extorno está `SEARCHING`, `PROCESSING` o `PENDING`, el POST devuelve `202` sin iniciar otro.
* Si ya fue `REVERSED`, devuelve `200` con el resultado guardado sin repetir el extorno; si fue `NOT_FOUND`, devuelve `404` sin otro intento.
* Tras un resultado final `DENIED`, `UNKNOWN` o `ERROR`, un nuevo `POST /reversals` con la misma referencia **puede ejecutar otro intento real**. Esta capacidad no autoriza reintentos automáticos ante incertidumbre: consulta, revisa el resultado financiero y decide antes de reenviar.
* Otra referencia activa devuelve `409 POS_BUSY`. Serializa operaciones por terminal.
* No reenvíes en paralelo ni cambies el cuerpo. Consulta antes de cualquier reenvío permitido.
* No sustituyas un resultado confirmado por un `PENDING` tardío ni inicies otra venta mientras no conozcas el resultado anterior.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.