# Create Wallet Webhooks

Source: https://developers.bitgo.com/docs/webhooks-wallet

## Overview

You can create wallet webhooks to receive an HTTP callback from BitGo to a specified URL when specific wallet events occur. Wallets can have up to 10 webhooks of each wallet-webhook type.

> 📘 **Note:** An unconfirmed webhook notification doesn't trigger if the chain confirms the transaction immediately after sending, or if it's a <a href="https://bitcoinops.org/en/topics/replace-by-fee/" target="_blank" rel="noreferrer">Replace-by-fee (RBF)</a> transaction.

### Wallet Webhook Types

BitGo offers the following types of webhooks for wallets:

| Type | Triggers When |
| :--- | :------------ |
| `address_confirmation` | A wallet address initializes on chain. This is only applicable for ETH and XRP. |
| `admin` | A wallet freezes, preventing withdrawals. |
| `circuitBreaker` | More than $20M USD withdraws from the wallet within 24 hours. |
| `lowFee` | The average fee on a blockchain drops below a configurable threshold set on a wallet. |
| `lowFeeAddressBalance` | Your gas tank balance is low. |
| `pendingapproval` | There's a wallet event that requires approval. For example, pending approval state updates, policy changes, sending transactions, or user changes. |
| `stuckTx` | A transaction that remains stuck in signed state with multiple retry broadcast attempts. Applies to Ethereum and EVM-compatible chains, Cosmos-based chains, Aptos, Polkadot, and Bittensor. |
| `transaction` | There's a transaction recorded on chain. Returns the transaction hash. |
| `transactionExpire` | A send request expires. |
| `transactionRemoved` | BitGo removes a transaction. |
| `transaction_finality_on_l1` | An L2 transaction reaches finality on the L1 chain. Applies to rollup chains such as Arbitrum, Optimism, and zkSync. |
| `transfer` | There's a transfer into or out of a wallet. |
| `txRequest` | A transaction request state changes, such as changing from `signed` to `pendingApproval`. |
| `txRequestTransaction` | The state of a transaction within a transaction request changes. |

## Prerequisites

* [Get Started](/docs/get-started-intro)
* [Create Wallets](/docs/wallets-create-wallets)
* If you want to verify webhook notifications, ensure your enterprise has a webhook secret (see [Create Webhook Secret](/reference/v2webhooksecretcreate)).

## Cookbook

Need just the steps? Expand the cookbook below to get started:

<Cookbook slug="create-wallet-webhooks" title="Create Wallet Webhooks" />

## 1. Create Wallet Webhooks

The following example creates a webhook that notifies you whenever there's a transfer into or out of a wallet.

>Endpoint: [Add Wallet Webhook](/reference/v2walletaddwebhook)

```shell cURL
export COIN="<ASSET_ID>"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export URL="<YOUR_WEBHOOK_URL>"
export LABEL="<YOUR_WEBHOOK_NAME>"

curl -X POST \
  https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/webhooks \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "type": "transfer",
    "url": "'"$URL"'",
    "label": "'"$LABEL"'",
    "listenToFailureStates": true,
    "customHttpHeaders": {          # Optional fields that you can customize
        "property1": "string",      # with any property names and values
        "property2": "string"
    }
  }'
```
```js JavaScript
const BitGo = require('bitgo');
const bitgo = new BitGo.BitGo({
  env: 'test',
  accessToken: process.env.TEST_ACCESS_TOKEN
});
bitgo.coin('tbtc4').wallets().get({
  id: '<wallet_id>'
}).then((wallet) => {
  wallet.addWebhook({
    type: 'transfer',
    allToken: false,
    url: 'http://your.server.com/webhook',
    label: '<your_webhook_label>',
    nnumConfirmations: 6,
    listenToFailureStates: true
  })
});
```

##### Step Result

```json JSON
{
  "id": "6853113bd6d99d1109391bc98a0dbfd5",
  "label": "my-btc-transfer-webhook",
  "created": "2025-06-18T19:19:23.127Z",
  "scope": "wallet",
  "walletId": "67536a92b294f87c998ea39f85a6bdc7",
  "coin": "tbtc4",
  "type": "transfer",
  "url": "https://webhook.site/f74addc1-c40a-4fce-879a-2d92b8d491c5",
  "version": 2,
  "state": "active",
  "successiveFailedAttempts": 0,
  "listenToFailureStates": true,
  "txRequestStates": [],
  "txRequestTransactionStates": [],
  "identityStatus": []
}
```

