[!tip] REST en una frase
REST es un estilo de arquitectura para diseñar APIs web que usan HTTP como protocolo, con recursos identificables por URLs, métodos HTTP semánticos y respuestas en formato JSON.
¿Qué es REST?
REST (Representational State Transfer) es un conjunto de principios (no un protocolo) propuesto por Roy Fielding en 2000. Define cómo diseñar servicios web que sean:
Escalables: El servidor puede manejar miles de peticiones sin colapsar
Stateless: Cada petición contiene toda la información necesaria
Interoperable: Cualquier cliente (navegador, móvil, IoT) puede hablar con cualquier servidor
Capas: Se pueden interponer proxies y caches entre cliente y servidor
Opcional: el servidor puede enviar código ejecutable
❌ Raro de usar
REST es un estilo, no una norma
[!warning] "REST" es mal usado
Muchas APIs que se llaman "REST" no son realmente RESTful. Lo común hoy en día es una API HTTP con JSON que usa métodos y status codes correctamente. Eso es lo que vamos a cubrir.
De lo que NO trata REST:
No es un protocolo
No requiere XML (aunque se podía)
No requiere HATEOAS
No requiere verbos custom
Recursos y URLs
En REST, todo es un recurso. Un recurso es cualquier cosa que quieras exponer: usuarios, productos, artículos, etc.
Principio de URLs
# Colección → GET /recursos (lista todos)
GET /users → Lista todos los usuarios (200)
POST /users → Crea un usuario (201)
# Recurso individual → GET /recursos/:id
GET /users/42 → Obtiene el usuario con ID 42 (200)
PUT /users/42 → Reemplaza el usuario 42 (200)
PATCH /users/42 │ Actualiza parcialmente el usuario 42 (200)
DELETE /users/42 │ Elimina el usuario 42 (204)
# Recursos anidados → /padre/:id/hijo
GET /users/42/posts → Posts del usuario 42
POST /users/42/posts → Crea un post para el usuario 42
GET /users/42/posts/7 → El post 7 del usuario 42
# Filtrado, paginación, ordenación
GET /users?role=admin&status=active
GET /users?page=2&limit=20
GET /users?sort=-created_at # - para descendente
[!tip] URLs deben ser sustantivos, no verbos
MALO: verbos en la URL
GET /getUsers
POST /createUser
DELETE /deleteUser/42
BUENO: recursos + métodos HTTP
GET /users
POST /users
DELETE /users/42
### Recursos vs acciones
MALO: acción en la URL
POST /users/42/disable
POST /users/42/enable
BUENO: PATCH con campo de estado
PATCH /users/42
{ "status": "disabled" }
MALO: acción en la URL
POST /posts/7/comments
BUENO: recurso anidado
POST /posts/7/comments
> [!caution] Anidación profunda
> ```
# MALO: 3 niveles de anidación
GET /users/42/posts/7/comments/15/replies
# BUENO: máximo 1-2 niveles, o IDs directos
GET /comments/15/replies
GET /replies?comment_id=15
Métodos HTTP semánticos
Cada método tiene un significado específico. Úsalos correctamente:
Método
Usar para
Idempotente
Seguro
GET
Leer recursos
✅
✅
POST
Crear recursos, ejecutar acciones
❌
❌
PUT
Reemplazar recurso completo
✅
❌
PATCH
Actualización parcial
❌
❌
DELETE
Eliminar recurso
✅
❌
POST para acciones
POST no es solo para crear recursos. Úsalo para acciones que no encajan en CRUD:
# Acciones que no son CRUD
POST /users/42/reset-password
POST /sessions → Login (crea una sesión)
POST /payments/process → Procesar pago
POST /export/pdf → Generar PDF
# Pero si la acción es un recurso en sí mismo, usa POST al recurso:
POST /payments → Crea un nuevo pago
[!tip] ¿Cuándo crear un recurso vs ejecutar una acción?
Si la acción tiene un ID, tiene historial, o puedes listar múltiples, es un recurso:
"Hacer un pago" → POST /payments (sí, es recurso)
"Resetear password" → POST /users/42/reset-password (no es recurso, no se puede listar)
"Publicar un post" → POST /posts (sí, es recurso)
"Hacer logout" → POST /sessions/current (debatible — muchos lo tratan como recurso)
Respuestas JSON
Las APIs modernas devuelven JSON como formato principal:
{ "error": { "code": "USER_NOT_FOUND", "message": "User with id 999 not found", "status": 404 }}
[!tip] Estructura de error consistente
Usa siempre la misma estructura para errores. Así el frontend puede manejarlos unificados:
{
"error": {
"code": "STRING_CODE",
"message": "Descripción legible para el usuario",
"details": { /* campos con errores de validación */ },
"status": 400
}
}
## HATEOAS (Hypermedia as the Engine of Application State)
HATEOAS es el principio más controvertido de REST. Significa que las respuestas del servidor incluyen **links** que el cliente puede seguir:
```json
{
"id": 42,
"name": "Carlos",
"email": "carlos@email.com",
"links": {
"self": "/users/42",
"posts": "/users/42/posts",
"comments": "/users/42/comments",
"update": {
"method": "PATCH",
"href": "/users/42"
},
"delete": {
"method": "DELETE",
"href": "/users/42"
}
}
}
[!note] HATEOAS en la práctica
HATEOAS es muy poco usado en APIs REST modernas. La razón:
Agrega complejidad al servidor (generar links dinámicamente)
Agrega complejidad al cliente (necesita entender la estructura de links)
La mayoría de APIs usan OpenAPI/Swagger para documentación en lugar de HATEOAS
Veredicto: No lo uses a menos que tengas un motivo específico. Las APIs REST modernas casi nunca lo implementan.
GraphQL vs REST vs RPC
Comparación
Característica
REST
GraphQL
RPC (gRPC, JSON-RPC)
Endpoint
Varios (/users, /posts)
Uno (/graphql)
Varios o uno
Datos
Datos fijos por endpoint
Cliente pide exactamente lo que necesita
Datos fijos
Overfetching
Posible (recibe todos los campos)
No (piden solo lo necesario)
Depende
Underfetching
Posible (necesita múltiples llamadas)
No (todo en una llamada)
Depende
Type system
Ninguno (OpenAPI opcional)
Schema fuerte
Protocol buffers / strong typing
Caching
HTTP cache nativo
Necesita caché a nivel cliente
No (cada llamada es nueva)
Learning curve
Baja
Media-Alta
Alta
Herramientas
HTTP + JSON
GraphQL playground
gRPC tools, etc.
¿Cuándo usar cada uno?
Escenario
Recomendación
Por qué
API pública
REST
Simple, estandarizado, cachéable
App móvil
REST o GraphQL
REST si la API es simple, GraphQL si necesitas flexibilidad
Dashboard interno
GraphQL
Equipo pequeño, muchos tipos de datos diferentes
Microservicios
gRPC
Alta performance, strong typing
Pocos endpoints
REST
Simple, rápido de implementar
Muchas variantes de datos
GraphQL
Un endpoint, datos flexibles
[!tip] REST y GraphQL no son mutuamente excluyentes
Muchos proyectos usan ambos: REST para la API pública, GraphQL para el dashboard interno. O viceversa.
Versionado de APIs
# Versionado en la URL (más común)
/api/v1/users
/api/v2/users
# Versionado en header
Accept: application/vnd.ejemplo.v1+json
# Versionado en query param
/users?version=1
[!tip] Versionado en URL es lo más práctico
GET /api/v1/users → fácil de debuggear, fácil de entender
Accept: application/vnd.ejemplo.v1+json → más REST puro pero más complejo
Nunca hagas breaking changes en la misma versión
Documentación de APIs
# OpenAPI / Swagger (REST)
https://editor.swagger.io/
Genera documentación interactiva desde un archivo YAML/JSON
# GraphQL
GraphQL tiene introspection integrada
http://localhost:4000/graphql → Playground automático
# Postman Collections
Colecciones de peticiones que se pueden ejecutar directamente
Errores comunes en APIs REST
Error
Correcto
Incorrecto
Verbos en URLs
DELETE /users/42
DELETE /users/42/delete
Colecciones en singular
GET /users
GET /user
No usar 404
GET /users/999 → 404
GET /users/999 → 200 { "null" }
No usar 405
POST /users/42 → 405
POST /users/42 → 200 con mensaje de error
JSON dentro de array innecesario
{ "data": [...] }
[{...}, {...}] (sin wrapper)
Campos camelCase vs snake_case
user_id o userId (consistente)
Mezclar ambos
Fechas sin ISO 8601
"2024-01-15T10:00:00Z"
"15/01/2024" o timestamp
No paginar listas largas
?page=1&limit=20
GET /users → [10000 elementos]
Resumen
REST se basa en recursos identificados por URLs + métodos HTTP semánticos
Las respuestas son JSON con estructura consistente
HATEOAS es un principio REST pero casi nunca se usa en la práctica
Versionado en URL (/api/v1/) es el enfoque más práctico
OpenAPI/Swagger es el estándar para documentación de APIs REST
[!quote] La clave
REST no es una norma estricta, es un conjunto de principios. Las APIs modernas que llaman "REST" suelen ser APIs HTTP con JSON que siguen los principios básicos (recursos + métodos + status codes) sin llegar a ser "puros" REST.