> Chytapay es una plataforma de cobros por transferencia en Argentina. Esta página es parte de la doc de la Integration API: https://chytapay.com.ar/api/
> Conciliación recomendada: por CUIL. Ambientes: test (https://integration-api.test.chytapay.com.ar) y producción (https://integration-api.chytapay.com.ar).
> Página: "Funciones por integración" (https://chytapay.com.ar/api/funciones/), actualizada el 2026-11-03.
> Índice completo para asistentes de IA: https://chytapay.com.ar/llms.txt

# Funciones por integración

Devoluciones y avisos por WhatsApp: qué podés usar, cómo se piden y qué elegís vos.

Dos funciones se configuran por integración:

| Función             | Cómo la activás                               | Qué elegís vos, en [Configuración](https://chytapay.com.ar/portal/settings) |
| ------------------- | --------------------------------------------- | --------------------------------------------------------------------------- |
| Avisos por WhatsApp | Ya vienen activos (Chytapay puede limitarlos) | Si sale el aviso del cobro                                                  |
| Devoluciones        | Pedilas a `contacto@chytapay.com.ar`          | Qué devoluciones automáticas corren                                         |

## Cómo se activan

Se configuran en Producción. Lo que tu integración no tiene aparece bloqueado, con un botón para pedirlo. El Portal no tiene un botón para devolver un cobro: eso lo hacés por API, o lo hace soporte de Chytapay.

## Devoluciones

La plata vuelve a la cuenta desde la que se pagó. Pedí los modos que vayas a usar:

| Modo                         | Qué hace                                                                                                                          |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Por API                      | Devolvés un cobro, total o parcial, con el endpoint de devoluciones.                                                              |
| Automática por excedente     | Si el pagador transfiere de más, devolvemos la diferencia (desde $1).                                                             |
| Automática por pago de menos | Si el pagador transfiere menos del total, devolvemos el pago entero. Llega `payment.unmatched` con motivo `partial_not_accepted`. |
| Automática sin asignar       | Si una transferencia no corresponde a ningún cobro, la devolvemos.                                                                |

### Devolver por API

Necesitás dos cosas: el modo por API en tu integración y la autorización del comercio. Mandá la autorización escrita del comercio a `contacto@chytapay.com.ar` o por WhatsApp al +54 9 351 543 0077. Hasta entonces el endpoint responde **403** `RefundsNotConsentedError`. Se devuelven pagos de los últimos 10 días. Con el `id_token` del comercio:

**cURL**

```bash
curl -X POST https://integration-api.test.chytapay.com.ar/payment-request/pedido-1001/refunds \
  -H "Authorization: Bearer $ID_TOKEN" \
  -H "Idempotency-Key: devolucion-pedido-1001-a" \
  -H "Content-Type: application/json" \
  -d '{ "amount": 5000, "reason": "Producto sin stock" }'
```

**Respuesta**

```json
{
  "refundId": "00000000-0000-0000-0000-000000000000",
  "paymentRequest": { "referenceId": "pedido-1001", "state": "total_payment" },
  "origin": "api",
  "trigger": null,
  "status": "pending",
  "requestedAmount": 5000,
  "refundedAmount": 0,
  "reason": "Producto sin stock",
  "items": [{ "amount": 5000, "status": "pending" }]
}
```

Responde **202**: la devolución es asincrónica y el resultado llega por [webhook](https://chytapay.com.ar/api/funciones/#devolucion-eventos).

| Campo                      | ¿Obligatorio? | Qué es                                                                                                                                                              |
| -------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Idempotency-Key` (header) | Sí            | De 1 a 255 caracteres. Un reintento con la misma clave y el mismo cuerpo devuelve la misma devolución.                                                              |
| `amount`                   | No            | Pesos, mayor a 0, hasta 2 decimales. Sin él, se devuelve todo lo que queda de los pagos de los últimos 10 días. Con él, esa parte, del pago más nuevo al más viejo. |
| `reason`                   | No            | Hasta 500 caracteres.                                                                                                                                               |

Podés hacer devoluciones parciales una tras otra hasta el total, de a una por vez. Para consultar una devolución, `GET /refunds/{refundId}` (incluye las automáticas).

`status` es `pending`, `processing`, `succeeded`, `failed` o `partially_failed`. Un cobro devuelto pasa a `refunded` o `partially_refunded`.

Los mensajes de la API están en inglés.

| Status | Error                                                             | Cuándo                                                                                    |
| ------ | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| 400    | `IdempotencyKeyRequiredError`                                     | Falta el header `Idempotency-Key` o tiene más de 255 caracteres.                          |
| 403    | `RefundsNotEnabledError`                                          | Tu integración no tiene devoluciones. Pedilas.                                            |
| 403    | `ApiRefundsNotAllowedError`                                       | Tu integración no tiene el modo por API. Pedilo.                                          |
| 403    | `RefundsNotConsentedError`                                        | Falta la autorización del comercio para devolver por API.                                 |
| 404    | `PaymentRequestNotFoundError`                                     | No hay un cobro con ese `referenceId` en tu integración.                                  |
| 409    | `RefundAlreadyRefundedError`, `RefundInProgressError`             | Ya está devuelto, o tiene una devolución en curso.                                        |
| 409    | `RefundNoPaymentsError`, `RefundPaymentTooOldError`               | No hay pagos para devolver, o ninguno en los últimos 10 días.                             |
| 409    | `RefundPaymentNotSettledError`, `RefundPaymentWithoutOriginError` | Un pago todavía no llegó a la cuenta principal del comercio, o no tiene cuenta de origen. |
| 409    | `RefundInvoicedPaymentRequestError`                               | El cobro está facturado: pedí la devolución a soporte.                                    |
| 409    | `RefundInsufficientBalanceError`                                  | El comercio no tiene saldo para la devolución.                                            |
| 409    | `IdempotencyRequestInProgressError`                               | Otra solicitud con la misma clave sigue en curso.                                         |
| 422    | `RefundAmountExceedsRefundableError`                              | El monto supera lo que queda por devolver.                                                |
| 422    | `IdempotencyKeyReusedError`                                       | La clave ya se usó con otro cuerpo.                                                       |
| 503    | `PrincipalBalanceUnavailableError`                                | No pudimos consultar el saldo. No se creó nada: reintentá con la misma clave.             |

### Devoluciones automáticas

Elegís cuáles corren en **Configuración**, **Devoluciones**. Un modo recién activado arranca prendido, salvo que ya hayas elegido sobre él: desde ese momento, las transferencias que cumplan la condición se devuelven solas. No necesitan la autorización del comercio.

No corren si el comercio tiene más de una integración activa y la transferencia no se asignó a un cobro.

### Eventos de devolución

`refund.succeeded` (toda la plata volvió al pagador) y `refund.failed` (al menos una parte no se pudo devolver) vienen apagados. Activalos en [**Webhooks**](https://chytapay.com.ar/portal/webhooks?tab=eventos), pestaña **Eventos**. Llegan a las mismas URLs que el resto, con la misma [firma](https://chytapay.com.ar/api/webhooks/#firma).

Ejemplo de `refund.succeeded`:

```json
{
  "event": "refund.succeeded",
  "livemode": false,
  "refundId": "00000000-0000-0000-0000-000000000000",
  "paymentRequest": { "referenceId": "pedido-1001", "state": "partially_refunded" },
  "origin": "api",
  "trigger": null,
  "status": "succeeded",
  "requestedAmount": 5000,
  "refundedAmount": 5000,
  "reason": "Producto sin stock",
  "items": [{ "amount": 5000, "status": "succeeded" }],
  "merchantUserId": "00000000-0000-4000-8000-000000000001",
  "merchantTaxId": "30712345671",
  "merchantName": "Comercio de Prueba"
}
```

- `origin` dice quién la pidió: `api`, `merchant`, `chyta` (soporte) o `auto`.
- `trigger` solo viaja con `auto`: `unmatched`, `partial` o `excess`.
- `paymentRequest` es `null` en la devolución automática de una transferencia que no se asignó a ningún cobro.
- `reason` es `null` en las devoluciones que pide soporte.
- `tenantKey` viaja solo si el comercio está en una [sede](https://chytapay.com.ar/api/sedes/).

## Avisos por WhatsApp

Son mensajes de Chytapay al pagador:

| Mensaje              | Qué manda                                                                                                                        |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Aviso del cobro      | El link de pago por WhatsApp al crear el cobro, y sus recordatorios. Solo sale si el cobro tiene monto y `customer.phoneNumber`. |
| Confirmación de pago | Avisa al pagador cuando el pago se acredita.                                                                                     |

### Qué arranca activado

Por defecto sale la **confirmación de pago**. El **aviso del cobro** arranca apagado: lo prendés vos en **Configuración**, **Avisos por WhatsApp**, y recién entonces rige.

Lo que elegís ahí vale cuando el cobro no dice nada. Lo que el cobro manda gana:

- `sendWhatsappNotification` omitido usa tu elección. `true` o `false` en el cobro la pisa.
- `sendWhatsappPaymentConfirmation` omitido conserva el comportamiento de cada modo de conciliación. Está en [confirmación de pago](https://chytapay.com.ar/api/crear-cobros/#confirmacion-de-pago).

Si un cobro pide un mensaje que tu integración no tiene, la API responde **403** (`WhatsappNotEnabledError`, `WhatsappNotificationNotAllowedError` o `WhatsappPaymentConfirmationNotAllowedError`). Escribinos para activarlo. El [tope diario](https://chytapay.com.ar/api/operacion/#limites) de mensajes sigue rigiendo.

- [Webhooks](https://chytapay.com.ar/api/webhooks/): Eventos, firma y reintentos.
- [Crear cobros](https://chytapay.com.ar/api/crear-cobros/): Campos y avisos al pagador.
- [Conciliación](https://chytapay.com.ar/api/conciliacion/): CUIL y el pagador tercero.
- [Operación y errores](https://chytapay.com.ar/api/operacion/): Límites y paso a producción.
