Blog · 5 de julio de 2026
¿Te han dicho ‘esto es REST’ cuando en realidad es solo HTTP con JSON? Aquí aclaramos la diferencia práctica entre REST y RESTful —con ejemplos reales, código funcional y consejos para decidir qué usar hoy (actualizado 5 de julio de 2026).
¿Has consumido una “REST API” que parece cambiar con cada versión y no tiene enlaces o auto-descripción? No eres el único. Muchas APIs dicen ser REST o RESTful por costumbre, pero eso puede ocultar decisiones de diseño importantes: contratos, evolutividad, descubribilidad y acoplamiento. Si trabajas con integraciones, productos o sistemas distribuidos, entender la diferencia te ahorra dolores de cabeza.
Actualizado a 5 de julio de 2026: voy a apoyarme en la definición original de Roy Fielding y en la documentación actual de desarrolladores para separar mito de práctica. (cs.lmu.edu)
REST (REpresentational State Transfer) es un estilo arquitectónico planteado por Roy Fielding en su tesis doctoral: un conjunto de restricciones para diseñar sistemas distribuidos. No es una librería ni un protocolo: son principios como cliente-servidor, stateless, cache, interfaz uniforme, sistemas en capas y HATEOAS (Hypermedia as the Engine of Application State). Todo esto aparece en la definición original. (cs.lmu.edu)
En la práctica, cuando la gente dice "REST API" o "RESTful API" suele referirse a una API HTTP que:
Pero cuidado: muchas APIs usan esos elementos sin cumplir todas las restricciones REST (especialmente HATEOAS). Por eso decir que algo es REST puede ser impreciso: a menudo es una API basada en HTTP que sigue algunas pautas REST. Esto está reflejado en guías modernas de desarrolladores. (developer.mozilla.org)
¿Entonces hay una “batalla” terminológica? Sí. En la práctica, la mayoría de la web moderna ofrece APIs que son REST-like, no puramente REST según los 6 constraints originales. (en.wikipedia.org)
Estas reglas te mantienen práctico sin entrar en dogmas.
# requirements: flask
from flask import Flask, jsonify, request, abort
app = Flask(__name__)
# datos en memoria para ejemplo
users = {1: {"id": 1, "name": "Ana"}}
@app.route("/users/<int:user_id>", methods=["GET"])
def get_user(user_id):
user = users.get(user_id)
if not user:
abort(404)
return jsonify(user)
@app.route("/users", methods=["POST"])
def create_user():
payload = request.get_json()
new_id = max(users.keys()) + 1
user = {"id": new_id, "name": payload.get("name")}
users[new_id] = user
return jsonify(user), 201
if __name__ == "__main__":
app.run(debug=True, port=5000)
Comentarios: este ejemplo es una API HTTP correcta y simple, pero no aporta HATEOAS ni enlaces de navegación. Es perfecta para la mayoría de apps web y móviles.
// requirements: express, body-parser
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
let users = {1: {id:1, name:'Ana'}};
app.get('/users/:id', (req, res) => {
const id = Number(req.params.id);
const user = users[id];
if (!user) return res.status(404).end();
// Representación HAL con enlaces
res.json({
id: user.id,
name: user.name,
_links: {
self: { href: `/users/${user.id}` },
orders: { href: `/users/${user.id}/orders` }
}
});
});
app.post('/users', (req, res) => {
const newId = Math.max(...Object.keys(users)) + 1;
const user = { id: newId, name: req.body.name };
users[newId] = user;
res.status(201).json(user);
});
app.listen(3000, () => console.log('Server 3000'));
Comentarios: aquí añadimos enlaces en la respuesta. Esto se acerca más a una implementación REST completa (HATEOAS), ya que el cliente puede descubrir rutas a través de la representación. Implementaciones puristas usan esto. (en.wikipedia.org)
# Obtener usuario con hipermedia
curl -s http://localhost:3000/users/1 | jq
# Resultado esperado (ejemplo):
# {
# "id": 1,
# "name": "Ana",
# "_links": { "self": {"href": "/users/1"}, "orders": {"href": "/users/1/orders"} }
# }
Comentarios: el cliente puede leer _links.orders.href y seguirlo sin conocer la estructura previa.
openapi: 3.0.1
info:
title: Users API
version: '1.0'
paths:
/users/{id}:
get:
summary: Get user by id
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/User'
components:
schemas:
User:
type: object
properties:
id:
type: integer
name:
type: string
Comentarios: aunque no implemente HATEOAS, OpenAPI provee contrato y tooling para generar clientes, tests y documentación. Muy usado en la industria. (ibm.com)
| ✅ Concepto | REST (arquitectura) | RESTful / REST API (uso común) |
|---|---|---|
| Naturaleza | Estilo arquitectónico con restricciones. | API HTTP que sigue prácticas REST-like. |
| HATEOAS | Requisito (ideal). | Generalmente NO implementado en muchas APIs. |
| Documentación | No prescriptiva (es arquitectura). | Se usa OpenAPI / Swagger para contratos. |
| Uso típico | Sistemas que necesitan descubribilidad y evolucionabilidad. | Servicios web estándar, móviles y microservicios. |
Fuentes: lectura de la tesis y guías de desarrolladores. (cs.lmu.edu)
Si vas a diseñar una API hoy: decide si necesitas HATEOAS o no, documenta con OpenAPI y céntrate en contratos estables. ¿Tu equipo quiere ejemplos concretos o una checklist para auditar una API existente? Puedo prepararla.
Fuentes seleccionadas y lectura recomendada (consultadas y vigentes a 5 de julio de 2026): tesis de Roy Fielding; MDN Web Docs; entradas técnicas de IBM y recursos comunitarios sobre implementación REST vs RESTful. (cs.lmu.edu)