REST es el estándar de facto de las APIs web, pero no es la única herramienta ni siempre la mejor. En los últimos años han madurado alternativas que atacan limitaciones muy concretas: GraphQL nació del problema de pedir datos a medida desde el móvil; gRPC, de la necesidad de comunicación interna de alto rendimiento; los webhooks, de la incapacidad de HTTP para que el servidor avise al cliente. Esta lección cierra el módulo dibujando el mapa completo de estilos de integración, con ejemplos aplicados a Tienda Aroma, para que sepas elegir con criterio y —lo más importante— entiendas que estos enfoques no compiten: conviven en la misma empresa, cada uno en su sitio.

Contenido

  1. Por qué no basta con un único estilo
  2. GraphQL: el cliente decide qué campos quiere
  3. Qué problemas resuelve GraphQL y cuáles introduce
  4. gRPC: contrato fuerte y alto rendimiento entre servicios
  5. Comunicación dirigida por eventos: webhooks
  6. Colas, streaming y tiempo real: SSE y WebSockets
  7. Tabla comparativa de los cuatro enfoques
  8. Criterios de decisión honestos
  9. La arquitectura final de Tienda Aroma

  1. Por qué no basta con un único estilo

Las necesidades de comunicación de Tienda Aroma no son homogéneas. Compara estos cuatro casos:

Necesidad Características ¿Encaja bien en REST?
Un blog muestra el catálogo Público, lectura, cacheable, cliente desconocido Perfectamente
La pantalla de pedido de Aroma Móvil Necesita datos de pedido, cliente, cafés y envío a la vez Regular: varias peticiones
El servicio de pedidos consulta stock 500 veces por segundo Interno, alto volumen, latencia crítica Mediocre: sobrecarga de JSON y HTTP/1
Avisar a RápidoEnvíos de que un pedido está pagado El emisor es el servidor; el receptor es externo Mal: HTTP solo va cliente → servidor

Cada desajuste tiene una respuesta específica. Verlas juntas te da criterio; usarlas todas a la vez sin motivo, te da una arquitectura ingobernable.

  1. GraphQL: el cliente decide qué campos quiere

GraphQL es un lenguaje de consulta para APIs, creado en Facebook en 2012 y publicado en 2015. Sus tres decisiones fundamentales:

  1. Un esquema tipado define todos los datos disponibles y sus relaciones. Es el contrato, y es obligatorio.
  2. Una sola URL (típicamente /graphql), a la que se hace POST.
  3. El cliente escribe la consulta: pide exactamente los campos que necesita, ni uno más.

El esquema de Tienda Aroma

type Cafe {
  id: ID!
  nombre: String!
  origen: String!
  tueste: Tueste!
  precioEuros: Float!
  stock: Int!
  notasCata: [String!]!
  resenas: [Resena!]!
}

type Resena {
  id: ID!
  autor: String!
  puntuacion: Int!
  comentario: String
}

enum Tueste { CLARO MEDIO OSCURO }

type Query {
  cafe(id: ID!): Cafe
  cafes(origen: String, tueste: Tueste, limite: Int): [Cafe!]!
}

El signo ! significa "no puede ser nulo". El esquema es a la vez documentación, validación y contrato: las herramientas lo leen y ofrecen autocompletado al escribir consultas.

La consulta

La app móvil necesita, para su pantalla de catálogo, solo el nombre, el precio y la puntuación media. Lo pide así:

query {
  cafes(origen: "Etiopía", limite: 10) {
    id
    nombre
    precioEuros
    resenas {
      puntuacion
    }
  }
}

Y recibe exactamente eso, con la misma forma que la consulta:

{
  "data": {
    "cafes": [
      {
        "id": "caf_001",
        "nombre": "Etiopía Yirgacheffe",
        "precioEuros": 14.50,
        "resenas": [{ "puntuacion": 5 }, { "puntuacion": 4 }]
      }
    ]
  }
}

Por HTTP, la petición real es un POST:

curl -X POST https://api.tiendaaroma.example/graphql \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer TOKEN" \
  -d '{"query":"{ cafes(origen: \"Etiopía\", limite: 10) { id nombre precioEuros resenas { puntuacion } } }"}'

El equivalente en REST

Para conseguir lo mismo con la API REST de Tienda Aroma harían falta varias llamadas:

