HTTP para APIs REST

Fundamentos Beginner 20 min Jan 12, 2026

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:#ffccbc

El 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étodoPropósito¿Tiene cuerpo?¿Idempotente?¿Seguro?
GETRecuperar un recursoNo
POSTCrear un recurso o disparar una acciónNoNo
PUTReemplazar un recurso completamenteNo
PATCHActualizar parte de un recursoNo*No
DELETEEliminar un recursoNoNo
HEADObtener solo cabeceras (sin cuerpo)No
OPTIONSObtener métodos permitidosNo

*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:#e3f2fd

DELETE: 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

RangoCategoríaSignificado
1xxInformativoPetición recibida, procesando
2xxÉxitoLa petición tuvo éxito
3xxRedirecciónSe necesita acción adicional
4xxError del ClienteEl cliente cometió un error
5xxError del ServidorEl 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:#c8e6c9

404 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:#ffccbc

4. 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 recursoGET
Crear un recursoPOST
Reemplazar un recurso completamentePUT
Actualizar parte de un recursoPATCH
Eliminar un recursoDELETE
Verificar si recurso existeHEAD
Obtener métodos permitidosOPTIONS

Selección de Código de Estado

SituaciónUsa
Éxito con datos200 OK
Creó nuevo recurso201 Created
Éxito, sin datos que devolver204 No Content
Procesamiento asíncrono iniciado202 Accepted
Formato de petición inválido400 Bad Request
No autenticado401 Unauthorized
No autorizado403 Forbidden
Recurso no existe404 Not Found
Método no soportado405 Method Not Allowed
Conflicto con estado actual409 Conflict
Formato válido, datos inválidos422 Unprocessable Entity
Demasiadas peticiones429 Too Many Requests
Bug del servidor500 Internal Server Error
Fallo upstream502 Bad Gateway
Temporalmente no disponible503 Service Unavailable

Cabeceras Esenciales

CabeceraDirecciónPropósito
Content-TypeAmbasFormato del cuerpo
AcceptPeticiónFormato de respuesta deseado
AuthorizationPeticiónAutenticación
LocationRespuestaURL de nuevo recurso
Cache-ControlRespuestaReglas de caching
Retry-AfterRespuestaCuá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: