Webhook

I webhook permettono di ricevere notifiche in tempo reale sugli eventi dei tuoi messaggi. UniMsg invierà una richiesta HTTP POST al tuo endpoint ogni volta che si verifica un evento.

Configurazione

Dalla Dashboard

  1. Accedi alla Dashboard
  2. Vai su Impostazioni → Webhook
  3. Inserisci l'URL del tuo endpoint
  4. Seleziona gli eventi da ricevere
  5. Copia il Webhook Secret per la verifica
  6. Clicca su "Salva"

Requisiti Endpoint

Eventi Disponibili

Evento Descrizione
message.sent Messaggio inviato al gateway
message.delivered Messaggio consegnato al destinatario
message.read Messaggio letto (WhatsApp/Telegram)
message.failed Invio fallito
email.opened Email aperta
email.clicked Link email cliccato
email.bounced Email rimbalzata
email.complained Email segnalata come spam
credits.low Saldo crediti basso

Formato Payload

Ogni webhook contiene:

{
    "id": "evt_xxxxxxxxxxxx",
    "event": "message.delivered",
    "created_at": "2024-01-15T10:30:00Z",
    "data": {
        "message_id": "msg_xxxxxxxxxxxx",
        "channel": "sms",
        "to": "+39123456789",
        "status": "delivered",
        "delivered_at": "2024-01-15T10:30:03Z"
    }
}

Esempi per Evento

message.sent

{
    "id": "evt_xxxxxxxxxxxx",
    "event": "message.sent",
    "created_at": "2024-01-15T10:30:00Z",
    "data": {
        "message_id": "msg_xxxxxxxxxxxx",
        "channel": "sms",
        "to": "+39123456789",
        "status": "sent"
    }
}

message.failed

{
    "id": "evt_xxxxxxxxxxxx",
    "event": "message.failed",
    "created_at": "2024-01-15T10:30:00Z",
    "data": {
        "message_id": "msg_xxxxxxxxxxxx",
        "channel": "sms",
        "to": "+39123456789",
        "status": "failed",
        "error_code": "INVALID_PHONE",
        "error_message": "Il numero non è valido"
    }
}

email.clicked

{
    "id": "evt_xxxxxxxxxxxx",
    "event": "email.clicked",
    "created_at": "2024-01-15T10:35:00Z",
    "data": {
        "message_id": "msg_email_xxxxxxxxxxxx",
        "to": "test@example.com",
        "url": "https://mysite.com/promo",
        "ip": "93.xxx.xxx.xxx",
        "user_agent": "Mozilla/5.0..."
    }
}

Verifica Signature

Ogni webhook include una firma HMAC-SHA256 nell'header X-UniMsg-Signature per verificare l'autenticità della richiesta.

Come Verificare

  1. Estrai l'header X-UniMsg-Signature
  2. Calcola l'HMAC-SHA256 del body usando il tuo Webhook Secret
  3. Confronta le due firme

Esempio PHP

<?php
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_UNIMSG_SIGNATURE'];
$secret = 'your_webhook_secret';

$expectedSignature = hash_hmac('sha256', $payload, $secret);

if (hash_equals($expectedSignature, $signature)) {
    // Webhook valido
    $event = json_decode($payload, true);

    switch ($event['event']) {
        case 'message.delivered':
            // Gestisci consegna
            break;
        case 'message.failed':
            // Gestisci errore
            break;
    }

    http_response_code(200);
} else {
    // Firma non valida
    http_response_code(401);
}

Esempio Node.js

const crypto = require('crypto');
const express = require('express');
const app = express();

app.use(express.json({
    verify: (req, res, buf) => {
        req.rawBody = buf.toString();
    }
}));

app.post('/webhook', (req, res) => {
    const signature = req.headers['x-unimsg-signature'];
    const secret = 'your_webhook_secret';

    const expectedSignature = crypto
        .createHmac('sha256', secret)
        .update(req.rawBody)
        .digest('hex');

    if (crypto.timingSafeEqual(
        Buffer.from(signature),
        Buffer.from(expectedSignature)
    )) {
        const event = req.body;
        console.log('Evento:', event.event);
        res.status(200).send('OK');
    } else {
        res.status(401).send('Invalid signature');
    }
});

Esempio Python

import hmac
import hashlib
from flask import Flask, request

app = Flask(__name__)
WEBHOOK_SECRET = 'your_webhook_secret'

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-UniMsg-Signature')
    payload = request.get_data()

    expected = hmac.new(
        WEBHOOK_SECRET.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()

    if hmac.compare_digest(signature, expected):
        event = request.json
        print(f"Evento: {event['event']}")
        return 'OK', 200
    else:
        return 'Invalid signature', 401

Retry e Gestione Errori

Se il tuo endpoint non risponde con 2xx, UniMsg ritenterà l'invio:

Tentativo Ritardo
1 Immediato
2 1 minuto
3 5 minuti
4 30 minuti
5 2 ore

Dopo 5 tentativi falliti, il webhook viene segnato come fallito e visibile in dashboard.

Debug Webhook

Dalla dashboard puoi:

Suggerimento: Per testare in locale, puoi usare servizi come ngrok o webhook.site.

Best Practices