Zapier
Ricevere webhook Blu Pantheon con Catch Raw Hook, verificare la firma in Code by Zapier e chiamare le API con Custom Request.
Zapier consente di ricevere webhook Blu Pantheon e verificarne la firma, a condizione di usare il trigger corretto: Catch Raw Hook.
Prima di iniziare
- Un account Zapier con piano che includa Webhooks by Zapier e Code by Zapier (piano Starter o superiore)
- La chiave API bp_live_xxxxxxxxxxxxxxxx
- Il segreto whsec_xxxxxxxxxxxxxxxx
- Familiarità con gli step Filter e Code di Zapier
Parte 1 — Catch Raw Hook
Crea lo Zap
Da Zaps → Create → New Zap, cerca Webhooks by Zapier come trigger.
Scegli Catch Raw Hook
Nel menu Event seleziona Catch Raw Hook, non Catch Hook.
Catch Hook non è utilizzabile
Catch Hook deserializza il JSON e restituisce i campi già elaborati: il corpo grezzo va
perso e la firma HMAC non è più verificabile. Solo Catch Raw Hook espone la stringa
originale nel campo raw_body insieme agli header in headers.
Copia l'URL del webhook
Zapier genera un URL nella forma:
https://hooks.zapier.com/hooks/catch/12345678/abcdefg/Copialo integralmente, inclusa la barra finale.
Registra l'endpoint in Console
| Campo | Valore |
|---|---|
| Nome | Zapier - automazioni ACME |
| URL | l'URL copiato da Zapier |
| Eventi | solo quelli che lo Zap gestisce |
Cattura un evento di prova
Torna in Zapier e clicca Test trigger. Dalla Console usa Invia evento di prova con
webhook.test. Zapier mostrerà raw_body e headers.
Zapier risponde sempre 200
Il trigger risponde 200 immediatamente, prima di eseguire gli step. Non puoi restituire
401 a Blu Pantheon in caso di firma non valida: la consegna risulterà comunque riuscita nei
log. La verifica serve quindi a bloccare l'elaborazione, non a rifiutare la richiesta.
Configura un allarme sugli Zap interrotti dal Filter.
Parte 2 — Code by Zapier: verifica della firma
Aggiungi lo step Code
Aggiungi un'azione Code by Zapier con Event Run JavaScript. Rinominala
Verifica firma HMAC.
Configura gli Input Data
| Chiave | Valore mappato dal trigger |
|---|---|
rawBody | 1. Raw Body |
signatureHeader | 1. Headers X Bp Signature |
deliveryId | 1. Headers X Bp Delivery |
eventType | 1. Headers X Bp Event |
secret | whsec_xxxxxxxxxxxxxxxx |
Nomi degli header in Zapier
Zapier normalizza gli header in minuscolo con underscore. Se non trovi il campo nel selettore,
usa la ricerca digitando signature e seleziona la voce corrispondente a x-bp-signature.
Incolla il codice
const crypto = require('crypto');
const TOLERANCE_SECONDS = 300;
const rawBody = inputData.rawBody || '';
const signatureHeader = inputData.signatureHeader || '';
const deliveryId = inputData.deliveryId || '';
const eventType = inputData.eventType || '';
const secret = inputData.secret || '';
if (!secret) {
throw new Error('Segreto webhook non configurato negli Input Data');
}
let timestamp = null;
const signatures = [];
for (const segment of signatureHeader.split(',')) {
const index = segment.indexOf('=');
if (index === -1) continue;
const key = segment.slice(0, index).trim();
const value = segment.slice(index + 1).trim();
if (key === 't') timestamp = Number(value);
if (key === 'v1') signatures.push(value);
}
function result(valid, reason, event) {
return {
valid,
reason,
deliveryId,
eventType,
eventId: event ? event.id : null,
sessionId: event && event.data ? event.data.sessionId || '' : '',
clientName:
event && event.data && event.data.client
? event.data.client.displayName || ''
: '',
clientEmail:
event && event.data && event.data.client ? event.data.client.email || '' : '',
summary: event && event.data ? event.data.summary || '' : '',
payload: event ? JSON.stringify(event) : '',
};
}
if (!Number.isFinite(timestamp)) {
return result(false, 'timestamp-non-valido', null);
}
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - timestamp) > TOLERANCE_SECONDS) {
return result(false, 'timestamp-fuori-tolleranza', null);
}
if (signatures.length === 0) {
return result(false, 'firma-assente', null);
}
const expected = crypto
.createHmac('sha256', secret)
.update(timestamp + '.' + rawBody, 'utf8')
.digest('hex');
const expectedBuffer = Buffer.from(expected, 'utf8');
let valid = false;
for (const candidate of signatures) {
const candidateBuffer = Buffer.from(candidate, 'utf8');
if (
candidateBuffer.length === expectedBuffer.length &&
crypto.timingSafeEqual(candidateBuffer, expectedBuffer)
) {
valid = true;
break;
}
}
if (!valid) {
return result(false, 'firma-non-corrispondente', null);
}
const event = JSON.parse(rawBody);
return result(true, 'ok', event);Verifica l'output
Esegui il test dello step. L'output deve contenere valid: true e i campi estratti dal
payload.
Parte 3 — Filter by Zapier
Aggiungi uno step Filter by Zapier rinominato Solo firme valide.
| Campo | Operatore | Valore |
|---|---|---|
2. Valid | (Boolean) Is true | — |
Aggiungi una seconda condizione con AND per limitare l'elaborazione agli eventi attesi:
| Campo | Operatore | Valore |
|---|---|---|
2. Event Type | (Text) Exactly matches | session.handover.requested |
Il Filter consuma un task
Ogni evento ricevuto consuma almeno due task (trigger e Code) anche quando viene scartato dal Filter. Sottoscrivi in Console solo gli eventi che ti servono per non esaurire la quota.
Parte 4 — Deduplica
Zapier non deduplica le consegne ripetute. Aggiungi uno step Storage by Zapier.
Leggi il valore esistente
Azione Storage by Zapier → Get Value.
| Campo | Valore |
|---|---|
| Storage Source | il tuo secret storage |
| Key | bp-{{2. Delivery Id}} |
Filtra i duplicati
Filter by Zapier rinominato Non ancora elaborato:
| Campo | Operatore |
|---|---|
4. Value | Does not exist |
Registra la consegna
Azione Storage by Zapier → Set Value.
| Campo | Valore |
|---|---|
| Key | bp-{{2. Delivery Id}} |
| Value | {{2. Event Id}} |
Parte 5 — Chiamare le API con Custom Request
Aggiungi l'azione
Aggiungi Webhooks by Zapier con Event Custom Request.
Configura la richiesta
| Campo | Valore |
|---|---|
| Method | POST |
| URL | https://api.blupantheon.com/identity/v1/sessions/{{2. Session Id}}/notes |
| Data Pass-Through? | false |
| Data | vedi JSON sotto |
| Unflatten | no |
| Headers | vedi tabella sotto |
Campo Data:
{"body": "Ticket aperto: {{5. Ticket Number}}", "visibility": "internal", "author": "zapier"}Headers:
| Chiave | Valore |
|---|---|
Authorization | Bearer bp_live_xxxxxxxxxxxxxxxx |
X-BP-Project | bp_proj_7f3a9c21 |
Content-Type | application/json |
Idempotency-Key | {{2. Delivery Id}} |
Testa la chiamata
Esegui il test dello step. Attendi risposta 201 e verifica in Console che la nota compaia
nella sessione.
Chiave API visibile
Il valore dell'header Authorization è leggibile da chiunque abbia accesso allo Zap. Limita
la condivisione dello Zap, usa una chiave dedicata a Zapier con scope minimi e ruotala se il
team cambia.
Gestione degli errori
| Situazione | Comportamento Zapier | Azione consigliata |
|---|---|---|
| Firma non valida | Il Filter interrompe lo Zap | Configura una notifica su Zap History → Filtered |
Errore 4xx dall'azione | Lo Zap va in Errored | Zapier invia email al proprietario. Correggi i dati e usa Replay |
Errore 5xx dall'azione | Zapier ritenta automaticamente | Nessuna azione, monitora |
| Timeout dello step Code | Lo Zap fallisce | Il Code ha un limite di 10 secondi: non fare chiamate di rete nel Code |
| Quota task esaurita | Gli Zap si fermano | Riduci gli eventi sottoscritti in Console |
Replay dalla cronologia
In Zap History puoi rieseguire una singola esecuzione fallita con Replay. Grazie
all'Idempotency-Key derivato da X-BP-Delivery il replay non genera duplicati lato Blu
Pantheon.
Procedura di test
Test con firma valida
Invia webhook.test. Lo Zap deve completare tutti gli step.
Test con firma non valida
Modifica temporaneamente il valore secret negli Input Data dello step Code con un valore
errato e invia di nuovo l'evento. Lo Zap deve fermarsi al Filter con motivo
firma-non-corrispondente. Ripristina il valore corretto.
Test di deduplica
Dai log consegne clicca Riprova sulla stessa consegna. Il secondo passaggio deve fermarsi al
Filter Non ancora elaborato.
Pubblica lo Zap
Attiva lo Zap con Publish. Verifica il funzionamento su un evento reale e controlla Zap History per le prime 24 ore.