Dokumentacja poglądowa. Interfejs jest w trakcie udostępniania — przykłady mają charakter zapowiedzi, a finalne wartości potwierdzimy przy starcie.
Webhooki: podpis, retry, replay
Webhooki wypychają zdarzenia commerce na Twój endpoint w miarę jak zmienia się status
zamówienia, kończy się próba połączenia lub gotowy jest wynik. Base URL zarządzania:
https://api.callbotagent.ai/api/v1/commerce. Żądania konfiguracyjne podpisujesz HMAC
(X-CBA-Key-Id, X-CBA-Timestamp, X-CBA-Signature); mutacje dodają Idempotency-Key.
Subskrypcja i sekret
GET /webhook-subscription
PUT /webhook-subscription
Odczyt i upsert subskrypcji: url (wymagany HTTPS), lista event_types, enabled.
Scope webhooks:write dla PUT.
POST /webhook-subscription/secret/rotate
Rotacja sekretu podpisu. Nowy sekret jest pokazywany tylko raz (reveal-once) w odpowiedzi — zapisz go od razu; później nie da się go odczytać.
POST /webhook-subscription/test
Wysyła zdarzenie testowe na skonfigurowany url, żeby zweryfikować odbiór i podpis.
url musi być publicznym adresem HTTPS. Adresy prywatne, loopback i link-local są
odrzucane (ochrona przed SSRF).
Zdarzenia i koperta
event_type |
Kiedy |
|---|---|
commerce.order.status_changed.v1 |
zmiana processing_state zamówienia |
commerce.call.attempt_completed.v1 |
zakończona próba połączenia (call_disposition) |
commerce.order.result_ready.v1 |
gotowy final_order_snapshot |
commerce.writeback.failed.v1 |
nieudany zapis zwrotny do sklepu |
Każde zdarzenie ma tę samą kopertę (pole data niesie payload konkretnego typu):
| Pole | Opis |
|---|---|
event_id |
Unikalny identyfikator zdarzenia (klucz deduplikacji). |
event_type / event_version |
Typ i wersja schematu, np. ...v1. |
occurred_at |
Znacznik czasu RFC 3339 UTC. |
integration_ref |
Identyfikator integracji odbiorcy. |
external_order_id |
Twój identyfikator zamówienia, którego dotyczy zdarzenie. |
correlation_id / causation_id |
Powiązanie i przyczyna w łańcuchu zdarzeń. |
data |
Payload właściwy dla event_type. |
Podpis i weryfikacja
Każde dostarczenie ma nagłówki X-CBA-Webhook-Timestamp, X-CBA-Webhook-Event-Id,
X-CBA-Webhook-Signature. Podpis to HMAC-SHA256 z bazy timestamp + "." + event_id + "." + raw_body (surowe ciało, bez ponownej serializacji), liczony sekretem z rotacji. Porównuj w
sposób odporny na timing i odrzucaj zdarzenia starsze niż kilka minut.
# Odtwórz podpis lokalnie i porównaj z nagłówkiem X-CBA-Webhook-Signature BASE="$TS.$EVENT_ID.$RAW_BODY" printf '%s' "$BASE" | openssl dgst -sha256 -hmac "$CBA_WEBHOOK_SECRET"
import crypto from "node:crypto";function verify(headers, rawBody, secret) { const base =
${headers["x-cba-webhook-timestamp"]}.+${headers["x-cba-webhook-event-id"]}.${rawBody}; const expected = crypto.createHmac("sha256", secret).update(base).digest("hex"); const got = headers["x-cba-webhook-signature"]; return expected.length === got.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(got)); } // secret pochodzi z rotacji (reveal-once), np. process.env.CBA_WEBHOOK_SECRET
function verify(array $headers, string $rawBody, string $secret): bool {
$base = $headers['x-cba-webhook-timestamp'].'.'.
$headers['x-cba-webhook-event-id'].'.'.$rawBody;
$expected = hash_hmac('sha256', $base, $secret);
return hash_equals($expected, $headers['x-cba-webhook-signature']);
}
// $secret pochodzi z rotacji (reveal-once), np. getenv('CBA_WEBHOOK_SECRET')Retry, dead-letter, dostarczenia
Dostarczenie uznajemy za udane, gdy odbiorca odpowie 2xx w limicie czasu. W innym razie
ponawiamy z rosnącym odstępem (backoff): do 8 prób w ciągu 24 godzin. Po wyczerpaniu prób
zdarzenie trafia do dead-letter i można je odtworzyć ręcznie.
GET /webhook-deliveries
Historia dostarczeń (opaque cursor, limit do 200): status, kod odpowiedzi, liczba prób.
POST /webhook-deliveries/{deliveryId}/replay
Ponowne wysłanie konkretnego dostarczenia. event_id pozostaje ten sam, więc buduj odbiorcę
idempotentnie — deduplikuj po event_id.
Diagnostyka niedostarczonych zdarzeń: ../help/troubleshooting/webhooki-niedostarczone.md.