Skip to main content
Webhooks tell your code when something happens to a trade: it needs confirmation, it completed on chain, it failed, or it was rejected. They replace polling GET /v1/trades/{id}.

Setting it up

Each API key can have a webhook URL. Set it on the key in the Kash web app under Settings → API Keys. Events for trades placed with that key are POSTed to that URL. The key’s signing secret is shown once when it is created, and can be rotated. The URL must be publicly reachable. Redirects are not followed, so register the final URL.

Events

Envelope

Common payload fields

Every trade.* payload carries:

trade.confirmation-required

Adds confirmationExpiresAt, the time the confirmation token expires (60 seconds after the trade was created). The token itself is never sent in a webhook; it is only in the 202 response to POST /v1/trades.

trade.completed

Adds txHash (a base58 Solana signature, or an EVM 0x hash on an EVM market) and tokensOut (outcome tokens received, an 18-decimal integer string).

trade.failed and trade.rejected

Add errorCode and errorMessage. errorMessage is sanitised. errorCode is a lowercase outcome code, which is a different namespace from the REST API’s error codes: account_not_found, insufficient_balance, wallet_invalid, wallet_not_delegated, market_closed, market_settled, market_not_found, no_matching_market, slippage, trade_too_large, no_position, no_results, blockchain_error, rate_limit, circuit_breaker_open. Treat the list as open: handle unknown values generically.

Headers

  • X-Kash-Signature: the HMAC of the body. Always verify it. See Verifying signatures.
  • X-Kash-Event-Id: same as the body’s id.
  • X-Kash-Event-Type: same as the body’s type.

Delivery semantics

  • At least once. An event can arrive more than once. Make your handler idempotent by deduplicating on the event id.
  • In order per key. Events for one API key are delivered one at a time, in order. A failing event holds back later events for the same key until it is delivered or its attempts run out.
  • Respond quickly with a 2xx. Each attempt times out after 10 seconds. Do slow work after you respond.
  • Retries happen automatically for timeouts, network errors, 5xx and most 4xx responses. Responding 400, 404, 410 or 422, or with a redirect, stops delivery of that event. See Retries & redelivery.

Inspecting deliveries

GET /v1/webhooks/events lists the key’s events with their delivery state:
Each trade also carries a webhookDelivery summary on GET /v1/trades/{id}.

A minimal receiver

Responding 400 to a bad signature stops retries of that request, which is right: a forged request should not be retried. To verify without the SDK, see Verifying signatures.

Next

Verifying signatures

The algorithm and reference code.

Retries & redelivery

Automatic retries and manual replay.

Secret rotation

Rotate with a 7-day overlap.