Lotes y límites
8 en paralelo, dos claves, y qué reintentar.
Un lote de cientos de llamadas no es «lo mismo pero más veces»: hay tres límites que gobiernan el diseño y uno que arruina la factura si se ignora.
Comprobar antes de empezar
Un lote que se queda sin saldo a mitad deja la mitad de las llamadas sin procesar y llena
los logs de 402.
def comprobar(cliente, llamadas_previstas, minutos_medios):
yo = cliente.get(f"{BASE}/me").raise_for_status().json()
print(f"Organización {yo['organization']['slug']} · scopes {yo['key']['scopes']}")
saldo = cliente.get(f"{BASE}/balance").raise_for_status().json()["balance_eur"]
# 0,39 €/h de ASR + 0,29 €/h del pack, sobre minutos empezados.
horas = llamadas_previstas * max(1, round(minutos_medios + 0.5)) / 60
estimado = horas * (0.39 + 0.29)
if saldo < estimado:
raise SystemExit(f"Saldo {saldo:.2f} € insuficiente para ~{estimado:.2f} €.")Los tres límites
| Límite | Valor | Consecuencia de diseño |
|---|---|---|
| Transcripciones en vuelo | 32 por organización | Cola propia de 8 simultáneas |
| Peticiones por minuto | 300 por clave | Dos claves: una transcribe, otra analiza |
| Sondeo | Sin cubo aparte | Sondea solo lo que está en vuelo |
El techo de 32 es el que gobierna el lote. Cuenta como «en vuelo» todo lo que esté en
queued o processing. Con 8 simultáneas nunca se toca; con 40 sí.
El cubo del rate limit es por clave, no por organización. Es una ventana deslizante
de 60 s sobre el identificador de la clave: dos claves distintas son dos cubos. Si el
mismo proceso transcribe y analiza con la misma clave, el sondeo de estado le quita
caudal a las llamadas de negocio. Separarlas cuesta un minuto y evita el 429 que
aparece solo cuando el lote es grande — o sea, en producción y no en las pruebas.
Qué reintentar
- Reintentables:
429,500,503. Espera exponencial con jitter, respetandoRetry-Aftersi viene. - No reintentables:
400,401,403,404,409,413,415,422. Reintentar gasta cuota y no cambia el resultado. 402es un caso aparte: para el lote entero, avisa y recarga.
La idempotencia es lo que evita cobrar dos veces
Un reintento de red sin Idempotency-Key crea una segunda transcripción y la cobra.
Con ella, durante 24 h la misma clave con el mismo cuerpo devuelve la respuesta original
y Idempotency-Replayed: true, gratis.
Usa un valor derivado del trabajo, no un aleatorio: el file_id, o el id de la llamada
en tu sistema con un sufijo de versión (llamada-91823-v1). Un uuid nuevo en cada
ejecución no protege de nada, porque un reintento genera otro uuid.
Y no la mandes en POST /v1/files: ahí el middleware lee el fichero entero en memoria
para hashearlo.
Dónde se va el dinero de verdad
No en la transcripción: en el análisis. Una llamada de 3,5 minutos con los siete módulos
son 0,045 €; el mismo análisis con callsist-llm-1-large en vez de small sube el total
por llamada de 0,076 € a 0,115 €. Sobre 400 llamadas son 30,50 € contra 46,00 €.
Para extracción y clasificación sobre texto dado —que es lo que es aplicar una plantilla
a una transcripción— small es el correcto. Y no mandes reasoning_effort: dejarlo
activo multiplica por 35 los tokens de salida.