Hipermedia

Fundamentos Jan 9, 2026 JSON
arquitectura rest hateoas diseño-api descubribilidad

Definición

La hipermedia es la idea de que el contenido debe incluir enlaces embebidos a contenido relacionado, tal como las páginas web tienen enlaces clicables a otras páginas. En el contexto de APIs REST, hipermedia significa que las respuestas de la API no solo devuelven datos - también incluyen URLs que indican a los clientes qué acciones pueden tomar a continuación o qué recursos relacionados pueden acceder.

Piensa en navegar la web. No necesitas memorizar URLs o construirlas manualmente. Haces clic en enlaces, y el sitio web te guía a través de las acciones disponibles. La hipermedia trae esta misma descubribilidad a las APIs. En lugar de codificar URLs en tu aplicación cliente, el servidor envía enlaces dinámicamente basados en el estado actual. Si un pedido puede ser cancelado, la respuesta incluye un enlace “cancel”. Si ya fue enviado, ese enlace no aparecerá.

El “hiper” en hipermedia se refiere a navegación no lineal - puedes saltar entre recursos relacionados sin seguir una secuencia fija. El “media” se refiere al formato de contenido (JSON, XML, HTML) que lleva tanto datos como enlaces de navegación. Esto hace que las APIs sean auto-documentadas y permite a los clientes descubrir funcionalidad sin documentación externa.

Ejemplo

Hipermedia en la API de GitHub: Cuando recuperas un repositorio vía GET /repos/facebook/react, la respuesta incluye datos sobre el repo más enlaces de hipermedia: "forks_url": "https://api.github.com/repos/facebook/react/forks", "issues_url": "https://api.github.com/repos/facebook/react/issues{/number}", "pulls_url": "https://api.github.com/repos/facebook/react/pulls{/number}". No necesitas construir estas URLs manualmente - la API te dice dónde encontrar recursos relacionados.

API de Pagos de PayPal: Cuando creas un pago, la respuesta HATEOAS de PayPal incluye enlaces: "self": "/v1/payments/payment/PAY-123", "approval_url": "https://paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-456", "execute": "/v1/payments/payment/PAY-123/execute". El cliente sigue estos enlaces para completar el flujo de pago sin codificar URLs.

AWS S3 con Listado de Buckets: Cuando listas objetos en un bucket S3, si hay más resultados, la respuesta incluye <NextContinuationToken> y construye la URL para la siguiente página. No calculas offsets de paginación - sigues el enlace proporcionado.

API de Stripe con Recursos Expandibles: Stripe usa hipermedia para recursos relacionados. Un objeto de cargo incluye "customer": "cus_123" (solo un ID), pero también proporciona una forma de expandirlo: la documentación de la API y las respuestas te guían a GET /v1/customers/cus_123. El patrón expandible es una forma de hipermedia que permite a los clientes navegar relaciones.

API de Contenido estilo Netflix: Un listado de películas podría incluir enlaces de hipermedia: "play_url": "/play/movie/12345", "trailer_url": "/media/trailer/12345", "cast_url": "/movies/12345/cast", "reviews_url": "/movies/12345/reviews". La app sigue estos enlaces en lugar de construir URLs desde plantillas.

Analogía

El Directorio del Centro Comercial: Cuando estás en un centro comercial, no necesitas conocer la ubicación exacta de cada tienda de antemano. Miras el directorio (hipermedia), que muestra tiendas relacionadas y te señala sus ubicaciones. Si una tienda está cerrada (estado no disponible), no está listada en el directorio. La hipermedia en APIs funciona de la misma manera - el servidor te dice qué está disponible y cómo llegar allí.

El Libro de Elige Tu Propia Aventura: Estos libros no fuerzan un camino lineal. Cada página dice “Si eliges entrar a la cueva, ve a la página 45. Si eliges cruzar el puente, ve a la página 78.” No necesitas hojear el libro al azar - la página actual te dice los siguientes pasos válidos. La hipermedia proporciona la misma navegación guiada para las APIs.

