Webhooky
Webhook nastavíte v tenant administraci v tabu Integrace. EasyPick očekává HTTPS URL dostupnou z internetu a odpověď ve třídě 2xx.
Doručované události
Sekce “Doručované události”reserved, loaded, picked_up, expired, cancelled, fault, removed a door_available.
Webhooková událost není totéž co stav zásilky. Payload proto obsahuje samostatně status a compartment_state.
| Událost | Význam | Stav zásilky po události | Typický compartment_state |
|---|---|---|---|
reserved |
Byla vytvořena rezervace schránky. | reserved |
reserved |
loaded |
Naskladnění je potvrzené a skončila ochranná lhůta. | loaded |
occupied |
picked_up |
Zákazník dokončil vyzvednutí. | picked_up |
cooldown |
cancelled |
Zásilka byla zrušena. | cancelled |
reserved u prázdné rezervace, jinak awaiting_removal; případné uvolnění oznámí až door_available |
expired |
Vypršel termín rezervace nebo vyzvednutí. | expired |
reserved u prázdné rezervace, jinak awaiting_removal; případné uvolnění oznámí až door_available |
fault |
Zásilku nebylo možné bezpečně dokončit. | fault |
zpravidla awaiting_removal |
removed |
Obsluha fyzicky odebrala obsah a potvrdila prázdnou schránku. | beze změny (cancelled, expired nebo fault) |
awaiting_removal; skutečné uvolnění oznámí následující door_available |
door_available |
Schránka je skutečně uvolněná a znovu rezervovatelná. | beze změny | available |
Událost loaded je zákaznický notifikační bod: doručí se až po ochranné lhůtě a se zavřenými dveřmi. Pokud zásilka před skutečným odesláním webhooku přejde do cancelled, expired nebo fault, čekající loaded se zruší, aby e-shop neposlal zákazníkovi neplatnou výzvu. removed a door_available jsou provozní události schránky, nikoliv nové stavy zásilky. door_available je kanonická událost po každém skutečném uvolnění: po cooldownu, po removed i po okamžitém uvolnění nenaskladněné rezervace. PIN není v payloadu nikdy.
{ "api_version": "1", "id": "event_01k3example", "type": "loaded", "occurred_at": "2026-08-02T10:04:12Z", "data": { "shipment_id": "shipment_01k3example", "external_order_id": "ORDER-2026-1042", "attempt_number": 1, "retry_of_shipment_id": null, "box_id": "box_01k3example", "box_name": "Box Praha 1", "compartment_code": "A2", "status": "loaded", "compartment_state": "occupied", "pickup_available_at": "2026-08-02T10:04:12Z", "pickup_expires_at": "2026-08-05T10:02:12Z" }}Integrace smí považovat schránku za volnou pouze při compartment_state=available. Terminální status sám o sobě dostupnost schránky nepotvrzuje.
Pole attempt_number začíná hodnotou 1. Nový pokus po chybě má vyšší číslo a retry_of_shipment_id odkazuje na bezprostředně předchozí chybný pokus.
Ověření podpisu
Sekce “Ověření podpisu”EasyPick posílá:
EasyPick-Event-Id: stabilní ID pro deduplikaci,EasyPick-Timestamp: Unix timestamp podpisu,EasyPick-Signature:v1=a hex HMAC-SHA256.
Podepisovaný řetězec je přesně timestamp + "." + raw_request_body. JSON před ověřením znovu neserializujte.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyEasyPickWebhook(rawBody, headers, secret) { const timestamp = headers['easypick-timestamp']; const received = headers['easypick-signature']?.replace(/^v1=/, ''); if (!timestamp || !received) return false; if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = createHmac('sha256', secret) .update(`${timestamp}.`) .update(rawBody) .digest('hex'); const a = Buffer.from(expected, 'hex'); const b = Buffer.from(received, 'hex'); return a.length === b.length && timingSafeEqual(a, b);}<?phpfunction verifyEasyPickWebhook(string $rawBody, string $timestamp, string $signature, string $secret): bool { if (abs(time() - (int) $timestamp) > 300) return false; $received = preg_replace('/^v1=/', '', $signature); $expected = hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret); return is_string($received) && hash_equals($expected, $received);}Doručení alespoň jednou
Sekce “Doručení alespoň jednou”Stejná událost může přijít opakovaně. Nejdřív atomicky uložte její id, duplicitní ID potvrďte 2xx bez dalšího zpracování a teprve potom změňte objednávku. Po neúspěchu EasyPick opakuje doručení přibližně po 1 min, 5 min, 30 min, 2 h a 12 h.
Webhook zpracujte rychle a asynchronně. Po ověření podpisu a uložení události vraťte 2xx; další obchodní logiku proveďte mimo HTTP request.