> 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: "Operación y errores" (https://chytapay.com.ar/api/operacion/), actualizada el 2026-10-09.
> Índice completo para asistentes de IA: https://chytapay.com.ar/llms.txt

# Operación y errores

Ambientes, checklist de paso a producción, límites de uso, errores por endpoint y descargas de la Integration API.

Los datos para operar la integración: ambientes, límites, errores y descargas.

1. [Ambientes](https://chytapay.com.ar/api/operacion/#ambientes): Sandbox y Producción
2. [Paso a producción](https://chytapay.com.ar/api/operacion/#produccion): qué revisar antes de cobrar
3. [Límites](https://chytapay.com.ar/api/operacion/#limites): mensajes de WhatsApp y pool de CVUs
4. [Errores](https://chytapay.com.ar/api/operacion/#errores): qué devuelve cada endpoint

## Ambientes y URLs

Tu integración tiene dos ambientes, Sandbox y Producción, con credenciales propias. Los dos se manejan desde el mismo portal, [chytapay.com.ar/portal/login](https://chytapay.com.ar/portal/login), con el selector de ambiente.

| Servicio                                     | Sandbox                                        | Producción                                |
| -------------------------------------------- | ---------------------------------------------- | ----------------------------------------- |
| Integration API (cobros, bulk, payer-lookup) | `https://integration-api.test.chytapay.com.ar` | `https://integration-api.chytapay.com.ar` |
| Auth API (OAuth: `/integration/oauth2/*`)    | `https://auth-api.test.chytapay.com.ar`        | `https://auth-api.chytapay.com.ar`        |
| Clave publicable del widget                  | `pk_test`                                      | `pk_live`                                 |

La Integration API monta sus rutas en la raíz: `/payment-request`, `/payment-request/bulk` y `/payer-lookup`. El widget usa `/v1/payments` en el mismo host.

Los tokens de prueba, el webhook de prueba y la simulación de pago existen solo en Sandbox. En Producción, `livemode` es `true` solo con un pago real.

## Paso a producción

Producción se pide en [**Credenciales**](https://chytapay.com.ar/portal/credentials): si el chequeo automático lo aprueba, generás las credenciales de producción con el selector de ambiente en Producción, y si no, el pedido pasa a revisión. Nada de Sandbox se copia solo. Antes de cobrar, revisá:

1. **Credenciales.** Generalas en [**Credenciales**](https://chytapay.com.ar/portal/credentials) y usá el `clientId` y el `clientSecret` de producción contra `auth-api.chytapay.com.ar`, y la `pk_live` si usás el widget (la `sk_live`, solo si creás cobros por `/v1/payments`).
2. **Comercios vinculados.** Los vínculos de Sandbox no existen en producción: cada comercio repite el OAuth de [Conectar comercios](https://chytapay.com.ar/api/conectar-comercios/).
3. **Webhooks.** Cargá la URL en [**Configuración**](https://chytapay.com.ar/portal/settings) con el ambiente en Producción, verificá la firma con el secreto de producción y activá `payment.unmatched` si lo necesitás, porque es opt-in. Consultá [las garantías de entrega](https://chytapay.com.ar/api/webhooks/#entrega) y [la suscripción](https://chytapay.com.ar/api/webhooks/#suscripcion).
4. **Errores.** Resolvé el 409, el 429 y los timeouts con la tabla de [reintentos](https://chytapay.com.ar/api/operacion/#reintentos).
5. **Tokens y eventos.** Renová el `idToken` de cada comercio con el `refreshToken` antes de la hora, deduplicá por `X-Chytapay-Webhook-Id` y respondé `2xx` en menos de 5 segundos.

### Reintentos de tu lado

No hay idempotency key. Lo que evita un cobro duplicado es el `referenceId`, único por integración y cuenta de comercio, cancelados incluidos.

| Situación                      | Qué hacer                                                                                                          |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------ |
| Timeout o 5xx en un create     | `GET /payment-request/{referenceId}`: con 404, reintentá con el mismo `referenceId`.                               |
| 409 `ReferenceIdAlreadyExists` | Ya se creó. Consultalo con GET; no generes otro `referenceId`.                                                     |
| 429 en create o bulk           | No reintentes en loop: esperá hasta las 00:00 hora Argentina. Un bulk que no entra entero en el tope no crea nada. |
| Timeout o 5xx en un bulk       | Consultá con GET un `referenceId` del lote: el bulk es todo o nada.                                                |
| 422 en un bulk reintentado     | Si el motivo es `The referenceId already exists for this integration`, el lote anterior se creó.                   |
| 503 en payer-lookup            | ARCA no respondió. Reintentá, o seguí sin validar al pagador.                                                      |

El ejemplo de create con timeout y 409 está en [Crear cobros](https://chytapay.com.ar/api/crear-cobros/#duplicados).



## Límites

El único tope diario al crear cobros es el de mensajes de WhatsApp. No hay tope de requests ni de cobros creados por día. Se reinicia a las 00:00 hora Argentina (UTC-3).

| Tope                                     | Valor                                                                                                                                                                                                                           | Al superarlo                                          |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
| Mensajes de tu integración               | Por integración, sumados todos sus comercios: 20 por día en Sandbox y 200 iniciales por día en Producción. Se amplía con **Pedir más límite**, en la [pantalla de inicio del Portal](https://chytapay.com.ar/portal/dashboard). | 429 `IntegrationDailyRequestLimitExceededError`       |
| Mensajes compartidos entre integraciones | Un tope global diario                                                                                                                                                                                                           | 429 `IntegrationGlobalDailyMessageLimitExceededError` |

### Qué cuenta como mensaje de WhatsApp

Cada cobro creado con `sendWhatsappNotification: true` cuenta como un mensaje. Los cobros que no piden notificación por WhatsApp no consumen el tope. Un bulk que no entra entero en el tope no crea nada.

### La respuesta 429 de los topes de mensajes

El cuerpo trae `code` (cuál de los dos topes) y `message`. El tope de tu integración suma `availableAt` (el reinicio, en hora argentina), `maxRequestsPerDay` y `maxMessagesPerDay`. El global suma `requestedMessages` y `availableAtUnixSeconds` (el reinicio, en segundos Unix). Si no se puede chequear el tope, el create y el bulk responden 503 `IntegrationDailyLimitUnavailableError`: reintentá en unos minutos. El reset es a las 00:00 hora Argentina: no reintentes en loop, esperá hasta entonces. Con creates en paralelo cerca del tope, un cobro puede quedar creado aunque responda 429: confirmá con GET antes de recrearlo.

### Otros límites

| Límite                               | Valor                            | Al superarlo                          |
| ------------------------------------ | -------------------------------- | ------------------------------------- |
| Items por bulk                       | 1 a 100 por llamada              | 400 `ValidationError`                 |
| Pool de CVUs, por cuenta de comercio | Hasta 100 por cuenta de comercio | 400 `InsufficientActiveAccountsError` |

### Payer-lookup

`GET /payer-lookup?document=` tiene su propia cuota, separada de los topes de creación: 1000 unidades por día, por integración y cuenta de comercio, que se reinician a las 00:00 hora Argentina. Un CUIL o CUIT cuesta 1 y un DNI cuesta 2, porque Chytapay consulta a ARCA los dos CUIL posibles. Al superarla, 429 `PayerLookupDailyLimitExceededError`.

- No consumen: el 400 por `document` inválido y el 503 que se responde sin consultar a ARCA.
- Sí consumen: el 200 con `name: null` y el 503 porque ARCA no respondió.
- El 429 trae `code`, `message`, `availableAtUnixSeconds` (el reset, en segundos Unix) y `maxLookupsPerDay` (`1000`).

Consultá cómo [validar al pagador](https://chytapay.com.ar/api/conciliacion/#validar-pagador).

### Pool de CVUs

El pool es de la cuenta de comercio, lo comparten todas sus integraciones y lo ocupan los CVUs de los cobros abiertos. Si no hay un CVU libre, el create y el bulk dan 400 `InsufficientActiveAccountsError` y no crean nada. Al cerrarse un cobro, su CVU vuelve al pool. Consultá cómo afecta a cada modo en [Conciliación](https://chytapay.com.ar/api/conciliacion/).



## Errores por endpoint

Decidí por el status HTTP y después por `code` o `error`, nunca por el texto de `message`. Las tablas siguen el [spec OpenAPI](https://chytapay.com.ar/api/operacion/#openapi).

### Formato del cuerpo de error

No hay header de request id. El `id` viene en el cuerpo, solo en la forma general: guardalo en tus logs. La mayoría de los mensajes están en inglés.

| Forma del cuerpo                           | Cuándo                                                                                                        |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------- |
| `{ code, message, id }`                    | Forma general: 400 de negocio, 409 `CustomerAlreadyAssociatedError`, 500                                      |
| `{ code, message, id, validationDetails }` | 400 `ValidationError`. `validationDetails` es una lista de `{ field, message }`; `message` repite el primero. |
| `{ error, message, referenceId }`          | 409 del create                                                                                                |
| `{ message, errors }`                      | 422 del bulk. `errors` es una lista de `{ index, referenceId, reason }`.                                      |
| `{ error, message, data }`                 | 409 del PATCH, del PATCH del pagador y del cancel                                                             |
| `{ message }`                              | 404 de cobro inexistente, de integración no lista para cobrar y de sede                                       |
| `{ code, message }`                        | 503 de payer-lookup                                                                                           |
| Texto plano, no JSON                       | 400, 403 y 404 del chequeo del token                                                                          |

### Comunes a todos los endpoints

| HTTP | Cuerpo                                              | Cuándo pasa y qué hacer                                                                                                                     |
| ---- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| 401  |                                                     | Token faltante, inválido o vencido. Renovalo con el refresh token de [Conectar comercios](https://chytapay.com.ar/api/conectar-comercios/). |
| 400  | `Bad request: Missing required authentication data` | El token no trae la cuenta, el rol o la aplicación. Mandá el `id_token` del comercio en `Authorization: Bearer`.                            |
| 404  | `Integration client not found`                      | El token es de otra aplicación. Pedilo con el `clientId` de tu integración en ese ambiente.                                                 |
| 403  | `Not authorized as user of integration client`      | La cuenta de comercio no está vinculada, o se desvinculó. Vinculala con el OAuth.                                                           |
| 500  | `{ code, message, id }`                             | Error interno. En un create o bulk, consultá con GET antes de reintentar.                                                                   |

### Crear un cobro: `POST /payment-request`

| HTTP | `code` o `error`                                                                                | Cuándo pasa y qué hacer                                                                                                 |
| ---- | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| 400  | `ValidationError`                                                                               | Falta un campo, tiene tipo o rango inválido, o ese `type` no lo acepta. Mirá `validationDetails`.                       |
| 400  | `WebhookUrlBlockedError`                                                                        | `webhookUrl` apunta a una dirección interna o privada.                                                                  |
| 400  | `InsufficientActiveAccountsError`                                                               | No hay CVU libre en el [pool del comercio](https://chytapay.com.ar/api/operacion/#pool-cvus).                           |
| 409  | `ReferenceIdAlreadyExists`                                                                      | El `referenceId` ya existe, aunque el cobro esté cancelado. No trae el cobro: consultalo con GET.                       |
| 409  | `CustomerAlreadyAssociatedError`                                                                | Chocaron dos creates simultáneos para el mismo pagador. Consultá con GET y reintentá si no existe.                      |
| 429  | `IntegrationDailyRequestLimitExceededError` o `IntegrationGlobalDailyMessageLimitExceededError` | Llegaste al tope de mensajes de WhatsApp. Consultá [los límites](https://chytapay.com.ar/api/operacion/#respuesta-429). |

### Crear cobros en lote: `POST /payment-request/bulk`

Si el bulk falla, no se crea ningún cobro del lote.

| HTTP | `code`                                                                                          | Cuándo pasa y qué hacer                                                                                                                      |
| ---- | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| 400  | `ValidationError`                                                                               | Lote vacío o de más de 100 items, un item fuera de contrato, o un vencimiento con hora (solo acepta `YYYY-MM-DD`). Mirá `validationDetails`. |
| 400  | `InsufficientActiveAccountsError`                                                               | El [pool del comercio](https://chytapay.com.ar/api/operacion/#pool-cvus) no alcanza para el lote.                                            |
| 404  |                                                                                                 | La integración no está lista para cobrar y reintentar no lo resuelve. Escribí a soporte.                                                     |
| 422  |                                                                                                 | Items que no pasan la validación de negocio, todos en `errors`. Corregilos y reenviá el lote completo.                                       |
| 429  | `IntegrationDailyRequestLimitExceededError` o `IntegrationGlobalDailyMessageLimitExceededError` | El lote no entra entero en el tope de mensajes de WhatsApp: no se crea nada.                                                                 |

Los `reason` del 422 son `Duplicate referenceId within the batch`, `The referenceId already exists for this integration`, `The taxDocument does not resolve to a valid CUIL` y `Duplicate payer within the batch` (el mismo documento en más de un item).

### Consultar un cobro: `GET /payment-request/{referenceId}`

| HTTP | Cuerpo                                       | Cuándo pasa y qué hacer                                                                                                       |
| ---- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| 404  | `{ "message": "Payment request not found" }` | No hay cobro con ese `referenceId` para esta integración y cuenta de comercio. Revisá que el token sea del comercio correcto. |

### Completar el monto: `PATCH /payment-request/{referenceId}`

| HTTP | `code` o `error`                 | Cuándo pasa y qué hacer                                                                   |
| ---- | -------------------------------- | ----------------------------------------------------------------------------------------- |
| 400  | `ValidationError`                | `amount` falta, no es positivo, tiene más de 2 decimales o supera 200.000.000.            |
| 404  |                                  | No existe el cobro.                                                                       |
| 409  | `PaymentRequestCannotBeModified` | El cobro no está en `draft`, o ya recibió pagos: solo un borrador sin pagos acepta PATCH. |

### Corregir el pagador: `PATCH /payment-request/{referenceId}/customer`

| HTTP | `code` o `error`                         | Cuándo pasa y qué hacer                                                                                                      |
| ---- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| 400  | `ValidationError`                        | `taxDocument` falta o es inválido (formato o dígito verificador), o `name`, `email` o `phoneNumber` están fuera de contrato. |
| 404  |                                          | No existe el cobro, o la integración no está lista para cobrar.                                                              |
| 409  | `PaymentRequestCustomerCannotBeModified` | No se puede cambiar el pagador. El motivo está en `data.reason`.                                                             |

| `data.reason`                     | Qué significa                                                      |
| --------------------------------- | ------------------------------------------------------------------ |
| `conciliation_type_not_cuil`      | El cobro es de modo CVU, que no guarda el documento del pagador.   |
| `state_not_modifiable`            | El cobro está en un estado final.                                  |
| `payment_already_received`        | El cobro ya recibió plata.                                         |
| `no_collision_free_account`       | Ningún CVU puede alojar el documento nuevo. No se cambió nada.     |
| `missing_notification_contact`    | Al pagador nuevo le falta el contacto que piden los recordatorios. |
| `incomplete_payment_request_data` | El cobro no tiene pagador asociado.                                |
| `concurrent_modification`         | Otro cambio en paralelo. Releé el cobro y reintentá.               |

Consultá cuándo usarlo en [corregir el pagador](https://chytapay.com.ar/api/conciliacion/#corregir-pagador).

### Cancelar un cobro: `POST /payment-request/{referenceId}/cancel`

| HTTP | `error`                          | Cuándo pasa y qué hacer                                                                               |
| ---- | -------------------------------- | ----------------------------------------------------------------------------------------------------- |
| 404  |                                  | No existe el cobro.                                                                                   |
| 409  | `PaymentRequestCannotBeCanceled` | El cobro no está en `draft` ni en `pending`: tiene pagos parciales, está pagado, vencido o cancelado. |

### Validar un documento: `GET /payer-lookup`

| HTTP                 | `code`                                | Cuándo pasa y qué hacer                                                                      |
| -------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------- |
| 200 con `name: null` |                                       | ARCA respondió y el documento no tiene titular. Pedile al pagador que lo revise.             |
| 400                  | `ValidationError`                     | `document` no es un CUIL o CUIT de 11 dígitos ni un DNI de 7 u 8.                            |
| 404                  |                                       | La cuenta no está vinculada.                                                                 |
| 429                  | `PayerLookupDailyLimitExceededError`  | Llegaste a las 1000 unidades del día.                                                        |
| 503                  | `PayerLookupProviderUnavailableError` | No se pudo consultar a ARCA: el pagador no quedó verificado. Reintentá, o seguí sin validar. |
| 503                  | `PayerLookupQuotaUnavailableError`    | No se pudo chequear la cuota. Reintentá.                                                     |

### Asignar la sede: `PUT /my-integration/tenant`

| HTTP | Cuerpo                                                                         | Cuándo pasa y qué hacer                                                                                     |
| ---- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| 400  | `ValidationError`                                                              | Falta `tenantKey` o está vacío.                                                                             |
| 404  | `{ "message": "The specified tenant does not exist or was deleted" }`          | La sede no existe, se borró o es de otra integración. Consultá [Sedes](https://chytapay.com.ar/api/sedes/). |
| 404  | `{ "message": "No integration account was found for the authenticated user" }` | La cuenta de comercio no está vinculada.                                                                    |

### OAuth

Los errores de `authorize`, `token`, `refresh` y `revoke` están en [Conectar comercios](https://chytapay.com.ar/api/conectar-comercios/).

## Errores típicos

- **Usar el token equivocado.** La Integration API recibe el `id_token` de la cuenta de comercio, no el del admin de la integración ni el `clientSecret`.
- **Recrear tras un timeout o reintentar un 429 en loop.** Consultá [reintentos](https://chytapay.com.ar/api/operacion/#reintentos) y [la respuesta 429](https://chytapay.com.ar/api/operacion/#respuesta-429).
- **Leer `name: null` como falla de ARCA.** El documento no tiene titular; la falla es el 503.

## Descargas

### OpenAPI

Importá el spec en Postman, Insomnia, Bruno o cualquier cliente de API, o navegá la [API Reference](https://chytapay.com.ar/api/reference/):

- Integration API: `https://public-api.chytapay.com.ar/integration-api-swagger`
- Auth API: `https://public-api.chytapay.com.ar/auth-api-swagger`

El spec todavía declara 10.000.000 como tope de monto en el PATCH; la API aplica 200.000.000.

### Colección Postman

Trae un environment de Sandbox (el archivo se llama `Test`) y otro de Producción, con los hosts cargados. Trae todos los endpoints de cobros, el payer-lookup y la corrección del pagador, con fechas de ejemplo que siempre quedan en el futuro.

- Colección: `/api/assets/postman/Chytapay-Integration-API.postman_collection.json`
- Environment de test: `/api/assets/postman/Chytapay-Test.postman_environment.json`
- Environment de producción: `/api/assets/postman/Chytapay-Production.postman_environment.json`

## Preguntas frecuentes

### ¿El límite y el pool son por comercio o por integración?

El tope de mensajes, por integración (suma todos sus comercios). La cuota del payer-lookup, por integración y cuenta de comercio. El pool de CVUs, por cuenta de comercio. Más respuestas en [Preguntas frecuentes](https://chytapay.com.ar/api/preguntas-frecuentes/).

- [Crear cobros](https://chytapay.com.ar/api/crear-cobros/): Campos, estados, duplicados y bulk.
- [Webhooks](https://chytapay.com.ar/api/webhooks/): Firma, reintentos y deduplicación.
- [Conectar comercios](https://chytapay.com.ar/api/conectar-comercios/): OAuth, tokens y sus errores.
- [Conciliación](https://chytapay.com.ar/api/conciliacion/): CUIL, payer-lookup y pagos sin imputar.
