Principios fundamentales del diseño de APIs REST
Una API REST bien disenada es predecible, consistente y fácil de consumir. No se trata solo de devolver JSON desde un servidor: se trata de crear un contrato claro entre tu backend y los clientes que lo consumen.
Nomenclatura de recursos
Reglas para URLs
Los endpoints deben ser sustantivos en plural que representen recursos, no acciones:
BIEN:
GET /api/v1/users -> listar usuarios
GET /api/v1/users/123 -> obtener un usuario
POST /api/v1/users -> crear un usuario
PUT /api/v1/users/123 -> actualizar un usuario completo
PATCH /api/v1/users/123 -> actualizar parcialmente
DELETE /api/v1/users/123 -> eliminar un usuario
MAL:
GET /api/v1/getUsers
POST /api/v1/createUser
POST /api/v1/deleteUser/123
GET /api/v1/user/listRecursos anidados
Para relaciones, usa anidamiento hasta dos niveles como máximo:
GET /api/v1/users/123/courses -> cursos del usuario
GET /api/v1/courses/456/lessons -> lecciones del curso
GET /api/v1/courses/456/lessons/789 -> una leccion específica
# Evitar anidamiento excesivo
MAL: /api/v1/users/123/courses/456/lessons/789/comments
BIEN: /api/v1/lessons/789/commentsConvenciones de nomenclatura
| Regla | Ejemplo |
|---|---|
| Usar kebab-case | /learning-paths no /learningPaths |
| Sustantivos en plural | /courses no /course |
| Minusculas | /blog-posts no /Blog-Posts |
| Sin trailing slash | /users no /users/ |
| Sin extensiones | /users no /users.json |
Métodos HTTP correctos
| Método | Uso | Idempotente | Body |
|---|---|---|---|
| GET | Leer recurso(s) | Si | No |
| POST | Crear recurso | No | Si |
| PUT | Reemplazar recurso completo | Si | Si |
| PATCH | Actualizar parcialmente | No* | Si |
| DELETE | Eliminar recurso | Si | No |
| HEAD | Verificar existencia | Si | No |
| OPTIONS | Obtener métodos permitidos | Si | No |
*PATCH puede ser idempotente dependiendo de la implementación.
Codigos de estado HTTP
Usar los códigos correctos es fundamental para que los clientes sepan como manejar cada respuesta:
Éxito (2xx)
| Código | Uso |
|---|---|
| 200 OK | Solicitud exitosa con body |
| 201 Created | Recurso creado (POST) |
| 204 No Content | Éxito sin body (DELETE, PUT) |
Redireccion (3xx)
| Código | Uso |
|---|---|
| 301 Moved Permanently | Recurso movido definitivamente |
| 304 Not Modified | Cache válido, no enviar body |
Error del cliente (4xx)
| Código | Uso |
|---|---|
| 400 Bad Request | JSON mal formado o parametros invalidos |
| 401 Unauthorized | No autenticado |
| 403 Forbidden | Autenticado pero sin permisos |
| 404 Not Found | Recurso no existe |
| 409 Conflict | Conflicto (ej: email duplicado) |
| 422 Unprocessable Entity | Validación fallida |
| 429 Too Many Requests | Rate limit excedido |
Error del servidor (5xx)
| Código | Uso |
|---|---|
| 500 Internal Server Error | Error no manejado |
| 502 Bad Gateway | Servicio upstream fallo |
| 503 Service Unavailable | Servicio temporalmente no disponible |
Estructura de respuestas
Respuesta exitosa
{
"data": {
"id": "crs_abc123",
"type": "course",
"attributes": {
"title": "HTML desde cero",
"level": "beginner",
"lessonsCount": 12
}
}
}Respuesta con lista paginada
{
"data": [
{ "id": "crs_001", "title": "HTML desde cero" },
{ "id": "crs_002", "title": "CSS Fundamentals" }
],
"pagination": {
"page": 1,
"perPage": 20,
"totalPages": 5,
"totalItems": 94,
"hasNextPage": true,
"hasPrevPage": false
},
"links": {
"self": "/api/v1/courses?page=1",
"next": "/api/v1/courses?page=2",
"last": "/api/v1/courses?page=5"
}
}Respuesta de error estandarizada
{
"error": {
"status": 404,
"code": "RESOURCE_NOT_FOUND",
"message": "El curso solicitado no existe.",
"details": []
}
}Paginación
Existen tres estrategias principales:
1. Offset-based (la más simple)
GET /api/v1/courses?page=2&per_page=20Ventajas: simple de implementar. Desventajas: ineficiente en tablas grandes, resultados inconsistentes si se insertan datos.
2. Cursor-based (la más robusta)
GET /api/v1/courses?cursor=eyJpZCI6MTIzfQ&limit=20Ventajas: rendimiento consistente, resultados estables. Desventajas: no permite saltar a una página específica.
3. Keyset pagination
GET /api/v1/courses?after_id=crs_123&limit=20Similar a cursor pero con un campo explícito como clave.
Filtrado, ordenamiento y busqueda
Filtrado
GET /api/v1/courses?level=beginner&category=frontend
GET /api/v1/courses?created_after=2025-01-01
GET /api/v1/courses?tags=html,cssOrdenamiento
GET /api/v1/courses?sort=created_at # ascendente
GET /api/v1/courses?sort=-created_at # descendente
GET /api/v1/courses?sort=-rating,title # multiples camposBusqueda
GET /api/v1/courses?q=angular+signals
GET /api/v1/search?q=javascript&type=course,blogVersionamiento
En la URL (recomendado)
GET /api/v1/courses
GET /api/v2/coursesSimple, explícito y fácil de cachear. Es la estrategia más usada por APIs como Stripe, GitHub y Twilio.
En headers (alternativa)
GET /api/courses
Accept: application/vnd.bemorex.v1+jsonMás "puro" semanticamente pero más difícil de usar y probar.
Seguridad
Autenticación con Bearer tokens
GET /api/v1/users/me
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...Headers de seguridad
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'Rate limiting
Incluir headers informativos en cada respuesta:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1706810400
Retry-After: 60Validación de entrada
- Validar siempre en el servidor, nunca confiar solo en el cliente
- Sanitizar inputs para prevenir XSS e inyección SQL
- Limitar el tamaño del body (ej: 1MB para JSON, 10MB para archivos)
- Validar Content-Type
Documentacion
Una buena API es una API bien documentada. Usa OpenAPI (Swagger) para generar documentación interactiva:
openapi: 3.1.0
info:
title: Bemore Learn API
versión: 1.0.0
paths:
/api/v1/courses:
get:
summary: Listar cursos
parameters:
- name: level
in: query
schema:
type: string
enum: [beginner, intermediate, advanced]
responses:
'200':
description: Lista de cursosConclusion
Disenar una buena API REST requiere disciplina y consistencia. Sigue convenciones establecidas, usa códigos HTTP correctamente, estandariza tus respuestas y documenta todo. Una API bien disenada es un multiplicador de productividad para todo tu equipo y tus consumidores. Los patrones presentados aquí son los mismos que usan empresas como Stripe, GitHub y Twilio en sus APIs de clase mundial.



Comentarios (0)
Inicia sesión para comentar