Batch API de Anthropic: procesa facturas a mitad de precio

Resumen

La Batch API de Anthropic te permite procesar miles de peticiones en lote pagando la mitad del costo, ideal para tareas sin urgencia. Si trabajas con Claude y manejas volúmenes grandes, aquí aprendes cuándo conviene el procesamiento asíncrono frente al tiempo real.

Imagina que tienes 1.000 facturas del mes para procesar. Si las mandas una por una, esperando cada respuesta antes de lanzar la siguiente, avanzas lento: una termina, sale la próxima, y así 1.000 veces mientras tú esperas. Y lo absurdo es que ninguna de esas facturas la necesitas ya mismo. El reporte es para fin de mes. Le estás exigiendo velocidad de tiempo real a un trabajo que nadie necesita con urgencia.

Por qué la Batch API cuesta la mitad que el tiempo real

Ese desperdicio es justo lo que elimina el procesamiento en lote. Le entregas las 1.000 peticiones de un solo envío y le dices, en la práctica, "no tengo prisa, procésalas cuando puedas". Por aceptar esa espera pagas la mitad.

  • 50% menos en lo que entra y en lo que sale de la API.
  • La misma calidad de respuesta y el mismo modelo.
  • El límite formal es de un día, pero casi siempre termina en menos de una hora.

Lo único que cambia es que dejas de pagar un sobreprecio por una urgencia que no tenías.

¿Qué es la Batch API de Anthropic? Es un modo de procesamiento asíncrono donde envías muchas peticiones juntas y Claude las resuelve cuando puede, en lugar de al instante. A cambio pagas 50% menos, con la misma calidad y el mismo modelo. [00:52]

Cómo armar el request por factura en Python

Para el ejemplo, generamos un resumen de un listado de facturas guardado en un archivo TXT. Todo arranca en el archivo main.py importando las dependencias necesarias.

  • os para variables de entorno.
  • time para hacer un delay entre consultas.
  • path para leer y escribir archivos.
  • La librería de Anthropic y varios types de Anthropic.

Definimos el modelo que venimos usando, claude-sonnet-4.6, y un objeto invoices con tres facturas de datos simulados. Lo más importante del inicio es que pedimos un request por factura.

Definimos una variable request con un array que engloba, por cada elemento, el custom_id (que es el invoice ID) y los parámetros con MessageCreateParamsNonStream. Dentro va la misma estructura del endpoint de messages: el modelo, el max_tokens y un mensaje del usuario con el contenido "Resume esta factura en una línea". Esa es la instrucción para cada factura, recorriendo cada invoice ID dentro de invoices.items.

Qué diferencia a batches de messages create

El paso dos define una variable batch usando client.messages pero con un agregado clave: batches. Ese es el que le indica a la API que no necesitamos respuesta inmediata, que la tome a su debido tiempo y que nos cobre la mitad.

Dentro va un parámetro requests, que ya teníamos definido arriba. Al crearlo, la API imprime que hay un batch creado con su batch ID y el status de ese batch.

¿Para qué sirve el custom_id en un batch? Es un identificador que le pones a cada petición para reconocer su resultado después. Cuando llegan las respuestas, cruzas el custom_id con cada factura y sabes cuál corresponde a cuál. [02:38]

Cómo consultar el estado de un batch asíncrono

Como el batch es asíncrono, puede tardar hasta 24 horas según la documentación de Anthropic. Por eso esperamos con un límite de tiempo en lugar de quedarnos colgados hasta que termine.

Para eso definimos un poll_interval, una espera máxima y un tiempo transcurrido que arranca en cero. Cada vuelta obtenemos el estado real desde client.messages.batches consultando por el batch ID.

  1. Si el estado es exactamente ended, el batch terminó y rompemos la espera.
  2. Si el tiempo supera nuestro límite, imprime que el batch sigue en proceso y sugiere consultar más tarde con el ID.
  3. Agregamos time.sleep con el poll_interval para no ejecutar miles de llamados por segundo.

Así evitamos saturar la API con consultas y respetamos un intervalo, en el ejemplo de 10 segundos, que se suma al tiempo total de espera. [04:11]

Cómo guardar los resultados en un archivo TXT

Con los resultados listos, escribimos un archivo llamado resumenes_facturas.txt. Definimos un array vacío de líneas y recorremos cada resultado de client.messages.batches.results con ese batch ID.

  • Validamos si el resultado es succeed, es decir, exitoso.
  • Si lo es, obtenemos el texto final, pero solo si el bloque es de tipo text.
  • Si no lo es, marcamos que ese resultado falló e imprimimos el custom_id.

Al final unimos todas las líneas con codificación UTF-8 y mostramos el mensaje "Resúmenes guardados en" con el path del archivo. [05:16]

Qué pasa al ejecutar el batch en la terminal

Al correr el código, primero aparece que el batch está creado con su identificador y que está in progress a los cero segundos. Esa consulta se repite cada 10 segundos, tal como lo configuramos.

A los 60 segundos, que era el máximo que marcamos, nos avisa que el batch sigue en proceso y que consultemos más tarde con ese ID. Como no alcanzamos a ver el proceso terminado, subimos el límite de 60 a 300 segundos, o sea cinco minutos.

Luego de dos minutos, hizo todos los llamados cada 10 segundos y finalmente entregó el resumen y escribió resumenes_facturas.txt. Al abrirlo, están los invoice uno, dos y tres, cada uno resumido en una sola línea. Cumplió el prompt al pie de la letra.

Tienes toda la información de cada factura y un archivo externo listo para usar donde lo necesites. La contra es el delay: no es inmediato, pero cuesta la mitad usando el mismo modelo.

Cuándo elegir tiempo real y cuándo elegir lote

Ahora tienes dónde elegir. Si hay alguien esperando una respuesta, vas en tiempo real. Si el trabajo puede esperar a mañana, lo mandas en lote y pagas la mitad por el mismo proceso.

Esa elección, repetida en miles de requests, es la diferencia entre una cuenta de cientos de dólares y una de miles. Pero todo esto da por sentado algo importante: que la API responde cuando se lo pides, y no siempre lo hace.

Cuando mandas muchos requests muy seguido, la API te frena, te corta o se cae a mitad del envío. Probando solo en tu máquina casi nunca aparece, pero el día que tengas usuarios y volumen de verdad, lo vas a ver seguido.

¿Ya tienes un caso donde te convenga procesar en lote en vez de tiempo real? Cuéntame en los comentarios cómo lo aplicarías.