Prijeđi na sadržaj

Odlazni webhookovi

Provjereno

Webhook je suprotnost REST-u i MCP-u: ne pitate Vi, nego se javlja MitoOps. Kada u računu nastane događaj na koji ste pretplaćeni, na Vašu adresu šaljemo POST s kratkom potpisanom omotnicom. Omotnica nosi identifikatore i stanja, a ne sadržaj narudžbe: detalje Vaš sustav učitava putem REST sučelja vlastitim ključem.

Pretplatama upravljate u aplikaciji: Postavke → API & MCP → Odlazni webhookovi. Dostupne su od tarife Start; potrebno je pravo Odlazni webhookovi (čitanje ili upravljanje).

Endpoint ima naziv, adresu, popis događaja i opseg web trgovina. Pri otvaranju dobivate tajnu: prikazuje se jednom, a zatim više nikada; bilo kada je možete zamijeniti (rotacija), a stara odmah prestaje vrijediti.

  • Adresa mora biti javna i putem https:// na standardnom portu. Adrese u unutarnju mrežu (lokalno računalo, privatni rasponi, metapodaci oblaka, VPN rasponi) odbijaju se pri spremanju i pri svakoj dostavi: naziv se ponovno razrješava, a veza se veže uz provjerene adrese.
  • Preusmjeravanja se ne slijede. Odgovor 3xx je neuspjeh.
  • Web trgovine: sve (i one koje se dodaju) ili odabrane. Događaj iz web trgovine izvan opsega ne šalje se.
  • Probna dostava s gumba šalje događaj ping istim putem kao stvarna: uključujući potpis i upis u dnevnik.
  • Endpoint se može isključiti (dostave koje čekaju se preskaču) i izbrisati (dnevnik ostaje).
Događaj Kada resource.type Polja u data
order.created nova narudžba iz web trgovine order order_code
order.paid narudžba označena kao plaćena order order_code
order.status_changed promjena statusa narudžbe order order_code, status_id, previous_status_id
shipment.created pošiljka izrađena kod dostavne službe shipment shipment_id, order_code, carrier_code, tracking_number
shipment.status_changed promjena statusa pošiljke (dostavna služba ili osoblje) shipment shipment_id, order_code, carrier_code, status, previous_status, tracking_number
shipment.delivered pošiljka dostavljena; dodatno uz shipment.status_changed shipment kao iznad, status je DELIVERED
inventory.stock_changed kretanje zalihe stavke inventory_item item_id, sku, kind
invoice.created izdan račun invoice invoice_code, order_code
claim.created otvorena reklamacija (od kupca ili osoblja) claim claim_code, order_code
claim.status_changed promjena stanja reklamacije claim claim_code, order_code, status_id
claim.closed reklamacija zatvorena claim claim_code, order_code
search_console.connection.changed promjena stanja veze Search Consolea (povezivanje, promjena stranice, gubitak pristupa, odspajanje) search_console_property market, status, previous_status, property, previous_property, changed_at
search_console.sync.completed sinkronizacija arhiva dodala je ili promijenila dane search_console_property market, property, search_types, data_state, final_data_through, fresh_data_through, days_upserted, revised_dates, sync_version, synced_at
search_console.sync.failed sinkronizacija arhiva nije uspjela search_console_property market, property, error, error_code, last_successful_sync_at, retry_at
product_content.changed MitoOps je u web trgovinu upisao promijenjeni opis, kratki opis ili SEO tekst proizvoda product store_id, market, entity, entity_id, canonical_url, source, source_run_id, changed_fields, before_hash, after_hash, changed_at
category_content.changed MitoOps je u web trgovinu upisao promijenjeni gornji ili donji opis ili SEO tekst kategorije category kao kod product_content.changed
ping probna dostava s gumba webhook_endpoint message, endpoint

Događaji potječu iz istog poslovnog sloja kao automatizacije: ono što pokreće automatizaciju, na to se može pretplatiti i webhookom. Povratne pošiljke (povrati) ne šalju se kao shipment.*: pripadaju reklamaciji.

Promjena tekstova proizvoda i kategorija

Odjeljak „Promjena tekstova proizvoda i kategorija”

