Webhooks
Notifikácie o udalostiach (faktúra vytvorená, platba prijatá, atď.).
Webhooky ti pošlú HTTP POST notifikáciu na tvoju URL kedykoľvek sa v Monivio stane vybraná udalosť. Subscriptiony spravuješ buď cez REST endpointy nižšie (scope webhooks:write), alebo v UI cez Nastavenia → Webhooks. Plaintext signing secret sa vracia iba pri vytvorení a regenerácii – odlož si ho hneď.
Udalosti
Pri prihlasovaní webhooku môžeš zvoliť konkrétne typy alebo wildcard: * matchne všetko, document.* všetky document udalosti, alebo presný kód.
- •
document.created– nový dokument - •
document.updated– nová verzia dokumentu - •
document.sent– dokument odoslaný emailom - •
document.paid– faktúra označená ako uhradená - •
document.overdue– splatnosť prekročená - •
document.cancelled– dokument stornovaný - •
contact.created - •
contact.updated - •
contact.deleted - •
expense.created - •
expense.updated - •
expense.deleted - •
transaction.imported– nová bankové transakcia - •
transaction.matched– transakcia spárovaná s dokumentom - •
transaction.unmatched– párovanie zrušené - •
transaction.skipped– transakcia označená ako preskočená
Endpointy
/api/v1/webhookswebhooks:writeVytvorí webhook subscription. Vracia plaintext secret iba raz – ulož ho hneď, neskôr sa už nedá načítať.
curl -X POST "https://monivio.sk/api/v1/webhooks" \
-H "Authorization: Bearer mk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Production webhook",
"url": "https://example.com/hooks/monivio",
"events": [
"document.created",
"document.paid"
]
}'{
"data": {
"id": "whe_2hf8pq3rxn4mlkzyt9abwvve",
"secret": "whsec_4b7f2a8c9d1e3f5a6b8c0d2e4f6a8b0c"
}
}/api/v1/webhookswebhooks:readZoznam webhook subscription-ov organizácie. Secret sa nevracia.
curl "https://monivio.sk/api/v1/webhooks" \
-H "Authorization: Bearer mk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{
"data": [
{
"id": "whe_2hf8pq3rxn4mlkzyt9abwvve",
"name": "Production webhook",
"url": "https://example.com/hooks/monivio",
"events": [
"document.created",
"document.paid"
],
"headers": {},
"is_active": true,
"failure_count": 0,
"disabled_at": null,
"disabled_reason": null,
"created_at": "2026-05-07T08:42:00.000Z",
"updated_at": "2026-05-07T08:42:00.000Z"
}
],
"meta": {
"page": 1,
"limit": 1,
"total": 1,
"total_pages": 1
}
}/api/v1/webhooks/{id}webhooks:readDetail subscription-u.
curl "https://monivio.sk/api/v1/webhooks/con_2hf8pq3rxn4mlkzyt9abwvve" \
-H "Authorization: Bearer mk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{
"data": {
"id": "whe_2hf8pq3rxn4mlkzyt9abwvve",
"name": "Production webhook",
"url": "https://example.com/hooks/monivio",
"events": [
"document.created",
"document.paid"
],
"headers": {},
"is_active": true,
"failure_count": 0,
"disabled_at": null,
"disabled_reason": null,
"created_at": "2026-05-07T08:42:00.000Z",
"updated_at": "2026-05-07T08:42:00.000Z"
}
}/api/v1/webhooks/{id}webhooks:writeUpdate polí subscription-u (name, url, events, headers, is_active). Aspoň jedno pole je povinné.
curl -X PATCH "https://monivio.sk/api/v1/webhooks/con_2hf8pq3rxn4mlkzyt9abwvve" \
-H "Authorization: Bearer mk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"events": [
"document.created",
"document.paid",
"document.cancelled"
]
}'{
"data": {
"id": "whe_2hf8pq3rxn4mlkzyt9abwvve",
"name": "Production webhook",
"url": "https://example.com/hooks/monivio",
"events": [
"document.created",
"document.paid",
"document.cancelled"
],
"headers": {},
"is_active": true,
"failure_count": 0,
"disabled_at": null,
"disabled_reason": null,
"created_at": "2026-05-07T08:42:00.000Z",
"updated_at": "2026-05-07T08:55:00.000Z"
}
}/api/v1/webhooks/{id}/testwebhooks:writePošle synthetic `webhook.test` event na URL subscription-u. Nemení doručené eventy v queue. Vracia HTTP status zacieleného endpointu.
curl -X POST "https://monivio.sk/api/v1/webhooks/con_2hf8pq3rxn4mlkzyt9abwvve/test" \
-H "Authorization: Bearer mk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{
"data": {
"success": true,
"response_status": 200,
"duration_ms": 142,
"error_message": null
}
}/api/v1/webhooks/{id}/regenerate-secretwebhooks:writeInvaliduje aktuálny signing secret a vráti nový. Predchádzajúce eventy podpísané starým secret-om už nebudú validné. Vracia plaintext secret iba raz.
curl -X POST "https://monivio.sk/api/v1/webhooks/con_2hf8pq3rxn4mlkzyt9abwvve/regenerate-secret" \
-H "Authorization: Bearer mk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{
"data": {
"id": "whe_2hf8pq3rxn4mlkzyt9abwvve",
"secret": "whsec_4b7f2a8c9d1e3f5a6b8c0d2e4f6a8b0c"
}
}/api/v1/webhooks/{id}webhooks:writeVymaže subscription. Pending deliveries v queue sa už nepošlú.
curl -X DELETE "https://monivio.sk/api/v1/webhooks/con_2hf8pq3rxn4mlkzyt9abwvve" \
-H "Authorization: Bearer mk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"Payload
{
"id": "evt_3kw9pmxn7rt2vyzqlhc8bfsj",
"type": "document.created",
"created_at": "2026-06-01T10:00:00.000Z",
"organization_id": "org_2hf8pq3rxn4mlkzyt9abwvve",
"data": {
"id": "doc_4kp9mxn8tq3vyz2lwbcr5shg",
"type": "invoice",
"number": "FA260042",
"amount_total": 495,
"currency": "EUR"
}
}Podpis (HMAC SHA-256)
Každá požiadavka je podpísaná HMAC SHA-256 hlavičkou Monivio-Signature. Secret dostaneš pri vytvorení webhooku (cez API alebo UI) a vieš ho rotovať cez POST /webhooks/{id}/regenerate-secret.
Monivio-Signature: t=1717689600,v1=8b2f3c9a...
Content-Type: application/json
User-Agent: Monivio-Webhook/1.0Verifikácia podpisu (TypeScript)
import crypto from "node:crypto";
function verifyMonivioSignature(
rawBody: string,
signatureHeader: string,
secret: string
): boolean {
const parts = signatureHeader.split(",").reduce<Record<string, string>>(
(acc, part) => {
const [k, v] = part.split("=");
if (k && v) acc[k] = v;
return acc;
},
{}
);
const timestamp = parts.t;
const sig = parts.v1;
if (!timestamp || !sig) return false;
// Reject replay attacks older than 5 minutes.
const age = Math.floor(Date.now() / 1000) - Number(timestamp);
if (age > 300) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(sig, "hex"),
Buffer.from(expected, "hex")
);
}Retry logika
- • Tvoj endpoint musí vrátiť 2xx do 10 sekúnd. Inak considerujeme delivery za neúspešnú.
- • Pri zlyhaní retryujeme spolu 5× v intervaloch 0 (okamžite), 1 min, 5 min, 30 min, 2 h. Po piatom pokuse je delivery označená ako failed.
- • Idempotenciu si zabezpeč na svojej strane podľa
idv payloade – pri retry posielame rovnaký event id, takže môžeš dedup-núť. - • Ak endpoint zlyhá 5× po sebe v rôznych eventoch, automaticky ho deaktivujeme (
is_active=false) a počkáme na manuálny re-enable cezPATCH /webhooks/{id}alebo v UI.