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-sha256HTTP 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
| Type | Triggers When |
|---|---|
accessToken | An access token is made. |
bankAccount | A bank account is added. |
Organization Webhook Types
| Type | Triggers When |
|---|---|
bankAccount | A bank account is added. |
enterpriseKycState | Enterprise KYC status changes. |
identityStatus | A user identity status changes. |
pendingapproval | A transaction request is pending approval. |
transfer | A transfer succeeds or fails. |
txRequest | A transaction request changes status. |
txRequestTransaction | A transaction request transaction state changes. |
userKycState | A user's KYC verification status changes. |
Prerequisites
- Get Started
- If you want to verify webhook notifications, ensure your enterprise has a webhook secret (see Create Webhook Secret).
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
Updated about 3 hours ago