Odchozí webhooky
Ověřeno
Stručně
Sekce “Stručně”Webhook je opak REST a MCP: neptáte se vy, ozve se MitoOps. Když v účtu vznikne událost, kterou odebíráte, pošleme na vaši adresu POST s krátkou podepsanou obálkou. Obálka nese identifikátory a stavy, ne obsah objednávky — detail si váš systém načte přes REST rozhraní vlastním klíčem.
Odběry spravujete v aplikaci: Nastavení → API & MCP → Odchozí webhooky. Jsou dostupné od tarifu Start; je třeba právo Odchozí webhooky (čtení nebo správa).
Odběr (endpoint)
Sekce “Odběr (endpoint)”Endpoint má název, adresu, seznam událostí a rozsah e-shopů. Při založení dostanete tajemství — ukáže se jednou, pak už nikdy; kdykoli ho vyměníte (rotace), staré přestane platit okamžitě.
- Adresa musí být veřejná a přes
https://na standardním portu. Adresy do vnitřní sítě (místní stroj, privátní rozsahy, metadata cloudu, VPN rozsahy) se odmítnou při uložení i při každém doručení — jméno se překládá znovu a spojení se váže na ověřené adresy. - Přesměrování se nenásledují. Odpověď
3xxje selhání. - E-shopy: všechny (i ty, které přibudou) nebo vybrané. Událost z e-shopu mimo rozsah se nepošle.
- Zkušební doručení z tlačítka pošle událost
pingstejnou cestou jako ostrá — včetně podpisu a zápisu do deníku. - Endpoint se dá vypnout (čekající doručení se přeskočí) a smazat (deník zůstává).
Události
Sekce “Události”| Událost | Kdy | resource.type |
Pole v data |
|---|---|---|---|
order.created |
nová objednávka z e-shopu | order |
order_code |
order.paid |
objednávka označená jako uhrazená | order |
order_code |
order.status_changed |
změna stavu objednávky | order |
order_code, status_id, previous_status_id |
shipment.created |
zásilka vytvořena u dopravce | shipment |
shipment_id, order_code, carrier_code, tracking_number |
shipment.status_changed |
změna stavu zásilky (dopravce nebo obsluha) | shipment |
shipment_id, order_code, carrier_code, status, previous_status, tracking_number |
shipment.delivered |
zásilka doručena; navíc k shipment.status_changed |
shipment |
jako výše, status je DELIVERED |
inventory.stock_changed |
pohyb zásoby položky | inventory_item |
item_id, sku, kind |
invoice.created |
vystavená faktura | invoice |
invoice_code, order_code |
claim.created |
založená reklamace (zákazníkem nebo obsluhou) | claim |
claim_code, order_code |
claim.status_changed |
změna stavu reklamace | claim |
claim_code, order_code, status_id |
claim.closed |
reklamace uzavřena | claim |
claim_code, order_code |
ping |
zkušební doručení z tlačítka | webhook_endpoint |
message, endpoint |
Události pocházejí ze stejné obchodní vrstvy jako automatizace: co spustí automatizaci, to se dá odebírat i webhookem. Zpětné zásilky (vratky) se jako shipment.* neposílají — patří k reklamaci.
Obálka
Sekce “Obálka”Každé doručení je JSON s verzí obálky. Nové pole může přibýt bez změny verze; změna významu pole je nová verze.
{ "event_id": "9b2f0c1e-6d3a-4c7e-9a2b-0f1e2d3c4b5a", "event_type": "shipment.delivered", "version": 1, "occurred_at": "2026-09-03T08:41:12.318Z", "tenant": "00001", "store": "sk", "resource": { "type": "shipment", "id": "5521" }, "data": { "shipment_id": "5521", "order_code": "2026001234", "carrier_code": "gls", "status": "DELIVERED", "previous_status": "IN_TRANSIT", "tracking_number": "GLS123456789" }}event_idje jedinečné pro událost. Pokud stejnou událost odebírají dva vaše endpointy, dostanou stejné ID. Opakovaný pokus nese stejné ID a stejné tělo.storeje kód e-shopu (market) — stejný, jaký používá REST.tenantje identifikátor vašeho účtu v MitoOps.
Hlavičky a podpis
Sekce “Hlavičky a podpis”Content-Type: application/jsonUser-Agent: MitoOps-Webhooks/1X-MitoOps-Event: shipment.deliveredX-MitoOps-Event-Id: 9b2f0c1e-6d3a-4c7e-9a2b-0f1e2d3c4b5aX-MitoOps-Timestamp: 1756888872X-MitoOps-Signature: v1=3f1a…c9e0X-MitoOps-Delivery: 184Podpis je HMAC-SHA256 klíčem = tajemství endpointu nad řetězcem:
<X-MitoOps-Timestamp> + "." + <přesné tělo požadavku>Výsledek je hexadecimální a v hlavičce stojí s předponou verze v1=. Časová značka je unixový čas v sekundách.
Ověření na vaší straně
Sekce “Ověření na vaší straně”Ověřujte nad surovým tělem požadavku (bajty tak, jak přišly), ne nad znovu serializovaným JSONem — každá změna mezery či pořadí klíčů podpis zneplatní. Porovnávejte v konstantním čase a odmítněte zprávy starší než 5 minut.
import { createHmac, timingSafeEqual } from 'node:crypto';
function overMitoOpsWebhook({ tajemstvi, hlavicky, suroveTelo, ted = Math.floor(Date.now() / 1000) }) { const cas = Number(hlavicky['x-mitoops-timestamp']); if (!Number.isFinite(cas) || Math.abs(ted - cas) > 300) return false; // stará nebo chybějící značka
const prijaty = String(hlavicky['x-mitoops-signature'] || '') .split(',').map((s) => s.trim()).find((s) => s.startsWith('v1=')); if (!prijaty) return false;
const ocekavany = createHmac('sha256', tajemstvi) .update(String(cas) + '.').update(suroveTelo).digest('hex'); const a = Buffer.from(prijaty.slice(3), 'hex'); const b = Buffer.from(ocekavany, 'hex'); return a.length === b.length && timingSafeEqual(a, b);}import hmac, hashlib, time
def over_mitoops_webhook(tajemstvi: str, hlavicky: dict, surove_telo: bytes) -> bool: try: cas = int(hlavicky["X-MitoOps-Timestamp"]) except (KeyError, ValueError): return False if abs(int(time.time()) - cas) > 300: return False podpis = next((s.strip() for s in hlavicky.get("X-MitoOps-Signature", "").split(",") if s.strip().startswith("v1=")), None) if not podpis: return False ocekavany = hmac.new(tajemstvi.encode(), f"{cas}.".encode() + surove_telo, hashlib.sha256).hexdigest() return hmac.compare_digest(podpis[3:], ocekavany)Ochrana proti přehrání
Sekce “Ochrana proti přehrání”Podpis pokrývá časovou značku, takže zachycenou zprávu nelze později poslat s novým časem. Vedle kontroly času si uchovávejte event_id posledních doručení a duplicitu ignorujte: opakované doručení je vlastnost systému, ne chyba.
Odpověď, opakování a deník
Sekce “Odpověď, opakování a deník”- Odpovězte
2xxdo 10 sekund. Tělo odpovědi se nečte. Zpracování, které trvá déle, si zařaďte na pozadí a odpovězte hned. - Jiná odpověď (
4xx,5xx), timeout nebo chyba spojení = selhání a opakování s odstupy 1, 5, 15, 60 a 240 minut; celkem šest pokusů. Pak je doručeníFAILEDa čeká na ruční opakování z deníku. - Odpověď
3xxa adresa, která se přestala překládat na veřejnou síť, jsou selhání bez opakování — sama se nevyřeší. - Deník doručení v aplikaci ukazuje pro každý pokus stav, HTTP kód, čas, počet pokusů a událost. Tělo zprávy se v deníku nezobrazuje.
| Stav | Význam |
|---|---|
PENDING |
čeká na pokus nebo na další opakování |
SENT |
příjemce odpověděl 2xx |
FAILED |
pokusy vyčerpány nebo trvalá chyba; dá se opakovat ručně |
SKIPPED |
endpoint byl mezitím vypnut nebo smazán |
Bezpečnost
Sekce “Bezpečnost”- Tajemství se ukládá šifrované a nikdy se nezapisuje do logů ani do deníku. Zobrazí se jednou; rotace funguje i tehdy, když tarif webhooky už neobsahuje — je to bezpečnostní operace.
- Bez osobních údajů. Obálka nese identifikátory a stavy. Jméno, adresa ani e-mail zákazníka se neposílají; kdo je potřebuje, čte je přes REST s vlastním rozsahem a auditem.
- Jen HTTPS, jen veřejné adresy, bez přesměrování. Kontrola při uložení i při každém doručení chrání před směrováním do vnitřní sítě a před změnou DNS.
- Odběr zakládá člověk, ne klíč. Přístupový klíč k REST ani souhlas OAuth odběr založit nemůže: čtení na vyžádání a trvalý proud událostí ven jsou dvě různá oprávnění.
- Izolace. Odběry i deník leží v prostoru vašeho účtu; rozsah e-shopů se vyhodnocuje při každé události.
Tarif
Sekce “Tarif”| Tarif | Odchozí webhooky | Endpointů |
|---|---|---|
| Zkušební | — | 0 |
| Začátečník | — | 0 |
| Start | ano | 5 |
| Růst | ano | 20 |
| Pro | ano | 50 |
| Na míru | podle dohody | podle dohody |
Počítají se nesmazané endpointy — zapnuté i vypnuté. Snížení tarifu existující endpointy nesmaže; nový nepřibude, dokud počet neklesne pod limit, a u tarifu bez webhooků se události přestanou posílat, dokud se tarif nevrátí.
Webhook z automatizace
Sekce “Webhook z automatizace”Endpoint můžete použít i jako krok Odeslat webhook v Automatizacích: zpráva odejde až po splnění podmínek pravidla, ne při každé události. Krok endpoint jen vybírá — adresa, tajemství a rozsah e-shopů zůstávají v registru.
Zpráva má typ automation.action (nedá se odebírat přímo) a stejnou obálku, podpis, opakování a deník jako ostatní události. V data nese automation.workflow_id, automation.run_id, automation.node_id, automation.source_event (událost, která pravidlo probudila) a identifikátory objednávky, zásilky nebo reklamačního případu; resource je entita běhu. Detail si načtete přes REST API.
Automatické pozastavení
Sekce “Automatické pozastavení”Pokud příjemce neodpoví 30 pokusů za sebou nebo má endpoint více než 5 000 čekajících doručení, MitoOps endpoint pozastaví a pošle vám upozornění. Čekající doručení zůstávají; po opravě příjemce endpoint zapněte a doběhnou. Deník doručení se drží 30 dní.