# 1. Los cafés de Etiopía (devuelve TODOS los campos de cada café)
curl "https://api.tiendaaroma.example/v1/cafes?origen=Etiopia&limite=10"

# 2. Las reseñas de cada café: una petición por café
curl "https://api.tiendaaroma.example/v1/cafes/caf_001/resenas"
curl "https://api.tiendaaroma.example/v1/cafes/caf_007/resenas"
curl "https://api.tiendaaroma.example/v1/cafes/caf_012/resenas"
# ... y así con los diez

Once peticiones frente a una, y en la primera se descargan origen, tueste, stock y notasCata que la pantalla no usa. Ese es exactamente el argumento de GraphQL.

Conviene matizarlo, en honor a la verdad: REST tiene respuestas parciales a este problema —parámetros de expansión (?incluir=resenas), selección de campos (?campos=nombre,precioEuros) y endpoints agregados diseñados para una pantalla concreta—. Lo que ocurre es que en REST son convenciones ad hoc que cada API resuelve a su manera, mientras que en GraphQL es el modelo mismo.

  1. Qué problemas resuelve GraphQL y cuáles introduce

Problemas que resuelve

Problema Explicación
Over-fetching Recibir más datos de los necesarios. La pantalla quiere el nombre y el precio, y recibe quince campos.
Under-fetching (N+1 de peticiones) Que una petición no baste y haya que hacer N más para completar la información.
Proliferación de endpoints a medida Sin GraphQL, cada nueva pantalla tiende a generar un endpoint específico.
Evolución del contrato Añadir campos no rompe a nadie, porque cada cliente pide los suyos; los campos en desuso se marcan como obsoletos y se mide quién los usa.
Documentación desactualizada El esquema es ejecutable e introspectivo: no puede mentir.

Problemas que introduce

Problema Explicación
Caché HTTP Todo va por POST a una URL. Se pierde la caché de navegadores, proxys y CDN, y hay que sustituirla por caché a nivel de cliente y de campo, mucho más compleja.
Complejidad de consultas Un cliente puede pedir relaciones anidadas profundas y tumbar el servidor. Hay que limitar profundidad, complejidad y coste de cada consulta.
N+1 en la base de datos La flexibilidad se paga en el resolutor: pedir las reseñas de 10 cafés puede lanzar 11 consultas SQL si no se usan técnicas de agrupación.
Seguridad y autorización Los permisos deben aplicarse campo a campo, no por endpoint.
Códigos de estado Los errores llegan en un array errors con 200 OK: la monitorización basada en HTTP no ve nada.
Límites de uso "100 peticiones por minuto" no significa nada si una consulta puede costar mil veces más que otra.
Subida de ficheros y binarios No está en el modelo; requiere extensiones.
Curva de aprendizaje Esquema, resolutores, fragmentos, caché normalizada y herramientas propias.

Fíjate en algo que ya sabes reconocer: GraphQL es, en términos de Richardson, un nivel 0 —un endpoint, todo por POST, la operación dentro del cuerpo—. La diferencia con el pantano de POX es que aquí la elección es deliberada y viene acompañada de un contrato tipado, introspección y un ecosistema de herramientas que compensan lo que se pierde.

  1. gRPC: contrato fuerte y alto rendimiento entre servicios

gRPC (Google, 2015) es RPC moderno. Sus pilares:

  • Protocol Buffers (protobuf): formato binario compacto y tipado para serializar los mensajes.
  • HTTP/2 como transporte, con multiplexado y cabeceras comprimidas.
  • Contrato en un fichero .proto del que se genera el código de cliente y servidor en más de diez lenguajes.
  • Cuatro modos de comunicación, incluido el streaming en ambos sentidos.

El contrato del servicio de inventario de Tienda Aroma

syntax = "proto3";

package tiendaaroma.inventario.v1;

// Servicio interno de inventario: lo consumen los servicios de
// pedidos, catálogo y almacén. No es accesible desde internet.
service Inventario {
  // Consulta puntual del stock de un café
  rpc ConsultarStock (ConsultarStockPeticion) returns (StockRespuesta);

  // Reserva unidades al confirmar un pedido
  rpc ReservarStock (ReservarStockPeticion) returns (StockRespuesta);

  // Flujo continuo de cambios de stock (streaming del servidor):
  // el panel interno se suscribe y recibe actualizaciones en vivo
  rpc SeguirCambios (SeguirCambiosPeticion) returns (stream CambioStock);
}

