Utvecklardokumentation
Bolio Webhooks
Utgående HTTPS-anrop varje gång något viktigt händer i din arbetsyta — skapade kunder, offerter, jobb, besök, fakturor och betalningar. Kompatibla med Zapier, Make.com, n8n eller en egen HTTP-server.
Kom igång på 60 sekunder
- Skapa en Zap med triggern Webhook by Zapier → Catch Hook.
- Kopiera Zapier-URL:en.
- Gå till
Inställningar → Webhooksi Bolio och klicka Ny webhook. - Klistra in URL:en, välj vilka händelser du vill lyssna på, spara.
- Spara hemligheten som visas — den används för att verifiera att anropen kommer från Bolio.
- Klicka på Skicka test-ikonen så får Zapier ett exempel-event att bygga vidare på.
Payload-format
Alla anrop är POST med JSON-body. Följande headers sätts alltid:
Content-Type: application/json
X-Webhook-Event: invoice.paid
X-Webhook-Timestamp: 1783165005
X-Webhook-Delivery: 4c7d0f0e-9b8c-4c67-9c66-3f6b0f8d4e10
X-Webhook-Signature: t=1783165005,v1=<hex>
User-Agent: Bolio-Webhooks/1.0Body-struktur:
{
"event": "invoice.paid",
"ts": 1783165005,
"delivery_id": "4c7d0f0e-9b8c-4c67-9c66-3f6b0f8d4e10",
"data": {
"invoice_id": "…",
"invoice_number": 1042,
"total_amount": 12500,
"amount_paid": 12500,
"method": "swish"
}
}Idempotens: vid retry återanvänds samma delivery_id. Filtrera bort dubbletter i din integration genom att spara mottagna id:n.
Verifiera signaturen (HMAC-SHA256)
Signaturen räknas ut som HMAC_SHA256(secret, "{ts}.{body}") och skickas i headern X-Webhook-Signature som t=<ts>,v1=<hex>.
// Node.js
import { createHmac, timingSafeEqual } from "node:crypto";
function verifyBolio(req, secret) {
const sig = req.headers["x-webhook-signature"] ?? "";
const ts = req.headers["x-webhook-timestamp"] ?? "";
const m = /t=(\d+),v1=([a-f0-9]+)/.exec(sig);
if (!m || m[1] !== ts) return false;
const expected = createHmac("sha256", secret)
.update(ts + "." + req.rawBody).digest("hex");
const a = Buffer.from(m[2]), b = Buffer.from(expected);
return a.length === b.length && timingSafeEqual(a, b);
}# Python
import hmac, hashlib, re
import { SITE_URL } from "@/lib/public-url";
def verify_bolio(headers, raw_body, secret):
sig = headers.get("x-webhook-signature", "")
ts = headers.get("x-webhook-timestamp", "")
m = re.match(r"t=(\d+),v1=([a-f0-9]+)", sig)
if not m or m.group(1) != ts:
return False
expected = hmac.new(secret.encode(), f"{ts}.{raw_body}".encode(),
hashlib.sha256).hexdigest()
return hmac.compare_digest(m.group(2), expected)Retry & auto-paus
- Timeout per försök: 5 sekunder.
- Räknas som lyckad vid HTTP
2xx. - Vid fel görs upp till 5 försök med exponentiell backoff: 5 → 10 → 20 → 40 → 60 min.
- Efter 20 misslyckade leveranser i rad pausas prenumerationen automatiskt och en notifikation skickas till org-adminen. Aktivera manuellt igen när URL:en fungerar.
- Räknaren nollställs vid varje lyckad leverans.
Alla event-typer
client.createdclient.updatedrequest.receivedquote.createdquote.sentquote.approvedquote.declinedjob.createdjob.startedjob.completedvisit.createdvisit.updatedvisit.rescheduledvisit.assignedvisit.unassignedvisit.completedvisit.cancelledbooking.createdinvoice.createdinvoice.sentinvoice.overdueinvoice.paidinvoice.voidedpayment.receivedNya event läggs till löpande — dina zaps påverkas inte.
