REST és l'estàndard de facto de les APIs web, però no és l'única eina ni sempre la millor. Els darrers anys han madurat alternatives que ataquen limitacions molt concretes: GraphQL va néixer del problema de demanar dades a mida des del mòbil; gRPC, de la necessitat de comunicació interna d'alt rendiment; els webhooks, de la incapacitat d'HTTP perquè el servidor avisi el client. Aquesta lliçó tanca el mòdul dibuixant el mapa complet d'estils d'integració, amb exemples aplicats a la Botiga Aroma, perquè sàpigues triar amb criteri i —el més important— entenguis que aquests enfocaments no competeixen: conviuen a la mateixa empresa, cadascun al seu lloc.
Contingut
- Per què no n'hi ha prou amb un únic estil
- GraphQL: el client decideix quins camps vol
- Quins problemes resol GraphQL i quins n'introdueix
- gRPC: contracte fort i alt rendiment entre serveis
- Comunicació dirigida per esdeveniments: webhooks
- Cues, streaming i temps real: SSE i WebSockets
- Taula comparativa dels quatre enfocaments
- Criteris de decisió honestos
- L'arquitectura final de la Botiga Aroma
- Per què no n'hi ha prou amb un únic estil
Les necessitats de comunicació de la Botiga Aroma no són homogènies. Compara aquests quatre casos:
| Necessitat | Característiques | Encaixa bé en REST? |
|---|---|---|
| Un blog mostra el catàleg | Públic, lectura, cacheable, client desconegut | Perfectament |
| La pantalla de comanda d'Aroma Mòbil | Necessita dades de comanda, client, cafès i enviament alhora | Regular: diverses peticions |
| El servei de comandes consulta l'estoc 500 vegades per segon | Intern, alt volum, latència crítica | Mediocre: sobrecàrrega de JSON i HTTP/1 |
| Avisar RàpidEnviaments que una comanda està pagada | L'emissor és el servidor; el receptor és extern | Malament: HTTP només va client → servidor |
Cada desajust té una resposta específica. Veure-les juntes et dona criteri; fer-les servir totes alhora sense motiu, et dona una arquitectura ingovernable.
- GraphQL: el client decideix quins camps vol
GraphQL és un llenguatge de consulta per a APIs, creat a Facebook el 2012 i publicat el 2015. Les seves tres decisions fonamentals:
- Un esquema tipat defineix totes les dades disponibles i les seves relacions. És el contracte, i és obligatori.
- Una sola URL (típicament
/graphql), a la qual es faPOST. - El client escriu la consulta: demana exactament els camps que necessita, ni un més.
L'esquema de la Botiga Aroma
type Cafe {
id: ID!
nom: String!
origen: String!
torrefaccio: Torrefaccio!
preuEuros: Float!
estoc: Int!
notesTast: [String!]!
ressenyes: [Ressenya!]!
}
type Ressenya {
id: ID!
autor: String!
puntuacio: Int!
comentari: String
}
enum Torrefaccio { CLAR MITJA FOSC }
type Query {
cafe(id: ID!): Cafe
cafes(origen: String, torrefaccio: Torrefaccio, limit: Int): [Cafe!]!
}El signe ! vol dir "no pot ser nul". L'esquema és alhora documentació, validació i contracte: les eines el llegeixen i ofereixen autocompleció en escriure consultes.
La consulta
L'app mòbil necessita, per a la seva pantalla de catàleg, només el nom, el preu i la puntuació mitjana. Ho demana així:
I rep exactament això, amb la mateixa forma que la consulta:
{
"data": {
"cafes": [
{
"id": "caf_001",
"nom": "Etiòpia Yirgacheffe",
"preuEuros": 14.50,
"ressenyes": [{ "puntuacio": 5 }, { "puntuacio": 4 }]
}
]
}
}Per HTTP, la petició real és un POST:
curl -X POST https://api.botigaaroma.example/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TOKEN" \
-d '{"query":"{ cafes(origen: \"Etiòpia\", limit: 10) { id nom preuEuros ressenyes { puntuacio } } }"}'L'equivalent en REST
Per aconseguir el mateix amb l'API REST de la Botiga Aroma caldrien diverses crides:
# 1. Els cafès d'Etiòpia (retorna TOTS els camps de cada cafè)
curl "https://api.botigaaroma.example/v1/cafes?origen=Etiopia&limit=10"
# 2. Les ressenyes de cada cafè: una petició per cafè
curl "https://api.botigaaroma.example/v1/cafes/caf_001/ressenyes"
curl "https://api.botigaaroma.example/v1/cafes/caf_007/ressenyes"
curl "https://api.botigaaroma.example/v1/cafes/caf_012/ressenyes"
# ... i així amb els deuOnze peticions davant d'una, i a la primera es descarreguen origen, torrefaccio, estoc i notesTast que la pantalla no fa servir. Aquest és exactament l'argument de GraphQL.
Convé matisar-ho, en honor a la veritat: REST té respostes parcials a aquest problema —paràmetres d'expansió (?incloure=ressenyes), selecció de camps (?camps=nom,preuEuros) i endpoints agregats dissenyats per a una pantalla concreta—. El que passa és que en REST són convencions ad hoc que cada API resol a la seva manera, mentre que en GraphQL és el model mateix.
- Quins problemes resol GraphQL i quins n'introdueix
Problemes que resol
| Problema | Explicació |
|---|---|
| Over-fetching | Rebre més dades de les necessàries. La pantalla vol el nom i el preu, i en rep quinze camps. |
| Under-fetching (N+1 de peticions) | Que una petició no basti i calgui fer-ne N més per completar la informació. |
| Proliferació d'endpoints a mida | Sense GraphQL, cada pantalla nova tendeix a generar un endpoint específic. |
| Evolució del contracte | Afegir camps no trenca ningú, perquè cada client demana els seus; els camps en desús es marquen com a obsolets i es mesura qui els fa servir. |
| Documentació desactualitzada | L'esquema és executable i introspectiu: no pot mentir. |
Problemes que introdueix
| Problema | Explicació |
|---|---|
| Memòria cau HTTP | Tot va per POST a una URL. Es perd la memòria cau de navegadors, servidors intermediaris i CDN, i cal substituir-la per memòria cau a nivell de client i de camp, molt més complexa. |
| Complexitat de consultes | Un client pot demanar relacions imbricades profundes i tombar el servidor. Cal limitar profunditat, complexitat i cost de cada consulta. |
| N+1 a la base de dades | La flexibilitat es paga al resolutor: demanar les ressenyes de 10 cafès pot llançar 11 consultes SQL si no es fan servir tècniques d'agrupació. |
| Seguretat i autorització | Els permisos s'han d'aplicar camp a camp, no per endpoint. |
| Codis d'estat | Els errors arriben en un array errors amb 200 OK: el monitoratge basat en HTTP no hi veu res. |
| Límits d'ús | "100 peticions per minut" no vol dir res si una consulta pot costar mil vegades més que una altra. |
| Pujada de fitxers i binaris | No és al model; requereix extensions. |
| Corba d'aprenentatge | Esquema, resolutors, fragments, memòria cau normalitzada i eines pròpies. |
Fixa't en una cosa que ja saps reconèixer: GraphQL és, en termes de Richardson, un nivell 0 —un endpoint, tot per POST, l'operació dins del cos—. La diferència amb el pantà de POX és que aquí l'elecció és deliberada i ve acompanyada d'un contracte tipat, introspecció i un ecosistema d'eines que compensen el que s'hi perd.
- gRPC: contracte fort i alt rendiment entre serveis
gRPC (Google, 2015) és RPC modern. Els seus pilars:
- Protocol Buffers (protobuf): format binari compacte i tipat per serialitzar els missatges.
- HTTP/2 com a transport, amb multiplexatge i capçaleres comprimides.
- Contracte en un fitxer
.protodel qual es genera el codi de client i de servidor en més de deu llenguatges. - Quatre modes de comunicació, inclòs l'streaming en tots dos sentits.
El contracte del servei d'inventari de la Botiga Aroma
syntax = "proto3";
package botigaaroma.inventari.v1;
// Servei intern d'inventari: el consumeixen els serveis de
// comandes, catàleg i magatzem. No és accessible des d'internet.
service Inventari {
// Consulta puntual de l'estoc d'un cafè
rpc ConsultarEstoc (ConsultarEstocPeticio) returns (EstocResposta);
// Reserva unitats en confirmar una comanda
rpc ReservarEstoc (ReservarEstocPeticio) returns (EstocResposta);
// Flux continu de canvis d'estoc (streaming del servidor):
// el panell intern s'hi subscriu i rep actualitzacions en directe
rpc SeguirCanvis (SeguirCanvisPeticio) returns (stream CanviEstoc);
}
message ConsultarEstocPeticio {
string cafe_id = 1; // el número és la posició al format binari
}
message ReservarEstocPeticio {
string cafe_id = 1;
int32 unitats = 2;
string comanda_id = 3;
}
message EstocResposta {
string cafe_id = 1;
int32 disponible = 2;
int32 reservat = 3;
}
message CanviEstoc {
string cafe_id = 1;
int32 disponible = 2;
string moment = 3; // marca temporal ISO 8601
}Els números (= 1, = 2) no són valors: són les etiquetes de camp que ocupen el lloc dels noms al format binari. Per això protobuf és tan compacte —no envia els noms dels camps— i per això aquests números no s'han de canviar mai un cop publicats: són el contracte real.
Des de Node.js, el consum s'assembla a una crida a funció:
// El servei de comandes comprova l'estoc abans de confirmar
const resposta = await clientInventari.consultarEstoc({ cafe_id: 'caf_001' });
if (resposta.disponible < unitatsSollicitades) {
throw new Error('Estoc insuficient per al cafè ' + resposta.cafe_id);
}Els quatre modes de gRPC
| Mode | Descripció | Exemple a la Botiga Aroma |
|---|---|---|
| Unari | Una petició, una resposta | ConsultarEstoc |
| Streaming del servidor | Una petició, moltes respostes | SeguirCanvis: canvis d'estoc en directe |
| Streaming del client | Moltes peticions, una resposta | Càrrega massiva de l'inventari després d'un recompte |
| Bidireccional | Flux continu en tots dos sentits | Sincronització en temps real amb el magatzem |
Fortaleses i límits
A favor: missatges molt més petits que JSON, serialització més ràpida, contracte fort amb generació de codi, streaming natiu, excel·lent per a trànsit intern d'alt volum i per a comunicació entre serveis escrits en llenguatges diferents.
En contra: no és consumible directament des d'un navegador (requereix una passarel·la com gRPC-Web), els missatges binaris no es llegeixen amb els ulls ni es depuren amb curl, no aprofita la memòria cau HTTP, i el tooling és pitjor fora d'entorns preparats. No és un bon candidat per a una API pública.
- Comunicació dirigida per esdeveniments: webhooks
Tot el que hem vist fins ara comparteix una limitació: el client pregunta i el servidor respon. Com avisa la Botiga Aroma RàpidEnviaments que una comanda està pagada i a punt per recollir?
L'opció ingènua és el polling: que RàpidEnviaments ho consulti cada minut.
# RàpidEnviaments preguntant una vegada i una altra... gairebé sempre per res
curl "https://api.botigaaroma.example/v1/comandes?estat=pagat&des=2026-08-14T09:00:00Z"Amb una comanda cada mitja hora i una consulta per minut, el 98 % de les peticions són inútils: gasten recursos a totes dues bandes i tot i així l'avís arriba amb fins a un minut de retard.
Un webhook inverteix la direcció: el consumidor registra una URL seva, i el proveïdor li fa un POST quan passa alguna cosa. És, literalment, "una API a l'inrevés": ara la Botiga Aroma és el client HTTP i RàpidEnviaments el servidor.
sequenceDiagram
participant TA as Botiga Aroma
participant RE as RàpidEnviaments
Note over RE,TA: Registre previ (una sola vegada)
RE->>TA: POST /v1/webhooks<br/>{"url":"https://api.rapidenviaments.example/aroma",<br/> "esdeveniments":["comanda.pagada"]}
TA-->>RE: 201 Created
Note over TA: Passa l'esdeveniment
TA->>RE: POST https://api.rapidenviaments.example/aroma<br/>{"tipus":"comanda.pagada", ...}
RE-->>TA: 200 OK (acusament de recepció)
L'enviament de l'esdeveniment:
POST /aroma HTTP/1.1
Host: api.rapidenviaments.example
Content-Type: application/json
Aroma-Esdeveniment-Id: evt_9f2c
Aroma-Signatura: sha256=7d38cb...
{
"id": "evt_9f2c",
"tipus": "comanda.pagada",
"data": "2026-08-14T09:20:11Z",
"dades": {
"comandaId": "com_5001",
"clientId": "cli_842",
"totalEuros": 29.00,
"adrecaEnviament": {
"carrer": "Carrer de Mallorca 120",
"ciutat": "Barcelona",
"codiPostal": "08036"
}
}
}Quatre decisions de disseny que veuràs en tots els webhooks seriosos i que convé interioritzar des d'ara:
- Signatura criptogràfica (
Aroma-Signatura): el receptor recalcula un HMAC del cos amb un secret compartit i verifica que coincideix. Sense això, qualsevol que conegui la URL pot inventar-se esdeveniments. - Identificador d'esdeveniment (
Aroma-Esdeveniment-Id): permet al receptor detectar duplicats. Els webhooks garanteixen lliurament "com a mínim una vegada", així que el receptor ha de ser idempotent. - Reintents amb espera creixent: si el receptor no respon
2xx, l'emissor reintenta a intervals cada cop més grans durant hores, i avisa si acaba desistint. - Tipus d'esdeveniment amb espai de noms (
comanda.pagada,comanda.enviada,ressenya.publicada): permet subscriure-s'hi selectivament i afegir esdeveniments nous sense trencar res.
| Polling | Webhook | |
|---|---|---|
| Qui l'inicia | El consumidor | El proveïdor |
| Latència de l'avís | Fins a l'interval de sondeig | Gairebé immediata |
| Peticions inútils | Moltes | Cap |
| Requisit del consumidor | Cap | Necessita una URL pública accessible |
| Complexitat | Molt baixa | Reintents, signatures, duplicats |
| Fiabilitat | Alta (si falla, es reintenta sol) | Requereix un disseny acurat |
Els webhooks no substitueixen l'API REST: la complementen. L'habitual és que l'esdeveniment contingui el just i que el receptor cridi després l'API per obtenir-ne el detall complet i actualitzat.
- Cues, streaming i temps real: SSE i WebSockets
Completem el mapa amb tres mecanismes que apareixeran en la teva vida professional:
- Cues i streaming de missatges (RabbitMQ, Kafka, SQS): l'equivalent intern dels webhooks. L'emissor publica un esdeveniment en un intermediari i els interessats el consumeixen al seu ritme. Aporten persistència, reintents, ordre i desacoblament total. La Botiga Aroma els faria servir perquè els serveis de facturació, fidelització i analítica reaccionin a
comanda.pagadasense que el servei de comandes sàpiga ni tan sols que existeixen. - Server-Sent Events (SSE): un canal HTTP de llarga durada pel qual el servidor envia missatges al client. Unidireccional, senzill, sobre HTTP normal, amb reconnexió automàtica inclosa al navegador. Ideal per al panell intern de la Botiga Aroma mostrant les comandes que entren en directe.
- WebSockets: canal bidireccional persistent sobre una connexió promocionada des d'HTTP. Necessari quan tots dos extrems parlen contínuament: un xat d'atenció al client, per exemple.
| Mecanisme | Direcció | Sobre HTTP | Cas típic |
|---|---|---|---|
| Webhook | Servidor → un altre servidor | Sí (POST) |
Integració entre empreses |
| Cua / streaming | Productor → consumidors | No | Esdeveniments entre serveis interns |
| SSE | Servidor → navegador | Sí | Panell en directe, notificacions |
| WebSocket | Bidireccional | Només l'inici | Xat, col·laboració en temps real |
Una regla útil: si l'usuari s'ha d'assabentar d'alguna cosa sense demanar-la, necessites un d'aquests quatre; cap API REST, GraphQL o gRPC unària no ho resol tota sola.
- Taula comparativa dels quatre enfocaments
| Criteri | REST | GraphQL | gRPC | Webhooks / esdeveniments |
|---|---|---|---|---|
| Model | Recursos i verbs HTTP | Consultes sobre un esquema | Crides a procediments | Notificació de fets |
| Transport | HTTP | HTTP (POST) |
HTTP/2 | HTTP (POST) o broker |
| Format | JSON (o d'altres) | JSON | Binari (protobuf) | JSON |
| Contracte | Opcional (OpenAPI) | Obligatori (esquema) | Obligatori (.proto) |
Documentat per esdeveniment |
| Tipatge | Feble tret que hi hagi esquema | Fort | Fort | Feble |
| Acoblament | Baix | Mitjà | Alt (contracte compartit) | Molt baix |
| Memòria cau HTTP | Nativa i gratuïta | Difícil | No aplica | No aplica |
| Streaming | No (fes servir SSE/WS) | Amb subscriptions | Natiu, en 4 modes | Asíncron per naturalesa |
| Des del navegador | Directe | Directe | Requereix passarel·la | No aplica |
| Depuració | curl, navegador |
Eines pròpies | Requereix eines | Registre de lliuraments |
| Públic objectiu | Qualsevol, inclosos tercers | Clients propis amb pantalles riques | Serveis interns | Socis i integracions |
| Corba d'aprenentatge | Suau | Mitjana-alta | Mitjana-alta | Mitjana (fiabilitat) |
| Punt fort | Simplicitat, memòria cau, universalitat | Dades a mida en una crida | Rendiment i contracte fort | Avisos sense sondeig |
| Punt feble | Over/under-fetching | Memòria cau i control de cost | No apte per al públic | Lliurament i duplicats |
- Criteris de decisió honestos
Preguntes concretes, en ordre d'importància:
- Qui consumeix l'API? Si són tercers que no controles, REST. La barrera d'entrada més baixa guanya gairebé sempre; una API pública en gRPC seria un error.
- Les dades són cacheables? Si el catàleg el consulten milers de vegades i canvia poc, la memòria cau HTTP gratuïta de REST és un argument de pes difícil d'igualar.
- Els teus clients necessiten combinacions molt variables de dades? Si tens moltes pantalles diferents sobre el mateix model i pateixes de debò l'over/under-fetching, GraphQL hi aporta valor real.
- És comunicació interna amb volum alt i latència crítica? gRPC. Controles tots dos extrems, així que l'acoblament del contracte no fa mal i el rendiment es nota.
- L'emissor és el servidor? Webhooks cap a fora, cues cap a dins. No hi ha debat: HTTP client-servidor no cobreix aquest cas.
- Quina és la mida i l'experiència del teu equip? Una arquitectura excel·lent que ningú no sap operar és pitjor que una de bona que tothom entén. GraphQL mal operat és una font inesgotable d'incidències de rendiment.
Tres advertiments, per experiència acumulada del sector:
- No adoptis GraphQL només per evitar dues peticions. Amb HTTP/2 diverses peticions petites surten barates, i REST admet paràmetres d'expansió i selecció de camps.
- No facis servir gRPC cap a l'exterior tret que els teus consumidors siguin equips tècnics amb capacitat per integrar-lo.
- No implementis webhooks sense signatura, reintents i idempotència. Un webhook mal fet genera comandes duplicades o esdeveniments perduts, i totes dues coses es veuen a la comptabilitat.
- L'arquitectura final de la Botiga Aroma
Amb tot el mapa sobre la taula, així queda la decisió de l'equip, i és la que seguirem durant la resta del curs:
graph TD
subgraph Exterior
W["Botiga web (SPA)"]
M["Aroma Mòbil"]
B["Blogs i comparadors"]
RE["RàpidEnviaments"]
end
subgraph "API pública i interna"
API["API REST v1<br/>Node.js 20 + Express<br/><i>api.botigaaroma.example/v1</i>"]
end
subgraph "Serveis interns"
INV["Servei d'inventari"]
FAC["Servei de facturació"]
end
W -->|REST/JSON| API
M -->|REST/JSON| API
B -->|REST/JSON públic| API
API -->|gRPC| INV
API -->|gRPC| FAC
API -->|"webhook: comanda.pagada"| RE
| Necessitat | Tecnologia triada | Motiu |
|---|---|---|
| API pública de catàleg i ressenyes | REST + JSON | Adopció sense fricció, cacheable, provable amb curl |
| Web, app mòbil i panell intern | REST + JSON | Un sol contracte estable per a tres clients propis |
| Consultes d'estoc entre serveis | gRPC | Alt volum, latència baixa, contracte fort, tots dos extrems propis |
| Avisos a RàpidEnviaments | Webhooks signats | L'emissor és el servidor; evita sondeig constant |
| Comandes en directe al panell intern | SSE | Unidireccional i senzill, sobre HTTP estàndard |
| Esdeveniments entre serveis interns | Cua de missatges | Desacobla facturació, fidelització i analítica |
I una decisió igual d'important: GraphQL, de moment, no. L'equip ho ha valorat i ha conclòs que les seves pantalles són poques i estables, que la memòria cau del catàleg és un actiu que no vol perdre i que l'equip és petit. És una decisió revisable, presa amb arguments i anotada. Això és dissenyar; el contrari és seguir la moda.
Errors Comuns i Consells
- Triar per moda i no per problema. Pregunta't sempre quina limitació concreta estàs patint avui. Si no la saps anomenar, no canviïs de tecnologia.
- Creure que GraphQL substitueix REST. Són complementaris. Moltes empreses exposen GraphQL per als seus propis clients i REST per a tercers, sobre el mateix backend.
- Oblidar que GraphQL perd la memòria cau HTTP. Si el teu trànsit és majoritàriament lectura de dades poc canviants, aquesta pèrdua pot costar més del que estalvies en peticions.
- Fer servir gRPC al navegador sense passarel·la. No funciona directament: necessites gRPC-Web i un servidor intermediari que tradueixi.
- Canviar els números de camp d'un
.proto. Trenca la compatibilitat binària de manera silenciosa i difícil de diagnosticar. Els números són el contracte. - Tractar un webhook com un lliurament garantit i únic. Arriba com a mínim una vegada, i de vegades més. Sense idempotència al receptor, tindràs duplicats.
- Posar dades completes i sensibles al cos del webhook. Envia el mínim i deixa que el receptor consulti l'API si necessita més: l'esdeveniment pot arribar tard i amb dades ja obsoletes.
- Consell: mantén una regla senzilla —REST cap a fora, gRPC cap a dins, esdeveniments per a allò asíncron— i desvia-te'n només amb una raó que puguis escriure en dues línies.
Exercicis
Exercici 1: triar la tecnologia adequada
Per a cada necessitat de la Botiga Aroma, tria entre REST, GraphQL, gRPC, webhook o SSE, i justifica-ho amb dos arguments:
- Un comparador de preus extern vol consultar el catàleg cada hora.
- El servei de comandes comprova l'estoc 800 vegades per segon abans de confirmar compres.
- La pantalla del "meu compte" d'Aroma Mòbil mostra dades del client, les seves tres últimes comandes, l'estat d'enviament de cadascuna i les seves ressenyes.
- El proveïdor de torrefacció s'ha d'assabentar tan bon punt l'estoc d'un cafè baixa de 20 unitats.
- El panell del magatzem mostra les comandes que van entrant, sense recarregar.
Exercici 2: dissenyar un webhook complet
Dissenya el webhook comanda.enviada que la Botiga Aroma enviarà al client que ho sol·liciti. Especifica: el cos JSON de l'esdeveniment, les capçaleres necessàries, què ha de respondre el receptor, què farà l'emissor si no respon i quines mesures de seguretat hi inclous.
Exercici 3: comparar cost de peticions
La pantalla de detall d'un cafè a Aroma Mòbil necessita: nom, preu, estoc, les cinc últimes ressenyes (autor i puntuació) i el nom del torrefactor.
- Quantes peticions REST caldrien amb un disseny ingenu?
- Escriu la consulta GraphQL equivalent.
- Proposa dues solucions dins de REST que redueixin el nombre de peticions sense adoptar GraphQL.
- Què s'hi perd en cada cas?
Solucions
Solució 1
- REST. És un tercer desconegut que s'ha d'integrar sense fricció, i el catàleg és contingut públic i cacheable:
Cache-Controlfa que moltes d'aquestes consultes ni tan sols arribin al servidor. - gRPC. És trànsit intern amb tots dos extrems sota control, on el format binari i HTTP/2 redueixen latència i CPU respecte a JSON; a més el contracte
.protoevita errors de tipus en un camí crític. - GraphQL seria el candidat ideal per combinar quatre fonts de dades en una sola consulta, i evitar l'N+1 de peticions. Ara bé, si és l'única pantalla amb aquest problema, la resposta pragmàtica és un endpoint REST agregat (
GET /v1/clients/cli_842/resum): resol el cas sense introduir tota una tecnologia. - Webhook. L'emissor és la Botiga Aroma i el receptor és una empresa externa; el sondeig constant seria un malbaratament i afegiria retard a l'avís.
- SSE. És un flux unidireccional del servidor al navegador, funciona sobre HTTP normal i es reconnecta sol. Un WebSocket seria innecessàriament complex perquè el panell no envia res de tornada.
Solució 2
Cos de l'esdeveniment:
{
"id": "evt_a41d",
"tipus": "comanda.enviada",
"data": "2026-08-15T11:04:00Z",
"versio": "1",
"dades": {
"comandaId": "com_5001",
"clientId": "cli_842",
"transportista": "RàpidEnviaments",
"numeroSeguiment": "RE9928374ES",
"lliuramentEstimat": "2026-08-17"
}
}Capçaleres:
POST /webhooks/aroma HTTP/1.1
Content-Type: application/json
Aroma-Esdeveniment-Id: evt_a41d
Aroma-Esdeveniment-Tipus: comanda.enviada
Aroma-Signatura: sha256=7d38cb...
Aroma-Data: 2026-08-15T11:04:00Z
User-Agent: BotigaAroma-Webhooks/1.0Què ha de respondre el receptor: un 2xx (idealment 200 OK o 204 No Content) com més aviat millor, abans de processar l'esdeveniment. La regla és acceptar, encuar i processar de manera asíncrona: si trigues a respondre perquè estàs fent feina pesant, l'emissor ho pot considerar una fallada i reintentar-ho, i generar duplicats.
Si no respon: reintents amb espera creixent (per exemple, als 30 s, 2 min, 10 min, 1 h, 6 h i 24 h), registre de cada intent accessible per al consumidor, avís per correu després de diverses fallades i desactivació de l'endpoint després d'un nombre de fallades consecutives.
Seguretat:
- Signatura HMAC-SHA256 del cos amb un secret compartit, que el receptor verifica abans de processar res.
- Marca temporal dins de la signatura per rebutjar reenviaments antics (atacs de repetició).
- HTTPS obligatori a la URL de destinació.
- Identificador d'esdeveniment per descartar duplicats al receptor.
- Dades mínimes: res de dades de pagament ni personals innecessàries; si en cal més, que consulti l'API autenticat.
Solució 3
1. Peticions REST amb disseny ingenu: tres.
curl https://api.botigaaroma.example/v1/cafes/caf_001
curl "https://api.botigaaroma.example/v1/cafes/caf_001/ressenyes?limit=5"
curl https://api.botigaaroma.example/v1/torrefactors/tor_032. Consulta GraphQL: una.
query {
cafe(id: "caf_001") {
nom
preuEuros
estoc
torrefactor { nom }
ressenyes(limit: 5) { autor puntuacio }
}
}3. Dues solucions dins de REST:
- Paràmetre d'expansió:
GET /v1/cafes/caf_001?incloure=ressenyes,torrefactor, que retorna els recursos relacionats incrustats a la mateixa resposta. Una sola petició, i continua sent unGETcacheable. - Recurs agregat orientat a la pantalla:
GET /v1/cafes/caf_001/detall, dissenyat específicament per a aquesta vista. Simple i molt eficient.
4. Què s'hi perd en cada cas:
- Amb GraphQL: la memòria cau HTTP (tot és
POSTa/graphql), els codis d'estat significatius i la possibilitat de provar la crida des del navegador; a més cal controlar el cost de les consultes. - Amb el paràmetre d'expansió: la memòria cau es fragmenta (cada combinació d'
incloureés una entrada diferent) i el servidor es complica; si se n'abusa, s'acaba reimplementant GraphQL a mà i pitjor. - Amb el recurs agregat: s'acobla l'API a una pantalla concreta. Si cada vista nova hi afegeix el seu propi endpoint, l'API s'omple de recursos a mida difícils de mantenir i de documentar.
No hi ha cap opció gratuïta: totes tres són intercanvis conscients, i triar bé consisteix a saber quin fa menys mal en el teu context.
Conclusió
Ja tens el mapa complet d'estils d'integració. REST destaca per la seva simplicitat, la seva universalitat i la memòria cau que hereta d'HTTP, i és l'elecció natural quan el consumidor pot ser qualsevol. GraphQL resol l'over-fetching i l'under-fetching donant al client el control dels camps, a canvi de perdre la memòria cau HTTP i d'haver de governar el cost de les consultes. gRPC aporta contracte fort, format binari i streaming, i brilla entre serveis interns on controles tots dos extrems. I els webhooks, juntament amb les cues, SSE i WebSockets, cobreixen el buit que cap model petició-resposta no pot cobrir: que el servidor prengui la iniciativa. La conclusió pràctica és que no competeixen: la Botiga Aroma farà servir REST cap a fora, gRPC cap a dins i webhooks per a les seves integracions, i ha deixat GraphQL fora per raons escrites i revisables.
Amb això tanquem el mòdul 1. Saps què és una API i per a qui es dissenya, d'on ve l'ecosistema actual, com funciona HTTP per sota, en què consisteixen les sis restriccions de REST, com mesurar la maduresa d'una API i quines alternatives hi ha. Toca passar de comprendre a construir. Al mòdul 2, Disseny d'APIs RESTful, començarem a dissenyar l'API de la Botiga Aroma peça a peça: els seus principis de disseny, els seus recursos i URI, l'ús precís de cada mètode HTTP i de cada codi d'estat, la negociació de contingut, el filtratge i la paginació, el versionat i la documentació. És el moment en què les idees d'aquest mòdul es converteixen en decisions concretes sobre un contracte real.
Curs de REST API: Principis de Disseny i Desenvolupament d'APIs RESTful
Mòdul 1: Introducció a les APIs RESTful
- Què és una API?
- Història i evolució de les APIs
- Fonaments d'HTTP per a APIs
- Principis bàsics de REST
- Model de maduresa de Richardson i HATEOAS
- REST vs. SOAP
- REST davant de GraphQL, gRPC i webhooks
Mòdul 2: Disseny d'APIs RESTful
- Principis de disseny d'APIs RESTful
- Recursos i URIs
- Mètodes HTTP
- Codis d'estat HTTP
- Representacions, capçaleres i negociació de contingut
- Filtratge, ordenació, paginació i cerca
- Versionat d'APIs
- Documentació d'APIs
Mòdul 3: Desenvolupament d'APIs RESTful
- Configuració de l'entorn de desenvolupament
- Creació d'un servidor bàsic
- Gestió de peticions i respostes
- Validació de dades d'entrada
- Persistència i capa d'accés a dades
- Autenticació i autorització
- Gestió d'errors
- Proves i validació
Mòdul 4: Bones Pràctiques i Seguretat
- Bones pràctiques en el disseny d'APIs
- Seguretat en APIs RESTful
- OAuth 2.0 i OpenID Connect a la pràctica
- Rate limiting i throttling
- CORS i polítiques de seguretat
- Memòria cau HTTP i rendiment
- Observabilitat: logs, mètriques i traces
Mòdul 5: Eines i Frameworks
- Postman per a proves d'APIs
- Swagger i OpenAPI per a documentació
- Frameworks populars per a APIs RESTful
- Contractes, mocks i proves automatitzades d'API
- Integració contínua i desplegament
- API gateways i portals de desenvolupador