message ConsultarStockPeticion {
  string cafe_id = 1;              // el número es la posición en el formato binario
}

message ReservarStockPeticion {
  string cafe_id = 1;
  int32  unidades = 2;
  string pedido_id = 3;
}

message StockRespuesta {
  string cafe_id = 1;
  int32  disponible = 2;
  int32  reservado = 3;
}

message CambioStock {
  string cafe_id = 1;
  int32  disponible = 2;
  string momento = 3;              // marca temporal ISO 8601
}

Los números (= 1, = 2) no son valores: son las etiquetas de campo que ocupan el lugar de los nombres en el formato binario. Por eso protobuf es tan compacto —no envía los nombres de los campos— y por eso esos números nunca deben cambiarse una vez publicados: son el contrato real.

Desde Node.js, el consumo se parece a una llamada a función:

// El servicio de pedidos comprueba el stock antes de confirmar
const respuesta = await clienteInventario.consultarStock({ cafe_id: 'caf_001' });

if (respuesta.disponible < unidadesSolicitadas) {
  throw new Error('Stock insuficiente para el café ' + respuesta.cafe_id);
}

Los cuatro modos de gRPC

Modo Descripción Ejemplo en Tienda Aroma
Unario Una petición, una respuesta ConsultarStock
Streaming del servidor Una petición, muchas respuestas SeguirCambios: cambios de stock en vivo
Streaming del cliente Muchas peticiones, una respuesta Carga masiva del inventario tras un recuento
Bidireccional Flujo continuo en ambos sentidos Sincronización en tiempo real con el almacén

Fortalezas y límites

A favor: mensajes mucho más pequeños que JSON, serialización más rápida, contrato fuerte con generación de código, streaming nativo, excelente para tráfico interno de alto volumen y para comunicación entre servicios escritos en lenguajes distintos.

En contra: no es consumible directamente desde un navegador (requiere una pasarela como gRPC-Web), los mensajes binarios no se leen con los ojos ni se depuran con curl, no aprovecha la caché HTTP, y el tooling es peor fuera de entornos preparados. No es un buen candidato para una API pública.

  1. Comunicación dirigida por eventos: webhooks

Todo lo visto hasta ahora comparte una limitación: el cliente pregunta y el servidor responde. ¿Cómo avisa Tienda Aroma a RápidoEnvíos de que un pedido está pagado y listo para recoger?

La opción ingenua es el polling: que RápidoEnvíos consulte cada minuto.

# RápidoEnvíos preguntando una y otra vez... casi siempre para nada
curl "https://api.tiendaaroma.example/v1/pedidos?estado=pagado&desde=2026-08-14T09:00:00Z"

Con un pedido cada media hora y una consulta por minuto, el 98 % de las peticiones son inútiles: gastan recursos en ambos lados y aun así el aviso llega con hasta un minuto de retraso.

Un webhook invierte la dirección: el consumidor registra una URL suya, y el proveedor le hace un POST cuando ocurre algo. Es, literalmente, "una API al revés": ahora Tienda Aroma es el cliente HTTP y RápidoEnvíos el servidor.

sequenceDiagram
    participant TA as Tienda Aroma
    participant RE as RápidoEnvíos
    Note over RE,TA: Registro previo (una sola vez)
    RE->>TA: POST /v1/webhooks<br/>{"url":"https://api.rapidoenvios.example/aroma",<br/> "eventos":["pedido.pagado"]}
    TA-->>RE: 201 Created
    Note over TA: Ocurre el evento
    TA->>RE: POST https://api.rapidoenvios.example/aroma<br/>{"tipo":"pedido.pagado", ...}
    RE-->>TA: 200 OK (acuse de recibo)

El envío del evento:

POST /aroma HTTP/1.1
Host: api.rapidoenvios.example
Content-Type: application/json
Aroma-Evento-Id: evt_9f2c
Aroma-Firma: sha256=7d38cb...

{
  "id": "evt_9f2c",
  "tipo": "pedido.pagado",
  "fecha": "2026-08-14T09:20:11Z",
  "datos": {
    "pedidoId": "ped_5001",
    "clienteId": "cli_842",
    "totalEuros": 29.00,
    "direccionEnvio": {
      "calle": "Carrer de Mallorca 120",
      "ciudad": "Barcelona",
      "codigoPostal": "08036"
    }
  }
}