Menú de Restaurante con Códigos QR: Los menús modernos incluyen códigos QR que enlazan a información de alérgenos, datos nutricionales o maridajes de vinos. No necesitas conocer las URLs - escaneas el código junto a cada ítem. El menú (respuesta) embebe enlaces a información relacionada (hipermedia).

Navegación GPS: El GPS no solo muestra tu ubicación actual - muestra rutas disponibles, gasolineras cercanas y caminos alternativos. La interfaz te guía a destinos relacionados sin requerir que memorices coordenadas de mapa. La hipermedia hace que las APIs sean navegables como el GPS hace navegables los mapas.

Audioguía de Museo: A medida que te mueves por un museo, la audioguía sugiere exhibiciones relacionadas basadas en tu ubicación actual: “Si disfrutaste la galería Impresionista, visita el ala de Arte Moderno (Sala 12).” Descubres el diseño del museo a través de enlaces guiados, no memorizando un plano. Las APIs con hipermedia funcionan de la misma manera.

Ejemplo de Código

// Ejemplo 1: Recurso de Pedido con Enlaces de Hipermedia
// GET /api/orders/789

{
  "id": 789,
  "user_id": 123,
  "status": "pending",
  "total": 59.98,
  "created_at": "2026-01-09T10:30:00Z",

  // Hipermedia: Enlaces a recursos relacionados y acciones disponibles
  "links": {
    "self": {
      "href": "/api/orders/789",
      "method": "GET"
    },
    "user": {
      "href": "/api/users/123",
      "method": "GET"
    },
    "items": {
      "href": "/api/orders/789/items",
      "method": "GET"
    },
    // Acciones disponibles basadas en el estado actual
    "pay": {
      "href": "/api/orders/789/payment",
      "method": "POST"
    },
    "cancel": {
      "href": "/api/orders/789",
      "method": "DELETE"
    },
    "update": {
      "href": "/api/orders/789",
      "method": "PATCH"
    }
  }
}

// Ejemplo 2: Pedido Después del Pago (estado cambiado)
// GET /api/orders/789 (después del pago)

{
  "id": 789,
  "user_id": 123,
  "status": "paid",
  "total": 59.98,
  "created_at": "2026-01-09T10:30:00Z",
  "paid_at": "2026-01-09T10:35:00Z",

  // Hipermedia: Diferentes enlaces basados en el nuevo estado
  "links": {
    "self": {
      "href": "/api/orders/789",
      "method": "GET"
    },
    "user": {
      "href": "/api/users/123",
      "method": "GET"
    },
    "items": {
      "href": "/api/orders/789/items",
      "method": "GET"
    },
    "invoice": {
      "href": "/api/orders/789/invoice.pdf",
      "method": "GET"
    },
    // Enlace "pay" eliminado (ya pagado)
    // Enlace "cancel" eliminado (no se puede cancelar pedido pagado)
    // Nueva acción disponible:
    "request_refund": {
      "href": "/api/orders/789/refund",
      "method": "POST"
    }
  }
}

// Ejemplo 3: Formato HAL (Hypertext Application Language)
// Formato de hipermedia estándar
{
  "_links": {
    "self": { "href": "/api/products/456" },
    "category": { "href": "/api/categories/electronics" },
    "manufacturer": { "href": "/api/manufacturers/apple" },
    "reviews": { "href": "/api/products/456/reviews" }
  },
  "_embedded": {
    "manufacturer": {
      "name": "Apple Inc.",
      "_links": {
        "self": { "href": "/api/manufacturers/apple" }
      }
    }
  },
  "id": 456,
  "name": "iPhone 16",
  "price": 999.00,
  "stock": 42
}

// Ejemplo 4: Colección con Hipermedia de Paginación
{
  "total": 1250,
  "page": 1,
  "per_page": 20,
  "data": [
    { "id": 1, "name": "Producto A" },
    { "id": 2, "name": "Producto B" }
    // ... 18 elementos más
  ],
  "links": {
    "self": "/api/products?page=1&per_page=20",
    "first": "/api/products?page=1&per_page=20",
    "next": "/api/products?page=2&per_page=20",
    "last": "/api/products?page=63&per_page=20"
    // "prev" no incluido porque estamos en la primera página
  }
}

