Límites de tasa
Shape del 429, dónde viene el tiempo de espera y el patrón de backoff que también cubre los errores transitorios del SII.
La API de Notta protege su estabilidad con límites de tasa (rate limiting). Cuando superas el límite, la API responde 429 con el código rate_limit y el tiempo de espera en detail.retryAfterSec:
Qué límites hay hoy, y dónde
| Freno | Alcance | Ventana | Tope |
|---|---|---|---|
| Emisión por MCP | Por organización | 60 s | El que fije la empresa en /app/mcp (por defecto 60 por minuto) |
| Acuse o reclamo de compras por MCP | Por organización | 60 s | El mismo tope configurable |
Los dos cuentan lo que ocurrió de verdad en la ventana —documentos emitidos por la conexión MCP más pedidos que quedaron esperando aprobación—, así que un umbral de aprobación no vuelve invisible al agente que está en loop.
Las llamadas con API key clásica todavía no tienen un tope por minuto. Lo que sí las
gobierna es la cuota mensual de tu plan (los planes están en https://notta.cl/pricing, y en
markdown en https://notta.cl/pricing.md); cuando el tope por
minuto exista, se anunciará en estos mismos headers antes de aplicarse.
Headers de cuota
Las respuestas de los endpoints con freno anuncian cuánto te queda antes de que topes, en los dos formatos que hoy conviven: el del borrador del IETF y el trío clásico.
q/RateLimit-Limit— el tope de la ventana.w— el largo de la ventana en segundos.r/RateLimit-Remaining— cuánto te queda.t/RateLimit-Reset— segundos hasta que se libere el primer cupo. Es una cota inferior: con la ventana llena, que expire el evento más viejo puede no alcanzar.
Cuando topas, el 429 agrega Retry-After con los mismos segundos. Un endpoint sin freno
propio no manda estos headers: preferimos no anunciar una cuota que nadie está
contando.
Cómo manejarlo
- Respeta
detail.retryAfterSec: espera esa cantidad de segundos antes de reintentar. - Para reintentos sucesivos usa backoff exponencial con jitter.
- El mismo patrón cubre los errores transitorios del SII:
sii_unavailable(503),boleta.rest.unavailableybhe.rest.unavailable(502) traen el mismodetail.retryAfterSec.
No reintentes los demás 4xx: un 400/422 va a fallar igual hasta que corrijas el payload (ver Catálogo de errores).
Estado actual
El contrato 429 / rate_limit / detail.retryAfterSec ya está mapeado y es estable, así que puedes programar tu manejo de reintentos contra él desde ahora. Los frenos por minuto de la tabla de arriba ya se aplican; el enforcement de cuotas por plan se está habilitando.
Próximos pasos
- Catálogo de errores: el shape completo de error y qué códigos se reintentan.
- Paginación: cómo iterar listados sin gatillar el límite con requests gigantes.
- Referencia API de DTEs: los endpoints sujetos a estos límites.
- Webhooks: la forma de no gastar cupo siguiendo el estado de un documento. El push no consume tus límites; el polling sí.
Última actualización