Cuatro decisiones de diseño que verás en todos los webhooks serios y que conviene interiorizar desde ya:

  1. Firma criptográfica (Aroma-Firma): el receptor recalcula un HMAC del cuerpo con un secreto compartido y verifica que coincide. Sin esto, cualquiera que conozca la URL puede inventarse eventos.
  2. Identificador de evento (Aroma-Evento-Id): permite al receptor detectar duplicados. Los webhooks garantizan entrega "al menos una vez", así que el receptor debe ser idempotente.
  3. Reintentos con espera creciente: si el receptor no responde 2xx, el emisor reintenta a intervalos cada vez mayores durante horas, y avisa si acaba desistiendo.
  4. Tipo de evento con espacio de nombres (pedido.pagado, pedido.enviado, resena.publicada): permite suscribirse selectivamente y añadir eventos nuevos sin romper nada.
Polling Webhook
Quién inicia El consumidor El proveedor
Latencia del aviso Hasta el intervalo de sondeo Casi inmediata
Peticiones inútiles Muchas Ninguna
Requisito del consumidor Ninguno Necesita URL pública accesible
Complejidad Muy baja Reintentos, firmas, duplicados
Fiabilidad Alta (si falla, se reintenta solo) Requiere diseño cuidadoso

Los webhooks no sustituyen a la API REST: la complementan. Lo habitual es que el evento contenga lo justo y el receptor llame después a la API para obtener el detalle completo y actualizado.

  1. Colas, streaming y tiempo real: SSE y WebSockets

Completemos el mapa con tres mecanismos que aparecerán en tu vida profesional:

  • Colas y streaming de mensajes (RabbitMQ, Kafka, SQS): el equivalente interno de los webhooks. El emisor publica un evento en un intermediario y los interesados lo consumen a su ritmo. Aportan persistencia, reintentos, orden y desacoplamiento total. Tienda Aroma los usaría para que los servicios de facturación, fidelización y analítica reaccionen a pedido.pagado sin que el servicio de pedidos sepa siquiera que existen.
  • Server-Sent Events (SSE): un canal HTTP de larga duración por el que el servidor envía mensajes al cliente. Unidireccional, sencillo, sobre HTTP normal, con reconexión automática incluida en el navegador. Ideal para el panel interno de Tienda Aroma mostrando los pedidos que entran en vivo.
  • WebSockets: canal bidireccional persistente sobre una conexión promocionada desde HTTP. Necesario cuando ambos extremos hablan continuamente: un chat de atención al cliente, por ejemplo.
Mecanismo Dirección Sobre HTTP Caso típico
Webhook Servidor → otro servidor Sí (POST) Integración entre empresas
Cola / streaming Productor → consumidores No Eventos entre servicios internos
SSE Servidor → navegador Panel en vivo, notificaciones
WebSocket Bidireccional Solo el inicio Chat, colaboración en tiempo real

Una regla útil: si el usuario debe enterarse de algo sin pedirlo, necesitas uno de estos cuatro; ninguna API REST, GraphQL o gRPC unaria lo resuelve por sí sola.

  1. Tabla comparativa de los cuatro enfoques

Criterio REST GraphQL gRPC Webhooks / eventos
Modelo Recursos y verbos HTTP Consultas sobre un esquema Llamadas a procedimientos Notificación de sucesos
Transporte HTTP HTTP (POST) HTTP/2 HTTP (POST) o broker
Formato JSON (u otros) JSON Binario (protobuf) JSON
Contrato Opcional (OpenAPI) Obligatorio (esquema) Obligatorio (.proto) Documentado por evento
Tipado Débil salvo con esquema Fuerte Fuerte Débil
Acoplamiento Bajo Medio Alto (contrato compartido) Muy bajo
Caché HTTP Nativa y gratuita Difícil No aplica No aplica
Streaming No (usar SSE/WS) Con subscriptions Nativo, en 4 modos Por naturaleza asíncrono
Desde navegador Directo Directo Requiere pasarela No aplica
Depuración curl, navegador Herramientas propias Requiere herramientas Registro de entregas
Público objetivo Cualquiera, incluidos terceros Clientes propios con pantallas ricas Servicios internos Socios e integraciones
Curva de aprendizaje Suave Media-alta Media-alta Media (fiabilidad)
Punto fuerte Simplicidad, caché, universalidad Datos a medida en una llamada Rendimiento y contrato fuerte Avisos sin sondeo
Punto débil Over/under-fetching Caché y control de coste No apto para público Entrega y duplicados

  1. Criterios de decisión honestos

