Llegamos al núcleo conceptual del curso. En la lección anterior aprendimos cómo funciona HTTP; ahora veremos cómo se usa bien, según el estilo arquitectónico que Roy Fielding describió en el año 2000. REST no es una biblioteca que se instala ni una especificación que se valida: es un conjunto de restricciones que, si las aceptas, te regalan escalabilidad, evolución independiente y simplicidad; y si las ignoras, te dejan con una API que se llama REST pero se comporta como cualquier otra cosa. En esta lección desmontaremos las seis restricciones una a una, aplicadas a Tienda Aroma, y fijaremos tres conceptos que se confunden constantemente: recurso, identificador y representación.

Contenido

  1. Qué es REST (y qué no es)
  2. Restricción 1: cliente-servidor
  3. Restricción 2: sin estado
  4. Restricción 3: cacheable
  5. Restricción 4: sistema en capas
  6. Restricción 5: interfaz uniforme
  7. Restricción 6: código bajo demanda (opcional)
  8. Recurso, identificador y representación
  9. Qué gana realmente una API al cumplir cada restricción
  10. Qué significa "RESTful" y por qué casi ninguna API lo es del todo

  1. Qué es REST (y qué no es)

REST significa Representational State Transfer: transferencia de estado representacional. El nombre, que suena críptico, describe con precisión el mecanismo: el cliente y el servidor se intercambian representaciones del estado de unos recursos. Cuando pides GET /v1/cafes/caf_001, no recibes "el café" (que es una fila en una base de datos y unos sacos en un almacén): recibes una representación en JSON de su estado en ese momento.

Es fundamental entender qué categoría de cosa es REST:

REST es REST no es
Un estilo arquitectónico: un conjunto de restricciones de diseño Un protocolo (eso es HTTP)
Independiente de la tecnología concreta Un estándar con una especificación que validar
Un modelo derivado de por qué la web escala Sinónimo de "JSON sobre HTTP"
Aplicable con distinto grado de fidelidad Una biblioteca o un framework

No existe un "validador REST", ni un certificado de conformidad. Existen restricciones, y una API las cumple en mayor o menor medida. Esa gradualidad es precisamente lo que mide el modelo de madurez de Richardson, tema de la próxima lección.

Fielding definió seis restricciones: cinco obligatorias y una opcional. Cada una elimina posibilidades de diseño, y a cambio de esa renuncia obtienes propiedades deseables. Es un intercambio consciente.

graph TD
    R["REST<br/>estilo arquitectónico"] --> C1["1. Cliente-servidor"]
    R --> C2["2. Sin estado"]
    R --> C3["3. Cacheable"]
    R --> C4["4. Sistema en capas"]
    R --> C5["5. Interfaz uniforme"]
    R --> C6["6. Código bajo demanda<br/><i>opcional</i>"]
    C5 --> U1["Identificación de recursos"]
    C5 --> U2["Manipulación por representaciones"]
    C5 --> U3["Mensajes autodescriptivos"]
    C5 --> U4["HATEOAS"]

  1. Restricción 1: cliente-servidor

Enunciado: la interfaz de usuario y el almacenamiento de datos están separados en componentes distintos que se comunican mediante una interfaz acordada.

Esto separa dos mundos con ritmos y responsabilidades diferentes:

  • El cliente se ocupa de la presentación y de la experiencia de usuario.
  • El servidor se ocupa de los datos, las reglas de negocio y su integridad.

En Tienda Aroma, esto significa que:

  • La web puede rediseñarse por completo sin tocar el servidor.
  • Aroma Móvil puede publicar una versión nueva mientras el backend sigue igual.
  • El backend puede migrar de MySQL a PostgreSQL sin que ningún cliente se entere.

La regla práctica: si un cambio de aspecto visual obliga a modificar la API, la separación está rota. Un síntoma clásico es un campo como colorBoton o textoDestacadoHome en la respuesta de un café: eso es presentación colándose en el contrato.

// ✗ La presentación se ha colado en la API
{ "nombre": "Etiopía Yirgacheffe", "precioFormateado": "14,50 €", "claseCss": "destacado-rojo" }

// ✓ La API da datos; el cliente decide cómo mostrarlos
{ "nombre": "Etiopía Yirgacheffe", "precioEuros": 14.50, "moneda": "EUR", "destacado": true }

En la segunda versión, el cliente decide si formatea 14,50 € o €14.50 según la configuración regional del usuario, y qué aspecto tiene un producto destacado. La API aporta el hecho, no la forma.

  1. Restricción 2: sin estado

