<!--
Sitemap:
- [Stridge](/index): Stridge is a crypto payment infrastructure platform — multi-chain wallets, automated deposit detection, secure payouts, and the Stridge Gateway Kit for any-to-any payments.
- [API Reference](/api-reference/): Stridge REST API reference — complete endpoint documentation for wallets, deposits, transfers, vaults, gas stations, networks, and transactions.
- [Changelog](/changelog): Release notes for Stridge SDKs and developer tools.
- [Example Page](/example): Example page demonstrating MDX features available in Stridge docs.
- [Stridge Gateway Kit](/gateway/): Stridge Gateway Kit — an integration kit for embedding any-to-any crypto payments in DeFi protocols and apps.
- [Getting Started](/getting-started): Get started with Stridge — create an API key, authenticate against the REST API, and make your first call.
- [Supported Networks](/networks): Blockchain networks and tokens supported by the Stridge payment infrastructure — network_id (SLIP-44), EIP-155 chain IDs, and the available native and stablecoin assets per chain.
- [Developer Tools](/sdk/): Headless Stridge SDKs for Node.js, Go, and React — wrap the Stridge REST API with fully-typed clients and ready-made flows.
- [Security](/security/): Stridge Security — how the Stridge KMS protects wallet keys and signs transactions without ever exposing private keys.
- [Universal Deposit Addresses](/uda/): Universal Deposit Addresses (UDA) — persistent, multi-chain deposit addresses with automatic cross-chain settlement to a fixed destination.
- [Webhooks](/webhooks/): Stridge webhooks — real-time HTTP notifications for deposits, wallet assignments, transactions, and balance changes with signed HMAC SHA-256 deliveries.
- [Go SDK](/sdk/go): Build on Stridge from Go with the official Stridge Go SDK.
- [Node.js SDK](/sdk/node): Build on Stridge from any Node.js runtime with the official Node SDK.
- [React SDK](/sdk/react): Embed Stridge payment flows in your React app with hooks and ready-made components.
- [Get a single deposit transaction by ID](/api-reference/deposits/get-a-single-deposit-transaction-by-id): Get details of a specific deposit transaction by its unique ID
- [Get a single deposit transaction by transaction id](/api-reference/deposits/get-a-single-deposit-transaction-by-transaction-id): Get details of a specific deposit transaction by on-chain transaction id (tx_id)
- [List deposit transactions](/api-reference/deposits/list-deposit-transactions): Get a paginated list of deposit transactions for the authenticated tenant with filtering support
- [Get gas station details by address](/api-reference/gas-stations/get-gas-station-details-by-address): Get detailed gas station information including all asset balances for a specific address
- [Get gas station details by wallet ID](/api-reference/gas-stations/get-gas-station-details-by-wallet-id): Get detailed gas station information including all asset balances for a specific wallet ID
- [List gas station wallets](/api-reference/gas-stations/list-gas-station-wallets): Get a paginated list of gas station wallets with filtering and sorting support
- [Get blockchain assets](/api-reference/networks/get-blockchain-assets): Get a list of all supported blockchain assets (tokens and native assets).
- [Get blockchain networks](/api-reference/networks/get-blockchain-networks): Get a list of all supported blockchain networks.
- [Get network list](/api-reference/networks/get-network-list): Get a public list of all networks with category grouping.
- [Get tenant network](/api-reference/networks/get-tenant-network): Get a specific network for the authenticated tenant by network ID and contract address
- [Get tenant networks](/api-reference/networks/get-tenant-networks): Get a list of networks available to the authenticated tenant with their enabled status
- [Update tenant network status](/api-reference/networks/update-tenant-network-status): Update the enabled status of a network for the authenticated tenant
- [Get a transaction by ID](/api-reference/transactions/get-a-transaction-by-id): Get details of a specific transaction by its ID
- [List unified transactions](/api-reference/transactions/list-unified-transactions): Get a paginated list of all transactions (deposits, payouts, refills, etc.) for the authenticated tenant
- [External transfer by address](/api-reference/transfers/external-transfer-by-address): Transfer assets from user wallet to an external address using wallet address.
- [External transfer by wallet ID](/api-reference/transfers/external-transfer-by-wallet-id): Transfer assets from user wallet to an external address using wallet ID.
- [Internal transfer between wallets by address](/api-reference/transfers/internal-transfer-between-wallets-by-address): Transfer assets from user wallet to hot wallet or gas station using addresses.
- [Internal transfer between wallets by ID](/api-reference/transfers/internal-transfer-between-wallets-by-id): Transfer assets from user wallet to hot wallet or gas station using wallet IDs.
- [Create payout](/api-reference/vault-transfers/create-payout): Creates a new payout from the tenant's vault wallet to an external address
- [Create payout with USD amount](/api-reference/vault-transfers/create-payout-with-usd-amount): Creates a new payout converting a USD amount to crypto at current rate
- [Get payout by ID](/api-reference/vault-transfers/get-payout-by-id): Retrieves a payout by its ID
- [List payouts](/api-reference/vault-transfers/list-payouts): Lists payouts for a vault with filtering and pagination
- [Transfer from vault to external address](/api-reference/vault-transfers/transfer-from-vault-to-external-address): Transfer assets from the tenant's vault wallet to an external address.
- [Get vault address by network](/api-reference/vaults/get-vault-address-by-network): Get the vault address for a specific network
- [Get vault balances](/api-reference/vaults/get-vault-balances): Get balances for all vault addresses with optional filtering
- [Get vault total value](/api-reference/vaults/get-vault-total-value): Get the total USD value across all vault assets
- [List vault addresses](/api-reference/vaults/list-vault-addresses): Get all vault addresses for the authenticated tenant
- [List vaults](/api-reference/vaults/list-vaults): List all vault accounts for the authenticated tenant
- [Create/assign a new wallet](/api-reference/wallets/create-assign-a-new-wallet): Assign a blockchain wallet to a user with the specified network and owner ID.
- [Get wallet details by address](/api-reference/wallets/get-wallet-details-by-address): Get detailed wallet information including all asset balances for a specific address
- [Get wallet details by ID](/api-reference/wallets/get-wallet-details-by-id): Get detailed wallet information including all asset balances for a specific wallet ID
- [Get wallets by owner](/api-reference/wallets/get-wallets-by-owner): Get all wallets assigned to a specific owner with optional filtering
- [List assigned wallets](/api-reference/wallets/list-assigned-wallets): Get a paginated list of assigned wallets for the authenticated tenant with filtering and sorting support
-->