Preguntas concretas, en orden de importancia:

  1. ¿Quién consume la API? Si son terceros que no controlas, REST. La barrera de entrada más baja gana casi siempre; una API pública en gRPC sería un error.
  2. ¿Los datos son cacheables? Si el catálogo lo consultan miles de veces y cambia poco, la caché HTTP gratuita de REST es un argumento de peso difícil de igualar.
  3. ¿Tus clientes necesitan combinaciones muy variables de datos? Si tienes muchas pantallas distintas sobre el mismo modelo y sufres de verdad el over/under-fetching, GraphQL aporta valor real.
  4. ¿Es comunicación interna con volumen alto y latencia crítica? gRPC. Controlas ambos extremos, así que el acoplamiento del contrato no duele y el rendimiento se nota.
  5. ¿El emisor es el servidor? Webhooks hacia fuera, colas hacia dentro. No hay debate: HTTP cliente-servidor no cubre este caso.
  6. ¿Cuál es el tamaño y la experiencia de tu equipo? Una arquitectura excelente que nadie sabe operar es peor que una buena que todos entienden. GraphQL mal operado es una fuente inagotable de incidencias de rendimiento.

Tres avisos, por experiencia acumulada del sector:

  • No adoptes GraphQL solo para evitar dos peticiones. Con HTTP/2 varias peticiones pequeñas salen baratas, y REST admite parámetros de expansión y selección de campos.
  • No uses gRPC hacia el exterior salvo que tus consumidores sean equipos técnicos con capacidad para integrarlo.
  • No implementes webhooks sin firma, reintentos e idempotencia. Un webhook mal hecho genera pedidos duplicados o eventos perdidos, y ambas cosas se ven en la contabilidad.

  1. La arquitectura final de Tienda Aroma

Con todo el mapa sobre la mesa, así queda la decisión del equipo, y es la que seguiremos durante el resto del curso:

graph TD
    subgraph Exterior
        W["Tienda web (SPA)"]
        M["Aroma Móvil"]
        B["Blogs y comparadores"]
        RE["RápidoEnvíos"]
    end

    subgraph "API pública e interna"
        API["API REST v1<br/>Node.js 20 + Express<br/><i>api.tiendaaroma.example/v1</i>"]
    end

    subgraph "Servicios internos"
        INV["Servicio de inventario"]
        FAC["Servicio de facturación"]
    end

    W -->|REST/JSON| API
    M -->|REST/JSON| API
    B -->|REST/JSON público| API
    API -->|gRPC| INV
    API -->|gRPC| FAC
    API -->|"webhook: pedido.pagado"| RE
Necesidad Tecnología elegida Motivo
API pública de catálogo y reseñas REST + JSON Adopción sin fricción, cacheable, probable con curl
Web, app móvil y panel interno REST + JSON Un solo contrato estable para tres clientes propios
Consultas de stock entre servicios gRPC Alto volumen, latencia baja, contrato fuerte, ambos extremos propios
Avisos a RápidoEnvíos Webhooks firmados El emisor es el servidor; evita sondeo constante
Pedidos en vivo en el panel interno SSE Unidireccional y sencillo, sobre HTTP estándar
Eventos entre servicios internos Cola de mensajes Desacopla facturación, fidelización y analítica

Y una decisión igual de importante: GraphQL, de momento, no. El equipo lo ha valorado y ha concluido que sus pantallas son pocas y estables, que la caché del catálogo es un activo que no quiere perder y que el equipo es pequeño. Es una decisión revisable, tomada con argumentos y anotada. Eso es diseñar; lo contrario es seguir la moda.