Enunciado: cada petición del cliente debe contener toda la información necesaria para ser comprendida. El servidor no almacena contexto de sesión entre peticiones.

Aquí conviene distinguir con precisión dos tipos de estado:

Tipo de estado Dónde vive en REST Ejemplo en Tienda Aroma
Estado del recurso (de aplicación) En el servidor, de forma persistente El pedido ped_5001 existe y está pagado
Estado de la sesión (de cliente) En el cliente, y viaja en cada petición Quién soy, en qué página del catálogo voy

El carrito de Tienda Aroma es un buen caso para afinar la comprensión. El carrito se guarda en el servidor, pero no como "sesión": es un recurso con identidad propia, /v1/carritos/car_77. El cliente guarda solo su identificador y lo envía cuando lo necesita. La diferencia es sutil pero decisiva: un recurso se puede consultar, compartir entre dispositivos y sobrevivir a un reinicio del servidor; una sesión en memoria no.

Comparemos dos diseños:

# ✗ Con estado de sesión en el servidor: la segunda petición depende de la primera
POST /v1/carrito/seleccionar-cliente   # el servidor "recuerda" el cliente en su memoria
POST /v1/carrito/anadir                # ¿a qué carrito? depende de lo anterior

# ✓ Sin estado: cada petición es autosuficiente
POST /v1/carritos/car_77/lineas
Authorization: Bearer <token del cliente cli_842>
{ "cafeId": "caf_001", "cantidad": 2 }

En la segunda versión, la petición identifica el carrito en la URL, al cliente mediante el token y el contenido en el cuerpo. Cualquier servidor del grupo puede atenderla sin conocimiento previo.

Lo que se gana:

  • Escalabilidad horizontal: añadir servidores es trivial, no hay que sincronizar sesiones.
  • Tolerancia a fallos: si un servidor cae, la siguiente petición la atiende otro sin pérdida de contexto.
  • Visibilidad: cualquier intermediario puede entender una petición aislada, lo que hace posible cachés, cortafuegos y monitorización.

Lo que se paga: cada petición es más grande, porque repite las credenciales y el contexto. Con la compresión de cabeceras de HTTP/2 el coste es menor de lo que parece.

  1. Restricción 3: cacheable

Enunciado: cada respuesta debe indicar, explícita o implícitamente, si es cacheable y durante cuánto tiempo.

En Tienda Aroma, no todos los datos tienen el mismo ritmo de cambio:

Recurso ¿Cambia a menudo? Política razonable
Catálogo de cafés Raramente Cache-Control: public, max-age=300
Detalle de un café Poco (el stock, más) max-age=60 + ETag para revalidar
Pedido de un cliente Es privado y crítico Cache-Control: no-store
Reseñas de un café Poco public, max-age=600

Así se ve en la práctica:

GET /v1/cafes HTTP/1.1
Host: api.tiendaaroma.example

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age=300
ETag: "a7f3c9"

El servidor está diciendo dos cosas: "puedes reutilizar esta respuesta durante 300 segundos sin preguntarme" y "esta versión del contenido tiene la huella a7f3c9". Pasados los 5 minutos, el cliente puede preguntar si ha cambiado enviando esa huella, y si no ha cambiado el servidor responde 304 Not Modified sin cuerpo: ahorro de ancho de banda y de tiempo.

Nada de esto es exclusivo de tu servidor: navegadores, CDN, proxys y gateways entienden estas cabeceras de serie. Ese es el gran regalo de apoyarse en HTTP en lugar de inventar un mecanismo propio. Toda la mecánica de caché se estudia en la lección 04-06.

Ojo con el riesgo: cachear datos privados con public es una brecha de seguridad. Si un proxy cachea el pedido de un cliente y se lo sirve a otro, has filtrado datos personales.

  1. Restricción 4: sistema en capas

Enunciado: la arquitectura se compone de capas jerárquicas; cada componente solo conoce la capa inmediata con la que interactúa, no toda la topología.

El cliente de Tienda Aroma cree que habla con "la API". En realidad, su petición atraviesa varias capas:

graph LR
    C["Aroma Móvil"] --> CDN["CDN / caché"]
    CDN --> GW["API Gateway<br/>auth, límites, métricas"]
    GW --> LB["Balanceador"]
    LB --> S1["Servidor API 1"]
    LB --> S2["Servidor API 2"]
    S1 --> BD[("Base de datos")]
    S2 --> BD