product_content.changed i category_content.changed nastaju jednom po upisu i web trgovini kada MitoOps u web trgovinu upiše tekst koji se stvarno promijenio — s kartice proizvoda, skupnog uređivanja, uvoza, zaslona kategorija, iz odobrenog prijedloga ili autonomnog upisa. Promjena cijene, zalihe ili šifre, kao ni ponovno spremanje istog teksta, ne izaziva događaj. Izmjene napravljene izravno u administraciji web trgovine ovaj događaj ne javlja.

  • entity je product ili category; entity_id (i resource.id) je šifra proizvoda, odnosno ID kategorije u web trgovini — isti s kojima čitate tekstove putem products_content_get i categories_content_get. store_id je šifra web trgovine, ista kao store.
  • source: ui (osoba u aplikaciji), assistant (asistent u aplikaciji), mcp (prijedlog putem MCP-a koji je odobrila osoba), autonomous (prijedlog upisan u autonomnom načinu). Vrijednost rest je rezervirana — REST je danas samo za čitanje.
  • source_run_id: ID prijedloga kod odobrenog i autonomnog upisa; kod ostalih upisa proizvoda ID serije upisa (Promjene proizvoda); kod kategorije spremljene izvan prijedloga null.
  • changed_fields navodi promijenjena polja: za proizvod description, shortDescription, metaTitle, metaDescription, za kategoriju description, descriptionBottom, metaTitle, metaDescription. before_hash i after_hash za svako od njih nose SHA-256 teksta u UTF-8 (vrijednost koja nedostaje = otisak praznog niza) — istu vrijednost koju pri čitanju vraća polje hash. Sam tekst omotnica ne nosi.
  • Nakon odobrenja prijedloga after_hash je otisak onoga što je web trgovina nakon upisa stvarno spremila (WordPress na primjer uklanja blok <style>), a ne onoga što je predloženo.
  • canonical_url je javna adresa proizvoda ili kategorije ako je MitoOps zna; inače null.

Što vaš ključ smije čitati i predlagati u određenoj web trgovini te hoće li se prijedlog upisati sam, provjerite unaprijed putem pravila sadržaja: GET /api/v1/product-content/policy?market=… ili MCP alatom products_content_policy (opseg product-content:read).

Svaka dostava je JSON s verzijom omotnice. Novo polje može se dodati bez promjene verzije; promjena značenja polja je nova verzija.

