Přeskočit na obsah

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.

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.

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);
}
<?php
function 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.