Ninguno de los extremos conoce la cadena completa: el cliente no sabe cuántos servidores hay, y el servidor de aplicación no sabe si la petición vino de un CDN o directamente. Eso permite:

  • Insertar un gateway que centralice autenticación y límites de uso sin cambiar ni una línea del cliente (lección 05-06).
  • Poner una CDN delante para servir el catálogo desde ubicaciones cercanas al usuario.
  • Añadir o quitar servidores según la carga.
  • Reescribir un servicio interno sin que nadie fuera lo note.

La contrapartida es la latencia adicional de cada salto y la dificultad de depurar: por eso importa tanto la observabilidad (lección 04-07) y las cabeceras de correlación que permiten seguir una petición a través de todas las capas.

  1. Restricción 5: interfaz uniforme

Es la restricción central, la que distingue a REST de cualquier otro estilo. La idea: en vez de que cada servicio invente su propia forma de hablar, todos usan la misma interfaz genérica. Se descompone en cuatro subrestricciones.

6.1. Identificación de recursos

Cada recurso tiene un identificador único y estable, su URI:

https://api.tiendaaroma.example/v1/cafes             -> la colección de cafés
https://api.tiendaaroma.example/v1/cafes/caf_001     -> un café concreto
https://api.tiendaaroma.example/v1/pedidos/ped_5001  -> un pedido concreto
https://api.tiendaaroma.example/v1/cafes/caf_001/resenas -> las reseñas de ese café

La URI identifica una cosa, no una acción. Esto explica por qué /v1/obtenerCafe?id=1 o /v1/crearPedido no son URIs REST: nombran verbos, no sustantivos. Las reglas concretas de diseño de URIs las trabajaremos en la lección 02-02.

6.2. Manipulación de recursos mediante representaciones

El cliente no modifica el recurso directamente: envía una representación del estado que desea, y el servidor decide si la aplica.

PUT /v1/cafes/caf_001 HTTP/1.1
Content-Type: application/json

{
  "nombre": "Etiopía Yirgacheffe",
  "origen": "Etiopía",
  "tueste": "claro",
  "precioEuros": 15.00,
  "stock": 95
}

El cliente dice: "quiero que el café caf_001 quede así". El servidor valida, comprueba permisos, aplica reglas de negocio y decide. Puede aceptar (200), rechazar por datos inválidos (422) o por falta de permisos (403). El cliente propone, el servidor dispone.

6.3. Mensajes autodescriptivos

Cada mensaje contiene la información necesaria para ser interpretado por sí solo, sin conocimiento externo:

POST /v1/pedidos HTTP/1.1
Host: api.tiendaaroma.example
Content-Type: application/json     <- el formato del cuerpo va declarado
Accept: application/json           <- lo que espero recibir, declarado
Authorization: Bearer ...          <- quién soy, declarado

HTTP/1.1 201 Created               <- el resultado, en un código estándar
Content-Type: application/json     <- el formato de la respuesta, declarado
Location: /v1/pedidos/ped_5001     <- dónde ha quedado, declarado

Un intermediario que jamás haya oído hablar de cafés puede, aun así, entender que se creó algo y dónde. Por eso importa usar los códigos de estado correctos y declarar bien los tipos de contenido: es lo que permite que la infraestructura genérica haga su trabajo.

6.4. Hipermedia como motor del estado de la aplicación (HATEOAS)

La respuesta incluye enlaces que indican qué puede hacerse a continuación:

{
  "id": "ped_5001",
  "estado": "pendiente_pago",
  "totalEuros": 29.00,
  "_links": {
    "self":     { "href": "/v1/pedidos/ped_5001" },
    "pagar":    { "href": "/v1/pedidos/ped_5001/pago", "method": "POST" },
    "cancelar": { "href": "/v1/pedidos/ped_5001", "method": "DELETE" },
    "cliente":  { "href": "/v1/clientes/cli_842" }
  }
}

El cliente no necesita tener codificadas las direcciones ni las reglas de negocio: descubre que este pedido se puede pagar o cancelar porque el servidor se lo dice. Si el pedido ya estuviera enviado, el enlace cancelar sencillamente no aparecería.

Es la subrestricción más ignorada de todo REST, y la que más debate genera. La estudiaremos a fondo en la próxima lección, 01-05.

  1. Restricción 6: código bajo demanda (opcional)

