HTTP y APIs en 10 Minutos

Toda app que has usado son dos computadoras pasándose notas. HTTP es el formato de la nota — y es tan simple que puedes leerlo en crudo. Esta página: el modelo de petición/respuesta, lo que los códigos de estado realmente te dicen (401 vs 403, resuelto para siempre), REST sin la teología, y la verdad sobre el error de CORS.

🎙️ Publicado y grabado:

01El modelo: dos notas, y luego silencio

Todo HTTP es un intercambio: el cliente envía una petición (una nota estructurada), el servidor devuelve una respuesta (otra nota), y entonces — esta es la parte que la gente no pilla — el servidor olvida que exististe. HTTP es stateless. Toda "experiencia de sesión iniciada" que has vivido se construye re-mostrando un carné (una cookie o token) en cada nota.

## la petición — literalmente así de legible:
GET /users/42 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbG...

## la respuesta:
HTTP/1.1 200 OK
Content-Type: application/json

{"id": 42, "name": "Ada"}
Por qué te importa la ausencia de estado
Es la razón de que tu sesión "expire" en medio de una acción, de que una API necesite la clave en cada llamada (no solo la primera), y de que los balanceadores de carga funcionen — cualquier servidor puede responder cualquier nota, porque ninguna depende de una anterior. Cuando la auth "deja de funcionar aleatoriamente", el carné dejó de adjuntarse, no la memoria del servidor.

02Anatomía de una URL

Una URL es una dirección con cuatro partes funcionales: el protocolo, el edificio (host), la habitación (path) y las notas adhesivas en la puerta (query parameters). Aprende a leerlas y la documentación de APIs deja de dar miedo.

https://api.example.com/users/42/orders?status=paid&limit=10
└─┬──┘  └──────┬──────┘└──────┬──────┘ └────────┬─────────┘
scheme        host           path         query params
(cómo)      (qué servidor)  (qué cosa)   (opciones: clave=valor, separadas con &)
La regla que se aprende por las malas
Los query params se registran en todas partes — logs del servidor, proxies, historial del navegador, analytics. Por eso los secretos nunca van en URLs: ?api_key=sk_live_... es una clave que ya deberías considerar filtrada. Los secretos viajan en headers (sección 07), que no se registran por defecto.

03Métodos: el verbo en el sobre

El método le dice al servidor qué tipo de nota es. Cinco cubren todo: GET lee, POST crea, PUT reemplaza, PATCH edita una parte, DELETE borra. El concepto que vale la pena entender: idempotencia — ¿puedo enviar esto dos veces sin problema?

GET    /users/42          # leer — nunca cambia nada
POST   /users             # crear uno nuevo  ⚠ dos veces = dos usuarios
PUT    /users/42          # reemplazar entero — dos veces = mismo resultado
PATCH  /users/42          # cambiar algunos campos
DELETE /users/42          # borrar — dos veces = sigue borrado
Por qué la idempotencia es un concepto de la vida real
"No hagas clic en Pagar dos veces" es un bug de idempotencia. GET, PUT, DELETE son seguros de reintentar; POST no — por eso las APIs de pago te obligan a enviar un header Idempotency-Key, para que una petición reintentada cree un cobro, no dos. Cuando la red se corta a mitad de un POST, "¿se procesó o no?" es la razón entera de que exista esta palabra.

04Códigos de estado: quién la regó

El primer dígito es toda la historia: 2xx funcionó, 3xx se movió, 4xx la regaste , 5xx la regaron ellos. Esa sola frase clasifica todo error de API que verás en "arregla mi petición" vs "espera / repórtalo". Y la pareja eterna de confusión, resuelta:

200 OK               # aquí tienes
201 Created          # creado (respuesta a un POST exitoso)
301 Moved            # nueva dirección, ve allí
400 Bad Request      # tu nota está malformada (JSON malo, campo faltante)
401 Unauthorized     # ¿QUIÉN ERES? — sin credenciales o inválidas
403 Forbidden        # Sé quién eres. No. — login válido, sin permisos
404 Not Found        # no existe nada en esta ruta
429 Too Many Requests # más lento (rate limit — espera y reintenta)
500 Internal Error   # el servidor crasheó. no es tu culpa
503 Unavailable      # servidor sobrecargado/caído. tampoco es tu culpa
401 vs 403, de una vez por todas
401 = el portero no puede leer tu identificación (token ausente, expirado o malformado → revisa tu header de auth). 403 = tu identificación está bien, simplemente no estás en la lista (→ revisa permisos/scopes, no el token). Los nombres están al revés ("Unauthorized" en realidad significa no autenticado) — un accidente de nomenclatura de hace 50 años con el que todos convivimos.

05Headers y body: el sobre y la carta

Los headers son metadatos en el sobre — qué formato, qué idioma, quién pregunta, qué credenciales. El body es la carta dentro — para APIs, casi siempre JSON. Vas a configurar dos headers constantemente y leer un tercero:

Content-Type: application/json    # "el body que ENVÍO es JSON"
Authorization: Bearer <token>     # "aquí va mi carné"
Accept: application/json          # "por favor RESPONDE en JSON"

