Ir al contenido

Errores y límites

Todos los errores tienen la misma forma: un objeto con una sola clave error, cuyo mensaje está en español y es apto para mostrarle a una persona.

{ "error": "No se encontró el CUIT solicitado." }
Código Cuándo Qué hacer
400 Parámetros inválidos Corregí el pedido. El mensaje dice qué campo falla.
401 Token ausente o inválido Revisá el header Authorization. Ver Autenticación.
403 Tu suscripción no está activa, o tu cuenta no tiene habilitada la escritura por API Ver Sobre el 403.
404 El CUIT no existe o no es tuyo Verificá el CUIT y que esté cargado en tu cuenta.
409 El pedido choca con el estado actual de tu cuenta Aparece en POST y en DELETE. Reintentarlo igual no cambia nada.
415 El cuerpo no viajó como application/json Solo aparece en POST y PATCH. Agregá el header Content-Type.
429 Se superó un límite de uso Esperá lo que indique Retry-After.
500 Error interno Reintentá; si persiste, escribinos.

Un 403 tiene dos motivos y el mensaje te dice cuál es.

Si tu suscripción no está activa, lo vas a ver en todos los endpoints, también en los de lectura. El mensaje cambia según por qué se cortó. Si Mercado Pago no pudo cobrar el último pago:

{ "error": "Mercado Pago pausó tu suscripción porque no pudimos procesar el último pago. Reactivala en https://app.afippi.com/dashboard/subscription para volver a acceder a tus datos." }

Y si la suscripción terminó o nunca se activó:

{ "error": "Tu suscripción no está activa. Suscribite en https://app.afippi.com/dashboard/subscription para volver a acceder a tus datos." }

En los dos casos se arregla desde el panel de Afippi, y el acceso vuelve en el pedido siguiente: no hace falta generar un token nuevo.

El otro motivo es que tu cuenta no tenga habilitada la escritura por API. Ese solo aparece en los endpoints de escritura y no se activa desde el panel: lo habilita el equipo de Afippi. Ver Escritura.

Un CUIT que no existe y un CUIT que existe pero pertenece a otra cuenta responden exactamente lo mismo. Es deliberado: si respondiéramos distinto, cualquiera podría usar la API para averiguar qué CUITs administran otros estudios.

POST /v1/cuits responde 409 cuando el CUIT ya está cargado en tu cuenta:

{ "error": "El CUIT ya está registrado" }

Es lo que hace innecesaria una idempotency key: si un POST se corta por timeout y lo reintentás, el segundo pedido responde 409 en vez de duplicar el cliente. Un 409 después de un reintento significa que el primero funcionó.

DELETE /v1/cuits/{cuit} responde 409 cuando el cliente representa a alguna sociedad cargada en tu cuenta: borrala, o cambiale el representante, y reintentá.

Cuando fallan varios campos, los mensajes se concatenan en un solo error:

{ "error": "'from_date' debe tener formato YYYY-MM-DD. 'offset' debe ser un entero mayor o igual a 0." }

Hay dos límites y se aplican por usuario, no por token: generar un token nuevo no reinicia ninguno de los dos contadores.

Límite Ventana
100 pedidos por minuto
200.000 pedidos por mes calendario

El mes calendario se calcula en UTC: el contador vuelve a cero el día 1 a las 00:00 UTC, no a la medianoche argentina.

{ "error": "Se superó el límite de solicitudes. Intentá nuevamente más tarde." }

Con status 429 y estos headers:

Header Qué dice
Retry-After Segundos a esperar antes de reintentar
X-RateLimit-Limit El límite que se superó (100 o 200000)
X-RateLimit-Remaining Siempre 0 en un 429
X-RateLimit-Reset Timestamp Unix en el que se libera el límite

Mirá X-RateLimit-Limit para saber cuál de los dos límites tocaste: si dice 200000, esperar unos segundos no te va a servir.

Ante un 429, esperá lo que diga Retry-After en vez de reintentar de una. Ante un 500, un backoff exponencial con algo de jitter es lo razonable. No reintentes 400, 401, 403, 404, 409 ni 415: el resultado va a ser el mismo.

GET /healthcheck responde OK en texto plano si la API está en servicio. Es público, no consume cuota y no requiere token.