GET /v1/orders/:id returns, so if you have already integrated the pull API there is no second format to learn.
Authentication for management calls: any valid read key. Registering an endpoint moves no money, so it does not need a trading key.
Quick start
1
Register your endpoint
secret starting csb_whsec_. It is shown once. Store it before you close the terminal — there is no endpoint that returns it again, only one that rotates it.2
Send yourself a test event
3
Verify the signature and ACK fast
Return
2xx as soon as you have verified and persisted the event. Do the actual work afterwards — see Respond fast below.Verifying the signature
Every request carries:
The signed material is
"{t}.{raw_request_body}" and the algorithm is HMAC-SHA256 keyed with your webhook secret. Compare in constant time, and reject anything whose t is more than 5 minutes from your clock.
t to get past your tolerance check without also forging the MAC.
Event payload
Every delivery has the same envelope.data is exactly the object GET /v1/orders/:id returns.
Envelope fields
Order fields
Item fields
A
hold order is not a stuck order. The items are bought and paid for; Steam will not let them move until hold_until. If the account is set to auto-claim they release on their own, otherwise call POST /v1/orders/{id}/claim once hold_until has passed.Delivery semantics
At-least-once, deduped byid. We may deliver the same event more than once — after a restart, or when your endpoint ACKs a request we had already timed out on. The id is stable per (order, state), so storing processed ids and ignoring repeats is the entire integration. It is also echoed in X-CSBoard-Event-Id, so you can dedupe before parsing the body.
Ordering is not guaranteed. Retries mean an older state can arrive after a newer one. Do not treat the webhook as a state machine you advance — treat each event as a snapshot and compare data.updated_at against what you have stored, discarding anything older. Every event carries the complete order, so a single event is always enough to render the current truth.
Retries. Any response outside 2xx, a redirect, a connection failure, or no answer within 10 seconds counts as a failure. Failed deliveries retry on a widening ladder — 10s, 30s, 1m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 12h — up to 12 attempts, spanning roughly 24 hours. An endpoint down for a working day still receives everything once it comes back.
Auto-disable. After 50 consecutive failures the endpoint is switched off and we stop attempting. Nothing is deleted — re-enable with PATCH /v1/webhooks/{id} and queued events resume.
Respond fast
ACK within 10 seconds. Verify the signature, write the event to your own queue or table, return200, and do the real work asynchronously. If you process inline — updating a user balance, calling Steam, sending a message — a slow dependency turns into a timeout on our side, a retry, and a duplicate you now have to handle under load.
Security
- HTTPS only. The payload carries order and delivery data.
- Endpoints must be publicly routable. URLs that resolve to private, loopback, link-local or CGNAT ranges are rejected at registration and re-checked before every send, because DNS can be re-pointed after the fact.
- Redirects are not followed. A
3xxcounts as a failure — register the final URL. - Rotating the secret:
POST /v1/webhooks/{id}/rotate-secret. Queued deliveries are signed with whichever secret is current at send time, so accept both values for a minute or rotate during a quiet window. - The secret is a signing key, not a credential. It grants no access to your account. It still belongs in your secret store, not your repo.
Managing endpoints
GET /v1/webhooks/{id}/deliveries is the self-serve answer to “did you actually send it?” — including the failed attempts and the exact error text your endpoint returned. Check it before opening a ticket; it is usually faster than we are.
Errors
Still want to poll?
Nothing is removed.GET /v1/orders and GET /v1/orders/info carry the same fields, including hold_until and per-item tradable_at, and remain the right tool for reconciliation sweeps. The recommended shape is push for latency and a periodic pull for truth — a nightly GET /v1/orders over the last 24 hours catches anything a permanently broken endpoint would otherwise have lost.