Overview

You can use webhooks to receive real-time HTTP callbacks when specific events occur. This enables you to automate workflows, notify your end-users, and keep your platform in sync with BitGo.

As a CaaS provider, you operate at the Organization level and manage numerous child Enterprises (your end-users). This guide covers the two scopes of webhooks you can integrate:

  • Organization Webhooks - Notifications for events that apply to your entire CaaS organization such as organization-level policy changes or new bank accounts.
  • Enterprise Webhooks - Notifications for events specific to one of your end-users such as an end-user KYC status change or a new bank account added to an end-user enterprise.

BitGo signs all webhook notifications, enabling you to verify their authenticity.

  • Webhook Secret - When you create a webhook, you can set a secret. BitGo uses this secret to generate an HMAC-SHA256 signature.
  • Signature Header - BitGo sends the signature in the x-signature-sha256 HTTP header.
  • Verification - To verify the payload, compute your own HMAC-SHA256 signature of the raw request body using your secret and compare it to the signature in the header. This is a critical security step.

Note

You may receive multiple of the same webhook notification due to at-least-once delivery infrastructure. Always design your webhook handlers to be idempotent so you can identify duplicate notifications.

Enterprise Webhook Types

Type Triggers When
accessToken A user creates an access token.
bankAccount A user adds a bank account.
reversal BitGo reverses a fiat transaction.

Organization Webhook Types

Type Triggers When
accessToken A user creates an access token.
bankAccount A user adds a bank account.
enterpriseKycState Enterprise KYC status changes.
identityStatus A user identity status changes.
idvStatus A user IDV status changes.
pendingapproval A transaction request is pending approval.
reversal BitGo reverses a fiat transaction.
transfer A transfer succeeds or fails.
txRequest A transaction request changes status.
txRequestTransaction A transaction request transaction state changes.
userKycState A user KYC verification status changes.
tradeOrder A trade order status changes.

Webhook Payload Schemas

Each webhook type returns a different JSON payload. Use these example schemas to parse and handle incoming webhook notifications.

Cookbooks

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

Create Webhooks (Enterprise)Open Cookbook Create Webhooks (Organization)Open Cookbook

Triggered when a user creates an access token.

{
  "userId": "59cd72485007a239fb00282a",
  "username": "user@example.com",
  "tokenCreateTime": "2024-01-15T10:30:00.000Z",
  "tokenExpireTime": "2024-01-15T18:30:00.000Z",
  "spendingLimits": "{\"txValue\":1000000,\"txValueLimit\":5000000}",
  "tokenIp": "192.168.1.100",
  "tokenIpWhitelist": ["192.168.1.0/24"],
  "tokenScope": "wallet_view_all wallet_spend_all",
  "enterpriseName": "Test Enterprise",
  "id": "59cd72485007a239fb00282b",
  "enterpriseId": "59cd72485007a239fb00282c",
  "organizationId": "59cd72485007a239fb00282d"
}

Prerequisites

1. Create Organization Webhooks

The following example creates a webhook that notifies you whenever a user adds a bank account.

Endpoint: Create Organization Webhook

export ORGANIZATION_ID="<YOUR_ORGANIZATION_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/organization/$ORGANIZATION_ID/webhook \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "type": "bankAccount",
    "url": "'"$URL"'",
    "label": "'"$LABEL"'"
  }'
Step Result
{
  "id": "690278897328c7fc41e81887d4b76964",
  "label": "test org webhook 1",
  "created": "2025-10-29T20:26:49.286Z",
  "scope": "organization",
  "organizationId": "68f6af3f2f29893d5863bc0eaf77b3c6",
  "type": "bankAccount",
  "url": "https://webhook.site/2635918b-018b-4179-82e9-6940a0b851e0",
  "version": 1,
  "state": "active",
  "successiveFailedAttempts": 0,
  "listenToFailureStates": false,
  "txRequestStates": [],
  "txRequestTransactionStates": [],
  "identityStatus": []
}

2. (Optional) Create Webhook Secret

Create a webhook secret that enables you to verify webhook notifications. BitGo uses this secret to generate HMAC-SHA256 signatures for all webhook payloads, enabling you to verify that notifications genuinely originate from BitGo and that no one has tampered with them.

Important

Store your webhook secret securely. If compromised, rotate it immediately by calling this endpoint again. You can rotate secrets once every 5 minutes.

Note

You must create your webhook secret before performing the action that triggers the notification. Otherwise, the notification won't include a signature and you won't be able to verify it.

Endpoint: Create Webhook Secret

export ORGANIZATION_ID="<YOUR_ORGANIZATION_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"

curl -X POST \
  https://app.bitgo-test.com/api/v2/webhook/secret \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "organizationId": "'"$ORGANIZATION_ID"'"
  }'
Step Result
{
  "secret": "whsec_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0"
}

Save this secret securely—you'll need it to verify incoming webhook notifications using the x-signature-sha256 header.

3. (Optional) Verify Webhook Notification

When BitGo sends a webhook notification, it includes an x-signature-sha256 header containing an HMAC-SHA256 signature. You can verify the notification is legitimate by passing the signature from this header along with the payload you received.

Endpoint: Verify Webhook Notification

export WEBHOOK_ID="<YOUR_WEBHOOK_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export SIGNATURE="<X_SIGNATURE_SHA256_HEADER_VALUE>" # Value from the x-signature-sha256 header in the webhook notification
export PAYLOAD="<YOUR_PAYLOAD>" # JSON payload as a string from the webhook notification body

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
{
  "webhookId": "wh119ecd15a4adf811f8f552fde21b9d819b4dc9a7f04c51513395816703c73511",
  "isValid": true
}

4. (Optional) Simulate Organization Webhook

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

Endpoint: Simulate Organization Webhook

export ORGANIZATION_ID="<YOUR_ORGANIZATION_ID>"
export WEBHOOK_ID="<YOUR_WEBHOOK_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export ACCESS_TOKEN_ID="<YOUR_ACCESS_TOKEN_ID>"

curl -X POST "https://app.bitgo-test.com/api/v2/organization/$ORGANIZATION_ID/webhook/$WEBHOOK_ID/simulate" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
  -d '{
  "bankAccountId": "string"
}'
Step Result
{
  "webhookNotifications": [
    {
      "id": "59cd72485007a239fb00282ed480da1f",
      "accessToken": "txRequest",
      "url": "https://webhook.site/f74addc1-c40a-4fce-879a-2d92b8d491c5",
      "hash": "db924f4cf2347ac5a6b464d3e8dc4a20cffc117eb29f4460645fbc34de171bfb",
      "simulation": true,
      "retries": 0,
      "webhook": "68531e154d28af627819bd3e183a930e",
      "updatedAt": "2025-06-19T20:48:43.525Z",
      "version": 1,
      "allowBlockedHosts": true,
      "payload": "string",
      "response": {
        "code": 0,
        "type": "string",
        "body": "string",
        "error": "string"
      }
    }
  ]
}

See Also