Create Webhooks

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's KYC status change or a new bank account added to an end-user's 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 - The signature is sent 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.

Enterprise Webhook Types

TypeTriggers When
accessTokenAn access token is made.
bankAccountA bank account is added.

Organization Webhook Types

TypeTriggers When
bankAccountA bank account is added.
enterpriseKycStateEnterprise KYC status changes.
identityStatusA user identity status changes.
pendingapprovalA transaction request is pending approval.
transferA transfer succeeds or fails.
txRequestA transaction request changes status.
txRequestTransactionA transaction request transaction state changes.
userKycStateA user's KYC verification status changes.

Prerequisites

1. Create Organization Webhooks

The following example creates a webhook that notifies you whenever a bank account is added.

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
{
  "success": "true",
  "data": {
    "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": []
}

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 endpoint).

Endpoint: Verify Webhook Notification

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

3. (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 Enterprise 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