Webhook
I webhook permettono alla vostra applicazione di ricevere callback HTTP in tempo reale quando si verificano eventi nella vostra organizzazione Gäld. Quando un evento viene attivato, Gäld invia una richiesta POST a ogni URL webhook registrato.
Configurare un webhook
Create un webhook tramite l'API:
curl -X POST https://app.gaeld.ch/api/v1/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/gaeld",
"events": ["invoice.created", "invoice.finalized", "customer.created"],
"is_active": true
}'
La risposta include un secret — conservatelo in modo sicuro, vi servirà per verificare le firme.
Eventi
| Evento | Si attiva quando |
|---|---|
invoice.created | Viene creata una nuova fattura |
invoice.updated | Una fattura viene modificata |
invoice.deleted | Una fattura viene eliminata |
invoice.finalized | Una fattura viene finalizzata (bloccata per la modifica) |
invoice.payment_recorded | Viene registrato un pagamento per una fattura |
customer.created | Viene creato un nuovo cliente |
customer.updated | Un cliente viene modificato |
customer.deleted | Un cliente viene eliminato |
expense.created | Viene creata una nuova spesa |
expense.updated | Una spesa viene modificata |
expense.deleted | Una spesa viene eliminata |
expense.approved | Una spesa viene approvata nel workflow |
Utilizzate GET /api/v1/meta/webhook-events per recuperare questo elenco programmaticamente.
Formato del payload
Ogni consegna webhook invia una richiesta JSON POST:
{
"event": "invoice.finalized",
"timestamp": "2025-06-01T12:00:00Z",
"data": {
"id": "uuid",
"number": "INV-2025-042",
"status": "finalized",
"customer": { "id": "uuid", "name": "ACME GmbH" },
"total": "1081.00",
"currency": "CHF"
}
}
Il campo data contiene la rappresentazione completa della risorsa (stesso formato della risposta dell'endpoint API corrispondente).
Header della richiesta
Ogni richiesta webhook include questi header:
| Header | Descrizione |
|---|---|
Content-Type | application/json |
X-Webhook-Signature | Digest HMAC-SHA256 esadecimale del corpo della richiesta |
X-Webhook-Event | Nome dell'evento (ad es. invoice.created) |
X-Webhook-Id | ID di consegna univoco |
User-Agent | Gaeld-Webhook/1.0 |
Verifica della firma
Ogni richiesta webhook è firmata con HMAC-SHA256 utilizzando il secret del webhook. Verificate sempre la firma prima di elaborare il payload.
PHP
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$computed = hash_hmac('sha256', $payload, $webhookSecret);
if (! hash_equals($computed, $signature)) {
http_response_code(400);
exit('Invalid signature');
}
$event = json_decode($payload, true);
// Elaborare $event
Node.js
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const computed = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(computed),
Buffer.from(signature)
);
}
// Nel vostro handler Express:
app.post('/webhooks/gaeld', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-webhook-signature'];
if (!verifySignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(400).send('Invalid signature');
}
const event = JSON.parse(req.body);
// Elaborare l'evento
res.sendStatus(200);
});
Python
import hmac
import hashlib
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
computed = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(computed, signature)
Consegna e tentativi
| Proprietà | Valore |
|---|---|
| Timeout HTTP | 10 secondi |
| Max tentativi | 3 |
| Backoff dei tentativi | 30 secondi, 5 minuti, 1 ora |
| Risposta attesa | Qualsiasi codice di stato 2xx |
Se il vostro endpoint restituisce uno stato non 2xx o va in timeout, Gäld riprova con backoff esponenziale. Dopo 3 tentativi falliti, la consegna viene contrassegnata come fallita. Potete verificare lo stato di consegna tramite l'API webhook.
Gestire i webhook
| Azione | Metodo | Endpoint |
|---|---|---|
| Elencare tutti | GET | /api/v1/webhooks |
| Visualizzare dettagli | GET | /api/v1/webhooks/{id} |
| Creare | POST | /api/v1/webhooks |
| Aggiornare eventi/URL | PUT | /api/v1/webhooks/{id} |
| Eliminare | DELETE | /api/v1/webhooks/{id} |
| Rigenerare il secret | POST | /api/v1/webhooks/{id}/regenerate-secret |
Dopo aver chiamato regenerate-secret, aggiornate immediatamente la vostra applicazione con il nuovo secret. Il vecchio secret viene invalidato e tutte le consegne successive utilizzeranno quello nuovo.
Best practice
- Verificate sempre le firme — non fidatevi mai del contenuto del payload senza controllare la firma HMAC
- Rispondete rapidamente — restituite immediatamente
200ed elaborate l'evento in modo asincrono (ad es. tramite una coda di lavoro) - Gestite i duplicati — utilizzate l'header
X-Webhook-Idper la deduplicazione se il vostro endpoint viene chiamato più di una volta - Utilizzate HTTPS — gli URL webhook devono utilizzare HTTPS in produzione
- Monitorate gli errori — verificate periodicamente lo stato di consegna dei webhook e correggete gli endpoint non funzionanti