Errores Comunes y Consejos

  • Elegir por moda y no por problema. Pregunta siempre qué limitación concreta estás sufriendo hoy. Si no sabes nombrarla, no cambies de tecnología.
  • Creer que GraphQL sustituye a REST. Son complementarios. Muchas empresas exponen GraphQL para sus propios clientes y REST para terceros, sobre el mismo backend.
  • Olvidar que GraphQL pierde la caché HTTP. Si tu tráfico es mayoritariamente lectura de datos poco cambiantes, esa pérdida puede costar más de lo que ahorras en peticiones.
  • Usar gRPC en el navegador sin pasarela. No funciona directamente: necesitas gRPC-Web y un proxy que traduzca.
  • Cambiar los números de campo de un .proto. Rompe la compatibilidad binaria de forma silenciosa y difícil de diagnosticar. Los números son el contrato.
  • Tratar un webhook como una entrega garantizada y única. Llega al menos una vez, y a veces más. Sin idempotencia en el receptor, tendrás duplicados.
  • Poner datos completos y sensibles en el cuerpo del webhook. Envía lo mínimo y deja que el receptor consulte la API si necesita más: el evento puede llegar tarde y con datos ya obsoletos.
  • Consejo: mantén una regla sencilla —REST hacia fuera, gRPC hacia dentro, eventos para lo asíncrono— y desvíate de ella solo con una razón que puedas escribir en dos líneas.

Ejercicios

Ejercicio 1: elegir la tecnología adecuada

Para cada necesidad de Tienda Aroma, elige entre REST, GraphQL, gRPC, webhook o SSE, y justifica con dos argumentos:

  1. Un comparador de precios externo quiere consultar el catálogo cada hora.
  2. El servicio de pedidos comprueba el stock 800 veces por segundo antes de confirmar compras.
  3. La pantalla de "mi cuenta" de Aroma Móvil muestra datos del cliente, sus tres últimos pedidos, el estado de envío de cada uno y sus reseñas.
  4. El proveedor de tostado debe enterarse en cuanto el stock de un café baja de 20 unidades.
  5. El panel del almacén muestra los pedidos que van entrando, sin recargar.

Ejercicio 2: diseñar un webhook completo

Diseña el webhook pedido.enviado que Tienda Aroma enviará al cliente que lo solicite. Especifica: el cuerpo JSON del evento, las cabeceras necesarias, qué debe responder el receptor, qué hará el emisor si no responde y qué medidas de seguridad incluyes.

Ejercicio 3: comparar coste de peticiones

La pantalla de detalle de un café en Aroma Móvil necesita: nombre, precio, stock, las cinco últimas reseñas (autor y puntuación) y el nombre del tostador.

  1. ¿Cuántas peticiones REST harían falta con un diseño ingenuo?
  2. Escribe la consulta GraphQL equivalente.
  3. Propón dos soluciones dentro de REST que reduzcan el número de peticiones sin adoptar GraphQL.
  4. ¿Qué se pierde en cada caso?

Soluciones

Solución 1

  1. REST. Es un tercero desconocido que debe integrarse sin fricción, y el catálogo es contenido público y cacheable: Cache-Control hace que muchas de esas consultas ni siquiera lleguen al servidor.
  2. gRPC. Es tráfico interno con ambos extremos bajo control, donde el formato binario y HTTP/2 reducen latencia y CPU frente a JSON; además el contrato .proto evita errores de tipos en un camino crítico.
  3. GraphQL sería el candidato ideal por combinar cuatro fuentes de datos en una sola consulta, evitando el N+1 de peticiones. Ahora bien, si es la única pantalla con ese problema, la respuesta pragmática es un endpoint REST agregado (GET /v1/clientes/cli_842/resumen): resuelve el caso sin introducir una tecnología entera.
  4. Webhook. El emisor es Tienda Aroma y el receptor es una empresa externa; el sondeo constante sería un desperdicio y añadiría retraso al aviso.
  5. SSE. Es un flujo unidireccional del servidor al navegador, funciona sobre HTTP normal y se reconecta solo. Un WebSocket sería innecesariamente complejo porque el panel no envía nada de vuelta.

Solución 2

Cuerpo del evento:

{
  "id": "evt_a41d",
  "tipo": "pedido.enviado",
  "fecha": "2026-08-15T11:04:00Z",
  "version": "1",
  "datos": {
    "pedidoId": "ped_5001",
    "clienteId": "cli_842",
    "transportista": "RápidoEnvíos",
    "numeroSeguimiento": "RE9928374ES",
    "entregaEstimada": "2026-08-17"
  }
}

Cabeceras:

POST /webhooks/aroma HTTP/1.1
Content-Type: application/json
Aroma-Evento-Id: evt_a41d
Aroma-Evento-Tipo: pedido.enviado
Aroma-Firma: sha256=7d38cb...
Aroma-Fecha: 2026-08-15T11:04:00Z
User-Agent: TiendaAroma-Webhooks/1.0