# el body (POST /users):
{ "name": "Ada", "country": "UK" }
Esto te va a pasar
Envías un POST con JSON perfecto y recibes 400 Bad Request o un misterioso null en todo — porque olvidaste Content-Type: application/json, y el servidor interpretó tu JSON como un envío de formulario. El body estaba bien. La etiqueta del sobre estaba mal. Este solo header explica una década de preguntas en Stack Overflow.

06curl: habla con cualquier API desde la terminal

curl envía peticiones HTTP desde la línea de comandos. Es cómo pruebas una API sin tu app de por medio — la mejor jugada de debugging: si curl funciona y tu código no, el bug está en tu código; si curl también falla, es la API. Divide y vencerás.

# leer
curl https://api.example.com/users/42

# crear (-X método, -H header, -d body)
curl -X POST https://api.example.com/users \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"name": "Ada"}'

# ver el CÓDIGO DE ESTADO y headers también (la vista de debugging)
curl -i https://api.example.com/users/42

07Auth: API keys y bearer tokens

Dos patrones cubren la mayoría de APIs. Un API key es una contraseña de larga duración para un programa. Un bearer token suele ser de corta vida, se obtiene al iniciar sesión, y se presenta como Authorization: Bearer … — "bearer" literalmente significa quien cargue esto, es esto. Lo cual es el modelo de seguridad y la advertencia de seguridad en una sola palabra.

# ambos viajan en el header Authorization:
Authorization: Bearer eyJhbGciOi...     # token (a menudo un JWT)
x-api-key: sk_live_4242...              # algunas APIs usan un header custom

# las claves viven en variables de entorno, nunca en el código:
curl -H "Authorization: Bearer $API_TOKEN" ...
Los tres mandamientos
Nunca en URLs (se registran en todas partes — sección 02). Nunca en git (los scrapers las encuentran en minutos — ver la página de Git para el protocolo de emergencia). Nunca en código frontend (ver código fuente = filtrada). Las claves viven en variables de entorno y gestores de secretos, y en el momento en que una pueda haberse filtrado, la rotas primero e investigas después.

08REST, sin la teología

REST es una convención de nombres, no una tecnología: las URLs nombran cosas (sustantivos), los métodos dicen qué hacer con ellas (verbos). Eso es el 90%. Una API es "RESTful" cuando puedes adivinar el siguiente endpoint sin leer la documentación — la predictibilidad es todo el punto.

# sustantivos en la URL, verbos en el método:
GET    /articles          # listar artículos
POST   /articles          # crear uno
GET    /articles/7        # leer uno
PATCH  /articles/7        # editarlo
DELETE /articles/7        # eliminarlo
GET    /articles/7/comments   # anidado: sus comentarios

✗ POST /getArticleById   ✗ GET /deleteUser?id=7  # verbos en URLs = mal olor
Opinión honesta
Te encontrarás con gente que discute sobre "REST verdadero" (HATEOAS, la tesis de Roy Fielding…). Sonríe y sigue adelante. En la práctica, "REST API" significa exactamente lo que muestra esta sección: URLs predecibles con sustantivos + verbos estándar + JSON. Ese vocabulario te lleva por cualquier codebase real y respuesta de entrevista que necesites.

09CORS: el error que no es lo que parece

Un día tu frontend llama a una API y la consola explota. El giro que todos se pierden: este error no es el servidor rechazándote — es tu propio navegador, aplicando una regla de seguridad: JavaScript del sitio A no puede leer respuestas del sitio B a menos que B lo permita explícitamente (mediante un header Access-Control-Allow-Origin). La prueba: la misma petición funciona perfecto en curl.

Access to fetch at 'https://api.other.com/data' from origin
'http://localhost:3000' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present...

# decodificando: api.other.com no dijo que localhost:3000 puede leerlo.
# el navegador obtuvo los datos — y luego se los ocultó a tu JS.
Quién puede realmente arreglarlo
Solo el servidor puede arreglar CORS (enviando el header de permiso) — ninguna cantidad de código frontend lo hace desaparecer legítimamente. Tus opciones: es tu API → añade el header para el origin de tu frontend; es de otro → llámala desde tu backend y que tu frontend te llame a ti (los backends no son navegadores; CORS no les aplica). Las extensiones de navegador que "desactivan CORS" arreglan tu máquina y luego fallan para todo usuario real.

10Chuleta

Las tablas mentales que responden el 90% de preguntas sobre APIs.

# métodos
GET leer · POST crear (⚠ no seguro de reintentar) · PUT reemplazar
PATCH editar · DELETE eliminar

# estado: primer dígito = quién la regó
2xx ✓ · 3xx se movió · 4xx tú · 5xx ellos
401 ¿quién eres? → arregla el token
403 ¿tú específicamente? no. → arregla los permisos
429 más lento → espera y reintenta

# el POST que "misteriosamente" falla
→ ¿enviaste Content-Type: application/json ?

# orden de debugging
curl -i primero. código después.
curl funciona + código falla → tu bug
curl también falla          → su bug (o tu token)

# error de CORS en la consola
→ regla del navegador, el servidor debe permitirlo. curl prueba que la API funciona.

# secretos
headers ✓ · env vars ✓ · URLs ✗ · git ✗ · frontend ✗

Ese es el núcleo funcional. Todo lo más avanzado — webhooks, GraphQL, gRPC — es una variación de las mismas dos notas. Cuando quieras llamar APIs desde código, Python más esta página es un toolkit completo.