Audiencia
Esta guía es para desarrolladores que trabajan con APIs REST y quieren entender HTTP correctamente:
- Desarrolladores backend que construyen APIs y quieren usar HTTP correctamente
- Desarrolladores frontend que consumen APIs y necesitan entender la semántica de las respuestas
- Diseñadores de APIs que toman decisiones sobre métodos, códigos de estado y cabeceras
- Cualquiera que haya estado confundido sobre por qué una API usa PUT vs PATCH, o 400 vs 422
Deberías entender qué es una API. Si no, empieza con Cómo funciona una API REST.
Objetivo
Después de leer esta guía, entenderás:
- Por qué HTTP es la base de las APIs REST (no solo un transporte)
- Cómo elegir el método HTTP correcto para cada operación
- Qué significan los códigos de estado y cuándo usarlos
- Qué cabeceras importan y por qué
- Qué rompe clientes cuando HTTP se usa mal
Esta guía construye criterio—la capacidad de tomar decisiones HTTP correctas con confianza.
1. HTTP No Es Solo Transporte
Muchos desarrolladores tratan HTTP como una “tubería” para enviar JSON de un lado a otro. Esto es un error.
HTTP Tiene Semántica
HTTP no es solo una forma de mover bytes. Es un protocolo semántico con significado incorporado:
- Los métodos le dicen al servidor qué acción realizar
- Los códigos de estado le dicen al cliente qué pasó
- Las cabeceras llevan metadatos sobre la petición y respuesta
- El caching, los reintentos y los proxies dependen de esta semántica
Cuando ignoras la semántica HTTP, pierdes:
graph LR
A[Ignorar Semántica HTTP] --> B[Sin caching automático]
A --> C[Reintentos inseguros]
A --> D[Comportamiento de proxy roto]
A --> E[Manejo de errores confuso]
A --> F[Soporte deficiente de herramientas]
style A fill:#ffccbcEl Coste de Hacerlo Mal
Si usas POST para todo:
- Los navegadores y CDNs no cachearán respuestas
- La lógica de reintento se vuelve peligrosa (podría duplicar acciones)
- Las herramientas de documentación de API no pueden inferir comportamiento
- Los desarrolladores tienen que leer la documentación para cada endpoint
Si devuelves 200 OK para errores:
- Los sistemas de monitorización no pueden detectar fallos
- Los balanceadores de carga no pueden enrutar alrededor de servidores no saludables
- Los clientes tienen que parsear el cuerpo para saber si funcionó
La semántica HTTP existe por una razón. Úsala.
2. Métodos HTTP: Lo Que Realmente Significan
HTTP define varios métodos. Cada uno tiene un significado específico y comportamiento esperado.
Los Métodos Principales
| Método | Propósito | ¿Tiene cuerpo? | ¿Idempotente? | ¿Seguro? |
|---|---|---|---|---|
| GET | Recuperar un recurso | No | Sí | Sí |
| POST | Crear un recurso o disparar una acción | Sí | No | No |
| PUT | Reemplazar un recurso completamente | Sí | Sí | No |
| PATCH | Actualizar parte de un recurso | Sí | No* | No |
| DELETE | Eliminar un recurso | No | Sí | No |
| HEAD | Obtener solo cabeceras (sin cuerpo) | No | Sí | Sí |
| OPTIONS | Obtener métodos permitidos | No | Sí | Sí |
*PATCH puede ser idempotente si se diseña cuidadosamente.
GET: Recuperar Sin Efectos Secundarios
Las peticiones GET nunca deberían modificar datos. Son “seguras”—puedes llamarlas repetidamente sin cambiar nada.
GET /users/123 HTTP/1.1
Host: api.example.com
Lo que GET garantiza:
- Seguro de cachear
- Seguro de reintentar
- Seguro para que los navegadores hagan prefetch
- Seguro para que los crawlers lo sigan
Qué se rompe cuando violas esto:
# MAL: GET con efectos secundarios
GET /users/123/delete HTTP/1.1
Si un crawler sigue este enlace, borra al usuario. Si un navegador hace prefetch, los datos desaparecen. Nunca uses GET para operaciones destructivas.
POST: Crear o Disparar Acciones
POST es el método “hacer algo”. No es idempotente—llamarlo dos veces podría crear dos recursos.
POST /users HTTP/1.1
Content-Type: application/json
{
"name": "Alice",
"email": "[email protected]"
}
Usa POST cuando:
- Creas un nuevo recurso
- Disparas una acción que no es idempotente
- Envías datos que no deberían estar en una URL
Por qué POST es peligroso de reintentar:
Si un pago falla con un timeout de red, ¿realmente se procesó? Reintentar POST /payments podría cobrar al cliente dos veces. Por eso la idempotencia importa (cubierto en cursos avanzados).
PUT: Reemplazar Completamente
PUT reemplaza el recurso entero. Envía la representación completa, no solo cambios.
PUT /users/123 HTTP/1.1
Content-Type: application/json
{
"name": "Alice Smith",
"email": "[email protected]",
"phone": "+1-555-1234"
}
PUT es idempotente: Llamarlo 10 veces con los mismos datos tiene el mismo efecto que llamarlo una vez. El recurso termina en el mismo estado.
Error común:
# MAL: Enviando solo campos cambiados
PUT /users/123 HTTP/1.1
{
"name": "Alice Smith"
}
Esto establecería email y phone a null (o lo que sea que tu API haga con campos faltantes). Para actualizaciones parciales, usa PATCH.
PATCH: Actualizar Parcialmente
PATCH actualiza campos específicos sin reemplazar el recurso entero.
PATCH /users/123 HTTP/1.1
Content-Type: application/json
{
"name": "Alice Smith"
}
Solo name cambia. Los otros campos permanecen sin cambios.
Decisión PUT vs PATCH:
flowchart TD
A[Necesito actualizar recurso] --> B{¿Enviando representación
completa?}
B -->|Sí| C[Usa PUT]
B -->|No| D{¿Enviando cambios
parciales?}
D -->|Sí| E[Usa PATCH]
D -->|No| F[Reconsidera tu diseño]
style C fill:#e8f5e9
style E fill:#e3f2fdDELETE: Eliminar un Recurso
DELETE elimina el recurso en la URL dada.
DELETE /users/123 HTTP/1.1
DELETE es idempotente: Eliminar un recurso que no existe debería devolver éxito (normalmente 204 o 404, dependiendo de tu diseño). El estado final es el mismo: el recurso ya no existe.
Pregunta común: ¿Debería DELETE tener cuerpo?
Técnicamente permitido, pero muchos proxies y clientes no lo soportan. Evita DELETE con cuerpo.
Métodos Que Raramente Usarás
- HEAD: Como GET pero devuelve solo cabeceras. Se usa para verificar si un recurso existe u obtener metadatos sin descargar el cuerpo.
- OPTIONS: Devuelve métodos permitidos para un recurso. Usado por peticiones preflight de CORS.
3. Códigos de Estado: Comunicando al Cliente Qué Pasó
Los códigos de estado no son solo números—son un protocolo de comunicación entre servidor y cliente.
Las Cinco Familias
| Rango | Categoría | Significado |
|---|---|---|
| 1xx | Informativo | Petición recibida, procesando |
| 2xx | Éxito | La petición tuvo éxito |
| 3xx | Redirección | Se necesita acción adicional |
| 4xx | Error del Cliente | El cliente cometió un error |
| 5xx | Error del Servidor | El servidor falló al cumplir petición válida |
Códigos de Éxito (2xx)
200 OK — La petición tuvo éxito.
Usar para: GET que devuelve datos, PUT/PATCH que devuelve recurso actualizado, POST que devuelve recurso creado.
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 123,
"name": "Alice"
}
201 Created — Se creó un nuevo recurso.
Usar para: POST exitoso que crea un recurso. Incluir cabecera Location con la URL del nuevo recurso.
HTTP/1.1 201 Created
Location: /users/123
Content-Type: application/json
{
"id": 123,
"name": "Alice"
}
204 No Content — Éxito, pero nada que devolver.
Usar para: DELETE que tuvo éxito, PUT/PATCH cuando no necesitas devolver el recurso actualizado.
HTTP/1.1 204 No Content
202 Accepted — Petición aceptada para procesamiento, pero aún no completada.
Usar para: Operaciones asíncronas donde el resultado no está disponible inmediatamente.
HTTP/1.1 202 Accepted
Location: /jobs/456
{
"jobId": 456,
"status": "processing"
}
Códigos de Error del Cliente (4xx)
Estos dicen: “El cliente hizo algo mal.”
400 Bad Request — La petición está malformada o es inválida.
Usar para: JSON inválido, campos requeridos faltantes, errores de validación.
HTTP/1.1 400 Bad Request
{
"error": "Validation failed",
"details": [
{"field": "email", "message": "Formato de email inválido"}
]
}
401 Unauthorized — Autenticación requerida o fallida.
Usar para: Token faltante, credenciales inválidas, sesión expirada.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
{
"error": "Autenticación requerida"
}
403 Forbidden — Autenticado, pero no autorizado.
Usar para: Usuario está logueado pero no tiene permiso.
HTTP/1.1 403 Forbidden
{
"error": "No tienes permiso para acceder a este recurso"
}
401 vs 403:
flowchart TD
A[Petición a
recurso protegido] --> B{¿Token presente?}
B -->|No| C[401 Unauthorized]
B -->|Sí| D{¿Token válido?}
D -->|No| C
D -->|Sí| E{¿Tiene permiso?}
E -->|No| F[403 Forbidden]
E -->|Sí| G[200 OK]
style C fill:#ffccbc
style F fill:#ffccbc
style G fill:#c8e6c9404 Not Found — El recurso no existe.
Usar para: Recurso solicitado no encontrado en esta URL.
HTTP/1.1 404 Not Found
{
"error": "Usuario no encontrado"
}
405 Method Not Allowed — El método no está soportado para este recurso.
Usar para: POST a un endpoint de solo lectura, DELETE cuando la eliminación no está permitida.
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD
{
"error": "DELETE no permitido en este recurso"
}
409 Conflict — La petición entra en conflicto con el estado actual.
Usar para: Creación duplicada, modificación concurrente, conflictos de estado.
HTTP/1.1 409 Conflict
{
"error": "Ya existe un usuario con este email"
}
422 Unprocessable Entity — La petición está bien formada pero es semánticamente inválida.
Usar para: JSON válido pero rechazo por lógica de negocio.
HTTP/1.1 422 Unprocessable Entity
{
"error": "No se puede transferir cantidad negativa"
}
429 Too Many Requests — Límite de tasa excedido.
Usar para: El cliente está enviando demasiadas peticiones.
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
"error": "Límite de tasa excedido",
"retryAfter": 60
}
Códigos de Error del Servidor (5xx)
Estos dicen: “El servidor falló.”
500 Internal Server Error — Algo salió mal en el servidor.
Usar para: Excepciones no manejadas, bugs, fallos inesperados.
HTTP/1.1 500 Internal Server Error
{
"error": "Ocurrió un error inesperado",
"requestId": "abc123"
}
502 Bad Gateway — El servidor upstream devolvió respuesta inválida.
Usar para: API gateway recibió respuesta incorrecta del backend.
503 Service Unavailable — Servidor temporalmente no disponible.
Usar para: Sobrecarga, mantenimiento, interrupción temporal.
HTTP/1.1 503 Service Unavailable
Retry-After: 300
{
"error": "Servicio temporalmente no disponible"
}
504 Gateway Timeout — El servidor upstream no respondió a tiempo.
Usar para: Timeout del backend.
Por Qué Importa 4xx vs 5xx
La distinción es crítica para reintentos:
- Errores 4xx: No reintentar automáticamente—la petición está rota
- Errores 5xx: Puede reintentarse—el servidor podría recuperarse
flowchart TD
A[Petición Falló] --> B{¿Código de Estado?}
B -->|4xx| C[Error del Cliente]
B -->|5xx| D[Error del Servidor]
C --> E[Arreglar la petición
No reintentar]
D --> F[Puede reintentarse
con backoff]
style C fill:#fff9c4
style D fill:#ffccbc4. Cabeceras Que Importan
Las cabeceras llevan metadatos. Algunas son esenciales para APIs REST.
Cabeceras de Petición
Content-Type — Formato del cuerpo de la petición.
Content-Type: application/json
Sin esto, el servidor podría no saber cómo parsear tu cuerpo.
Accept — Formato que quieres en la respuesta.
Accept: application/json
Le dice al servidor que quieres JSON (no HTML, XML, etc.).
Authorization — Credenciales de autenticación.
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Lleva el token de acceso para peticiones autenticadas.
User-Agent — Identificación del cliente.
User-Agent: MyApp/1.0.0 (iOS 16.0)
Ayuda con debugging y analíticas.
Cabeceras de Respuesta
Content-Type — Formato del cuerpo de la respuesta.
Content-Type: application/json; charset=utf-8
Le dice al cliente cómo parsear la respuesta.
Location — URL de un recurso creado o redirigido.
Location: /users/123
Usado con 201 Created y redirecciones 3xx.
Cache-Control — Instrucciones de caching.
Cache-Control: max-age=3600, public
Le dice a clientes y proxies cómo cachear la respuesta.
Retry-After — Cuándo reintentar después de rate limiting o errores.
Retry-After: 60
Usado con 429 y 503. Valor en segundos.
Cabeceras para Metadatos de API
X-Request-Id — Identificador único para la petición.
X-Request-Id: abc123-def456
Esencial para debugging y correlación de logs.
X-RateLimit-* — Información de límite de tasa.
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1609459200
Le dice a los clientes su estado de cuota.
5. Qué Rompe Clientes
Entender qué rompe clientes te ayuda a evitar errores comunes.
Patrón Roto 1: Usar GET para Efectos Secundarios
# Código del servidor
GET /[email protected]
Qué se rompe:
- El prefetching del navegador envía emails
- Los crawlers disparan acciones
- El caching devuelve respuesta antigua pero la acción ya ocurrió
Solución: Usa POST para acciones con efectos secundarios.
Patrón Roto 2: Devolver 200 para Errores
HTTP/1.1 200 OK
{
"success": false,
"error": "Usuario no encontrado"
}
Qué se rompe:
- Los sistemas de monitorización piensan que todo está bien
- Los manejadores de error HTTP no se disparan
- La lógica de reintento no funciona
Solución: Usa códigos de estado 4xx/5xx apropiados.
Patrón Roto 3: Content-Type Inconsistente
# Respuesta exitosa
HTTP/1.1 200 OK
Content-Type: application/json
{"user": {...}}
# Respuesta de error (¡de repente HTML!)
HTTP/1.1 500 Internal Server Error
Content-Type: text/html
<html><body>Ocurrió un error</body></html>
Qué se rompe:
- El parseo de JSON falla en errores
- El manejo de errores se vuelve complejo
- Los clientes no pueden procesar respuestas de forma fiable
Solución: Siempre devuelve el mismo formato (JSON para APIs).
Patrón Roto 4: Content-Type Faltante
HTTP/1.1 200 OK
{"user": {...}}
¡Sin cabecera Content-Type!
Qué se rompe:
- Los clientes pueden adivinar el formato incorrecto
- Algunos clientes HTTP requieren Content-Type explícito
- Los navegadores podrían intentar “sniffear” el tipo de contenido incorrectamente
Solución: Siempre incluye la cabecera Content-Type.
Patrón Roto 5: Códigos de Estado Incorrectos
# MAL: 200 para error de validación
POST /users HTTP/1.1
{"email": "invalid"}
---
HTTP/1.1 200 OK
{"error": "Email inválido"}
Qué se rompe:
- Los clientes piensan que la petición tuvo éxito
- La lógica de manejo de errores no se dispara
- La monitorización muestra falsos positivos
Solución: Usa 400 para errores de validación, 4xx/5xx para fallos.
Patrón Roto 6: Cambiar Comportamiento Sin Aviso
# Antes: PUT reemplaza recurso
PUT /users/123
{"name": "Alice"}
# Otros campos permanecen
# Después: PUT ahora limpia campos faltantes
PUT /users/123
{"name": "Alice"}
# ¡email y phone ahora son null!
Qué se rompe:
- Los clientes existentes pierden datos
- Las integraciones corrompen datos silenciosamente
Solución: Documenta el comportamiento claramente. Versiona APIs para cambios que rompen.
6. Referencia Rápida
Selección de Método
| Quieres… | Usa |
|---|---|
| Obtener un recurso | GET |
| Crear un recurso | POST |
| Reemplazar un recurso completamente | PUT |
| Actualizar parte de un recurso | PATCH |
| Eliminar un recurso | DELETE |
| Verificar si recurso existe | HEAD |
| Obtener métodos permitidos | OPTIONS |
Selección de Código de Estado
| Situación | Usa |
|---|---|
| Éxito con datos | 200 OK |
| Creó nuevo recurso | 201 Created |
| Éxito, sin datos que devolver | 204 No Content |
| Procesamiento asíncrono iniciado | 202 Accepted |
| Formato de petición inválido | 400 Bad Request |
| No autenticado | 401 Unauthorized |
| No autorizado | 403 Forbidden |
| Recurso no existe | 404 Not Found |
| Método no soportado | 405 Method Not Allowed |
| Conflicto con estado actual | 409 Conflict |
| Formato válido, datos inválidos | 422 Unprocessable Entity |
| Demasiadas peticiones | 429 Too Many Requests |
| Bug del servidor | 500 Internal Server Error |
| Fallo upstream | 502 Bad Gateway |
| Temporalmente no disponible | 503 Service Unavailable |
Cabeceras Esenciales
| Cabecera | Dirección | Propósito |
|---|---|---|
| Content-Type | Ambas | Formato del cuerpo |
| Accept | Petición | Formato de respuesta deseado |
| Authorization | Petición | Autenticación |
| Location | Respuesta | URL de nuevo recurso |
| Cache-Control | Respuesta | Reglas de caching |
| Retry-After | Respuesta | Cuándo reintentar |
Qué Sigue
Esta guía cubrió la semántica HTTP a nivel de criterio—cómo pensar sobre HTTP correctamente.
Para temas más profundos como:
- Casos límite en selección de códigos de estado
- Claves de idempotencia y estrategias de reintento
- Manejo de timeouts y circuit breakers
- Estrategias avanzadas de caching
Ve el próximo curso: HTTP para APIs REST en Producción.
Términos Relacionados del Vocabulario
Profundiza tu comprensión:
- HTTP - El protocolo que alimenta las APIs REST
- Métodos HTTP - GET, POST, PUT, PATCH, DELETE
- Códigos de Estado HTTP - El lenguaje de éxito y errores
- Idempotencia - Por qué algunos métodos son seguros de reintentar
- Métodos Seguros - Métodos que no modifican recursos
- Negociación de Contenido - Selección de formato via cabeceras