Casi cualquier aplicación moderna habla con un servidor en algún momento: para guardar datos, para mostrar información actualizada, para autenticar a un usuario. Esa comunicación casi siempre pasa por una API REST. Entender cómo funciona no es opcional si vas a trabajar con desarrollo web, sea frontend o backend.
REST son las siglas de Representational State Transfer, un estilo arquitectónico para diseñar APIs sobre HTTP — no un protocolo que se instala ni una tecnología concreta que se aprende, sino un conjunto de convenciones: cada "recurso" (un usuario, un pedido, un producto) tiene una URL propia, y las acciones sobre ese recurso se expresan con verbos HTTP en lugar de con nombres de función.
La idea central: recursos y verbos
En vez de tener una URL distinta para cada acción posible (/obtenerUsuario, /borrarUsuario, /actualizarUsuario), REST usa la misma URL de recurso y cambia el verbo HTTP según lo que quieras hacer:
| Verbo | Acción | Ejemplo |
|---|---|---|
GET | Leer un recurso o una lista | GET /usuarios/3 |
POST | Crear un recurso nuevo | POST /usuarios |
PUT | Reemplazar un recurso entero | PUT /usuarios/3 |
PATCH | Modificar parte de un recurso | PATCH /usuarios/3 |
DELETE | Eliminar un recurso | DELETE /usuarios/3 |
Es la misma lógica que aplicarías montando tu propio servidor con Node.js y Express: cada ruta define un recurso, y el verbo determina qué controlador se ejecuta.
Códigos de estado: lo que la respuesta te está diciendo
Cada respuesta HTTP incluye un código numérico que resume qué pasó. Aprender a leerlos te ahorra tiempo depurando: el código ya te dice si el problema está en tu petición o en el servidor.
| Código | Significado | Cuándo aparece |
|---|---|---|
200 OK | Éxito | La petición se procesó correctamente |
201 Created | Recurso creado | Después de un POST exitoso |
400 Bad Request | Petición mal formada | Falta un campo o el formato es incorrecto |
401 Unauthorized | No autenticado | Falta o es inválido el token de acceso |
403 Forbidden | Sin permisos | Autenticado, pero sin acceso a ese recurso |
404 Not Found | No existe | El recurso solicitado no está en el servidor |
500 Internal Server Error | Error del servidor | Algo falló en el backend, no en tu petición |
Confundir un 401 con un 403, o un error de red con un 500, es de los fallos más comunes al depurar una integración. Merece la pena tenerlos claros, sobre todo porque muchos de los fallos de seguridad del OWASP Top 10 giran precisamente en torno a devolver el código de acceso equivocado en el momento equivocado.
Consumiendo una API real con fetch
La forma más directa de hacer peticiones HTTP desde JavaScript, sin instalar nada, es con fetch. A continuación tienes dos ejemplos reales contra JSONPlaceholder, una API pública gratuita pensada exactamente para practicar este tipo de peticiones.
async function obtenerPost(id) {
const respuesta = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);
if (!respuesta.ok) {
throw new Error(`Error ${respuesta.status}: no se pudo obtener el post`);
}
const post = await respuesta.json();
return post;
}
obtenerPost(1).then(post => console.log(post.title));
// "sunt aut facere repellat provident occaecati excepturi optio"
async function crearPost(titulo, cuerpo, usuarioId) {
const respuesta = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title: titulo,
body: cuerpo,
userId: usuarioId
})
});
if (!respuesta.ok) {
throw new Error(`Error ${respuesta.status}: no se pudo crear el post`);
}
return respuesta.json(); // incluye el id asignado por el servidor
}
crearPost('Mi primer post', 'Contenido de prueba', 1)
.then(nuevo => console.log(nuevo.id)); // 101
Fíjate en dos detalles que se repiten en casi cualquier petición real: el GET no necesita más que la URL, mientras que el POST necesita indicar la cabecera Content-Type: application/json y convertir el objeto a texto con JSON.stringify antes de enviarlo. Olvidar cualquiera de los dos es la causa número uno de un POST que "no hace nada" sin dar ningún error visible.
Manejo de errores: no confíes solo en el try/catch
Un error habitual es pensar que fetch lanza una excepción cuando la respuesta es un error HTTP. No es así: fetch solo rechaza la promesa si hay un fallo de red (sin conexión, dominio inexistente). Un 404 o un 500 llegan como una respuesta "normal", y por eso siempre hay que comprobar respuesta.ok explícitamente, como en los ejemplos anteriores, antes de asumir que todo fue bien.
Autenticación básica en APIs REST
Muchas APIs reales no son públicas como JSONPlaceholder: requieren identificarte en cada petición, normalmente con un token en la cabecera Authorization.
const respuesta = await fetch('https://api.ejemplo.com/perfil', {
headers: {
'Authorization': `Bearer ${token}`
}
});
Ese token nunca debería quedar visible en el código fuente del frontend ni subirse a un repositorio público: es una de las formas más comunes de sufrir un problema de configuración de seguridad incorrecta. Si necesitas construir tu propia API para que otras aplicaciones la consuman así, Express es un buen punto de partida por lo directo que resulta definir rutas y middlewares de autenticación.
REST no es la única opción, pero sigue siendo la más común
Existen alternativas como GraphQL o gRPC, más adecuadas para casos concretos (consultas muy flexibles, comunicación entre microservicios de alto rendimiento). Pero REST sigue siendo el estándar de facto para APIs públicas y para la comunicación típica entre frontend y backend, precisamente porque es simple, se apoya en HTTP tal cual y cualquier cliente —desde un navegador hasta un script de terminal— puede consumirla sin dependencias especiales.