Topics
Subscribe
There are two ways to register an endpoint. Both require anhttps:// URL, and both return the signing secret exactly once — SignSealShip stores only its SHA-256 hash, so a breach of our database never yields a key that can forge deliveries.
Partner dashboard (all topics). Sign in at signsealship.com/partner and add a webhook under webhook management, choosing the topics you want. The response shows your sss_whsec_ secret once; copy it into your secret manager immediately.
Proof Passport API (passport.sealed only). Registering with your partner key subscribes you to sealed-passport events:
Register a passport webhook
Response
Event payloads
Deliveries are JSON POSTs. The event name also rides in aSignSealShip-Event header, and the id field is deterministic per event so you can deduplicate redeliveries.
passport.sealed
room.order_attached
room.passport_sealed
orderCode on order-attached, passportVerifyCode on passport-sealed. Payloads are PII-free and never contain another partner’s data.
The signature scheme
Every delivery includes:Headers
t=,v1= format, so existing verification code ports directly:
- Derive the key once. The HMAC key is the UTF-8 bytes of
lowercase_hex(sha256(your_raw_secret)). You re-derive it from thesss_whsec_secret you were shown; SignSealShip signs with the stored hash, so the two sides always agree without the secret ever being stored in reversible form. - Build the signed payload. Concatenate the
tvalue, a literal., and the raw request body bytes:{t}.{rawBody}. - Compute HMAC-SHA256 over that payload with the derived key, hex-encoded lowercase.
- Compare against
v1with a constant-time comparison. - Reject stale timestamps. Refuse deliveries where
tis more than 5 minutes from now — this bounds replay of a captured request.
Complete verification recipe
Both examples read the raw body, verify the signature and timestamp, and only then parse the event.Delivery semantics
- Best-effort and non-blocking. Deliveries never block or fail the operation that triggered them. A sealed passport is durable before its webhook fires.
- Respond fast with a 2xx. Acknowledge immediately and process asynchronously; slow endpoints get timed out at 10 seconds.
- Expect redeliveries. Deliveries can be enqueued and retried, so design your handler to be idempotent. Deduplicate on the
idfield — it is deterministic per event. - Ordering is not guaranteed. Use
occurredAtUtc/sealedAtUtcwhen sequence matters. - Verify every delivery. An unsigned or badly signed request to your endpoint is not from SignSealShip. Return a 400 and ignore it.
Related
Webhooks API reference
Endpoint shapes for registering, listing, and deleting webhook subscriptions.
Closing Passport
What the
room.passport_sealed event points at, and how to verify it.