## 2. (Optional) Verify Webhook Notification

You can verify the webhook notification is legitimate by passing the payload you received in the prior step as a JSON string with your webhook secret (created with the [Create webhook secret](/reference/v2webhooksecretcreate) endpoint).

>Endpoint: [Verify Webhook Notification](/reference/v2webhooknotificationverify)

```shell cURL
export WEBHOOK_ID="<YOUR_WEBHOOK_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export SIGNATURE="<YOUR_WEBHOOK_SECRET>" # Created using the Create webhook secret endpoint
export PAYLOAD="<YOUR_PAYLOAD>" # JSON payload as a string that you received in the prior step

curl -X POST "https://app.bitgo-test.com/api/v2/webhook/$WEBHOOK_ID/verify" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "signature": "'"$SIGNATURE"'",
    "notificationPayload": "'"$PAYLOAD"'"
  }'
```

##### Step Result

```json JSON
{
  "webhookId": "wh119ecd15a4adf811f8f552fde21b9d819b4dc9a7f04c51513395816703c73511",
  "isValid": true
}
```

## 3. (Optional) Simulate Wallet Webhook

You can simulate your webhook with real data from the prior step or with placeholder data (also known as dummy data).

>Endpoint: [Simulate Wallet Webhook](/reference/v2walletsimulatewebhook)

```shell cURL
export COIN="<ASSET_ID>"
export WALLET_ID="<YOUR_WALLET_ID>"
export WEBHOOK_ID="<YOUR_WEBHOOK_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export TRANSFER_ID="<YOUR_TRANSFER_TOKEN>"

curl -X POST "https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/webhooks/$WEBHOOK_ID/simulate" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
  -d '{
  "transferId": "'"$TRANSFER_ID"'"
}'
```
```shell cURL (Placeholder)
export COIN="<ASSET_ID>"
export WALLET_ID="<YOUR_WALLET_ID>"
export WEBHOOK_ID="<YOUR_WEBHOOK_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export TRANSFER_ID="<YOUR_TRANSFER_TOKEN>"

curl -X POST "https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/webhooks/$WEBHOOK_ID/simulate" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
  -d '{
  "usePlaceholderData": true
}'
```

##### Step Result

```json JSON
{
    "webhookNotifications": [
        {
            "id": "6853262b9da229cea98569ce71fc060e",
            "type": "transfer",
            "wallet": "62c5b5c9d0ece30007cec9616ff29edc",
            "enterprise": "62c5ae8174ac860007aff138a2d74df7",
            "organization": "62c5ae8174ac860007aff1555ffb960d",
            "url": "https://webhook.site/f74addc1-c40a-4fce-879a-2d92b8d491c5",
            "hash": "db924f4cf2347ac5a6b464d3e8dc4a20cffc117eb29f4460645fbc34de171bfb",
            "coin": "tbtc4",
            "transfer": "68531ea4e3669330070c95e454f5b366",
            "state": "sent_via_ncc",
            "simulation": true,
            "retries": 0,
            "webhook": "68531e154d28af627819bd3e183a930e",
            "updatedAt": "2025-06-18T20:48:43.525Z",
            "idempotencyKey": "e3094fa873a8e5b5"
        }
    ]
}
```

## Next

Before you process webhook notifications, BitGo strongly recommends that you verify response details by fetching the transfer or block data from BitGo. For example, if you create a transfer webhook and receive a transfer ID, pass that ID to the [Get Transfer](/reference/v2walletgettransfer) endpoint to verify the transfer details.

For more examples, see the BitGo JavaScript SDK <a href="https://github.com/BitGo/BitGoJS/tree/master/examples" target="_blank" rel="noreferrer">GitHub repository</a>.

## See Also

* [API Reference: Add Wallet Webhook](/reference/v2walletaddwebhook)
* [API Reference: Create Webhook Secret](/reference/v2webhooksecretcreate)
* [API Reference: Simulate Wallet Webhook](/reference/v2walletsimulatewebhook)
* [API Reference: Verify Webhook Notification](/reference/v2webhooknotificationverify)
* <a href="https://webhook.site/" target="_blank" rel="noreferrer">Webhook.site</a>