Qué debe responder el receptor: un 2xx (idealmente 200 OK o 204 No Content) lo antes posible, antes de procesar el evento. La regla es aceptar, encolar y procesar de forma asíncrona: si tardas en responder porque estás haciendo trabajo pesado, el emisor puede considerarlo un fallo y reintentar, generando duplicados.

Si no responde: reintentos con espera creciente (por ejemplo, a los 30 s, 2 min, 10 min, 1 h, 6 h y 24 h), registro de cada intento accesible para el consumidor, aviso por correo tras varios fallos y desactivación del endpoint tras un número de fallos consecutivos.

Seguridad:

  • Firma HMAC-SHA256 del cuerpo con un secreto compartido, que el receptor verifica antes de procesar nada.
  • Marca temporal en la firma para rechazar reenvíos antiguos (ataques de repetición).
  • HTTPS obligatorio en la URL de destino.
  • Identificador de evento para descartar duplicados en el receptor.
  • Datos mínimos: nada de datos de pago ni personales innecesarios; si hace falta más, que consulte la API autenticado.

Solución 3

1. Peticiones REST con diseño ingenuo: tres.

curl https://api.tiendaaroma.example/v1/cafes/caf_001
curl "https://api.tiendaaroma.example/v1/cafes/caf_001/resenas?limite=5"
curl https://api.tiendaaroma.example/v1/tostadores/tos_03

2. Consulta GraphQL: una.

query {
  cafe(id: "caf_001") {
    nombre
    precioEuros
    stock
    tostador { nombre }
    resenas(limite: 5) { autor puntuacion }
  }
}

3. Dos soluciones dentro de REST:

  • Parámetro de expansión: GET /v1/cafes/caf_001?incluir=resenas,tostador, que devuelve los recursos relacionados incrustados en la misma respuesta. Una sola petición, y sigue siendo un GET cacheable.
  • Recurso agregado orientado a la pantalla: GET /v1/cafes/caf_001/detalle, diseñado específicamente para esa vista. Simple y muy eficiente.

4. Qué se pierde en cada caso:

  • Con GraphQL: la caché HTTP (todo es POST a /graphql), los códigos de estado significativos y la posibilidad de probar la llamada desde el navegador; además hay que controlar el coste de las consultas.
  • Con el parámetro de expansión: la caché se fragmenta (cada combinación de incluir es una entrada distinta) y el servidor se complica; si se abusa, se acaba reimplementando GraphQL a mano y peor.
  • Con el recurso agregado: se acopla la API a una pantalla concreta. Si cada vista nueva añade su propio endpoint, la API se llena de recursos a medida difíciles de mantener y de documentar.

No hay opción gratuita: las tres son intercambios conscientes, y elegir bien consiste en saber cuál duele menos en tu contexto.

Conclusión

Ya tienes el mapa completo de estilos de integración. REST destaca por su simplicidad, su universalidad y la caché que hereda de HTTP, y es la elección natural cuando el consumidor puede ser cualquiera. GraphQL resuelve el over-fetching y el under-fetching dando al cliente el control de los campos, a cambio de perder la caché HTTP y de tener que gobernar el coste de las consultas. gRPC aporta contrato fuerte, formato binario y streaming, y brilla entre servicios internos donde controlas ambos extremos. Y los webhooks, junto con las colas, SSE y WebSockets, cubren el hueco que ningún modelo petición-respuesta puede cubrir: que el servidor tome la iniciativa. La conclusión práctica es que no compiten: Tienda Aroma usará REST hacia fuera, gRPC hacia dentro y webhooks para sus integraciones, y ha dejado GraphQL fuera por razones escritas y revisables.

Con esto cerramos el módulo 1. Sabes qué es una API y para quién se diseña, de dónde viene el ecosistema actual, cómo funciona HTTP por debajo, en qué consisten las seis restricciones de REST, cómo medir la madurez de una API y qué alternativas existen. Toca pasar de comprender a construir. En el módulo 2, Diseño de APIs RESTful, empezaremos a diseñar la API de Tienda Aroma pieza a pieza: sus principios de diseño, sus recursos y URIs, el uso preciso de cada método HTTP y de cada código de estado, la negociación de contenido, el filtrado y la paginación, el versionado y la documentación. Es el momento en que las ideas de este módulo se convierten en decisiones concretas sobre un contrato real.

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