Claves de API y tu primera llamada a un LLM
Con una clave y diez líneas de código tienes un LLM trabajando para ti.
Qué vas a aprender
- Guardar claves de API de forma segura con variables de entorno y archivos
.env - Hacer una llamada a la API de un LLM con el SDK de Python de Anthropic y con HTTP «a pelo»
- Comparar el formato de petición y respuesta del SDK y de HTTP directo para depurar
- Reconocer y gestionar los errores típicos de una API: autenticación y límites de uso
Por qué importa
A partir del módulo 12 (Construir aplicaciones con LLMs) llamarás a APIs de LLMs (Anthropic, OpenAI, Google). En los módulos 15 a 22 construirás herramientas y agentes que usan esas APIs dentro de bucles. Necesitas saber cómo funcionan las claves de API, cómo guardarlas de forma segura y cómo hacer tu primera llamada.
La idea clave
sequenceDiagram
participant C as Tu código
participant S as Servidor de la API
C->>S: Petición HTTP (con la clave de API)
S->>C: Respuesta HTTP (JSON)
Toda llamada a una API tiene: 1. Un endpoint (la URL) 2. Una clave de API (la autenticación) 3. Un cuerpo de petición (lo que quieres) 4. Un cuerpo de respuesta (lo que recibes)
Paso a paso
Paso 1: guarda tus claves de forma segura
Nunca pongas claves de API en el código. Usa variables de entorno.
export ANTHROPIC_API_KEY="sk-ant-..."
export OPENAI_API_KEY="sk-..."
O usa un archivo .env (y añádelo a .gitignore):
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...
Si una clave se filtra, revócala al momento. Hay bots que rastrean GitHub buscando claves publicadas y las usan en minutos. Borrar el commit no basta: la clave sigue en el historial. Entra en el panel del proveedor, revócala y crea una nueva.
Paso 2: tu primera llamada (Python)
Instala el SDK con uv pip install anthropic y ejecuta este código (también lo tienes listo para descargar como primera_llamada.py en «Archivos de la lección», con gestión de errores incluida):
import os
import anthropic
client = anthropic.Anthropic() # lee ANTHROPIC_API_KEY del entorno
MODEL = os.environ.get("LLM_MODEL", "claude-opus-5-5")
response = client.messages.create(
model=MODEL,
max_tokens=1024,
messages=[{"role": "user", "content": "¿Qué es una red neuronal? Responde en una frase."}],
)
for block in response.content:
if block.type == "text":
print(block.text)
LLM_MODEL elige el identificador del modelo de Anthropic (puedes poner uno más económico para practicar). Fíjate en que recorremos response.content: la respuesta es una lista de bloques (texto, razonamiento, llamadas a herramientas…) y solo imprimimos los de tipo text. Otros proveedores (OpenAI, Google…) siguen el mismo patrón de clave + identificador de modelo, pero cada uno tiene su propio SDK, endpoint y formato de petición y respuesta.
Paso 3: tu primera llamada (TypeScript)
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const MODEL = process.env.LLM_MODEL ?? "claude-opus-5-5";
const response = await client.messages.create({
model: MODEL,
max_tokens: 1024,
messages: [{ role: "user", content: "¿Qué es una red neuronal? Responde en una frase." }],
});
for (const block of response.content) {
if (block.type === "text") console.log(block.text);
}
Paso 4: HTTP directo (sin SDK)
import os
import urllib.request
import json
url = "https://api.anthropic.com/v1/messages"
headers = {
"Content-Type": "application/json",
"x-api-key": os.environ["ANTHROPIC_API_KEY"],
"anthropic-version": "2023-06-01",
}
body = json.dumps({
"model": os.environ.get("LLM_MODEL", "claude-opus-5-5"),
"max_tokens": 1024,
"messages": [{"role": "user", "content": "¿Qué es una red neuronal? Responde en una frase."}],
}).encode()
req = urllib.request.Request(url, data=body, headers=headers, method="POST")
with urllib.request.urlopen(req) as resp:
result = json.loads(resp.read())
for block in result["content"]:
if block["type"] == "text":
print(block["text"])
Esto es lo que hacen los SDK por debajo. Entender la llamada HTTP directa te ayuda muchísimo a depurar. Observa que la API de Anthropic usa la cabecera x-api-key en lugar de la más habitual Authorization: Bearer ....
Paso 5: los errores que te vas a encontrar
| Código HTTP | Qué significa | Qué hacer |
|---|---|---|
| 401 | Clave inválida o ausente | Revisa la variable de entorno (¿la has exportado en esta terminal?) |
| 400 | Petición mal formada | Lee el mensaje de error: suele decir exactamente qué campo falla |
| 404 | Modelo o endpoint inexistente | Revisa el identificador del modelo |
| 429 | Has superado el límite de uso (rate limit) | Espera y reintenta con espera exponencial |
| 5xx | Error del servidor o sobrecarga | Reintenta más tarde |
La espera exponencial (exponential backoff) consiste en esperar 1 s, luego 2 s, 4 s, 8 s… entre reintentos, con un máximo. Los SDK oficiales ya reintentan automáticamente los 429 y los 5xx un par de veces, pero en tus propios bucles de agentes tendrás que pensar en ello.
Pruébalo aquí mismo con una API simulada que devuelve 429 las primeras veces (no hace llamadas reales ni espera de verdad: solo calcula cuánto esperaría). Cambia base o maximo y vuelve a ejecutarlo:
import random
def api_simulada(intento):
"""Devuelve 429 (rate limit) en los tres primeros intentos y 200 después."""
return 429 if intento < 3 else 200
def llamar_con_reintentos(max_intentos=6, base=1.0, maximo=8.0):
for intento in range(max_intentos):
codigo = api_simulada(intento)
if codigo == 200:
print(f"Intento {intento + 1}: 200 OK")
return
espera = min(base * 2 ** intento, maximo) + random.uniform(0, 0.5) # con algo de aleatoriedad
print(f"Intento {intento + 1}: {codigo} → esperaría {espera:.1f} s antes de reintentar")
print("Demasiados reintentos: me rindo")
llamar_con_reintentos()
Comprueba también por qué terminó la respuesta: el campo stop_reason vale end_turn si el modelo acabó con normalidad, max_tokens si se cortó por el límite que pusiste y refusal si el modelo declinó responder. Revísalo siempre antes de usar el contenido en producción.
En la práctica
Para este curso:
| API | Cuándo la necesitas | Coste para empezar |
|---|---|---|
| Anthropic (Claude) | Módulos 12-22 (aplicaciones, herramientas y agentes) | De pago por uso; revisa si hay créditos de bienvenida |
| OpenAI | Módulos 12-15 (comparativas) | De pago por uso; revisa si hay créditos de bienvenida |
| Hugging Face | Módulos 6-11 y 24-27 (modelos y datasets) | Gratis para lo que necesitas |
No necesitas todas ahora. Configura cada una cuando una lección te la pida. Y pon un límite de gasto mensual en el panel de cada proveedor: es tu red de seguridad si un bucle se descontrola.
Tu caja de herramientas
Te llevas primera_llamada.py (en «Archivos de la lección»): una llamada completa con gestión de errores que puedes usar como plantilla.
Y un prompt para diagnosticar errores de API con ayuda de un asistente de IA. Cópialo, pégalo y añade el error exacto que te devuelve la API:
Eres un experto en depurar integraciones con APIs de modelos de lenguaje (Anthropic, OpenAI,
Hugging Face). Te voy a pasar un error de API. Ayúdame así:
1. Clasifica el error por su código HTTP:
- 401: clave inválida, caducada o no cargada en la variable de entorno.
- 403: la clave no tiene permiso para ese modelo o recurso.
- 429: límite de uso superado (peticiones o tokens por minuto) o crédito agotado.
- 400: petición mal formada (campo obligatorio, max_tokens, formato de mensajes, modelo).
- 5xx: error o sobrecarga del proveedor.
- Timeout o error de conexión: red, proxy, cortafuegos o respuesta demasiado larga.
2. Dime qué comprobar primero, en orden, con comandos concretos (por ejemplo:
`echo $ANTHROPIC_API_KEY | head -c 10` para ver si la clave está cargada sin mostrarla entera).
3. Dame el código corregido o la configuración exacta que debo cambiar.
4. Si el error es transitorio (429, 5xx, timeout), muéstrame cómo reintentar con espera exponencial.
Nunca me pidas que pegue mi clave de API completa.
Este es mi error:
Retos para tu ordenador
- Consigue una clave de API de Anthropic y haz tu primera llamada
- Prueba la versión con HTTP directo y compara el formato de respuesta con el del SDK
- Usa a propósito una clave incorrecta y lee el mensaje de error
Glosario de la lección
| Término | Como se suele decir | Qué es exactamente |
|---|---|---|
| Clave de API | «La contraseña de la API» | Una cadena única que identifica tu cuenta y autoriza tus peticiones |
| Rate limit | «Me están limitando» | El máximo de peticiones (o tokens) por minuto u hora, para evitar abusos y repartir la capacidad |
| Token | «Una palabra» (en contexto de API) | La unidad de facturación: los tokens de entrada y de salida se cuentan y cobran por separado |
| Streaming | «Respuestas en tiempo real» | Recibir la respuesta poco a poco, a medida que se genera, en lugar de esperar a que termine |