REST API
REST API (Representational State Transfer) es un estilo arquitectónico para diseñar servicios web que utiliza HTTP de manera estandardizada.
¿Qué es REST API?
Imagina que una API es como un menú de restaurante que te permite pedir comida, entonces REST API es un menú muy bien organizado donde cada plato tiene un nombre claro, precio especificado, y instrucciones precisas sobre cómo pedirlo.
REST (Representational State Transfer) es un estilo arquitectónico que define reglas claras sobre cómo diseñar APIs web. Es como tener un manual de buenas prácticas que hace que las APIs sean predecibles, organizadas y fáciles de usar.
REST API te da:
- URLs organizadas y lógicas - Como
/usuarios/123/pedidospara ver pedidos del usuario 123 - Métodos HTTP claros - GET para obtener, POST para crear, PUT para actualizar, DELETE para eliminar
- Sin dependencias entre peticiones - Cada petición es independiente, como ordenar platos por separado
- Respuestas consistentes - Siempre sabes qué formato esperar
- Fácil de cachear - Las respuestas se pueden guardar temporalmente para ser más rápido
REST se volvió el estándar porque hace que trabajar con APIs sea intuitivo: si sabes cómo usar una API REST, puedes entender fácilmente otra API REST diferente.
Principios REST
1. Recursos
Todo en REST es un recurso identificado por una URL:
Usuarios: /api/usuarios
Usuario: /api/usuarios/123
Posts: /api/usuarios/123/posts
Post: /api/usuarios/123/posts/456
2. Métodos HTTP
Usar métodos HTTP para diferentes acciones:
GET → Leer/Obtener
POST → Crear
PUT → Actualizar completo
PATCH → Actualizar parcial
DELETE → Eliminar
3. Representaciones
Los recursos se representan en diferentes formatos:
JSON → application/json
XML → application/xml
HTML → text/html
4. Sin Estado
Cada petición debe contener toda la información necesaria:
# ✓ Bueno: Incluye autenticación
GET /api/usuarios/123 HTTP/1.1
Authorization: Bearer token123
# ✗ Malo: Depende del estado de sesión
GET /api/usuarios/123 HTTP/1.1
# Asume que ya se inició sesión
Diseño de URLs REST
Estructura Básica
# Colección de recursos
GET /api/usuarios # Listar usuarios
POST /api/usuarios # Crear usuario
# Recurso individual
GET /api/usuarios/123 # Obtener usuario 123
PUT /api/usuarios/123 # Actualizar usuario 123
PATCH /api/usuarios/123 # Actualizar parcialmente
DELETE /api/usuarios/123 # Eliminar usuario 123
Recursos Anidados
# Posts de un usuario
GET /api/usuarios/123/posts # Posts del usuario 123
POST /api/usuarios/123/posts # Crear post para usuario 123
# Post específico
GET /api/usuarios/123/posts/456 # Post 456 del usuario 123
PUT /api/usuarios/123/posts/456 # Actualizar post 456
DELETE /api/usuarios/123/posts/456 # Eliminar post 456
Parámetros de Consulta
# Filtrado
GET /api/usuarios?activo=true
GET /api/usuarios?rol=admin
# Paginación
GET /api/usuarios?page=2&limit=10
GET /api/usuarios?offset=20&limit=10
# Ordenamiento
GET /api/usuarios?sort=nombre&order=asc
GET /api/usuarios?sort=-fechaCreacion # - para descendente
# Búsqueda
GET /api/usuarios?q=juan
GET /api/usuarios?search=desarrollador
# Inclusión de relaciones
GET /api/usuarios/123?include=posts,profile
# Selección de campos
GET /api/usuarios?fields=id,nombre,email
Ejemplos de API REST
Obtener Lista de Usuarios
Petición:
GET /api/usuarios?page=1&limit=5 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer eyJ0eXAiOiJKV1Q...
Respuesta:
HTTP/1.1 200 OK
Content-Type: application/json
X-Total-Count: 150
X-Page: 1
X-Per-Page: 5
{
"data": [
{
"id": 1,
"nombre": "Ana García",
"email": "[email protected]",
"fechaCreacion": "2023-01-15T10:30:00Z"
},
{
"id": 2,
"nombre": "Carlos López",
"email": "[email protected]",
"fechaCreacion": "2023-01-16T14:22:00Z"
}
],
"meta": {
"page": 1,
"perPage": 5,
"total": 150,
"totalPages": 30
},
"links": {
"self": "/api/usuarios?page=1&limit=5",
"next": "/api/usuarios?page=2&limit=5",
"last": "/api/usuarios?page=30&limit=5"
}
}
Crear Usuario
Petición:
POST /api/usuarios HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJ0eXAiOiJKV1Q...
{
"nombre": "Juan Pérez",
"email": "[email protected]",
"password": "secreto123",
"rol": "usuario"
}
Respuesta:
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/usuarios/151
{
"id": 151,
"nombre": "Juan Pérez",
"email": "[email protected]",
"rol": "usuario",
"fechaCreacion": "2023-07-27T12:28:53Z",
"fechaActualizacion": "2023-07-27T12:28:53Z"
}
Actualizar Usuario
Petición:
PATCH /api/usuarios/151 HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJ0eXAiOiJKV1Q...
{
"nombre": "Juan Pérez Actualizado"
}
Respuesta:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 151,
"nombre": "Juan Pérez Actualizado",
"email": "[email protected]",
"rol": "usuario",
"fechaCreacion": "2023-07-27T12:28:53Z",
"fechaActualizacion": "2023-07-27T13:45:12Z"
}
Manejo de Errores
Usuario No Encontrado:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"code": "USER_NOT_FOUND",
"message": "El usuario con ID 999 no existe",
"details": {
"resource": "usuarios",
"id": 999
}
}
}
Error de Validación:
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Los datos proporcionados no son válidos",
"fields": {
"email": ["El email ya está en uso"],
"password": ["La contraseña debe tener al menos 8 caracteres"]
}
}
}
Versionado de APIs
En la URL
GET /api/v1/usuarios
GET /api/v2/usuarios
En Headers
GET /api/usuarios HTTP/1.1
API-Version: 2
# o
Accept: application/vnd.api+json;version=2
En Parámetros
GET /api/usuarios?version=2
Autenticación y Autorización
JWT Token
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
API Key
X-API-Key: tu-api-key-secreta
# o en parámetros
GET /api/usuarios?api_key=tu-api-key
OAuth 2.0
Authorization: Bearer oauth-access-token
Mejores Prácticas
1. Usar Sustantivos, No Verbos
✓ GET /api/usuarios
✗ GET /api/obtenerUsuarios
✓ POST /api/usuarios
✗ POST /api/crearUsuario
2. Plurales para Colecciones
✓ /api/usuarios
✗ /api/usuario
3. Estructura Consistente
{
"data": { /* contenido principal */ },
"meta": { /* metadata */ },
"links": { /* enlaces de navegación */ },
"included": { /* recursos relacionados */ }
}
4. Códigos de Estado Apropiados
200 OK → Éxito general
201 Created → Recurso creado
204 No Content → Éxito sin contenido
400 Bad Request → Petición inválida
401 Unauthorized → No autenticado
403 Forbidden → No autorizado
404 Not Found → Recurso no encontrado
422 Unprocessable Entity → Error de validación
500 Internal Server Error → Error del servidor
5. Filtrado y Paginación
# Filtros
GET /api/productos?categoria=electronica&precio_min=100
# Paginación
GET /api/productos?page=2&per_page=20
# Ordenamiento
GET /api/productos?sort=precio&order=desc
6. HATEOAS (Hypermedia as the Engine of Application State)
{
"id": 123,
"nombre": "Juan Pérez",
"links": {
"self": "/api/usuarios/123",
"posts": "/api/usuarios/123/posts",
"profile": "/api/usuarios/123/profile"
}
}
Herramientas para APIs REST
Desarrollo
- Postman: Testing de APIs
- Insomnia: Cliente REST
- Swagger/OpenAPI: Documentación
- JSONPlaceholder: API de prueba
Testing
- Newman: Postman en CLI
- REST Assured: Testing en Java
- SuperTest: Testing en Node.js
- Pytest: Testing en Python
Documentación
- Swagger UI: Interfaz interactiva
- Redoc: Documentación estática
- API Blueprint: Markdown para APIs
- Postman Docs: Documentación automática