{
"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 jedinstven za događaj. Ako su na isti događaj pretplaćena dva Vaša endpointa, dobivaju isti ID. Ponovljeni pokušaj nosi isti ID i isto tijelo.
  • store je kod web trgovine (market): isti koji koristi REST.
  • tenant je identifikator Vašeg računa u 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

Potpis je HMAC-SHA256 s ključem = tajna endpointa nad nizom:

<X-MitoOps-Timestamp> + "." + <točno tijelo zahtjeva>

Rezultat je heksadecimalan, a u zaglavlju stoji s prefiksom verzije v1=. Vremenska oznaka je unixovo vrijeme u sekundama.

Provjeravajte nad sirovim tijelom zahtjeva (bajtovi onakvi kakvi su stigli), a ne nad ponovno serijaliziranim JSON-om: svaka promjena razmaka ili redoslijeda ključeva poništava potpis. Uspoređujte u konstantnom vremenu i odbijte poruke starije od 5 minuta.

import { createHmac, timingSafeEqual } from 'node:crypto';
function overMitoOpsWebhook({ tajomstvo, hlavicky, suroveTelo, teraz = Math.floor(Date.now() / 1000) }) {
const cas = Number(hlavicky['x-mitoops-timestamp']);
if (!Number.isFinite(cas) || Math.abs(teraz - cas) > 300) return false; // stara ili nedostajuća oznaka
const prijaty = String(hlavicky['x-mitoops-signature'] || '')
.split(',').map((s) => s.trim()).find((s) => s.startsWith('v1='));
if (!prijaty) return false;
const ocakavany = createHmac('sha256', tajomstvo)
.update(String(cas) + '.').update(suroveTelo).digest('hex');
const a = Buffer.from(prijaty.slice(3), 'hex');
const b = Buffer.from(ocakavany, 'hex');
return a.length === b.length && timingSafeEqual(a, b);
}
import hmac, hashlib, time
def over_mitoops_webhook(tajomstvo: 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
ocakavany = hmac.new(tajomstvo.encode(), f"{cas}.".encode() + surove_telo, hashlib.sha256).hexdigest()
return hmac.compare_digest(podpis[3:], ocakavany)

Zaštita od ponovne reprodukcije

Odjeljak „Zaštita od ponovne reprodukcije”

Potpis pokriva vremensku oznaku, pa presretnutu poruku nije moguće kasnije poslati s novim vremenom. Uz provjeru vremena čuvajte event_id posljednjih dostava i zanemarite duplikate: ponovljena dostava svojstvo je sustava, a ne greška.

Odgovor, ponavljanje i dnevnik

Odjeljak „Odgovor, ponavljanje i dnevnik”
  • Odgovorite 2xx unutar 10 sekundi. Tijelo odgovora se ne čita. Obradu koja traje dulje stavite u pozadinu i odgovorite odmah.
  • Drugi odgovor (4xx, 5xx), istek vremena ili greška veze = neuspjeh i ponavljanje s razmacima od 1, 5, 15, 60 i 240 minuta; ukupno šest pokušaja. Zatim je dostava FAILED i čeka ručno ponavljanje iz dnevnika.
  • Odgovor 3xx i adresa koja se prestala razrješavati na javnu mrežu neuspjesi su bez ponavljanja: sami se neće riješiti.
  • Dnevnik dostava u aplikaciji za svaki pokušaj prikazuje stanje, HTTP kod, vrijeme, broj pokušaja i događaj. Tijelo poruke u dnevniku se ne prikazuje.
Stanje Značenje
PENDING čeka pokušaj ili sljedeće ponavljanje
SENT primatelj je odgovorio 2xx
FAILED pokušaji su iscrpljeni ili je greška trajna; može se ponoviti ručno
SKIPPED endpoint je u međuvremenu isključen ili izbrisan
  • Tajna se sprema šifrirano i nikada se ne zapisuje u logove ni u dnevnik. Prikazuje se jednom; rotacija radi i kada tarifa više ne uključuje webhookove: to je sigurnosna operacija.
  • Bez osobnih podataka. Omotnica nosi identifikatore i stanja. Ime, adresa ni e-pošta kupca ne šalju se; tko ih treba, čita ih putem REST-a s vlastitim opsegom i revizijom.
  • Samo HTTPS, samo javne adrese, bez preusmjeravanja. Provjera pri spremanju i pri svakoj dostavi štiti od usmjeravanja u unutarnju mrežu i od promjene DNS-a.
  • Pretplatu otvara osoba, a ne ključ. Pristupni ključ za REST ni OAuth privola ne mogu otvoriti pretplatu: čitanje na zahtjev i trajni tok događaja prema van dva su različita ovlaštenja.
  • Izolacija. Pretplate i dnevnik nalaze se u prostoru Vašeg računa; opseg web trgovina procjenjuje se pri svakom događaju.
Tarifa Odlazni webhookovi Endpointa
Probna ne 0
Početnik ne 0
Start da 5
Rast da 20
Pro da 50
Po mjeri prema dogovoru prema dogovoru

Broje se neizbrisani endpointi: uključeni i isključeni. Snižavanje tarife ne briše postojeće endpointe; novi se ne dodaje dok broj ne padne ispod ograničenja, a kod tarife bez webhookova događaji se prestaju slati dok se tarifa ne vrati.

Endpoint možete koristiti i kao korak Poslati webhook u Automatizacijama: poruka odlazi tek nakon ispunjenja uvjeta pravila, a ne pri svakom događaju. Korak endpoint samo odabire: adresa, tajna i opseg web trgovina ostaju u registru.

Poruka ima vrstu automation.action (na nju se ne može izravno pretplatiti) i istu omotnicu, potpis, ponavljanje i dnevnik kao ostali događaji. U data nosi automation.workflow_id, automation.run_id, automation.node_id, automation.source_event (događaj koji je probudio pravilo) i identifikatore narudžbe, pošiljke ili reklamacijskog predmeta; resource je entitet izvođenja. Detalje učitavate putem REST API-ja.

Ako primatelj ne odgovori na 30 uzastopnih pokušaja ili endpoint ima više od 5 000 dostava koje čekaju, MitoOps privremeno zaustavlja endpoint i šalje Vam upozorenje. Dostave koje čekaju ostaju; nakon popravka primatelja uključite endpoint i one će se dovršiti. Dnevnik dostava čuva se 30 dana.