Přeskočit na obsah

Odchozí webhooky

Ověřeno

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).

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ěď 3xx je 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 ping stejnou 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á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.

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_id je 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.
  • store je kód e-shopu (market) — stejný, jaký používá REST.
  • tenant je identifikátor vašeho účtu v MitoOps.
Content-Type: application/json
User-Agent: MitoOps-Webhooks/1
X-MitoOps-Event: shipment.delivered
X-MitoOps-Event-Id: 9b2f0c1e-6d3a-4c7e-9a2b-0f1e2d3c4b5a
X-MitoOps-Timestamp: 1756888872
X-MitoOps-Signature: v1=3f1a…c9e0
X-MitoOps-Delivery: 184

Podpis 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 2xx do 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í FAILED a čeká na ruční opakování z deníku.
  • Odpověď 3xx a 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
  • 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 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í.

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í.