The four order topics deliver only for orders your partner created through the Order API — orders placed elsewhere never reach your endpoint.
Every delivery is an HTTPS POST with a JSON body, a
SignSealShip-Signature HMAC header, and a SignSealShip-Event header naming the event.
Two ways to register
- Passport-only shortcut —
POST /api/passport/webhooksregisters apassport.sealed-only endpoint. Subscriptions created this way have no topic list and never receive room or order events. - Topic-aware management — the
/api/partner/webhooksendpoints below let you choose topics, including the room and order events.
Authentication
The/api/partner/webhooks management routes accept either credential:
- Partner API key —
Authorization: Bearer sss_pk_..., for server-to-server management: your own provisioning code, a Zapier zap, or any integration that never sees a browser. - Dashboard session — the SignSealShip login session cookie, where your signed-in user must be linked to your partner account. Linking happens once, by proving possession of a valid partner API key — sign in at
https://signsealship.com/partnerand paste your key (the underlying call isPOST /api/partner/linkwith{"apiKey": "..."}). The first linked member of a partner becomesowner; later onesmember.
401; an unlinked session gets:
403 Forbidden
partner-portal rate limit of 120 requests per minute.
List subscriptions
GET /api/partner/webhooks
Returns a JSON array of your partner’s subscriptions, newest first. Legacy subscriptions created with the passport-only route report "topics": ["passport.sealed"].
curl
200 OK
Create a subscription
POST /api/partner/webhooks
string
required
Your webhook endpoint. Must be an absolute
https:// URL.string[]
required
One or more of
passport.sealed, room.order_attached,
room.passport_sealed, order.created, payment.cleared,
signature.completed, shipment.delivered. Deliveries go only to
subscriptions whose topics include the event; the order topics fire only
for Order API orders.curl
string
Subscription id (UUID) — use it to delete.
string
The signing secret, prefixed
sss_whsec_. Shown exactly once —
SignSealShip stores only its SHA-256 hash. Save it now.string
The registered endpoint.
string[]
The subscribed topics.
string
"SignSealShip-Signature" — the header carrying the signature on every
delivery.400 {"error": "A https:// webhook URL is required."}, 400 when topics is empty or contains anything outside the allowed set.
Delete a subscription
DELETE /api/partner/webhooks/{id}
string
required
The subscription id. You can only delete your own partner’s subscriptions.
curl
{"ok": true}, or 404 {"error": "No such webhook."}.
Rotate a signing secret
POST /api/partner/webhooks/{id}/rotate
Reissues the subscription’s signing secret without recreating the subscription.
string
required
The subscription id.
curl
string
The new signing secret, prefixed
sss_whsec_. Shown exactly once —
only its hash is stored. Save it now.SignSealShip-Signature header carries a v1 entry for each. Accept a delivery when any v1 entry matches (the samples below check a single v1; during a rotation window, test each entry) and you ride through the cutover without dropping a delivery. After the overlap the old secret stops signing.
List delivery attempts
GET /api/partner/webhooks/{id}/deliveries
A metadata-only feed of the subscription’s recent delivery attempts, newest first — what was attempted, when, and how your endpoint answered. Event payload bodies are never stored or returned; use the feed to confirm your endpoint is receiving and answering deliveries, not to replay them.
string
required
The subscription id.
curl
Event payloads
All payloads are PII-free and never carry another partner’s data. Optional fields are omitted from the JSON entirely (not sent asnull) when they don’t apply.
passport.sealed
id is the passport’s UUID.
passport.sealed
environment is live or test — the environment of the API key that sealed the passport. Test-keyed passports verify publicly with the distinct verdict verified_test, so sandbox evidence is never mistaken for production evidence.
room.order_attached
id is deterministic per event, room, and subject — {event}:{roomCode}:{orderCode} — so you can deduplicate a redelivery. orderCode is the attached order’s public code; passportVerifyCode is omitted.
room.order_attached
room.passport_sealed
passportVerifyCode is the room’s latest sealed passport verify code (for /v/room/{passportVerifyCode}); orderCode is omitted.
room.passport_sealed
Order events
order.created, payment.cleared, signature.completed, and shipment.delivered share one body shape. They deliver only for orders your partner created through the Order API, signed identically to every other delivery, with the SignSealShip-Event header carrying the topic.
id is deterministic — {topic}:{orderCode} — so a redelivery deduplicates cleanly. externalReference echoes the external_reference you sent at order creation and is omitted when you sent none. status is the order’s status name at dispatch time.
payment.cleared
Verifying the signature
Every delivery carries two headers:Delivery headers
t=,v1= format, so you can reuse familiar verification code:
1
Derive the key
The HMAC key is
lowercase_hex(sha256(secret)) — the SHA-256 of your raw
signing secret, as a lowercase hex string, used as UTF-8 bytes.2
Compute the expected signature
HMAC-SHA256 over the string
"{t}.{rawBody}", where t is the value from
the header and rawBody is the exact request body bytes. Compare the
lowercase hex result to v1 with a constant-time comparison.3
Reject stale timestamps
Reject deliveries whose
t is more than 5 minutes from now to blunt
replay.Delivery semantics — honest version
Webhook delivery is best-effort and fire-and-forget. A slow or failing endpoint can never block, slow, or fail the seal or room operation that triggered it.- Outbound POSTs time out after 10 seconds; a non-2xx response is logged and not retried by the dispatcher.
passport.sealeddeliveries may be routed through an internal task queue when available, which can produce a redelivery — treat deliveries as at-least-once and deduplicate byid.- Room events are dispatched after the underlying write commits; if your endpoint is down, that notification is lost.
GET /api/partner/orders/{code}, GET /api/rooms/{roomCode}, GET /api/verify/room/{verifyCode}, and GET /api/passport/{id} — whenever correctness matters. The delivery attempts feed tells you whether your endpoint has been answering.