# Webhooks

Stridge webhooks send real-time HTTP notifications when activity happens in your account — deposits, wallet assignments, transaction lifecycle updates, and balance changes — so you don't have to poll the API.

## How it works

:::::steps

### An event is created

Deposits, wallets, transactions, and balance changes generate events when account activity occurs.

### Stridge matches subscribers

Active webhook subscribers for your tenant are filtered by event type.

### Stridge signs and sends the payload

Each delivery is wrapped in a standard envelope, signed with **HMAC SHA-256**, and sent as an HTTP `POST` to your webhook URL.

### Stridge retries failed deliveries

If your endpoint returns a non-2xx response or times out, Stridge retries with exponential backoff.

:::::

:::info
Deliveries follow the [Standard Webhooks specification](https://github.com/standard-webhooks/standard-webhooks/blob/main/spec/standard-webhooks.md) with an envelope-based payload.
:::

## Event types

| Event                     | Description                  | Trigger                                               |
| ------------------------- | ---------------------------- | ----------------------------------------------------- |
| `deposit.new`             | New deposit detected         | A blockchain transaction is detected for your address |
| `address.assigned`        | Address assigned to an owner | A wallet address is assigned to a user or owner       |
| `transaction.broadcasted` | Transaction broadcasted      | A transaction is submitted to the blockchain          |
| `transaction.confirmed`   | Transaction confirmed        | A transaction reaches required confirmations          |
| `transaction.failed`      | Transaction failed           | A transaction fails on-chain                          |
| `balance.updated`         | Balance updated              | A wallet balance changes                              |

## Delivery format

Every delivery uses the same envelope:

```json
{
  "id": "7401d9c7-e29d-4374-8952-af40f05168b7",
  "version": "1",
  "type": "deposit.new",
  "time": "2026-02-08 09:46:54.699313",
  "payload": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "network_symbol": "ethereum",
    "tx_hash": "0xabc123...",
    "amount": "100.50",
    "owner": "user@example.com"
  }
}
```

| Field     | Description                                  |
| --------- | -------------------------------------------- |
| `id`      | Unique event idempotency key                 |
| `version` | Webhook format version, currently `1`        |
| `type`    | Event type such as `deposit.new`             |
| `time`    | Event timestamp                              |
| `payload` | Event-specific payload data                  |

## Signature verification

Each request includes three headers:

| Header              | Description                                  |
| ------------------- | -------------------------------------------- |
| `webhook-id`        | Unique event idempotency key                 |
| `webhook-signature` | HMAC SHA-256 signature, hex-encoded          |
| `webhook-timestamp` | Unix timestamp when Stridge sent the request |

The signature is computed as:

```text
message   = webhook-timestamp + "." + raw_request_body
signature = HMAC-SHA256(signing_secret, message)
```

Verify it before trusting the body:

:::code-group

```ts [Node.js]
import { createHmac, timingSafeEqual } from 'node:crypto'

export function verifyWebhookSignature(
  secret: string,
  body: string,
  timestamp: string,
  receivedSignature: string,
) {
  const message = `${timestamp}.${body}`
  const expected = createHmac('sha256', secret).update(message).digest('hex')
  return timingSafeEqual(Buffer.from(expected), Buffer.from(receivedSignature))
}
```

```go [Go]
func verifyWebhookSignature(secret, body, timestamp, receivedSignature string) bool {
    message := timestamp + "." + body
    h := hmac.New(sha256.New, []byte(secret))
    h.Write([]byte(message))
    expected := hex.EncodeToString(h.Sum(nil))
    return hmac.Equal([]byte(expected), []byte(receivedSignature))
}
```

```python [Python]
import hmac, hashlib

def verify_webhook_signature(secret, body, timestamp, received_signature):
    message = f"{timestamp}.{body}"
    expected = hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, received_signature)
```

:::

:::warning
Always verify the signature before processing the payload. Reject requests with old timestamps to reduce replay risk.
:::

## Retry behavior

Stridge retries failed deliveries with exponential backoff — **up to 5 retries, 10 s initial delay, 10 min cap**. Any `2xx` response marks the delivery as successful.

| Attempt | Delay       |
| ------- | ----------- |
| 1       | Immediate   |
| 2       | 10 seconds  |
| 3       | 20 seconds  |
| 4       | 40 seconds  |
| 5       | 80 seconds  |
| 6       | 160 seconds |

## Consumer checklist

* **Verify every signature** — check `webhook-signature` with the `webhook-timestamp`.
* **Deduplicate by `webhook-id`** — retries will deliver the same event more than once.
* **Respond fast** — return `2xx` immediately after enqueuing; process asynchronously.
* **Expect duplicates** — idempotent handlers are required, not optional.