Enunciado: el servidor puede extender temporalmente la funcionalidad del cliente enviándole código ejecutable.

Es la única restricción opcional de las seis. El ejemplo canónico es una página web que envía JavaScript al navegador: el navegador no sabía validar ese formulario y el servidor le manda el código para hacerlo.

En APIs REST casi no se usa, y con razón: enviar código ejecutable a un cliente es un riesgo de seguridad considerable y rompe la simplicidad. Tienda Aroma no la usará. Basta con saber que existe y por qué es opcional: reduce la visibilidad del sistema, y por eso Fielding la dejó fuera del conjunto obligatorio.

  1. Recurso, identificador y representación

Estos tres conceptos son la base de todo, y confundirlos es la causa de la mayoría de diseños malos.

Concepto Definición Ejemplo
Recurso Cualquier cosa con identidad e interés para el negocio El café Etiopía Yirgacheffe
Identificador (URI) La dirección única y estable de ese recurso /v1/cafes/caf_001
Representación Una forma concreta de expresar su estado en un momento dado Un documento JSON, XML o HTML

La clave: un recurso puede tener muchas representaciones, y ninguna de ellas es el recurso. El mismo /v1/cafes/caf_001 puede devolverse en distintos formatos según lo que pida el cliente:

GET /v1/cafes/caf_001 HTTP/1.1
Accept: application/json

HTTP/1.1 200 OK
Content-Type: application/json

{"id":"caf_001","nombre":"Etiopía Yirgacheffe","precioEuros":14.50}
GET /v1/cafes/caf_001 HTTP/1.1
Accept: application/xml

HTTP/1.1 200 OK
Content-Type: application/xml

<cafe><id>caf_001</id><nombre>Etiopía Yirgacheffe</nombre><precioEuros>14.50</precioEuros></cafe>

Mismo recurso, mismo identificador, dos representaciones. Este mecanismo se llama negociación de contenido y es materia de la lección 02-05.

Tres consecuencias prácticas de esta distinción:

  1. La representación no tiene por qué reflejar la tabla de la base de datos. El recurso "café" puede componerse de tres tablas internas, y la representación puede omitir campos internos como costeProveedorEuros.
  2. Puede haber representaciones distintas para contextos distintos. El listado puede devolver una versión resumida y el detalle una completa. Sigue siendo el mismo recurso.
  3. Un recurso no es necesariamente una entidad de datos. Puede ser un concepto o un proceso: /v1/cafes/mas-vendidos es un recurso perfectamente legítimo aunque no exista una tabla "más vendidos".

  1. Qué gana realmente una API al cumplir cada restricción

Las restricciones no son burocracia: cada una compra una propiedad concreta.

Restricción Qué te obliga a renunciar Qué obtienes a cambio
Cliente-servidor A mezclar presentación y datos Evolución independiente de cada lado; varios clientes sobre un backend
Sin estado A guardar sesión en memoria del servidor Escalabilidad horizontal, tolerancia a fallos, visibilidad
Cacheable A tratar todas las respuestas igual Menos latencia, menos carga, menos coste
Sistema en capas A que el cliente conozca la topología Poder insertar gateways, CDN y balanceadores sin romper nada
Interfaz uniforme A inventar tu propia semántica Herramientas genéricas que funcionan sin conocer tu dominio
Código bajo demanda (opcional) Clientes extensibles, a costa de visibilidad y seguridad

El precio global es real: la interfaz uniforme es menos eficiente que una interfaz a medida para un caso concreto. Fielding lo reconoce explícitamente. La apuesta es que, a escala de internet y en el largo plazo, la generalidad vale más que la optimización puntual. Cuando esa apuesta no compensa —comunicación interna de altísimo rendimiento, o clientes que necesitan datos a medida—, aparecen gRPC y GraphQL, que veremos en 01-07.

  1. Qué significa "RESTful" y por qué casi ninguna API lo es del todo

Se llama RESTful a una API que sigue el estilo REST. En la práctica, el término se usa con mucha manga ancha. Estos son los incumplimientos más habituales:

Práctica frecuente Restricción que incumple Por qué ocurre
URIs con verbos: /v1/crearPedido Interfaz uniforme (identificación) Se piensa en funciones, no en recursos
Todo por POST, incluidas las consultas Interfaz uniforme + cacheable Comodidad, o herencia de SOAP
Devolver 200 OK con {"error": ...} Mensajes autodescriptivos Miedo a que el cliente "no sepa gestionar" un 4xx
Sesiones en memoria del servidor Sin estado Se arrastra el modelo de la web tradicional
Respuestas sin ningún enlace HATEOAS Coste de implementación y clientes que no lo aprovechan
Ignorar Cache-Control Cacheable Se desconoce el mecanismo

