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
- Por qué no basta con un único estilo
- GraphQL: el cliente decide qué campos quiere
- Qué problemas resuelve GraphQL y cuáles introduce
- gRPC: contrato fuerte y alto rendimiento entre servicios
- Comunicación dirigida por eventos: webhooks
- Colas, streaming y tiempo real: SSE y WebSockets
- Tabla comparativa de los cuatro enfoques
- Criterios de decisión honestos
- La arquitectura final de Tienda Aroma
- 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.
- 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:
- Un esquema tipado define todos los datos disponibles y sus relaciones. Es el contrato, y es obligatorio.
- Una sola URL (típicamente
/graphql), a la que se hacePOST. - 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í:
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 diezOnce 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.
- 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.
- 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
.protodel 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.
- 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:
- 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. - 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. - 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. - 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.
- 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.pagadosin 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 | Sí | 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.
- 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 |
- Criterios de decisión honestos
Preguntas concretas, en orden de importancia:
- ¿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.
- ¿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.
- ¿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.
- ¿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.
- ¿El emisor es el servidor? Webhooks hacia fuera, colas hacia dentro. No hay debate: HTTP cliente-servidor no cubre este caso.
- ¿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.
- 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:
- Un comparador de precios externo quiere consultar el catálogo cada hora.
- El servicio de pedidos comprueba el stock 800 veces por segundo antes de confirmar compras.
- 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.
- El proveedor de tostado debe enterarse en cuanto el stock de un café baja de 20 unidades.
- 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.
- ¿Cuántas peticiones REST harían falta con un diseño ingenuo?
- Escribe la consulta GraphQL equivalente.
- Propón dos soluciones dentro de REST que reduzcan el número de peticiones sin adoptar GraphQL.
- ¿Qué se pierde en cada caso?
Soluciones
Solución 1
- REST. Es un tercero desconocido que debe integrarse sin fricción, y el catálogo es contenido público y cacheable:
Cache-Controlhace que muchas de esas consultas ni siquiera lleguen al servidor. - 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
.protoevita errores de tipos en un camino crítico. - 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. - 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.
- 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.0Qué 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_032. 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 unGETcacheable. - 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
POSTa/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
incluires 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
- ¿Qué es una API?
- Historia y evolución de las APIs
- Fundamentos de HTTP para APIs
- Principios básicos de REST
- Modelo de madurez de Richardson y HATEOAS
- REST vs. SOAP
- REST frente a GraphQL, gRPC y webhooks
Módulo 2: Diseño de APIs RESTful
- Principios de diseño de APIs RESTful
- Recursos y URIs
- Métodos HTTP
- Códigos de estado HTTP
- Representaciones, cabeceras y negociación de contenido
- Filtrado, ordenación, paginación y búsqueda
- Versionado de APIs
- Documentación de APIs
Módulo 3: Desarrollo de APIs RESTful
- Configuración del entorno de desarrollo
- Creación de un servidor básico
- Manejo de peticiones y respuestas
- Validación de datos de entrada
- Persistencia y capa de acceso a datos
- Autenticación y autorización
- Manejo de errores
- Pruebas y validación
Módulo 4: Buenas Prácticas y Seguridad
- Buenas prácticas en el diseño de APIs
- Seguridad en APIs RESTful
- OAuth 2.0 y OpenID Connect en la práctica
- Rate limiting y throttling
- CORS y políticas de seguridad
- Caché HTTP y rendimiento
- Observabilidad: logs, métricas y trazas
Módulo 5: Herramientas y Frameworks
- Postman para pruebas de APIs
- Swagger y OpenAPI para documentación
- Frameworks populares para APIs RESTful
- Contratos, mocks y pruebas automatizadas de API
- Integración continua y despliegue
- API gateways y portales de desarrollador
