Registrace endpointu
Všechna volání níže vyžadují hlavičku Authorization: Bearer <API klíč>.
Základní adresa staging prostředí je
https://invoicehub-api.zeabur.app/api/v1.
POST /api/v1/webhooks
Content-Type: application/json
{
"name": "Zapier – zaplacené faktury",
"url": "https://hooks.example.com/invoicehub",
"events": ["document.sent", "document.paid"]
}
name– interní pojmenování endpointu.-
url– absolutní HTTPS adresa, na kterou se posíláPOST. -
events– pole názvů událostí, které tento endpoint odebírá. Obvykle sem patří názvy z katalogu událostí. Server obsah neověřuje proti číselníku – přijme libovolné řetězce, takže si sem můžete zapsat i vlastní název odpalovaný akcíTRIGGER_WEBHOOK. Nezná-li server zapsaný název, prostě se pro něj nikdy nic nedoručí.
Pole description v této verzi neexistuje; pokud ho pošlete, nikde se
neprojeví.
Secret dostanete jen jednou
Při vytvoření server vygeneruje podepisovací tajemství (32 náhodných bajtů v hex
zápisu) a vrátí ho pouze v odpovědi na tento jeden request. Následné
GET volání už secret nevrací a znovu ho nezobrazíte.
Uložte si secret hned – ideálně do trezoru tajemství nebo proměnné prostředí přijímající aplikace. Když ho ztratíte, jediná cesta zpět je smazat webhook a založit ho znovu (dostanete nový secret).
Správa a vypnutí
| Operace | Endpoint |
|---|---|
| Seznam webhooků | GET /api/v1/webhooks |
| Detail webhooku | GET /api/v1/webhooks/:id |
| Registrace | POST /api/v1/webhooks |
| Úprava | PUT /api/v1/webhooks/:id |
Přes PUT lze měnit name, url,
events a isActive. Dočasné vypnutí endpointu se dělá právě
nastavením isActive na false:
PUT /api/v1/webhooks/:id
Content-Type: application/json
{ "isActive": false }
Formát doručení
Tělo požadavku je vždy JSON obálka se čtyřmi klíči. Vlastní data události jsou
v data:
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "document.paid",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"…": "obsah podle události – viz katalog níž"
}
}
Klíč se jmenuje event (nikoli type) a čas
timestamp (nikoli created_at) – v ISO 8601.
Tvar data pro každou událost najdete
v katalogu událostí.
HTTP hlavičky
| Hlavička | Obsah |
|---|---|
X-InvoiceHub-Signature |
sha256=<hex> – HMAC‑SHA256 podpis těla |
X-InvoiceHub-Event |
název události, stejný jako event v těle |
X-InvoiceHub-Delivery |
hodnota id z obálky – identifikátor doručení |
Samostatná hlavička s časovým razítkem neexistuje a systém nemá
žádnou ochranu proti replay útoku nad rámec toho, že timestamp je
součástí podepsaných dat. Pokud replay ochranu potřebujete, vyhodnoťte si na své
straně stáří timestamp a zahazujte již viděná
id doručení.
Ověření podpisu
Podpis vzniká jako HMAC-SHA256 nad přesným JSON řetězcem
obálky, se secretem daného webhooku jako klíčem, výsledek je hex. Proto musíte podpis
počítat nad surovým (nezparsovaným) tělem požadavku – jakmile tělo
zparsujete a znovu serializujete, pořadí klíčů či mezery se mohou lišit a podpis
nebude sedět.
Oficiální SDK pro žádný jazyk zatím neexistuje; ověření je pár řádků nad standardní kryptografickou knihovnou. Příklad pro Node.js a Express:
const crypto = require('crypto');
const express = require('express');
const app = express();
const SECRET = process.env.INVOICEHUB_WEBHOOK_SECRET;
// pozor: express.raw(), ne express.json() – potřebujeme surové tělo
app.post('/invoicehub', express.raw({ type: 'application/json' }), (req, res) => {
const header = req.get('X-InvoiceHub-Signature') || '';
const received = header.startsWith('sha256=') ? header.slice(7) : '';
const expected = crypto
.createHmac('sha256', SECRET)
.update(req.body) // Buffer se surovým tělem
.digest('hex');
const a = Buffer.from(received, 'hex');
const b = Buffer.from(expected, 'hex');
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
return res.status(401).send('invalid signature');
}
const payload = JSON.parse(req.body.toString('utf8'));
console.log(payload.event, payload.id, payload.timestamp);
res.status(200).send('ok');
});
A totéž v Pythonu – podstatné je opět surové tělo a porovnání v konstantním čase:
import hmac, hashlib
def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
received = signature_header.removeprefix("sha256=")
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, received)
Nikdy neporovnávejte podpisy operátorem == nad
řetězci – použijte porovnání v konstantním čase
(crypto.timingSafeEqual, hmac.compare_digest). A na
nepodepsané či nesedící požadavky odpovídejte 401, ne
200.
Opakování pokusů
Jedno doručení má nejvýše 3 pokusy a timeout jednoho pokusu je 10 sekund. Zpoždění mezi pokusy jsou 1 minuta, 5 minut a 30 minut a čeká se blokujícím způsobem – doručení neúspěšného webhooku se tak může protáhnout na desítky minut.
Každý pokus, včetně neúspěšného, se zapíše do historie doručení. Po vyčerpání všech
pokusů se endpoint automaticky nedeaktivuje –
isActive zůstává true a odešle se pouze interní notifikace
o selhání. Trvale nedostupný endpoint tedy musíte vypnout sami přes
PUT.
Z pohledu příjemce z toho plyne: odpovězte rychle (do 10 s) stavovým kódem
2xx a těžkou práci si zařaďte do vlastní fronty. A počítejte s tím, že
stejné doručení můžete dostat vícekrát – zpracování dělejte idempotentní podle
id z obálky (hlavička X-InvoiceHub-Delivery).
Testovací doručení
POST /api/v1/webhooks/:id/test
Odešle jeden pokus bez opakování. Událost je vždy
webhook.test a tělo vypadá takto:
{
"id": "0c7b4f2a-6a1e-45f0-9f1c-3b8d5e2a7c10",
"event": "webhook.test",
"timestamp": "2026-08-19T09:14:22.481Z",
"data": {
"message": "This is a test delivery from InvoiceHub",
"webhookId": "3d2a1b0c-…"
}
}
Je to nejrychlejší způsob, jak si na svém endpointu ověřit dostupnost, TLS a hlavně správnost ověřování podpisu, ještě než postavíte zbytek integrace.
Historie a znovuodeslání
GET /api/v1/webhooks/:id/deliveries
POST /api/v1/webhooks/:id/deliveries/:deliveryId/replay
První endpoint vrací stránkovaný seznam doručení včetně neúspěšných pokusů, druhý odešle konkrétní doručení znovu. Hodí se, když váš systém měl výpadek a chcete zameškaná doručení dohnat.
Pozor na rozpor s API reference: v OpenAPI specifikaci na
/ je tato operace zatím uvedená pod cestou
…/deliveries/:deliveryId/resend a chybí tam
…/test. Skutečná implementace používá
replay – řiďte se touto stránkou, specifikace bude doplněna.
Katalog událostí
Server odpaluje níže uvedené události sám, jakmile k dané akci v aplikaci dojde.
Endpoint dostane jen ty, které má zapsané v poli events. Stejný
katalog vydává i API voláním
GET /api/v1/webhooks/events – používá ho i nabídka v aplikaci
(Nastavení → API a webhooky), takže co je v nabídce, to se i doručuje.
| Událost | Kdy nastane |
|---|---|
document.created |
Byl založen nový doklad (POST /documents) — včetně dokladů vzniklých z opakované série nebo ze schránky nákladů. |
document.updated |
Doklad byl změněn přes PATCH /documents/:id — položky, částky, odběratel nebo štítky. |
document.deleted |
Koncept byl smazán (DELETE /documents/:id). Payload nese poslední známý stav dokladu — po smazání už ho nelze dohledat. |
document.sent |
Doklad byl úspěšně odeslán odběrateli e-mailem (POST /documents/:id/send-email) — včetně upomínky, poděkování za platbu a nabídky. |
document.viewed |
Odběratel otevřel doklad přes veřejný odkaz. Posílá se při každém zobrazení, ne jen při prvním. |
document.paid |
Doklad se dostal do stavu PAID — přechodem stavu, spárováním platby, nebo hned při založení jako uhrazený. |
document.overdue |
Denní kontrola (8:00) našla neuhrazenou fakturu po splatnosti. Posílá se jednou za doklad, ne každý den — stejně jako odpovídající notifikace. |
document.archived |
Doklad přešel do stavu ARCHIVED (POST /documents/:id/transition). |
contact.created |
Byl založen nový kontakt (POST /contacts). |
contact.updated |
Kontakt byl změněn přes PATCH /contacts/:id. Archivace ani rozarchivování sem nespadá — na to je contact.archived. |
contact.archived |
Kontakt byl archivován (PATCH /contacts/:id s archived: true). Kontakty se nemažou, jen archivují. |
product.created |
Byla založena nová položka ceníku (POST /products). |
product.updated |
Položka ceníku byla změněna přes PATCH /products/:id. |
product.archived |
Položka ceníku byla vyřazena (DELETE /products/:id) — jde o měkké smazání, záznam zůstává s active: false. |
payment.imported |
Ze synchronizace s bankou nebo z ručního importu výpisu vznikla nová platba. Posílá se za každou nově založenou platbu. |
payment.matched |
Platba byla spojena s dokladem — ručně (PUT /payments/:id/match), potvrzením návrhu, nebo automatickým párováním při importu. |
payment.unmatched |
Platbě byla zrušena vazba na doklad (DELETE /payments/:id/match). |
automation.started |
Automatizace navěšená na systémovou událost začala běžet. Vzniká i pro běh, který následně skončí přeskočením kvůli nesplněným podmínkám. |
automation.finished |
Běh automatizace doběhl — buď provedl akce (COMPLETED), nebo se přeskočil, protože nesedly podmínky (SKIPPED). |
automation.failed |
Běh automatizace skončil chybou — buď spadl celý (výjimka), nebo neprošla některá z akcí. |
ai.completed |
Operace AI (OCR dokladu, chat, analýza dat firmy) doběhla úspěšně. |
ai.failed |
Operace AI skončila chybou — model neodpověděl, nebo se nepodařilo zpracovat vstup. |
Dokumenty
document.created
Byl založen nový doklad (POST /documents) — včetně dokladů vzniklých z opakované série nebo ze schránky nákladů.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "document.created",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0001qw3f7h2n5m1a",
"number": "2026-0042",
"type": "INVOICE",
"status": "DRAFT",
"currency": "CZK",
"total": 12100,
"paidAmount": 0,
"contactId": "clx8k2p9c0002qw3f8j4k6l2b",
"clientName": "Novák s.r.o.",
"issuedAt": "2026-08-19T00:00:00.000Z",
"dueAt": "2026-09-02T00:00:00.000Z"
}
}
document.updated
Doklad byl změněn přes PATCH /documents/:id — položky, částky, odběratel nebo štítky.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "document.updated",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0001qw3f7h2n5m1a",
"number": "2026-0042",
"type": "INVOICE",
"status": "ISSUED",
"currency": "CZK",
"total": 12100,
"paidAmount": 0,
"contactId": "clx8k2p9c0002qw3f8j4k6l2b",
"clientName": "Novák s.r.o.",
"issuedAt": "2026-08-19T00:00:00.000Z",
"dueAt": "2026-09-02T00:00:00.000Z"
}
}
document.deleted
Koncept byl smazán (DELETE /documents/:id). Payload nese poslední známý stav dokladu — po smazání už ho nelze dohledat.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "document.deleted",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0001qw3f7h2n5m1a",
"number": "2026-0042",
"type": "INVOICE",
"status": "DRAFT",
"currency": "CZK",
"total": 12100,
"paidAmount": 0,
"contactId": "clx8k2p9c0002qw3f8j4k6l2b",
"clientName": "Novák s.r.o.",
"issuedAt": "2026-08-19T00:00:00.000Z",
"dueAt": "2026-09-02T00:00:00.000Z"
}
}
document.sent
Doklad byl úspěšně odeslán odběrateli e-mailem (POST /documents/:id/send-email) — včetně upomínky, poděkování za platbu a nabídky.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "document.sent",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0001qw3f7h2n5m1a",
"number": "2026-0042",
"type": "INVOICE",
"status": "SENT",
"currency": "CZK",
"total": 12100,
"paidAmount": 0,
"contactId": "clx8k2p9c0002qw3f8j4k6l2b",
"clientName": "Novák s.r.o.",
"issuedAt": "2026-08-19T00:00:00.000Z",
"dueAt": "2026-09-02T00:00:00.000Z",
"sentTo": "fakturace@novak.cz",
"subject": "Faktura 2026-0042",
"emailType": "DOCUMENT"
}
}
document.viewed
Odběratel otevřel doklad přes veřejný odkaz. Posílá se při každém zobrazení, ne jen při prvním.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "document.viewed",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0001qw3f7h2n5m1a",
"number": "2026-0042",
"type": "INVOICE",
"status": "SENT",
"currency": "CZK",
"total": 12100,
"paidAmount": 0,
"contactId": "clx8k2p9c0002qw3f8j4k6l2b",
"clientName": "Novák s.r.o.",
"issuedAt": "2026-08-19T00:00:00.000Z",
"dueAt": "2026-09-02T00:00:00.000Z",
"viewedAt": "2026-08-20T10:12:45.221Z"
}
}
document.paid
Doklad se dostal do stavu PAID — přechodem stavu, spárováním platby, nebo hned při založení jako uhrazený.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "document.paid",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0001qw3f7h2n5m1a",
"number": "2026-0042",
"type": "INVOICE",
"status": "PAID",
"currency": "CZK",
"total": 12100,
"paidAmount": 12100,
"contactId": "clx8k2p9c0002qw3f8j4k6l2b",
"clientName": "Novák s.r.o.",
"issuedAt": "2026-08-19T00:00:00.000Z",
"dueAt": "2026-09-02T00:00:00.000Z"
}
}
document.overdue
Denní kontrola (8:00) našla neuhrazenou fakturu po splatnosti. Posílá se jednou za doklad, ne každý den — stejně jako odpovídající notifikace.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "document.overdue",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0001qw3f7h2n5m1a",
"number": "2026-0042",
"type": "INVOICE",
"status": "SENT",
"currency": "CZK",
"total": 12100,
"paidAmount": 0,
"contactId": "clx8k2p9c0002qw3f8j4k6l2b",
"clientName": "Novák s.r.o.",
"issuedAt": "2026-08-19T00:00:00.000Z",
"dueAt": "2026-09-02T00:00:00.000Z",
"daysOverdue": 7,
"remainingAmount": 12100
}
}
document.archived
Doklad přešel do stavu ARCHIVED (POST /documents/:id/transition).
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "document.archived",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0001qw3f7h2n5m1a",
"number": "2026-0042",
"type": "INVOICE",
"status": "ARCHIVED",
"currency": "CZK",
"total": 12100,
"paidAmount": 0,
"contactId": "clx8k2p9c0002qw3f8j4k6l2b",
"clientName": "Novák s.r.o.",
"issuedAt": "2026-08-19T00:00:00.000Z",
"dueAt": "2026-09-02T00:00:00.000Z",
"previousStatus": "PAID"
}
}
Kontakty
contact.created
Byl založen nový kontakt (POST /contacts).
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "contact.created",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0002qw3f8j4k6l2b",
"name": "Novák s.r.o.",
"email": "fakturace@novak.cz",
"phone": "+420 601 234 567",
"type": "CLIENT",
"taxId": "25596641",
"vatId": "CZ25596641",
"archived": false
}
}
contact.updated
Kontakt byl změněn přes PATCH /contacts/:id. Archivace ani rozarchivování sem nespadá — na to je contact.archived.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "contact.updated",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0002qw3f8j4k6l2b",
"name": "Novák s.r.o.",
"email": "fakturace@novak.cz",
"phone": "+420 601 234 567",
"type": "CLIENT",
"taxId": "25596641",
"vatId": "CZ25596641",
"archived": false
}
}
contact.archived
Kontakt byl archivován (PATCH /contacts/:id s archived: true). Kontakty se nemažou, jen archivují.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "contact.archived",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0002qw3f8j4k6l2b",
"name": "Novák s.r.o.",
"email": "fakturace@novak.cz",
"phone": "+420 601 234 567",
"type": "CLIENT",
"taxId": "25596641",
"vatId": "CZ25596641",
"archived": true
}
}
Produkty
product.created
Byla založena nová položka ceníku (POST /products).
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "product.created",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0003qw3f9m5n7o3c",
"name": "Konzultace",
"sku": "KONZ-01",
"unit": "hod",
"price": 1500,
"vatRate": 21,
"active": true
}
}
product.updated
Položka ceníku byla změněna přes PATCH /products/:id.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "product.updated",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0003qw3f9m5n7o3c",
"name": "Konzultace",
"sku": "KONZ-01",
"unit": "hod",
"price": 1500,
"vatRate": 21,
"active": true
}
}
product.archived
Položka ceníku byla vyřazena (DELETE /products/:id) — jde o měkké smazání, záznam zůstává s active: false.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "product.archived",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0003qw3f9m5n7o3c",
"name": "Konzultace",
"sku": "KONZ-01",
"unit": "hod",
"price": 1500,
"vatRate": 21,
"active": false
}
}
Platby
payment.imported
Ze synchronizace s bankou nebo z ručního importu výpisu vznikla nová platba. Posílá se za každou nově založenou platbu.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "payment.imported",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0004qw3f0n6o8p4d",
"amount": 12100,
"currency": "CZK",
"direction": "IN",
"receivedAt": "2026-08-25T00:00:00.000Z",
"variableSymbol": "20260042",
"counterAccount": "123456789/0800",
"matchStatus": "AUTO_MATCHED",
"documentId": "clx8k2p9c0001qw3f7h2n5m1a",
"bankAccountId": "clx8k2p9c0005qw3f1o7p9q5e",
"source": "BANK_SYNC"
}
}
payment.matched
Platba byla spojena s dokladem — ručně (PUT /payments/:id/match), potvrzením návrhu, nebo automatickým párováním při importu.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "payment.matched",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0004qw3f0n6o8p4d",
"amount": 12100,
"currency": "CZK",
"direction": "IN",
"receivedAt": "2026-08-25T00:00:00.000Z",
"variableSymbol": "20260042",
"counterAccount": "123456789/0800",
"matchStatus": "MANUAL_MATCHED",
"documentId": "clx8k2p9c0001qw3f7h2n5m1a",
"bankAccountId": "clx8k2p9c0005qw3f1o7p9q5e",
"documentNumber": "2026-0042",
"matchedBy": "clx8k2p9c0006qw3f2p8q0r6f"
}
}
payment.unmatched
Platbě byla zrušena vazba na doklad (DELETE /payments/:id/match).
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "payment.unmatched",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"id": "clx8k2p9c0004qw3f0n6o8p4d",
"amount": 12100,
"currency": "CZK",
"direction": "IN",
"receivedAt": "2026-08-25T00:00:00.000Z",
"variableSymbol": "20260042",
"counterAccount": "123456789/0800",
"matchStatus": "UNMATCHED",
"documentId": null,
"bankAccountId": "clx8k2p9c0005qw3f1o7p9q5e",
"previousDocumentId": "clx8k2p9c0001qw3f7h2n5m1a"
}
}
Automatizace
automation.started
Automatizace navěšená na systémovou událost začala běžet. Vzniká i pro běh, který následně skončí přeskočením kvůli nesplněným podmínkám.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "automation.started",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"automationId": "clx8k2p9c0007qw3f3q9r1s7g",
"runId": "clx8k2p9c0008qw3f4r0s2t8h",
"name": "Upomínka po splatnosti",
"triggerEvent": "document.created",
"documentId": "clx8k2p9c0001qw3f7h2n5m1a"
}
}
automation.finished
Běh automatizace doběhl — buď provedl akce (COMPLETED), nebo se přeskočil, protože nesedly podmínky (SKIPPED).
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "automation.finished",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"automationId": "clx8k2p9c0007qw3f3q9r1s7g",
"runId": "clx8k2p9c0008qw3f4r0s2t8h",
"name": "Upomínka po splatnosti",
"triggerEvent": "document.created",
"documentId": "clx8k2p9c0001qw3f7h2n5m1a",
"status": "COMPLETED",
"actionsRun": 2,
"actionsFailed": 0
}
}
automation.failed
Běh automatizace skončil chybou — buď spadl celý (výjimka), nebo neprošla některá z akcí.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "automation.failed",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"automationId": "clx8k2p9c0007qw3f3q9r1s7g",
"runId": "clx8k2p9c0008qw3f4r0s2t8h",
"name": "Upomínka po splatnosti",
"triggerEvent": "document.created",
"documentId": "clx8k2p9c0001qw3f7h2n5m1a",
"status": "FAILED",
"errorMessage": "SMTP connection timed out"
}
}
AI
ai.completed
Operace AI (OCR dokladu, chat, analýza dat firmy) doběhla úspěšně.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "ai.completed",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"operation": "ocr",
"model": "claude-opus-4-6",
"inputSummary": "Soubor: faktura.pdf, 214KB",
"outputSummary": "Dodavatel: Novák s.r.o., Částka: 12100"
}
}
ai.failed
Operace AI skončila chybou — model neodpověděl, nebo se nepodařilo zpracovat vstup.
{
"id": "8f1c9a2e-4d3b-4a17-9a51-2c9f0b3d7e64",
"event": "ai.failed",
"timestamp": "2026-08-19T06:00:04.812Z",
"data": {
"operation": "chat",
"model": "claude-opus-4-6",
"errorMessage": "Request timed out"
}
}
Vlastní názvy událostí
Pole events se neověřuje proti katalogu – server přijme
libovolný řetězec. To je záměr: kromě událostí z katalogu si můžete posílat i vlastní,
které si odpálíte akcí TRIGGER_WEBHOOK v
automatizaci.
-
Zvolte si název ve tvaru
oblast.akce, napříkladreminder.dueneboinvoice.recurring.due. Vyhněte se názvům z katalogu výš, ať se vám vlastní doručení nemíchají se systémovými. - Zapište ho do
eventspři registraci webhooku. -
Stejný název použijte v parametru akce
TRIGGER_WEBHOOKv automatizaci. -
Na své straně větvěte zpracování podle hlavičky
X-InvoiceHub-Event.
Obsah data u vlastní události není payload z katalogu:
akce TRIGGER_WEBHOOK posílá kontext automatizace (mimo jiné
documentId, organizationId, documentType,
amount, status, tags). Nespoléhejte tedy
u vlastních názvů na tvar popsaný výš.
Checklist příjemce
- Endpoint na veřejné HTTPS adrese, odpověď
2xxdo 10 sekund. - Podpis ověřený nad surovým tělem, porovnání v konstantním čase.
- Neplatný podpis →
401, žádné zpracování. -
Idempotence podle
X-InvoiceHub-Delivery– doručení může dorazit opakovaně. - Vlastní kontrola stáří
timestamp, chcete‑li replay ochranu. - Monitoring vaší strany – InvoiceHub vám vypnutí mrtvého endpointu neudělá.