La conclusión honesta: la mayoría de las APIs llamadas REST son, en realidad, "HTTP APIs bien organizadas". Cumplen las restricciones estructurales importantes (cliente-servidor, sin estado, recursos con URI, verbos y códigos correctos) pero no implementan HATEOAS.

¿Es un problema? Depende del contexto, y merece una respuesta matizada:

  • Los incumplimientos graves sí importan: guardar sesión en el servidor te impide escalar; usar POST para leer te deja sin caché; devolver 200 en los errores rompe la monitorización. Son costes técnicos medibles.
  • La ausencia de HATEOAS es discutible: aporta menos cuando controlas a todos los clientes y su ciclo de vida.

Lo importante es que sepas qué estás incumpliendo y por qué. Una decisión consciente de no implementar HATEOAS es profesional; no saber que existe, no. Para medir con precisión dónde está tu API en esa escala, existe una herramienta que veremos ahora mismo.

Errores Comunes y Consejos

  • Creer que usar JSON y HTTP ya es REST. Es condición necesaria en la práctica, pero no suficiente ni siquiera de lejos.
  • Confundir "sin estado" con "sin datos". El servidor guarda recursos persistentes; lo que no guarda es contexto de conversación entre peticiones.
  • Modelar acciones como recursos por defecto. Si te sale /v1/cafes/caf_001/actualizarPrecio, el verbo debe estar en el método (PATCH), no en la URI.
  • Meter presentación en las respuestas. Cadenas ya formateadas, textos traducidos o clases CSS atan la API a un cliente concreto.
  • Cachear datos privados como públicos. Es una fuga de datos personales esperando a ocurrir.
  • Discutir de pureza REST en lugar de resolver problemas. El objetivo es una API útil, mantenible y evolutiva, no ganar una discusión.
  • Consejo: cuando dudes de un diseño, pregúntate "¿qué recurso es este y qué le estoy haciendo?". Si la respuesta se expresa con un sustantivo y uno de los métodos HTTP, vas bien.

Ejercicios

Ejercicio 1: identificar la restricción incumplida

Para cada diseño, indica qué restricción REST se incumple y propón una alternativa correcta:

  1. POST /v1/buscarCafes con cuerpo {"origen":"Etiopía"}.
  2. La API guarda el carrito en la memoria del servidor tras POST /v1/iniciarCompra, y las siguientes peticiones dependen de ello.
  3. GET /v1/cafes responde 200 OK con {"exito": false, "mensaje": "servicio caído"}.
  4. La respuesta de un café incluye "precioHtml": "<span class='oferta'>14,50 €</span>".

Ejercicio 2: recurso, identificador y representación

Tienda Aroma quiere exponer el "informe de ventas del mes actual". Responde:

  1. ¿Es esto un recurso legítimo aunque no exista una tabla llamada informes?
  2. Propón su URI.
  3. Propón dos representaciones distintas del mismo recurso y cómo las pediría el cliente.
  4. ¿Debería ser cacheable? Justifícalo.

Ejercicio 3: rediseñar una API que no es RESTful

Un equipo ha entregado esta API para gestionar reseñas. Rediseña las cuatro operaciones respetando las restricciones REST y explica cada cambio.

POST /v1/api?accion=nuevaResena       cuerpo: {resena}
POST /v1/api?accion=listarResenas     cuerpo: {cafeId}
POST /v1/api?accion=borrarResena      cuerpo: {resenaId}
POST /v1/api?accion=editarPuntuacion  cuerpo: {resenaId, puntuacion}

Soluciones

Solución 1

  1. Interfaz uniforme y cacheable. Una búsqueda es una lectura, y usar POST con un verbo en la URI impide cachear e induce a error. Alternativa: GET /v1/cafes?origen=Etiopia. (Nota: cuando los criterios de búsqueda son enormes y no caben en una URL, POST a un recurso de búsqueda es una excepción aceptada y consciente.)
  2. Sin estado. El servidor guarda contexto entre peticiones, lo que impide escalar y rompe si cae el nodo. Alternativa: el carrito es un recurso, POST /v1/carritos devuelve car_77, y las siguientes peticiones van a /v1/carritos/car_77/lineas con el identificador explícito.
  3. Mensajes autodescriptivos. Un fallo del servidor debe señalarse con 503 Service Unavailable; devolver 200 engaña a cachés, reintentos y monitorización, que creerán que todo va bien.
  4. Cliente-servidor. La presentación (HTML y clases CSS) invade el contrato de datos. Alternativa: {"precioEuros": 14.50, "enOferta": true} y que cada cliente decida cómo se pinta.

