Crypto-as-a-Service
Set Up Organization
Overview
An organization sits above enterprises in the BitGo hierarchy. One organization can contain many enterprises, but each enterprise belongs to only one organization. Within your organization, you create a child enterprise for each of your users so they can independently initiate trades, withdrawals, and other actions.
Organization admins manage the organization. They can view balances, KYC statuses, and transaction history across child enterprises. They can also create org-level webhooks and manage organization users. However, it's the role of the service user to create and manage child enterprises and handle the day-to-day operations. For a full comparison, see Crypto-as-a-Service Key Roles.
Your organization has an organization name and organization ID. The organization name matches your enterprise name, but the organization ID and enterprise ID are always different.
Note
Organization-wide policies don't exist. Policies are available only at the enterprise and wallet levels, and policies you create for one enterprise or wallet don't apply to child enterprises. To apply a policy to a child enterprise, create the policy within that specific child enterprise. See Create Policy Rules.
Prerequisites
1. Create Access Token
You must create an access token to authenticate your requests to the BitGo API. This will be required for operations like programmatically adding users to an enterprise, setting up child enterprises, submitting their KYC verification, creating, and trading with their Go Accounts.
You can create short-lived access tokens and keep rotating them or long-lived access tokens with timed rotations. BitGo recommends using long-lived access tokens. The following example uses relevant scopes for a long-lived access token.
Note
You must use a short-lived access token to programmatically generate a long-lived access token. Alternatively, you can generate long-lived access tokens in the BitGo web app.
Note
If you create a long-lived access token without a spending limit, the token's sessions start locked. Call the Unlock session endpoint to unlock them as needed.
To have sessions unlocked by default, set spendingLimits with one entry per coin. Each entry requires a txValueLimit. You can also set maxLimit to true, but this applies a very high spending limit and is not recommended.
Endpoints:
- Create access token (long lived)
- Login (short lived)
export ACCESS_TOKEN="<YOUR_SHORT_LIVED_ACCESS_TOKEN>"
export DURATION="<DURATION>"
export LABEL="<DESIRED_TOKEN_NAME>"
export IP_RESTRICT="<IP_ADDRESS_OR_CIDR_BLOCK>"
export COIN="<ASSET_ID>" # Coin that needs an unlocked session, e.g. sol
export TX_VALUE_LIMIT="<TX_VALUE_LIMIT>" # e.g. "10000000000" for 10 SOL
curl -X POST \
https://app.bitgo-test.com/api/v2/user/accesstoken \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"scope": [
"pending_approval_update", # Update pending approvals
"profile", # View your BitGo profile
"settlement_network_read", # Enables partners engage in allocations with clients
"settlement_network_write", # Enables partners engage in allocations with clients
"trade_trade", # Make trades
"trade_view", # View trades
"wallet_approve_all", # Approve transactions for all wallets
"wallet_create", # Create wallets
"wallet_edit_all", # Edit comments for all wallets
"wallet_freeze_all", # Freeze all wallets
"wallet_manage_all", # Manage settings for all wallets (required to use webhooks)
"enterprise_view_all", # View child enterprises
"enterprise_manage_all", # Manage users and settings for child enterprises
"wallet_spend_all", # Send transactions from a wallet
"wallet_view_all" # View transactions for all wallets
],
"duration": "'"$DURATION"'",
"label": "'"$LABEL"'",
"ipRestrict": ["'"$IP_RESTRICT"'"],
"spendingLimits": [
{
"coin": "'"$COIN"'",
"txValueLimit": "'"$TX_VALUE_LIMIT"'",
"maxLimit": false
}
]
}'
export EMAIL="<YOUR_LOGIN_EMAIL>"
export PASSWORD="<YOUR_LOGIN_PASSPHRASE>" # BitGo recommends passing your hashed password that the SDK provides from the `preprocessAuthenticationParams` function
curl -X POST \
"https://app.bitgo-test.com/api/v2/user/login" \
-H "Content-Type: application/json" \
-d '{
"email": "'"$EMAIL"'",
"otp": "0000000", # testnet OTP is always 0000000
"password": "'"$PASSWORD"'"
}'
import { BitGoAPI } from '@bitgo/sdk-api';
const bitgo = new BitGoAPI({ env: 'test' });
const auth_res = await bitgo.authenticate({
username: "user@example.com",
password: process.env.PASS,
otp: "0000000",
});
const access_token = await bitgo.addAccessToken({
otp: "0000000",
label: "Service user long lived access Token",
"duration": 157788000,
"ipRestrict": [], // required for access tokens in production. CIDR blocks must have prefix lengths between /24 and /32 for IPv4, and between /64 and /128 for IPv6.
spendingLimits: [
{
coin: "sol",
txValueLimit: "10000000000", // 10 SOL (10 * 1e9)
},
],
scope: [
"pending_approval_update", // Update pending approvals
"profile", // View your BitGo profile
"settlement_network_read", // Enables partners engage in allocations with clients
"settlement_network_write", // Enables partners engage in allocations with clients
"trade_trade", // Make trades
"trade_view", // View trades
"wallet_approve_all", // Approve transactions for all wallets
"wallet_create", // Create wallets
"wallet_edit_all", // Edit comments for all wallets
"wallet_freeze_all", // Freeze all wallets
"wallet_manage_all", // Manage settings for all wallets (required to use webhooks)
"enterprise_view_all", // View child enterprises
"enterprise_manage_all", // Manage users and settings for child enterprises
"wallet_spend_all", // Send transactions from a wallet
"wallet_view_all", // View transactions for all wallets
]
});
console.log(access_token);
bitgo.authenticate({ username: 'user@example.com', password: password, otp: '0000000' }).then(function (response) {
var token = response.access_token;
var user = response.user;
// etc.
});
Step Result
{
"id": "68fbacf7cb97a5715c070799676efb54",
"client": "bitgo",
"user": "68928b8c66417fe09212fda389cc92c6",
"scope": [
"pending_approval_update",
"profile",
"settlement_network_read",
"settlement_network_write",
"trade_trade",
"trade_view",
"wallet_approve_all",
"wallet_create",
"wallet_edit_all",
"wallet_freeze_all",
"wallet_manage_all",
"wallet_spend_all",
"enterprise_view_all",
"enterprise_manage_all",
"wallet_view_all"
],
"created": "2025-10-24T16:44:39.108Z",
"expires": "2030-10-24T22:44:39.108Z",
"ip": "142.122.155.155",
"ipRestrict": [
"127.0.0.0"
],
"origin": "app.bitgo-test.com",
"label": "Taseen-Test-CaaS-long-access-token",
"isExtensible": false,
"organizations": [
"68928b9066417fe09212fe9965c88552"
],
"oauth": {
"oauthRequired": false
},
"token": "5c1e0147645d92ae774c2f35f823467fbfcaffea92bd420d2cbacab25686c782"
}
{
"token_type": "bearer",
"access_token": "c9e4574dea9c706377907177d2861bf17e65476587cda449c08d81024aad8f5f",
"expires_in": 86400,
"expires_at": 1710016687,
"scope": [
"user_manage",
"openid",
"openid_enterprises",
"profile",
"wallet_create",
"wallet_freeze_all",
"wallet_manage_all",
"wallet_approve_all",
"wallet_spend_all",
"wallet_edit_all",
"wallet_view_all",
"settlement_network_read",
"settlement_network_write",
"trade_view",
"trade_trade",
"portfolio_view",
"pending_approval_update",
"metamask_institutional",
"crypto_compare",
"third_party_user_lookup",
"enterprise_view_all",
"enterprise_manage_all"
],
"user": {
"id": "62ab90e06dfda30007974f0a52a12995",
"username": "nakamoto@bitcoin.com",
"enterprises": [
{
"id": "61fab88a336c18000813831c85a3f2fe",
"permissions": ["admin"],
"beneficialOwner": false
},
{
"id": "62c5ae8174ac860007aff138a2d74df7",
"permissions": ["admin"],
"beneficialOwner": false
},
{
"id": "640971cfba5a34e391cd52daaaffd4c6",
"permissions": ["admin"],
"beneficialOwner": false
},
{
"id": "5ef51a6c7c74daa7004d4e23c62022b2",
"permissions": ["admin"],
"beneficialOwner": false
}
],
"organizations": [],
"name": { "full": "Satoshi Nakamoto", "first": "Satoshi", "last": "Nakamoto" },
"email": { "email": "nakamoto@bitcoin.com", "verified": true },
"phone": { "phone": "", "verified": false },
"country": "USA",
"identity": {
"kyc": {
"failureCount": 0,
"fullyRequired": false,
"required": true,
"available": true,
"hasVideoID": false,
"passport": { "required": false, "state": "unverified" },
"isScreeningRequired": true,
"data": {
"state": "approved",
"fields": {
"country": "USA",
"firstName": "Satoshi",
"lastName": "Nakamoto",
"dob": "19XX-XX-XX"
}
},
"overallState": "approved",
"documents": { "state": "unverified" },
"residency": { "state": "unverified" }
},
"verified": false
},
"otpDevices": [
{
"id": "62ab917e4159d500079e5b836e41fba2",
"createDate": "2022-06-16T20:24:30.000Z",
"type": "totp",
"label": "Google Authenticator",
"verified": true,
"lastValidatedDate": "2023-02-06T21:14:09.469Z",
"scopes": []
}
],
"rateLimits": {},
"disableReset2FA": false,
"currency": { "currency": "USD", "bitcoinUnit": "BTC" },
"timezone": "America/Los_Angeles",
"isActive": true,
"ecdhKeychain": "xpub661MyMwAqRbcG9rxFyVx56soHRSzi6kCD1GPwd838qDJ7piucKe8JYfBS4VVLChNHZytXUkWf8sQb5jjXC1abjdS968rJEDjJrGQu3qVsCP",
"referrer": { "source": null, "campaign": null },
"forceResetPassword": false,
"allowedCoins": [],
"agreements": {
"termsOfUse": 1,
"termsOfUseAcceptanceDate": "2022-06-16T20:24:33.159Z",
"patriotAct": 0
},
"lastLogin": "2024-03-08T20:38:07.708Z",
"featureFlags": [],
"bitgoEmployee": false,
"state": "California",
"sourceVerificationRequiredForReadOnlyAccess": true
}
}
2. Add Admins to Enterprises
Before you can add admins to your organization, you must first add them as users with admin permission to your enterprise.
Endpoint: Add User to Enterprise
export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
curl -X POST \
"https://app.bitgo-test.com/api/v2/enterprise/$ENTERPRISE_ID/user" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"permission": "admin",
"usernames": [
"user1@example.com",
"user2@example.com",
"user3@example.com"
]
}'
Step Result
You sent email invitations to join your enterprise with an admin role.
{
"id": "65eb7a68d35b5e7856e94fcc1f7a48bb",
"enterprise": "62c5ae8174ac860007aff138a2d74df7",
"creator": "62ab90e06dfda30007974f0a52a12995",
"createDate": "2024-03-08T20:51:52.447Z",
"info": {
"type": "updateEnterpriseRequest",
"updateEnterpriseRequest": {
"action": "add",
"email": "user2@bitcoin.com",
"permissions": "admin",
"userId": "5f063f7e319d6800263aff885de41fa0"
}
},
"approvers": [],
"state": "pending",
"scope": "enterprise",
"userIds": [
"5543247a32d9b1f4037cfd782fc4b06d",
"621d08a634ad8a0007fcddffd7c429cc",
"627ff9325a5c1b0007c05a40d15e1522",
"62ab90e06dfda30007974f0a52a12995"
],
"approvalsRequired": 1,
"singleRunResults": [],
"resolvers": [],
"actions": [],
"resolutionOrder": []
}
Note
Ensure you select a number of admins to be video approvers. BitGo requires video approval for withdrawals that exceed $250,000 USD.
3. Fetch Organization Details
BitGo uses your organization name and organization ID to link child enterprises together.
Endpoint: Get Enterprise
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
curl -X GET \
"http://$BITGO_EXPRESS_HOST/api/v2/enterprise/$ENTERPRISE_ID" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN"
Step Result
The following abridged response highlights the organization details:
{
"id": "62c5ae8174ac860007aff138a2d74df7", // your enterprise ID
"name": "Prestige Worldwide", // your enterprise and organization name
"type": "Other",
"organizationId": "62c5ae8174ac860007aff1555ffb960d", // your organization ID
"wallets": []
}
4. Add Organization Admins
Select enterprise admins that you want to make organization admins.
To assign them, contact support@bitgo.com and request that BitGo grant organization admin access to specific enterprise admins.
Step Result
Your organization now has admins that can view balances, KYC statuses, and transaction history, create org-level webhooks, and manage users.
5. Configure Organization
Contact support@bitgo.com to configure your organization. BitGo Support works with you to configure your organization settings for your integration. BitGo uses these settings during child enterprise creation and you must configure them before moving forward.
Step Result
Your organization is now ready, you may move forward to creating child enterprises.