Guías
Backend Actualizado el 6 de noviembre de 2026

HTTP y APIs REST

Métodos y códigos HTTP, cabeceras comunes, diseño de URLs REST, paginación, curl, errores con problem+json y autenticación.

  • #http
  • #rest
  • #api
  • #curl

Métodos HTTP

MétodoUso
GETLeer un recurso o una colección. Seguro e idempotente
POSTCrear un recurso o lanzar una acción. Ni seguro ni idempotente
PUTReemplazar el recurso completo. Idempotente
PATCHModificar parte del recurso. No idempotente por definición
DELETEEliminar un recurso. Idempotente
HEADIgual que GET pero solo cabeceras. Seguro e idempotente
OPTIONSConsultar métodos permitidos; lo usa el preflight de CORS. Seguro

Seguro: no modifica el estado del servidor. Idempotente: repetir la petición deja el mismo resultado que hacerla una vez (se puede reintentar sin miedo).

Códigos 2xx y 3xx

CódigoSignificado
200 OKÉxito con cuerpo en la respuesta
201 CreatedRecurso creado; incluye Location con su URL
202 AcceptedAceptado para procesarse de forma asíncrona
204 No ContentÉxito sin cuerpo (típico en DELETE o PUT)
206 Partial ContentRespuesta parcial a una petición con Range
301 Moved PermanentlyLa URL cambió para siempre
302 FoundRedirección temporal
304 Not ModifiedLa copia en caché sigue siendo válida (con ETag)
307 / 308Redirección temporal / permanente que conserva el método y el cuerpo

Códigos 4xx: error del cliente

CódigoSignificado
400 Bad RequestPetición mal formada (JSON inválido, parámetro erróneo)
401 UnauthorizedFalta autenticarse o el token no es válido
403 ForbiddenAutenticado, pero sin permiso para esto
404 Not FoundEl recurso no existe
405 Method Not AllowedEl método no está soportado en esa URL
409 ConflictChoca con el estado actual (duplicado, versión antigua)
422 Unprocessable ContentSintaxis correcta pero datos que no pasan la validación
429 Too Many RequestsLímite de peticiones superado; mira Retry-After

Códigos 5xx: error del servidor

CódigoSignificado
500 Internal Server ErrorError no controlado en el servidor
501 Not ImplementedEl servidor no soporta esa funcionalidad
502 Bad GatewayUn proxy recibió una respuesta inválida del servicio de atrás
503 Service UnavailableCaído o saturado temporalmente; puede incluir Retry-After
504 Gateway TimeoutEl servicio de atrás no respondió a tiempo
507 Insufficient StorageEl servidor no puede guardar lo necesario

Regla rápida: un 4xx se corrige cambiando la petición; un 5xx no es culpa del cliente y a veces vale la pena reintentar.

Cabeceras comunes

CabeceraPara qué sirve
Content-Type: application/jsonFormato del cuerpo enviado
Accept: application/jsonFormato que el cliente quiere recibir
Authorization: Bearer <token>Credenciales de la petición
Cache-Control: no-storePolítica de caché (max-age=3600, no-cache, private)
ETag / If-None-MatchVersión del recurso; si no cambió, el servidor responde 304
LocationURL del recurso creado (201) o del destino de una redirección
Retry-AfterSegundos (o fecha) a esperar antes de reintentar
Idempotency-KeyClave única para reintentar un POST sin duplicar el efecto

CORS

CabeceraPara qué sirve
Access-Control-Allow-OriginOrígenes permitidos (https://app.example.com); evita * con credenciales
Access-Control-Allow-MethodsMétodos permitidos en peticiones cruzadas
Access-Control-Allow-HeadersCabeceras que el cliente puede enviar (Authorization, Content-Type)
Access-Control-Allow-Credentialstrue para permitir cookies o credenciales
Access-Control-Max-AgeSegundos que el navegador cachea el preflight
Access-Control-Expose-HeadersCabeceras de respuesta que el JavaScript puede leer

CORS lo aplica el navegador: curl o un backend no lo comprueban. El preflight es un OPTIONS automático antes de peticiones no simples.

Diseño de URLs REST

PeticiónSignificado
GET /usersListar usuarios
POST /usersCrear un usuario
GET /users/42Obtener el usuario 42
PATCH /users/42Modificar campos del usuario 42
DELETE /users/42Eliminar el usuario 42
GET /users/42/ordersPedidos del usuario 42 (recurso anidado)
POST /orders/7/cancelAcción que no encaja en CRUD (úsalo con moderación)
/v1/usersVersión de la API en la ruta

Convenciones: sustantivos en plural, kebab-case en rutas (/order-items), sin verbos ni extensiones (/getUsers.json), y máximo uno o dos niveles de anidación.

Paginación, filtros y orden

PeticiónQué hace
GET /orders?page=2&per_page=20Paginación por offset: simple, pero lenta e inestable en tablas grandes o cambiantes
GET /orders?limit=20&cursor=eyJpZCI6MTIzfQPaginación por cursor: estable y eficiente; el servidor devuelve el siguiente cursor
GET /orders?status=paidFiltrar por un campo
GET /orders?created_after=2026-11-01T00:00:00ZFiltrar por rango de fechas en ISO 8601 UTC
GET /orders?sort=-created_at,totalOrdenar: - indica descendente
GET /orders?fields=id,total,statusDevolver solo algunos campos
json
{
  "data": [{ "id": 124, "total": 59.9, "createdAt": "2026-11-06T14:32:00Z" }],
  "pagination": { "limit": 20, "nextCursor": "eyJpZCI6MTQ0fQ", "hasMore": true }
}

curl

AcciónComando
GET con cabeceras
POST con JSON
POST con JSON (atajo, curl 7.82+)
PUT leyendo el cuerpo de un archivo
DELETE
Enviar un archivo (multipart)
Ver cabeceras y cuerpo
Ver solo cabeceras (HEAD)
Seguir redirecciones
Modo detallado (depurar TLS y cabeceras)
Límite de tiempo total en segundos
Guardar la respuesta en un archivo
Fallar con código de salida en 4xx/5xx (scripts)

Formato de error estándar (RFC 9457)

Responde los errores con Content-Type: application/problem+json y una estructura común:

json
{
  "type": "https://api.example.com/problems/validation-error",
  "title": "Validation failed",
  "status": 422,
  "detail": "The request body has 2 invalid fields.",
  "instance": "/users",
  "timestamp": "2026-11-06T14:32:00Z",
  "errors": [
    { "field": "email", "message": "must be a valid email" },
    { "field": "birthDate", "message": "must be in the past" }
  ]
}

type, title, status, detail e instance son los campos estándar; puedes añadir otros propios como errors o timestamp. Nunca expongas trazas de error ni detalles internos.

Autenticación

EsquemaDescripción
Bearer / JWTAuthorization: Bearer <token>; el JWT es un token firmado con claims (sub, exp) que el servidor verifica sin estado
API keyClave estática en una cabecera como X-API-Key: <clave>; simple, ideal entre servicios. Nunca en la URL
OAuth 2.0Un servidor de autorización emite access tokens de corta vida; usa Authorization Code + PKCE para apps y Client Credentials entre servicios
BasicAuthorization: Basic <base64(user:pass)>; solo sobre HTTPS y para casos internos

Guarda los secretos en un gestor de secretos (por ejemplo, AWS Secrets Manager), nunca en el código ni en el repositorio.