Solución 2

  1. Sí es un recurso legítimo. Un recurso es cualquier cosa con identidad e interés para el negocio; no tiene por qué corresponder a una tabla. El informe es un concepto perfectamente identificable.
  2. URI propuesta: /v1/informes/ventas?periodo=2026-08. La ruta identifica el tipo de informe y el parámetro acota el periodo. Alternativa igualmente válida y más "de recurso": /v1/informes/ventas/2026-08.
  3. Dos representaciones: JSON para el panel interno (Accept: application/json) y CSV para que el equipo financiero lo abra en una hoja de cálculo (Accept: text/csv). Mismo recurso, mismo identificador, distinta representación negociada por cabecera.
  4. Sí, con cuidado. Es un cálculo costoso que no cambia cada segundo, así que Cache-Control: private, max-age=600 es razonable: se reutiliza durante diez minutos pero se marca private porque es información sensible que ninguna caché compartida debe guardar. El informe de un mes ya cerrado podría cachearse mucho más tiempo.

Solución 3

POST   /v1/cafes/caf_001/resenas    cuerpo: {"puntuacion":5,"comentario":"..."}  -> 201 Created
GET    /v1/cafes/caf_001/resenas                                                  -> 200 OK
DELETE /v1/resenas/res_101                                                        -> 204 No Content
PATCH  /v1/resenas/res_101          cuerpo: {"puntuacion":4}                      -> 200 OK

Cambios y su justificación:

  • Desaparece el endpoint único /v1/api y el parámetro accion. Cada recurso tiene su propia URI identificable: se cumple la subrestricción de identificación de recursos.
  • El verbo pasa de la URL al método HTTP. POST crea, GET lee, DELETE borra, PATCH modifica parcialmente. Ahora los intermediarios entienden la intención sin conocer el dominio.
  • Listar reseñas pasa a GET, lo que la hace segura, idempotente y cacheable: un cambio con impacto directo en rendimiento y coste.
  • Los identificadores salen del cuerpo y entran en la URI, porque identifican el recurso destinatario, no son datos de la operación.
  • Las reseñas de un café cuelgan del café (/v1/cafes/caf_001/resenas), lo que expresa la relación en la propia estructura; para operar sobre una reseña concreta basta su URI propia.
  • Se añaden códigos de estado significativos: 201 con cabecera Location al crear, 204 al borrar (no hay nada que devolver).

Conclusión

REST es un estilo arquitectónico, no un protocolo: seis restricciones —cliente-servidor, sin estado, cacheable, sistema en capas, interfaz uniforme y código bajo demanda— que renuncian a cierta libertad de diseño a cambio de escalabilidad, evolución independiente y compatibilidad con toda la infraestructura genérica de la web. Hemos visto que la interfaz uniforme es su corazón, con sus cuatro subrestricciones, y hemos fijado la distinción entre recurso (la cosa), identificador (su dirección) y representación (la forma concreta en que viaja). También hemos admitido con honestidad que la mayoría de las APIs reales incumplen algo, sobre todo HATEOAS, y que lo profesional es saber qué se incumple y por qué.

Falta una herramienta para medir ese "cuánto" con precisión. En la siguiente lección, Modelo de madurez de Richardson y HATEOAS, recorreremos los cuatro niveles del modelo reescribiendo la misma operación de Tienda Aroma —crear un pedido— en cada uno de ellos, veremos formatos hipermedia reales como HAL y JSON:API, y discutiremos sin dogmatismo cuándo compensa llegar al nivel 3.

Curso de REST API: Principios de Diseño y Desarrollo de APIs RESTful

Módulo 1: Introducción a las APIs RESTful

Módulo 2: Diseño de APIs RESTful

Módulo 3: Desarrollo de APIs RESTful

Módulo 4: Buenas Prácticas y Seguridad

Módulo 5: Herramientas y Frameworks

Módulo 6: Casos de Estudio y Proyectos

© Copyright 2026. Todos los derechos reservados