// Ejemplo 5: Formato JSON:API (Especificación de Hipermedia Estándar)
{
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "Diseño de APIs REST",
      "body": "..."
    },
    "relationships": {
      "author": {
        "links": {
          "self": "/articles/1/relationships/author",
          "related": "/articles/1/author"
        },
        "data": { "type": "people", "id": "9" }
      },
      "comments": {
        "links": {
          "self": "/articles/1/relationships/comments",
          "related": "/articles/1/comments"
        }
      }
    },
    "links": {
      "self": "/articles/1"
    }
  }
}

Diagrama

graph TB
    Start[GET /api/orders/789]

    Start --> Response1{Respuesta Pedido
status: pending} Response1 --> L1["link: self
/api/orders/789"] Response1 --> L2["link: user
/api/users/123"] Response1 --> L3["link: items
/api/orders/789/items"] Response1 --> L4["link: pay
/api/orders/789/payment"] Response1 --> L5["link: cancel
/api/orders/789"] L4 --> |Cliente sigue enlace pay| Pay[POST /api/orders/789/payment] Pay --> Response2{Respuesta Pedido
status: paid} Response2 --> L6["link: self
/api/orders/789"] Response2 --> L7["link: invoice
/api/orders/789/invoice.pdf"] Response2 --> L8["link: request_refund
/api/orders/789/refund"] Response2 --> L9["link: items
/api/orders/789/items"] style L4 fill:#90EE90 style L8 fill:#FFB6C1 style Response1 fill:#ADD8E6 style Response2 fill:#FFE4B5

Mejores Prácticas

  1. Incluir enlaces para todos los recursos relacionados: Usuario, ítems, pedidos relacionados, etc.
  2. Proporcionar enlaces de acción basados en estado: Solo incluir “cancel” si el pedido es cancelable
  3. Usar formatos de hipermedia estándar: HAL, JSON:API o Siren para consistencia
  4. Incluir enlace self: Cada recurso debe enlazar a sí mismo
  5. Usar relaciones de enlace: Atributos rel como “next”, “prev”, “self”, “related” clarifican el propósito del enlace
  6. Proporcionar enlaces de paginación: “first”, “last”, “next”, “prev” para colecciones
  7. Incluir información del método: Especificar GET, POST, PUT, DELETE para cada enlace de acción
  8. Hacer enlaces URLs absolutas: Evitar rutas relativas que requieran construcción del lado del cliente
  9. Documentar relaciones de enlaces: Explicar qué significa cada relación de enlace en la documentación de tu API
  10. Versionar contratos de hipermedia: Asegurar que las estructuras de enlaces permanezcan estables entre versiones de API

Errores Comunes

Devolver datos sin enlaces: Solo devolver {"id": 123, "name": "Usuario"} obliga a los clientes a codificar patrones de URL.

Formatos de enlace inconsistentes: Mezclar strings ("user_url": "/users/123") con objetos ("items": {"href": "/items"}) crea confusión.

Incluir enlaces independientemente del estado: Mostrar enlace “cancel” incluso cuando el pedido ya fue enviado viola los principios de HATEOAS.

URLs relativas sin contexto: Usar /users/123 en lugar de https://api.example.com/users/123 requiere que los clientes construyan URLs base.

Falta de relaciones de enlace: No especificar atributos rel hace poco claro lo que cada enlace representa.

Sobre-anidamiento: Embeber recursos relacionados completos en lugar de proporcionar enlaces hincha las respuestas.

Ignorar estándares: Inventar formatos de hipermedia personalizados en lugar de usar HAL, JSON:API o Siren.

Enlaces estáticos en documentación: La hipermedia debe estar en las respuestas, no solo en la documentación.

Romper contratos de enlaces: Cambiar estructuras de enlaces entre versiones de API rompe clientes que siguen enlaces.

Estándares y RFCs

Standards & RFCs
4)- HAL - Hypertext Application Language
5)- JSON:API - JSON API Specification
6)- Siren - Hypermedia Specification

Términos Relacionados