NAV Navbar
Logo
javascript shell

Getting Started

Overview

BitGo provides a simple and robust REST-ful API as well as a simple client javascript SDK to integrate multi-signature technology into your existing bitcoin applications and services.

The BitGo SDK enables the following operations:

Multi-Signature Wallets

The primary advantage of multi-signature wallets is the ability for multiple machines and people to work together to approve a given transaction. Without multiple signatures on a transaction, all credentials to approve a transaction must reside with a single person on a machine. If that person, or machine is compromised by an attacker, all of your bitcoin can be taken.

Traditionally, it has been so difficult to secure these single person / single machine systems, that many vendors have opted to simply use “cold storage” and move Bitcoin offline entirely.

Multi-signature wallets offer all the flexibility you would expect from a modern Bitcoin address without having to take your bitcoin offline. The BitGo API enables you to use multi-signature features in your own applications so you can harness the full flexibility of multiple users, cosigners and state-of-the-art fraud detection services to protect against loss and theft.

For more information, please read the BitGo Whitepaper.

HD Wallets

All BitGo wallets are hierarchical deterministic wallets - also known as “HD Wallets”. HD Wallets are implemented using the bitcoin BIP32 standard. As such, BitGo’s HD Wallets are built from ‘keychains’ rather than from individual keys, and offer two distinct security and privacy enhancing features:

Software Development Kit

The BitGo API provides developers with a means to create and manage multi-signature wallets, manipulate their policies and interact with the Bitcoin network. However, several sensitive operations, such as the creation of user private keys and signing of transactions, are required to be performed client-side.

For this reason, we provide and recommend the use of our Software Development Kit (SDK), which implements these client side wallet features and interfaces with our APIs. In practice, developers contemplating use of the BitGo API will likely be using both the BitGo client-side SDK as well as the BitGo REST service.

Currently, our SDK is available in Javascript and runs in either node.js or a browser. If you are using a non-supported programming language, see the “BitGo Express REST API” section of the documentation for how to setup BitGo Express, or contact us for further help.

Installing the Javascript SDK (via npm)

npm install bitgo --save

Installing the Javascript SDK (via Github)

node auth.js <testusername> <testpassword> 0000000

Importing and initializing the library

// If importing via package
var BitGoJS = require('BitGoJS/src/index.js');
var bitgo = new BitGoJS.BitGo();

// If importing from npm install bitgo
// var bitgo = require('bitgo');

bitgo.ping({}, function(err, res) {
    // do stuff here
});

To import the library, you simply require the src/index.js file. You can then initialize the SDK by doing BitGoJS.BitGo().

Parameter Value
useproduction Whether or not to connect to production. Defaults to false.

The Javascript SDK supports both promises and callbacks. If you pass in a callback as the last argument, it will return callback-style. Otherwise, a promise will be returned.

Important notes on test environment

Our SDK and examples default to the BitGo test environment which is connected to the Bitcoin TestNet. Please refer to the Test Environments section for further details.

BitGo API Endpoints

var BitGoJS = require('BitGoJS/src/index.js');

var useProduction = false;
var bitgo = new BitGoJS.BitGo(useProduction);

bitgo.ping({}, function(err, res) {
  if (err) {
    console.dir(err);
  } else {
    console.log(JSON.stringify(res, null, 4));
  }
});
TEST_ENDPOINT='https://test.bitgo.com/api/v1'
PROD_ENDPOINT='https://www.bitgo.com/api/v1'

curl "$TEST_ENDPOINT/ping"

BitGo provides two separate environments for development and production. For security reasons, all BitGo API requests are made using TLS over HTTPS.

All responses are of content-type application/json

Example Response

{
    "status": "service is ok!",
    "environment": "BitGo Test"
}

Production Environment

The BitGo production endpoint is live and used by partners and our own web application on www.bitgo.com.

Test Environment

The BitGo test environment is used by default in our examples and the SDK. It is entirely separate from BitGo production and there is no overlap in data and accounts. To use the test environment, you will need to create accounts at test.bitgo.com.

On the test environment only, you can use 0000000 in place of the one-time password (OTP) when authenticating with BitGo (for the purpose of automated tests).

This environment is connected to the Bitcoin TestNet. A block explorer to navigate the Bitcoin TestNet can be found at Smartbit. To get some TestNet coins, try a faucet or send us a message with your testnet address requesting TBTC.

BitGo Express REST API

./bitgo-express --debug --port 3080 --env test --bind localhost
BITGO_EXPRESS_HOST='localhost'
curl http://$BITGO_EXPRESS_HOST:3080/api/v1/ping

The BitGo Express REST API is a lightweight service for developers that want to take advantage of BitGo but are developing in a language without a native BitGo SDK.

BitGo Express runs as a service in your own datacenter, and handles the client-side operations involving your own keys, such as partially signing transactions before submitting to BitGo. This ensures your keys never leave your network, and are not seen by BitGo. BitGo Express can also proxy the standard BitGo REST APIs, providing a unified interface to BitGo through a single REST API.

To use BitGo Express:

./bitgo-express --debug --port 3080 --env test --bind localhost

Error Handling

Example JSON Error

{
  "status":  "400 Bad Request",
  "error": "missing user name"
}

All errors follow general REST principles. Included in the body of any error response (e.g. non-200 status code) will be an error object of the form:

Parameter Value
status The HTTP error status returned
error The detailed description of the error

User Authentication

BitGo’s authentication is via the “Authorization” header, which allows the caller to specify an access token.

Access tokens are used to maintain a session and are created via the password login (requires OTP) or Oauth login paths. Typical access tokens are locked to a single IP-address and valid for 60 minutes. After expiry the user must re-authenticate.

For API calls that spend funds, a valid session token is not sufficient. To access these API calls, the session must be explicitly unlocked using the Unlock API, using an additional OTP. A single unlock call enables the user to do one transaction of any size (still subject to wallet policy), or any number of transactions up to an internal BitGo-managed quota.

Alternatively, custom access tokens can be created bound to specific scopes for expiration time, permission level, and spending amount.

API Access Tokens

ACCESS_TOKEN='DeveloperAccessToken'
curl -X GET -H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{}' \
-H "Content-Type: application/json" \
https://test.bitgo.com/api/v1/user/session
var bitgo = new BitGoJS.BitGo({accessToken:'DeveloperAccessToken'});
bitgo.session({}, function callback(err, session) {
  if (err) {
    // handle error
  }
  console.dir(session);
});

For the purposes of automation, developers can request long-lived access tokens with a custom expiration time that are already unlocked for a specified spending limit.

Manually via Settings

  1. Access the BitGo dashboard and head into the “Settings” page.
  2. Click on the “Developer” tab.
  3. You can now create a long-lived access token.

The token will come unlocked by default with your specified spending limit. Do not attempt to unlock the token again via API as this will reset the unlock.

Access tokens via API

Alternatively, custom access tokens can be requested via the API command addAccessToken. This call requires an OTP, a label, and an authorization scope. It may specify an expiration time, an IP whitelist, and a spending limit.

TOKEN Parameters

Parameter Type Required Description
label string Yes The label identifying the token, e.g. for subsequent revocation.
otp string Yes The 2-factor-authentication otp code.
duration number No The duration in seconds for which the token will be valid. If this parameter is not set, the duration defaults to ten years.
txValueLimit number No The total spending allowance permitted by this token given in satoshis. Do not attempt to unlock the token via API as this will reset the limit.
ipRestrict array of strings No A whitelist of IP addresses that may use the token.
scope array of strings Yes The list of privileges authorized by this token.

Current User Profile

curl -X GET -H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/user/me
bitgo.me({}, function callback(err, user) {
  if (err) {
    // handle error
  }
  // etc
});

Get information about the current authenticated user.

HTTP Request

GET /api/v1/user/me

Example User Model response

{
  "user": {
    "id": "53532a4b43fd69a42f000005f0a2ed87fd8b020040739beb513524b5",
    "isActive": true,
    "name": {
      "first": "Jane",
        "full": "Jane Doe",
        "last": "Doe"
    },
    "username": "janedoe@bitgo.com"
  }
}

Response

Returns a User Model object for the currently authenticated user.

Login

Get a token for first-party access to the BitGo API. First-party access is only intended for users accessing their own BitGo accounts. For 3rd party access to the BitGo API on behalf of another user, please see Partner Authentication.

EMAIL="janedoe@bitgo.com"
PASSWORD="mypassword"
HMAC=`echo -n "$PASSWORD" | openssl dgst -sha256 -hmac "$EMAIL" | sed 's/^.* //' `

curl -X POST \
-H "Content-Type: application/json" \
-d "{\"email\": \"$EMAIL\", \"password\": \"$HMAC\", \"otp\": \"0000000\"}" \
https://test.bitgo.com/api/v1/user/login

Note: The rest of the shell examples the share variable assume the shell variable ACCESS_TOKEN contains the access token.
var useTestnet = false;
var bitgo = new Bitgo(useTestnet);
bitgo.authenticate({ username: user, password: password, otp: otp }, function callback(err, response) {
  if (err) {
    // handle error
  }
  var token = response.token;
  var user = response.user;
  // etc
});

HTTP Request

POST /api/v1/user/login

BODY Parameters

Parameter Type Required Description
email string Yes The email address of the user
password string Yes The password of the user
otp string Yes The 2-factor-authentication token (Authy token).
extensible boolean No True if the session is supposed to be extensible beyond a one-hour duration.

Example Response

{
    "access_token": "3fe0bf671c943af5ee3b739d2b17ffced7fdde62",
    "expires_in": 3600,
    "token_type": "bearer",
    "user": {
        "id": "53532a4b43fd69a42f000005f0a2ed87fd8b020040739beb513524b5",
        "isActive": true,
        "name": {
            "first": "Jane",
            "full": "Jane Doe",
            "last": "Doe"
        },
        "username": "janedoe@bitgo.com"
    }
}

Response

Returns a token for use with the API.

The token must be added as a HTTP header to all API calls in the HTTP “Authorization” header:

Authorization: Bearer <your token goes here>

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.

Logout

Logout of the BitGo service.

curl -X GET -H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/user/logout
bitgo.logout({}, function callback(err) {
  if (err) {
    // handle error
  }
  // the user is now logged out.
});

HTTP Request

GET /api/v1/user/logout

QUERY Parameters

None

Response

None

Session Information

Get information about the current session access token

curl -X GET -H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{}' \
-H "Content-Type: application/json" \
https://test.bitgo.com/api/v1/user/session
bitgo.session({}, function callback(err, session) {
  if (err) {
    // handle error
  }
  console.dir(session);
});

Example response

{ "client": "bitgo",
  "user": "5458141599f715232500000530a94fd2",
  "scope":
   [ "user_manage",
     "openid",
     "profile",
     "wallet_create",
     "wallet_manage_all",
     "wallet_approve_all",
     "wallet_spend_all",
     "wallet_edit_all",
     "wallet_view_all" ],
  "expires": "2015-01-21T02:18:11.534Z",
  "origin": "test.bitgo.com",
  "unlock":
      { "time": "2015-01-21T01:20:25.366Z",
        "expires": "2015-01-21T01:30:25.366Z",
        "txCount": 0,
        "txValue": 0
      }
}

HTTP Request

GET /api/v1/user/session

QUERY Parameters

None

Response

Field Description
client OAuth client ID where the user token was obtained
user BitGo user ID
expires Timestamp until which the login session will last
scope List of allowed privileges for this session token
origin Origin hostname where token was created, if the session was initiated in the browser
unlock Available if session is unlocked. Shows number of transactions and expiry time of the unlock

Send OTP

Sends the one time password (2nd Factor Auth) token to the user, which can be used for login / unlock.

curl -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{}' \
-H "Content-Type: application/json" \
https://test.bitgo.com/api/v1/user/sendotp
bitgo.sendOTP({forceSMS: true}, function callback(err) {
  if (err) {
    // handle error
  }
  // etc
});

HTTP Request

POST /api/v1/user/sendotp

BODY Parameters

Name Type Required Description
forceSMS boolean No Use SMS to send the OTP to the user, even if they have Authy set up

Response

None

Unlock

Unlock the current session, which is required for certain other sensitive API calls.

curl -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{"otp": "0000000"}' \
-H "Content-Type: application/json" \
https://test.bitgo.com/api/v1/user/unlock
bitgo.unlock({otp: otp}, function callback(err) {
  if (err) {
    // handle error
  }
  // etc
});

HTTP Request

POST /api/v1/user/unlock

BODY Parameters

Parameter Type Required Description
otp string Yes An Authy OTP code for the account
duration number No Desired duration of the unlock in seconds (default=600, max=3600)

Response

None

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect
401 Unauthorized The authentication parameters did not match, or OTP code was incorrect

Lock

Re-lock the current session.

curl -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/user/lock \
bitgo.lock({}, function callback(err) {
  // ...
});

HTTP Request

POST /api/v1/user/lock

BODY Parameters

None

Response

None

Errors

Response Description
401 Unauthorized The authentication parameters did not match

Partner Authentication

3rd party applications using the BitGo API use OAuth to authenticate through BitGo. Please contact BitGo for a partner ID and more information.

Keychains

All BitGo wallets are created using keychains. Unlike traditional bitcoin keys that use independent single ECDSA key pairs, a keychain derives any number of key pairs from a single master private key. This allows the user to retain a single private key, but generate an infinite number of public keys. BitGo uses standard BIP32 extended HD keys to keep your bitcoin more private and secure.

To make wallet creation simple, BitGo maintains a list of keychains for each user. By default, a new keychain is created for each wallet. However, the user may chose to use one keychain for multiple BitGo Wallets in order to be able to rely on a single master private key.

There are two types of keychains:

All keychains are identified by their xpub. For convenience, each keychain may have a label.

Before creating your first wallet, you must create keychains to use with that wallet.

List Keychains

curl -X GET -H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/keychain
var keychains = bitgo.keychains();
keychains.list({}, function callback(err, keychains) {
  if (err) {
    // handle error
  }
  console.dir(keychains);
});

Get the list of public keychains for the user

HTTP Request

GET /api/v1/keychain

Example Keychain Model response

{
    "keychains": [
        {
            "xpub": "xpub661MyMwAqRbcEnCqci8PwkTJgBPbfU54z5rS44bBFtm23hudhYaf73e5Jt8e3JhYYizyFpFcXb4Ahd7wBHmoDFqf2GTGZFaHSC1JyJoURpw"
        },
        {
            "xpub": "xpub661MyMwAqRbcFHjomRhjJybA7rh75j4Cn9Hz4EPG9FUumurJFVbWVgqeDCkCJtnoB5zBHvqsSoi4ArVUKQszzfzuAk9L3LwLZKKQ4RQe8k3"
        },
        {
            "xpub": "xpub69gHkWcECsrNhcpkPBvvpHq8uX4AwYWcciVZAkvdaKNEj2Cr2mAkUzyQ2X4f9W8fBTt6jp6rvAwUDym4GypkApJZUgKt81vpjyYVs4RDvE8",
            "isBitGo": true
        }
    ],
    "start": 0,
    "count": 3,
    "total": 3
}

QUERY Parameters

Parameter Type Required Description
skip number No The starting index number to list from. Default is 0.
limit number No Max number of results to return in a single call (default=100, max=500)

Response

Returns an array of Keychain Model objects.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.

Create Keychain

Available only as a local method (BitGo Express)

curl -X POST http://$BITGO_EXPRESS_HOST:3080/api/v1/keychain/local
var keychains = bitgo.keychains();
var keychain = keychains.create();

console.dir(keychain);

Example response

  {
    "xpub": "xpub661MyMwAqRbcFdEUWdhDhgKKQ9tQzLSuqZzVM2AZf9TiijPMD84tPYmemZcQosg63SZit3jGQpCDsbbeXPv7A3aT1phPaBgAWQWKwFUioPR",
    "xprv": "xprv9s21ZrQH143K39A1QcADLYNar83vasj4UM4tYdkx6ovjqw4CfakdqkTAvFrY8BoR8TFTCYShYJ3XjZCicvyuavmYjPLVbmASmHrz144nVCy"
  }

Local client-side function to create a new keychain.

Optionally, a seed may be provided as the only parameter. If provided the seed is used to deterministically create your keychain. The seed should be an array of numbers with at least 32 elements. Calling this function with the same seed will generate the same BIP32 keychain.

Returns an object containing the xprv and xpub for the new chain. The created keychain is not known to the BitGo service. To use it with the BitGo service, use the Keychains.Add API.

For security reasons, it is highly recommended that you encrypt and destroy the original xprv immediately to prevent theft.

HTTP Request

This method is only available client-side.

Method Parameters

Parameter Type Required Description
seed array of numbers No Array of numbers with at least 32 elements.

Response

Response Description
xpub BIP32 extended public key.
xprv BIP32 extended private key in /unencrypted/ form. It is highly recommended to encrypt the xprv before storage and then unencrypted destroy the original to prevent theft.

Add Keychain

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{"xpub": "xpub661MyMwAqRbcGn6m3YB7CJ2ToyUJYEsBpCc2UDJP9s3hzFif9dKucLotrJBbLgNqojM4q4Sddweka1WG2NvMccYyo3SpnfRrTvMuXUTpHwC"}' \
https://test.bitgo.com/api/v1/keychain
var data = {
  "xpub": "xpub.....",
  "encryptedXprv": "<encrypted xprv goes here>" // optional, provide it for the user key
};

bitgo.keychains().add(data, function callback(err, keychain) {
  if (err) {
    // handle error
  }
  // etc
});

Registers a new keychain for the user. You must supply at least the public key. An encrypted private key may be uploaded, but it will be treated as opaque to the server.

The purpose in providing an encrypted private key with the address is so users will be able to access their keys securely whenever they are connected to BitGo without the burden of storing it. It is highly recommended that you encrypt any private keys stored at the server with a strong password from the user. Encryption must be performed on the client. For convenience, you can use BitGo’s encrypt/decrypt functions, but you can use any encryption you wish.

HTTP Request

POST /api/v1/keychain

BODY Parameters

Parameter Type Required Description
xpub string Yes The BIP32 xpub for this keychain
encryptedXprv string No The encrypted, BIP32 xprv for this keychain

Example Keychain Model response

{
  "xpub": "xpub661MyMwAqRbcGn6m3YB7CJ2ToyUJYEsBpCc2UDJP9s3hzFif9dKucLotrJBbLgNqojM4q4Sddweka1WG2NvMccYyo3SpnfRrTvMuXUTpHwC",
  "encryptedXprv": "<encrypted data here>",
  "path": "m"
}

Response

Returns a Keychain Model object.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match, or unlock is required.

Create BitGo Keychain

curl -X POST \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/keychain/bitgo
bitgo.keychains().createBitGo({}, function callback(err, keychain) {
  if (err) {
    // handle error
  }
  console.dir(keychain);
});

Creates a new keychain on BitGo’s servers and returns the public keychain to the caller.

HTTP Request

POST /api/v1/keychain/bitgo

BODY Parameters

None.

Example Keychain Model response

{
  "xpub": "xpub661MyMwAqRbcGzVAChrAGb6MYDrAXndUC7h8T7AF8UhfbjS7Au7UKTXmVXaFasQPdfmnUjccreRTMrW7kTmjzwMqVrTHNAFs8M3CXTJpcnL",
  "isBitGo": true,
  "path": "m"
}

Response

Returns a Keychain Model object.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match, or unlock is required.

Create Backup Keychain

curl -X POST \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "{ \"provider\": \"lastkeysolutions\" }" \
https://test.bitgo.com/api/v1/keychain/backup
bitgo.keychains().createBackup({ provider: 'lastkeysolutions' }, function callback(err, keychain) {
  console.dir(keychain);
});

Creates a new backup keychain on a third party specializing in key recovery services. This keychain will be stored on the third party service and usable for recovery purposes only.

HTTP Request

POST /api/v1/keychain/backup

BODY Parameters

Parameter Type Required Description
provider string Yes name of the KRS or backup key provider to use

Example Keychain Model response

{
  "xpub": "xpub661MyMwAqRbcGzVAChrAGb6MYDrAXndUC7h8T7AF8UhfbjS7Au7UKTXmVXaFasQPdfmnUjccreRTMrW7kTmjzwMqVrTHNAFs8M3CXTJpcnL",
  "path": "m"
}

Response

Returns a Keychain Model object.

Get Keychain

XPUB=xpub661MyMwAqRbcGn6m3YB7CJ2ToyUJYEsBpCc2UDJP9s3hzFif9dKucLotrJBbLgNqojM4q4Sddweka1WG2NvMccYyo3SpnfRrTvMuXUTpHwC

curl -X POST \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/keychain/$XPUB
bitgo.keychains().get({xpub: xpub}, function callback(err, keychain) {
  console.dir(keychain);
});

Lookup a keychain by xpub

HTTP Request

POST /api/v1/keychain/:xpub

URL Parameters

Parameter Type Required Description
xpub string Yes The BIP32 xpub to lookup

Example Keychain Model response

{
  "xpub": "xpub661MyMwAqRbcGn6m3YB7CJ2ToyUJYEsBpCc2UDJP9s3hzFif9dKucLotrJBbLgNqojM4q4Sddweka1WG2NvMccYyo3SpnfRrTvMuXUTpHwC",
  "encryptedXprv": "<client-encrypted data here>",
  "path": "m"
}

Response

Returns a Keychain Model object.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match, or unlock is required.
404 Bad Request The xpub was not found

Update Keychain

XPUB=xpub661MyMwAqRbcGn6m3YB7CJ2ToyUJYEsBpCc2UDJP9s3hzFif9dKucLotrJBbLgNqojM4q4Sddweka1WG2NvMccYyo3SpnfRrTvMuXUTpHwC

curl -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{"encryptedXprv": "my encrypted data"}' \
https://test.bitgo.com/api/v1/keychain/$XPUB
var params = {
  xpub: xpub,
  encryptedXprv: "<encrypted xprv goes here>"
};
bitgo.keychains().update(params, function callback(err, keychain) {
  // handle error, do something with keychain
  console.dir(keychain);
});

Update a keychain. This is used if you wish to store a new version of the xprv (for example, if you changed the password used to encrypt the xprv).

HTTP Request

PUT /api/v1/keychain/:xpub

URL Request

Parameter Type Required Description
xpub string Yes The xpub of the keychain to be updated.

BODY Parameters

Parameter Type Required Description
xpub string Yes The xpub of the keychain to be updated.
encryptedXprv string No A new encrypted, BIP32 xprv for this keychain

Example Keychain Model response

{
  "xpub": "xpub661MyMwAqRbcGzVAChrAGb6MYDrAXndUC7h8T7AF8UhfbjS7Au7UKTXmVXaFasQPdfmnUjccreRTMrW7kTmjzwMqVrTHNAFs8M3CXTJpcnL",
  "encryptedXprv": "<encrypted data here>",
  "path": "m"
}

Response

Returns a Keychain Model object.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match, or unlock is required.
404 Not Found The xpub was not found

Wallets

All BitGo Wallets are multi-signature, hierarchical, deterministic wallets. Multi-signature wallets are comprised of N keys, and require M keys to sign a transaction before the transaction is valid. This is called an M-of-N wallet.

BitGo currently supports only 2-of-3 wallets. We use a policy layer to support m-of-n permission models.

To create a wallet, three keychains must be provided. The first two keychains are provided by the user; the last must be a BitGo keychain. While BitGo can see the public portion of the first two keys, BitGo never has access to the private portion of these keys and therefore cannot conduct transactions without the user. BitGo’s single key is not sufficient to sign transactions, and BitGo will only use this key in accordance with the policies set by the user.

List Wallets

curl -X GET \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet
var wallets = bitgo.wallets();
wallets.list({}, function callback(err, wallets) {
// handle error, do something with wallets
for (id in wallets) {
  var wallet = wallets[id].wallet;
  console.log(JSON.stringify(wallet, null, 4));
}
});

Get the list of wallets for the user

HTTP Request

GET /api/v1/wallet

Example response

{
    "wallets": [
        {
            "admin": {},
            "id": "2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf",
            "isActive": true,
            "label": "Example wallet",
            "permissions": "admin,spend,view",
            "private": {
                "keychains": [
                    "... truncated for clarity ..."
                ]
            },
            "spendingAccount": true,
            "type": "safehd"
        },
        {
            "admin": {},
            "id": "2MyWgQ3PMAWPenJnHJUPpVjFDLHhaPkZCz5",
            "isActive": true,
            "label": "My wallet",
            "permissions": "admin,spend,view",
            "private": {
                "keychains": [
                    "... truncated for clarity ..."
                ]
            },
            "spendingAccount": true,
            "type": "safehd"
        }
        ...
    ]
    "start": 0,
    "count": 25,
    "total": 36
}

QUERY Parameters

Parameter Type Required Description
skip number No The starting index number to list from. Default is 0.
limit number No Max number of results to return in a single call (default=25, max=250)
enterpriseId string No Filter list by Enterprise ID

Response

Returns an array of Wallet Model objects.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.

Add Wallet

XPUB_USER=xpub661MyMwAqRbcF8BFQAaLnkkDar6uHQZn9cvzPX5qdfUL42gyts7YeYHZgWvNVjcUDP8BEDMduMBhtKLnVAKaT3sW1g14xnv29w5D3ts8LVd

XPUB_BACKUP=xpub661MyMwAqRbcF3MqMfvo7swQwRzEVRyCPry4rmp346Dv6zR4CNFzrtu4bMpeNazCNNa9p3p5z56svzRcnF9LEm3Ha2zSgq2cLrperm7z4oh

XPUB_BITGO=xpub661MyMwAqRbcG96fDEgYGmjKwdQvxG38rr9gTcqszjdU1s5kjLkTD8pTDxYf4ECrkVbGdpTktuc2BwUR1YKvTdNu5U8mxnDp68QAnvdy1WE

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"label\": \"My Test Wallet\", \"m\": 2, \"n\": 3, \"keychains\": [{\"xpub\": \"$XPUB_USER\"}, {\"xpub\": \"$XPUB_BACKUP\"}, {\"xpub\": \"$XPUB_BITGO\"}] }" \
https://test.bitgo.com/api/v1/wallet
var data = {
  "label": "My Wallet",
  "m": 2,
  "n": 3,
  "keychains": [
    { "xpub": "xPub of user keychain (may be created with keychains.create)"},
    { "xpub": "xPub of backup keychain (may be created with keychains.create or keychains.createBackup)"},
    { "xpub": "xPub of BitGo keychain (created with keychains.createBitGo)"}
  ]
};
bitgo.wallets().add(data, function callback(err, wallet) {
  if (err) {
    // handle error
  }
  console.dir(wallet);
});

This API creates a new wallet for the user. The keychains to use with the new wallet must be registered with BitGo prior to using this API.

BitGo currently only supports 2-of-3 (e.g. m=2 and n=3) wallets. The third keychain, and only the third keychain, must be a BitGo key. The first keychain is by convention the user key, with it’s encrypted xpriv stored on BitGo.

BitGo wallets currently are hard-coded with their root at m/0/0 across all 3 keychains (however, older legacy wallets may use different key paths). Below the root, the wallet supports four chains of addresses, 0 and 1, as well as 10 and 11. The 0-chain is for external receiving addresses, while the 1-chain is for internal (change) addresses. The 10-chain is for external SegWit receiving addresses, while the 11-chain is for internal SegWit (change) addresses.

The first receiving address of a wallet is at the BIP32 path m/0/0/0/0, which is also the ID used to refer to a wallet in BitGo’s system. The first change address of a wallet is at m/0/0/1/0. Correspondingly, the first SegWit receiving address of a wallet is at m/0/0/10/0, and the first SegWit change address of a wallet is at m/0/0/11/0.

HTTP Request

POST /api/v1/wallet

BODY Parameters

Parameter Type Required Description
label string Yes A label for this wallet
m number Yes The number of signatures required to redeem (must be 2)
n number Yes The number of keys in the wallet (must be 3)
keychains array Yes An array of n keychain xpubs to use with this wallet; last must be a BitGo key
enterprise string No Enterprise ID to create this wallet under.
disableTransactionNotifications boolean No Set to true to prevent wallet transaction notifications.

Example response

{
  "id":"2MsajnHwkzQvggkb6Zbi7kaLMcpeCko4BKB",
  "label":"My Test Wallet",
  "isActive":true,
  "private":{
    "keychains":[
      {
        "xpub":"xpub661MyMwAqRbcF8BFQAaLnkkDar6uHQZn9cvzPX5qdfUL42gyts7YeYHZgWvNVjcUDP8BEDMduMBhtKLnVAKaT3sW1g14xnv29w5D3ts8LVd",
        "path":"/0/0"
      },
      {
        "xpub":"xpub661MyMwAqRbcF3MqMfvo7swQwRzEVRyCPry4rmp346Dv6zR4CNFzrtu4bMpeNazCNNa9p3p5z56svzRcnF9LEm3Ha2zSgq2cLrperm7z4oh",
        "path":"/0/0"
      },
      {
        "xpub":"xpub661MyMwAqRbcG96fDEgYGmjKwdQvxG38rr9gTcqszjdU1s5kjLkTD8pTDxYf4ECrkVbGdpTktuc2BwUR1YKvTdNu5U8mxnDp68QAnvdy1WE",
        "path":"/0/0"
      }
    ]
  },
  "permissions":"admin,spend,view",
  "admin":{},
  "spendingAccount":true,
  "confirmedBalance":0,
  "balance":0,
  "pendingApprovals":[]
}

Response

Returns a Wallet Model object.

The path attribute gives the last two parts of the full path, so e.g. the fifteenth SegWit change address would be /11/15.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.
406 Not acceptable One of the keychains provided was not acceptable.

Get Wallet

WALLET=2N76BgbTnLJz9WWbXw15gp6K9mE5wrP4JFb

curl -X GET \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLET
var wallets = bitgo.wallets();
var data = {
  "type": "bitcoin",
  "id": "2N76BgbTnLJz9WWbXw15gp6K9mE5wrP4JFb",
};
wallets.get(data, function callback(err, wallet) {
  if (err) {
    // handle error
  }
  console.dir(wallet);
});

var wallets = bitgo.wallets();
var data = {
  "type": "bitcoin",
  "id": "2My4uGbvFoBvBtLpADVTTai1w6roxQafJki",
};
wallets.get(data, function callback(err, wallet) {
  if (err) {
    // handle error
  }
  // Use wallet object here
  console.dir(wallet);
  console.dir(wallet.balance());
});

Lookup wallet information, returning the wallet model including balances, permissions etc. The ID of a wallet is its first receiving address (/0/0)

HTTP Request

GET /api/v1/wallet/:id

Example response

{
  "_id": "57bb66f07cf7c6da4f2956011df25aa6",
  "id": "2N6GYGJQSLZyXSgviEmdhWd5jWHoDcSKAfJ",
  "label": "TestNet Wallet",
  "isActive": true,
  "type": "safehd",
  "freeze": {},
  "adminCount": 1,
  "disableTransactionNotifications": false,
  "private": {
    "keychains": [
      {
        "xpub": "xpub661MyMwAqRbcGDNuXKbT5Uyeth3yNYQAJY4KksbDSLdHgXdh2q5bjH6aQzSRQ4nPjanfWrkE8LVa1Svet4Nh5EnvA7Rh52tfbC4RjFHAwMZ",
        "path": "/0/0",
        "params": {
          "pubKey": "02b910dc08af71a28648e4e1efd3bb851587aad7b87fd0ba73ffc50467d0b85b75",
          "chainCode": "a7e22c7bb28727f49ccf1c04b4371a8d79cf286ee6a018fb8ea4bc454023e498",
          "depth": 0,
          "index": 0,
          "parentFingerprint": 0
        }
      },
      {
        "xpub": "xpub6GiRC55CRwu5aiyDHeGFdAqUJ5ieMFsEdJ3BrjufgZNarq1FdcB3uGcqYEAxdsiegXypW2RjfBCmcdwJhRbcCNHZFonmasetQdwUNZHbrus",
        "path": "/0/0",
        "params": {
          "pubKey": "03e21d7fc8383ab067771463b55991480d2b133c96233d6182e0fe779118762c3f",
          "chainCode": "d4d37ed900e592dac8f5ac3ea546d4a37ed5fe6854526d482bde2109a6808b5c",
          "depth": 5,
          "index": 176980,
          "parentFingerprint": 2966462100
        }
      },
      {
        "xpub": "xpub661MyMwAqRbcGLsjvczmhk2twZfwfhZx16ai3TXf32QcpMfApjKcaTEnLt4oCz4HTss6CQ8gQfQKSyr8ca4s1Xme8FrsPjsNwEo2XBVdJSQ",
        "path": "/0/0",
        "params": {
          "pubKey": "0256002e463c6cde950d0f8319b8c3d98e85e49ea626fff60760db6ff6b8bade52",
          "chainCode": "b4dddf8762d82896a1c8ee63ae2dcfed45037e73dcb8609bb0baba997fc7e2f1",
          "depth": 0,
          "index": 0,
          "parentFingerprint": 0
        }
      }
    ]
  },
  "canSendInstant": true,
  "permissions": "admin,spend,view",
  "admin": {
    "policy": {
      "id": "57d73dedd1187a4a7b2bdeebedddcd6b",
      "version": 2,
      "date": "2016-09-13T00:08:30.661Z",
      "rules": [
        {
          "id": "my velocity limit",
          "type": "velocityLimit",
          "action": {
            "type": "getApproval"
          },
          "condition": {
            "amount": 10000000,
            "timeWindow": 86400,
            "groupTags": [
              ":tag"
            ],
            "excludeTags": []
          }
        }
      ]
    },
    "users": [
      {
        "user": "5624ade20e86bd04483895223800a967",
        "permissions": "admin,spend,view"
      }
    ]
  },
  "tags": [],
  "approvalsRequired": 1,
  "spendingAccount": true,
  "pendingApprovals": [],
  "balance": 39564772124,
  "instantBalance": 39564772124,
  "spendableConfirmedBalance": 39564772124,
  "confirmedBalance": 39564772124,
  "spendableBalance": 39564772124,
  "sent": 0,
  "received": 39564772124,
  "unconfirmedSends": 0,
  "unconfirmedReceives": 0
}

QUERY Parameters

Parameter Type Required Description
id string Yes The id of the wallet to get.

Response

Returns a Wallet Model object.

Field Description
id id of the wallet (also the first receiving address)
label the wallet label, as shown in the UI
index the index of the address within the chain (0, 1, 2, …)
private contains summarised version of keychains
permissions user’s permissions on this wallet
admin policy information on the wallet’s administrators
pendingApprovals pending transaction approvals on the wallet
confirmedBalance the confirmed balance
balance the balance, including transactions with 0 confirmations
canSendInstant boolean indicating if wallet is eligible to send instant transactions backed by BitGo’s guarantee against double spends

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.
404 Not Found The wallet was not found
406 Not acceptable One of the keychains provided were not acceptable.

Create Wallet With Keychains

Available only as a local method (BitGo Express)
Advanced users should consider the Create Wallet API.

WALLETPASSPHRASE='newverylongishsecretivepassword'
LABEL='nicenewpurse'

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"passphrase\": \"$WALLETPASSPHRASE\", \"label\": \"$LABEL\", \"backupXpub\": \"$BACKUPXPUB\" }" \
http://$BITGO_EXPRESS_HOST:3080/api/v1/wallets/simplecreate
var data = {
  "passphrase": password,
  "label": label,
  "backupXpubProvider": "keyternal"
}

bitgo.wallets().createWalletWithKeychains(data, function(err, result) {
  if (err) { console.dir(err); throw new Error("Could not create wallet!"); }
  console.dir(result.wallet.wallet);
  console.log("User keychain encrypted xPrv: " + result.userKeychain.encryptedXprv);
  console.log("Backup keychain xPub: " + result.backupKeychain.xPub);
});

This method is available on the client SDK as an easy way to create a wallet. It performs the following:

  1. Creates the user keychain and the backup keychain
  2. Encrypts the user keychain
  3. Uploads the encrypted user and backup keychains to BitGo
  4. Creates the BitGo key on the service
  5. Creates the wallet on BitGo with the 3 public keys above

BitGo Instant Wallets

By default, this method will create backup keychains locally. To create a wallet that can be used to send BitGo Instant, use the backupXpubProvider parameter to specify a KRS, e.g. “keyternal”.

HTTP Request

This method is only available client-side.

Method Parameters

Name Type Required Description
passphrase string Yes The passphrase that will be used to encrypt the user keys of the wallet before sending it to BitGo
label string Yes A label for this wallet
backupXpub string No Public key of a backup keychain, created on another device, such that no 2 private keys are ever on the same machine. See also backupXpubProvider as an option to have your key hosted remotely.
backupXpubProvider string No Create a backup xPub on your KRS of choice, e.g. “keyternal”. This will make the wallet BitGo Instant compatible.
enterprise string No Enterprise ID to create this wallet under.
disableTransactionNotifications boolean No Set to true to prevent wallet transaction notifications..

Example response

{ "id": "2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf",
 "label": "testwallet",
 "isActive": true,
 "type": "safehd",
 "private": { "keychains": [{}] },
 "permissions": "admin,spend,view",
 "admin": {},
 "spendingAccount": true,
 "confirmedBalance": 0,
 "balance": 0,
 "pendingApprovals": [] }
User keychain encrypted xPrv: {"iv":"v2aVEG5A8VwnI+ewS..."}
Backup keychain encrypted xPrv: {"iv":"vNOUQpzUmHNPwKt..."}

Response

Response Description
wallet the wallet model object
userKeychain the newly created user keychain, which has an encrypted xprv stored on BitGo - back this up
backupKeychain the newly created backup keychain - back this up

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.
406 Not acceptable One of the keychains provided were not acceptable.

Wallet Operations - Basic

Each wallet is comprised of many addresses, and each address can be used to receive Bitcoin. The Wallet API provides helpful interfaces for interacting with a user’s wallets.

Create Address

Creates a new address for an existing wallet. BitGo wallets consist of two independent chains of addresses, designated 0 and 1. The 0-chain is typically used for receiving funds, while the 1-chain is used internally for creating change when spending from a wallet. It is considered best practice to generate a new receiving address for each new incoming transaction, in order to help maximize privacy.

BitGo SDK 4.0.0 and later use SegWit addresses by default. SegWit addresses are derived on 10-chain for SegWit receive addresses and 11-chain for SegWit change addresses.

CHAIN=0
WALLETID="3GonoRKFSzcqJCktZPA2NHDd3jJoH4154o"
curl -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLETID/address/$CHAIN
var id = '2My4uGbvFoBvBtLpADVTTai1w6roxQafJki';
bitgo.wallets().get({ "id": id }, function callback(err, wallet) {
  if (err) {
    throw err;
  }
  wallet.createAddress({ "chain": 0 }, function callback(err, address) {
    console.dir(address);
  });
});

HTTP Request

POST /api/v1/wallet/:walletId/address/:chain

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID of the wallet
chain number Yes 0, 1, 10 or 11 (10 or 11 for SegWit)
number Yes 10 or 11 for SegWit

Example response

{
  "address": "3GonoRKFSzcqJCktZPA2NHDd3jJoH4154o",
  "chain": 0,
  "index": 42,
  "path": "/0/42",
  "redeemScript": "522102d83bba35a8022c247b645eed6f81ac41b7c1580de550e7e82c75ad63ee9ac2fd2103aeb681df5ac19e449a872b9e9347f1db5a0394d2ec5caf2a9c143f86e232b0d92103d728ad6758d4784effea04d47baafa216cf474866c2d4dc99b1e8e3eb936e73053ae"
}

Response

Returns a new bitcoin address which is associated with the wallet.

Field Description
address the chained address
chain the chain (0, 1, 10 or 11)
index the index of the address within the chain (0, 1, 2, …)
path the BIP32 path of the address relative to the wallet root
redeemScript the redeemScript for the address

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.
403 Forbidden The wallet is not a multi-sig BIP32 (SafeHD) wallet
404 Not Found The wallet was not found
406 Not acceptable One of the keychains provided were not acceptable.

Send Coins to Address

var destinationAddress = '2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD';
var amountSatoshis = 0.1 * 1e8; // send 0.1 bitcoins
var walletPassphrase = 'incorrect horse battery stable' // replace with wallet passphrase

bitgo.wallets().get({id: walletId}, function(err, wallet) {
  if (err) { console.log("Error getting wallet!"); console.dir(err); return process.exit(-1); }
  console.log("Balance is: " + (wallet.balance() / 1e8).toFixed(4));

  wallet.sendCoins({ address: destinationAddress, amount: amountSatoshis, walletPassphrase: walletPassphrase }, function(err, result) {
    if (err) { console.log("Error sending coins!"); console.dir(err); return process.exit(-1); }

    console.dir(result);
  });
});
Available only as a local method (BitGo Express)
Advanced users should consider the Send Transaction API.

WALLETID='2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa'
DESTINATIONADDRESS='2N9JiEUYgRwKAw6FfnUca54VUeaSYSL9qqG'
AMOUNT=1000000
WALLETPASSPHRASE='password'

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"address\": \"$DESTINATIONADDRESS\", \"amount\": $AMOUNT, \"walletPassphrase\": \"$WALLETPASSPHRASE\" }" \
http://$BITGO_EXPRESS_HOST:3080/api/v1/wallet/$WALLETID/sendcoins

Easiest way to send coins from your BitGo wallet to a destination Bitcoin address.

This method will perform the following on the client:

It will send the partially signed transaction to BitGo servers for processing, where we will:

Parameters

Name Type Required Description
address string Yes Destination bitcoin address
amount number Yes Amount to be sent (in Satoshis), e.g. 0.1 * 1e8 for a tenth of a Bitcoin
walletPassphrase string Yes Passphrase for the wallet, used to decrypt the encrypted user key (on client)
fee number No The absolute fee in satoshis to be paid to the Bitcoin miners. HIGHLY recommended to leave undefined and use ‘feeTxConfirmTarget’ instead for dynamic fee estimates.
message string No User-provided string (this does not hit the blockchain)
feeRate number No The fee in satoshis /per kB/ of transaction size to be paid to the Bitcoin miners. HIGHLY recommended to leave undefined and use ‘feeTxConfirmTarget’ instead for dynamic fee estimates.
feeTxConfirmTarget number No Calculate fees per kilobyte, targeting transaction confirmation in this number of blocks. Default: 2, Minimum: 1, Maximum: 1000.
maxFeeRate number No An upper bound for the fee rate in satoshi per kB. Useful to set as a safety measure when using dynamic fees.
minUnspentSize number No Minimum amount in satoshis for an unspent to be considered usable. Defaults to 5460 (to combat tx dust spam).
minConfirms number No only choose unspent inputs with a certain number of confirmations. We recommend setting this to 1 and using enforceMinConfirmsForChange.
enforceMinConfirms ForChange boolean No Defaults to false. When constructing a transaction, minConfirms will only be enforced for unspents not originating from the wallet.
sequenceId string No A custom user-provided string that can be used to uniquely identify the state of this transaction before and after signing
instant boolean No set to true to request that the transaction be sent with BitGo’s instant guarantee against double-spends (fees may apply).
forceChangeAtEnd boolean No Forces the change address to be the last output.
changeAddress address (string) No Specifies the change address instead of creating a new one.
noSplitChange boolean No Set to true to disable automatic change splitting for purposes of unspent management.
targetWalletUnspents number No Specify a number of target unspents to maintain in the wallet.
validate boolean No Extra verification of the change addresses, which is always done server-side and is redundant client-side (defaults to true).
feeSingleKeySourceAddress address (string) No Use this single key address to pay fees
feeSingleKeyWIF private key in WIF No Use the address based on this private key to pay fees
otp string No A 7 digit code used to bypass a policy with the “getOTP” action type. See Wallet Policy for more details

Example Response

{ "tx": "0100000001a366332472cebceabdd541beb582d5dbaaecccdbec639b0a2d2b...",
  "hash": "b3bd8ac76de2340c1159337acdfcaabf08a9470e8157870bd1d84631a0acc67b",
  "fee": 10000,
  "status": "signed",
  "instant": true,
  "instantId": "56651c4c4e82b975616b58647c77fe1dc"
}

Example Response (pending approval required because of wallet policy)

{
  "error": "exceeds a spending limit",
  "pendingApproval": "56050b1368217cde3667fcfe0157556b",
  "triggeredPolicy": "5578defa5e44dbcb20c0caf98b297ad7",
  "status": "pendingApproval"
}

Success Response

Field Description
tx hex-encoded form of the signed transaction
hash the transaction id
fee amount in satoshis sent to the Bitcoin miners as part of this transaction
feeRate amount in satoshis per kilobyte sent to the Bitcoin miners as part of this transaction

Policy/Failure Response

Field Description
error the message from the policy that triggered this pending approval
pendingApproval the pending approval id, which will need to be approved by another user
otp set to true if the policy that fired was a “getOTP” type
triggeredPolicy id of the policy that triggered this pending approval
status the transaction status

Send Coins to Multiple Addresses

var recipients = [];
recipients.push({address: '2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD', amount: 0.1 * 1e8});
recipients.push({address: '2NGJP7z9DZwyVjtY32YSoPqgU6cG2QXpjHu', amount: 0.2 * 1e8});

var walletPassphrase = 'incorrect horse battery stable' // replace with wallet passphrase

bitgo.wallets().get({id: walletId}, function(err, wallet) {
  if (err) { console.log("Error getting wallet!"); console.dir(err); return process.exit(-1); }
  console.log("Balance is: " + (wallet.balance() / 1e8).toFixed(4));

  wallet.sendMany({ recipients: recipients, walletPassphrase: walletPassphrase }, function(err, result) {
    if (err) { console.log("Error sending coins!"); console.dir(err); return process.exit(-1); }

    console.dir(result);
  });
});
Available only as a local method (BitGo Express)
Advanced users should consider the Send Transaction API.

WALLETID='2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa'
WALLETPASSPHRASE='watashinobitcoin'

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"recipients\": [{ \"address\": \"2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD\", \"amount\": 1500000}, { \"address\": \"2NGJP7z9DZwyVjtY32YSoPqgU6cG2QXpjHu\", \"amount\": 2500000 }], \"walletPassphrase\": \"$WALLETPASSPHRASE\" }" \
http://$BITGO_EXPRESS_HOST:3080/api/v1/wallet/$WALLETID/sendmany

Convenience function to send Bitcoin to multiple destination addresses in a single transaction.

Parameters

Name Type Required Description
recipients string Yes array of recipient objects and the amount to send to each e.g. [{address: ‘38BKDNZbPcLogvVbcx2ekJ9E6Vv94DqDqw’, amount: 1500}, ..]
message string No Notes about the transaction
fee number No Fee (in Satoshis), leave blank for autodetect. Do not specify unless you are sure it is sufficient.
feeTxConfirmTarget number No Calculate fees per kilobyte, targeting transaction confirmation in this number of blocks. Default: 2, Minimum: 1, Maximum: 1000.
minConfirms number No only choose unspent inputs with a certain number of confirmations. We recommend setting this to 1 and using enforceMinConfirmsForChange.
enforceMinConfirms ForChange boolean No Defaults to false. When constructing a transaction, minConfirms will only be enforced for unspents not originating from the wallet.
sequenceId string No A custom user-provided string that can be used to uniquely identify the state of this transaction before and after signing
otp string No A 7 digit code used to bypass a policy with the “getOTP” action type. See Wallet Policy for more details

Example Response

{ "tx": "0100000001c69d05d3897a25c611324a935d0c688669dc416cb8d8e9ebb36e364fa79547c8000..",
  "hash": "27374a97df2cd8a63640dd7a40fce9a1d8dfeec3cf7a8b2fbf1ef609f4a5370d",
  "fee": 10000 }

Response

Field Description
tx hex-encoded form of the signed transaction
hash the transaction id
fee amount in satoshis sent to the Bitcoin miners as part of this transaction
feeRate amount in satoshis per kilobyte sent to the Bitcoin miners as part of this transaction

Policy/Failure Response

Field Description
error the message from the policy that triggered this pending approval
pendingApproval the pending approval id, which will need to be approved by another user
otp set to true if the policy that fired was a “getOTP” type
triggeredPolicy id of the policy that triggered this pending approval
status the transaction status

List Wallet Transactions

WALLET=2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLET/tx
var walletId = '2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov';
bitgo.wallets().get({ "id": walletId }, function callback(err, wallet) {
  if (err) { throw err; }
  wallet.transactions({}, function callback(err, transactions) {
    // handle transactions
    console.log(JSON.stringify(transactions, null, 4));
  });
});

Example response

{
  "transactions": [
    {
      "blockhash": "00000000000004b6b832552c96f8c88e6da1a99a8411573b702c455ae0f967a1",
      "confirmations": 4842,
      "date": "2015-01-16T01:12:52.000Z",
      "entries": [
        {
          "account": "2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov",
          "value": -10000
        }
      ],
      "fee": 10000,
      "height": 318528,
      "id": "90669b53a2004e0c4efb918f71f60ecbdc63fbdbad53b5c84ef940f31ddef552",
      "inputs": [
        {
          "previousHash": "c9a55f32d4b63d02a617eea58873227e4f011d0dfc836cb2e9cab531c4db0c4a",
          "previousOutputIndex": 1
        }
      ],
      "outputs": [
        {
          "account": "2MupvpwQQ7dqUizKFookiSzkmxxv8HFgnx6",
          "isMine": true,
          "value": 2000000,
          "chain": 0,
          "chainIndex": 15,
          "vout": 0
        },
        {
          "account": "2Mxy4voQQRi81vm8U7EEhKjgLLHu2njS5ia",
          "isMine": true,
          "value": 7990000,
          "chain": 1,
          "chainIndex": 5,
          "vout": 1
        }
      ],
      "pending": false,
      "instant": true,
      "instantId": "56651c4c4e82b975616b58647c788fad",
      "sequenceId": "CustomID1",
      "comment": "test transaction"
    },
    {
      "blockhash": "000000007e190d73d38f1372cb21562405c7ad88fdc3fe6bcba841228dc354c1",
      "confirmations": 16672,
      "date": "2014-11-06T03:22:58.000Z",
      "entries": [
        {
          "account": "monQzkZiHkBSzLJtAJpiDAEF2fQhvyPdeb",
          "value": -36855030260
        },
        {
          "account": "2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov",
          "value": 81000000
        },
        {
          "account": "n1VbwcNawZ2vBTrza3SxbHDPFg9tY1f9eg",
          "value": 36774030260
        }
      ],
      "fee": 0,
      "height": 306698,
      "id": "16c5e8cb01a453382723730afb6ca4621cad84ea759b8727c046b38a9c41193f",
      "inputs": [
        {
          "previousHash": "c9a55f32d4b63d02a617eea58873227e4f011d0dfc836cb2e9cab531c4db0c4a",
          "previousOutputIndex": 1
        }
      ],
      "outputs": [
        {
          "account": "n1VbwcNawZ2vBTrza3SxbHDPFg9tY1f9eg",
          "value": 36774030260,
          "vout": 0
        },
        {
          "account": "2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov",
          "isMine": true,
          "chain": 0,
          "chainIndex": 28,
          "value": 81000000,
          "vout": 1
        }
      ],
      "pending": false,
      "instant": false,
      "sequenceId": "CustomID2",
      "comment": "test transaction"
    }
  ],
  "start": 0,
  "count": 2,
  "total": 2
}

Get transactions for a given wallet, ordered by reverse block height (unconfirmed transactions first).

HTTP Request

GET /api/v1/wallet/:walletId/tx

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID of the wallet

QUERY Parameters

Parameter Type Required Description
skip number No The starting index number to list from. Default is 0.
limit number No Max number of results to return in a single call (default=25, max=250)
compact boolean No Omit inputs and outputs in the transaction results
minHeight number No A lower limit of blockchain height at which the transaction was confirmed. Does not filter unconfirmed transactions.

Response

Returns an array of Transaction objects. Each transaction contains summary information about how that transaction affected any wallet or bitcoin address involved in the transaction.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match, or unlock is required.

Get Wallet Transaction

WALLET=2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov
TXID=af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLET/tx/$TXID
var walletId = '2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov';
var transactionId = 'af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648';

bitgo.wallets().get({ "id": walletId }, function callback(err, wallet) {
  if (err) { throw err; }
  wallet.getTransaction({ "id": transactionId }, function callback(err, transaction) {
    console.log(JSON.stringify(transaction, null, 4));
  });
});

Example response

{
    "blockhash": "000000009249e7d725cc087cb781ade1dbfaf2bd777822948d5fccd4044f8299",
    "confirmations": 16661,
    "date": "2014-11-06T02:22:55.000Z",
    "entries": [
        {
            "account": "2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov",
            "value": 84000000
        },
        {
            "account": "msj42CCGruhRsFrGATiUuh25dtxYtnpbTx",
            "value": -85900000
        },
        {
            "account": "mwahoJcaVuy2TiMtGDZV9PaujFeD9z1a1q",
            "value": 1890000
        }
    ],
    "fee": 10000,
    "height": 306695,
    "hex": "0100000001b6e8b36132d351b3d66b5452d8f4601e2271a7bb52b644397db956a4ffe2a053000000006a4730440220127c4adc1cf985cd884c383e69440ce4d48a0c4fdce6bf9d70faa0ee8092acb80220632cb6c99ded7f261814e602fc8fa8e7fe8cb6a95d45c497846b8624f7d19b3c012103df001c8b58ac42b6cbfc2223b8efaa7e9a1911e529bd2c8b7f90140079034e75ffffffff0200bd01050000000017a914c449a7fafb3b13b2952e064f2c3c58e851bb943087d0d61c00000000001976a914b0379374df5eab8be9a21ee96711712bdb781a9588ac00000000",
    "id": "af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648",
    "outputs": [
        {
            "account": "2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov",
            "isMine": true,
            "chain": 0,
            "chainIndex": 28,
            "value": 84000000,
            "vout": 0
        },
        {
            "account": "mwahoJcaVuy2TiMtGDZV9PaujFeD9z1a1q",
            "value": 1890000,
            "vout": 1
        }
    ],
    "pending": false,
    "instant": true,
    "instantId": "56651c4c4e82b975616b58661bad3ac",
    "sequenceId": "Custom1a",
    "comment": "test transaction"
}

Get information about a transaction on a wallet.

HTTP Request

GET /api/v1/wallet/:walletId/tx/:txId

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID of the wallet
txId transaction hash (string) Yes The hash of the transaction to fetch

Response

Returns a Transaction object

Parameter Type Description
id string Hash of the transaction
hex string Raw hex of the transaction
date DateTime Date this transaction was first seen
blockhash string Hash of the block, if this transaction has been confirmed
height Number Height of the block this transaction was seen in
confirmations Number Number of blocks this transaction has been part of the blockchain
entries Array Consolidated entries of the transaction, taking into account net inputs/outputs
outputs Array Information about outputs of the transaction, including the wallet account, value, vout index, isMine, chain (0 for receive addresses, 1 for change addresses, 10 for SegWit receive addresses, 11 for SegWit change addresses)
fee Number Amount in Satoshis paid to the miners for this transaction
pending Boolean Set to true if the transaction has not yet been confirmed on the blockchain
instant Boolean Set to true if this transaction was sent using BitGo instant
instantId string The identifier for the instant transaction to be used to reference / obtain the guarantee from BitGo
sequenceId string The sequenceId (unique custom data provided when the transaction was sent)
comment string The comment as set on the transaction

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match, or unlock is required.
404 Not Found The transaction was not found on the wallet

List Wallet Addresses

Gets a list of addresses which have been instantiated for a wallet using the New Address API.

WALLET=2N76BgbTnLJz9WWbXw15gp6K9mE5wrP4JFb

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLET/addresses
var id = '2N76BgbTnLJz9WWbXw15gp6K9mE5wrP4JFb';
bitgo.wallets().get({ "id": id }, function(err, wallet) {
  if (err) { console.log(err); process.exit(-1); }
  wallet.addresses({}, function(err, walletAddress) {
    console.dir(walletAddress);
  });
});

HTTP Request

GET /api/v1/wallet/:walletId/addresses

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID of the wallet

QUERY Parameters

Parameter Type Required Description
chain number No Optionally restrict to chain 0, 1, 10 or 11
skip number No Skip this number of results
limit number No Limit number of results to this number (default=25, max=500)
details boolean No include balance and transaction count info

Example response

{
  "addresses":[
    {
      "chain":0,
      "index":0,
      "path":"/0/0",
      "address":"2N76BgbTnLJz9WWbXw15gp6K9mE5wrP4JFb"
    },
    {
      "chain":0,
      "index":1,
      "path":"/0/1",
      "address":"2NCT7eymRYvAoYALNkcBPuftr5scSpBKLuY"
    },
    {
      "chain":0,
      "index":2,
      "path":"/0/2",
      "address":"2NCngTQw49WEHQD7pvDEAc1LzVVPQcoxEU7"
    }
  ],
  "start":0,
  "count":3,
  "total":28,
  "hasMore":true
}

Response

Returns an array of Wallet Address objects.

Field Description
chain Which chain is the address on (0, 1, 10, or 11)
index BIP32 index on the chain
path BIP32 path from wallet
address the bitcoin address

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.

Get Single Wallet Address

Gets information about an address on a wallet. Can also be used to check if an address exists on a wallet.

WALLET=2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa
ADDRESS=2NBMGw7K9XiBPfvW3nUQcrANKncmAoLUdDX

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLET/addresses/$ADDRESS
var id = '2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa';
var address = '2NBMGw7K9XiBPfvW3nUQcrANKncmAoLUdDX';
bitgo.wallets().get({ "id": id }, function(err, wallet) {
  if (err) { console.log(err); process.exit(-1); }
  wallet.address({ address: address }, function(err, walletAddress) {
    console.dir(walletAddress);
  });
});

HTTP Request

GET /api/v1/wallet/:walletId/addresses/:address

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID of the wallet
address bitcoin address (string) Yes The address on the wallet to get information of

Example response

{
    "address": "2NBMGw7K9XiBPfvW3nUQcrANKncmAoLUdDX",
    "balance": 0,
    "chain": 1,
    "index": 3,
    "path": "/1/3",
    "received": 879990000,
    "redeemScript": "522102d22299c1bc9fb7b2788ba48241bdd51a83740b4eb10c0e95b28f6fa1121877482102f91a6957b2a230e958396152ae70076b7c031f5aa446d87bb071da5eac158a1d2103025d939cf6b546e3e44c92097c534366cc64747c3a227664a7ff70e2ebeab32653ae",
    "sent": 879990000,
    "txCount": 2
}

Response

Returns a wallet address object

Field Description
address The bitcoin address being looked up
balance Current balance (satoshis) in this address
chain The HD chain used to generate this address (0 for external receive addresses, 1 for change addresses, 10 for external SegWit receive addresses, 11 for SegWit change addresses)
index The index in the HD chain used to generate this address
path The HD path of the address on the wallet
received Total amount (satoshis) received on this address
sent Total amount (satoshis) sent on this address
txCount Total number of transactions on this address
redeemScript The redeemScript that may be used to spend funds from this P2SH address

Wallet Operations - Advanced

These features are available and recommended for advanced developers. Using these APIs will provide expanded (but potentially complex) functionality and greater control of the transaction creation process.

Get Transaction By Sequence Id

WALLET=2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa
SEQUENCEID=hello123

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLET/tx/sequence/$SEQUENCEID
var walletId = '2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa';
var sequenceId = 'hello123';

bitgo.wallets().get({ "id": walletId }, function callback(err, wallet) {
  if (err) { throw err; }
  wallet.getWalletTransactionBySequenceId({ "sequenceId": sequenceId }, function callback(err, transaction) {
    console.log(JSON.stringify(transaction, null, 4));
  });
});

Example response

{
    "transaction": {
        "amount": -106215,
        "createdDate": "2015-09-25T08:39:38.897Z",
        "creator": "5458141599f715232500000530a94fd2",
        "date": "2015-09-25T08:39:39.893Z",
        "fee": 6215,
        "history": [
            {
                "action": "unconfirmed",
                "date": "2015-09-25T08:39:39.893Z"
            },
            {
                "action": "signed",
                "date": "2015-09-25T08:39:38.897Z",
                "user": "5458141599f715232500000530a94fd2"
            },
            {
                "action": "created",
                "date": "2015-09-25T08:39:38.897Z",
                "user": "5458141599f715232500000530a94fd2"
            }
        ],
        "id": "5605084a68217cde3667f2ad4a640875",
        "sequenceId": "hello123",
        "signedDate": "2015-09-25T08:39:38.897Z",
        "size": 367,
        "state": "unconfirmed",
        "transactionId": "50430eeffdd1272ff39d0d3667cbc8e60de0a8ea6bb118e6236e0964389e6d19",
        "walletId": "2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa"
    }
}

Get the transaction on a wallet sequence ID that was passed in when sending an outgoing transaction (via sendCoins or sendTransaction). This is useful for tracking an unsigned/unconfirmed transaction via your own unique ID, as Bitcoin transaction IDs are not defined before co-signing and malleable before confirmation.

A pending transaction that has not yet been co-signed by BitGo will still have a sequence id.

HTTP Request

GET /api/v1/wallet/:walletId/tx/sequence/:sequenceId

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID of the wallet
sequenceId custom user-provided string Yes The unique id previously sent with an outgoing transaction.

Response

Returns a WalletTx object, containing the history and state of the transaction on the Bitcoin network.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match, or unlock is required.
404 Not Found The transaction was not found on the wallet

List Wallet Unspents

WALLET=2N91XzUxLrSkfDMaRcwQhe9DauhZMhUoxGr

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLET/unspents
  var id = '2N91XzUxLrSkfDMaRcwQhe9DauhZMhUoxGr';
  bitgo.wallets().get({ id: id }, function callback(err, wallet) {
    if (err) {
      throw err;
    }
    wallet.unspents({limit: 4.2}, function callback(err, wallet) {
      // handle error, use unspents
      console.dir(wallet);
    });
  });

Gets a list of unspent input transactions for a wallet.

In order to create a bitcoin transaction, the creator of the transaction will need to accumulate a set of bitcoin ‘inputs’ for use in creation of that transaction.

HTTP Request

GET /api/v1/wallet/:walletId/unspents

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID of the wallet

QUERY Parameters

Parameter Type Required Description
target number No The API will attempt to return enough unspents to accumulate to at least this amount (in satoshis).
skip number No The starting index number to list from. Default is 0.
limit number No Max number of results to return in a single call (default=100, max=250)
minConfirms number No Only include unspents with at least this many confirmations.
minSize number No Only include unspents that are at least this many satoshis.
segwit boolean No Defaults to false, but is passed and set to true automatically from SDK version 4.3.0 forward.

Example response

{
    "count": 2,
    "pendingTransactions": false,
    "start": 0,
    "total": 2,
    "unspents": [
        {
            "address": "2N26EdwtVNQe6P9QkVgLHGhoWtU5W98ohNB",
            "blockHeight": 570611,
            "chainPath": "/1/117",
            "confirmations": 3474,
            "date": "2015-09-18T21:58:11.620Z",
            "isChange": true,
            "redeemScript": "522102f90f2bb90f6572af7bf5c7317ebd48311b417b005352ae71c3c79990fea1f60f2102f817f403092d09abbbb955410d1e50fca4d1ee56e145a29dde01e505558dec43210307527a3928d2711212730ef6585d1a82af80d1fe2979e167b7cc1a397c654ba253ae",
            "script": "a9146105ee32b12a94436f19592e18b135d206e5f46987",
            "tx_hash": "3246b59fcec99c81e5f59522327b632f5c54e4da42ccb512550ed91a3f9b5ce6",
            "tx_output_n": 0,
            "value": 78273186932,
            "wallet": "2N91XzUxLrSkfDMaRcwQhe9DauhZMhUoxGr",
            "instant": false
        },
        {
            "address": "2NCB6qVywiBvWmrpcnFJ4jq8m6oZrFTCKDd",
            "blockHeight": 570611,
            "chainPath": "/1/118",
            "confirmations": 3474,
            "date": "2015-09-18T21:58:23.698Z",
            "isChange": true,
            "redeemScript": "522103e48e6f9e7c2f1011b104f3353973e08c8eb83e5d276bea3d274abd1e458700582103ac2554d01691c694683fc2976183afb25492645bc338deb6425371119c163ec7210212d5e3a68be3b78f266e6247cc34d8ce8bba8d964dbe7da3d1101261ffa07af953ae",
            "script": "a914cfa2c19e759f7a3bc58ed7ae1f72d0125965a81a87",
            "tx_hash": "c005f114cbf443c7c0d2fc82bba6b78d0fd677f131467a6d7b17a67ffacd79b9",
            "tx_output_n": 1,
            "value": 1808807240,
            "wallet": "2N91XzUxLrSkfDMaRcwQhe9DauhZMhUoxGr",
            "instant": true
        }
    ]
}

Response

Returns an array of Unspent Input objects.

Field Description
tx_hash The hash of the unspent input
tx_output_n The index of the unspent input from tx_hash
value The value, in satoshis of the unspent input
script Output script hash (in hex format)
redeemScript The redeem script
chainPath The BIP32 path of the unspent output relative to the wallet
confirmations Number of blocks seen on and after the unspent transaction was included in a block
isChange Boolean indicating this is an output from a previous spend originating on this wallet, and may be safe to spend even with 0 confirmations
instant Boolean indicating if this unspent can be used to create a BitGo Instant transaction guaranteed against double spends

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.

Consolidate Unspents

bitgo.wallets().get({ "id": walletId }, function callback (err, wallet) {
  if (err) { throw err; }
  wallet.consolidateUnspents(
    {
      target: desiredUnspentCount,
      minConfirms: minConfirmCountPerIteration,
      walletPassphrase: passphrase
    },
    function (err, consolidationTransactions) {
      if (err) { throw err; }
      // All the transactions used for consolidation, by reverse block height
      console.dir(consolidationTransactions);
    }
  );
});
Available only as a local method (BitGo Express)
WALLETID="2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa"
WALLETPASSPHRASE="mypassword"

curl -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"walletPassphrase\": \"$WALLETPASSPHRASE\", \"target\": 1, \"minConfirms\": 1 }" \
http://$BITGO_EXPRESS_HOST:3080/api/v1/wallet/$WALLETID/consolidateunspents

Coalesce the unspents currently held in a wallet to a smaller number. This is an iterative process, largely due to transaction size limits and signing speed. Each iteration requires its own transaction fees.

Parameters

Parameter Type Required Description
target number No desired number of unspents after running the function
maxInputCountPerConsolidation number No maximum number of unspents to be used for each iteration. Defaults to 85.
minConfirms number No only choose unspent inputs with a certain number of confirmations
walletPassphrase string No Passphrase of the wallet
xprv string No the private key in string form, if walletPassphrase is not available
progressCallback function No Closure to be called after each iteration. It can be used for monitoring the progress.
minSize number No Only use unspents with at least this many satoshis for consolidation.
maxSize number No Don’t use any unspents larger than this number of satoshis in consolidation.
maxIterationCount integer No Maximum number of consolidation iterations to perform. Must be greater than or equal to 1.
feeRate number No Fee rate to be used for the consolidation transactions in satoshis per KB.

Fan Out Unspents

bitgo.wallets().get({ "id": walletId }, function callback (err, wallet) {
  if (err) { throw err; }
  wallet.fanOutUnspents(
    {
      target: desiredUnspentCount,
      minConfirms: minConfirmCount,
      walletPassphrase: passphrase
    },
    function (err, fanoutTransaction) {
      if (err) { throw err; }
      // Transaction used to fan out unspents
      console.dir(fanoutTransaction);
    }
  );
});
Available only as a local method (BitGo Express)
WALLETID="2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa"
WALLETPASSPHRASE="mypassword"

curl -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"walletPassphrase\": \"$WALLETPASSPHRASE\", \"target\": 85, \"minConfirms\": 1 }" \
http://$BITGO_EXPRESS_HOST:3080/api/v1/wallet/$WALLETID/fanoutunspents

Take all the wallet’s unspents (that match the selection criteria, such as minimum confirm count) and redistributes them into a higher number of equal-sized unspents.

Parameters

Parameter Type Required Description
target number Yes desired number of unspents after running the function
minConfirms number No only choose unspent inputs with a certain number of confirmations
walletPassphrase string No Passphrase of the wallet
xprv string No the private key in string form, if walletPassphrase is not available

Create Transaction

bitgo.wallets().get({ "id": walletId }, function callback(err, wallet) {
  if (err) { throw err; }
  var recipients = [];
  recipients.push({address: address, amount: amountSatoshis});
  wallet.createTransaction(
    {
      recipients: recipients,
      fee: fee
    },
    function(err, transaction) {
      // The transaction with selected unspents, ready to be signed with signTransaction
      console.dir(transaction);
    });
  });
});
Available only as a local method (BitGo Express)
WALLETID='2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa'

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"recipients\": [{ \"address\": \"2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD\", \"amount\": 1500000}, { \"address\": \"2NGJP7z9DZwyVjtY32YSoPqgU6cG2QXpjHu\", \"amount\": 2500000 }] }" \
http://$BITGO_EXPRESS_HOST:3080/api/v1/wallet/$WALLETID/createtransaction

Create a transaction with multiple recipients from a wallet using unspents from addresses on that wallet. This is client-side functionality only in the SDK.

Typically used before signTransaction, which signs a created transaction. Change will be sent to a newly created change address (path of /1) on the wallet.

This is an advanced method that allows you to manually specify the miner fee (could be 0) and decrypted keychain.

WARNING: If you provide an insufficient fee, your transaction may not get confirmed and your unspents may be unusable for some time.

Example Response

{
    "changeAddress": {
        "address": "2MvaEJUHmL6wzsxwqW8Xm8Qac4PTa3zMuvE",
        "path": "/1/65"
    },
    "fee": 20000,
    "transactionHex": "0100000003f6a05b9ab9d7c62cb70a662a4016cbd4740d1d6d35d3c903e3a74fd9f943d...",
    "unspents": [
        {
            "chainPath": "/0/10",
            "redeemScript": "522102f96f3d88ca43810306a7fff2e99da9f052d56a26c73a094237c55b5ec72fead62102981092615521d2d6a44a652631309b5136f589f6c625dbf94efa3edae74ddd2f2103b08e8933fc38a3eb2dc0616f336910b884f9ad80b4a7984f2d9f9e19759ff01553ae"
        },
        ...
    ],
    "walletId": "2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa",
    "walletKeychains": [
        {
            "path": "/0/0",
            "xpub": "xpub661MyMwAqRbcGM9kbvxAfLzr9WwqaVKSqw1dEm16mZmPmigQBrqzVQz314kd9jV68JjpRLCtrRWRpEJqe3FCaN4fuMTZNaDa3uMSjxUaZEj"
        },
        ...
    ]
}

HTTP Request

This method is only available client-side.

Parameters

Parameter Type Required Description
recipients string Yes array of recipient objects and the amount to send to each e.g. [{address: ‘38BKDNZbPcLogvVbcx2ekJ9E6Vv94DqDqw’, amount: 1500}, ..]
fee number No The absolute fee in satoshis to be paid to the Bitcoin miners. HIGHLY recommended to leave undefined and use ‘feeTxConfirmTarget’ instead for dynamic fee estimates.
feeRate number No The fee in satoshis /per kB/ of transaction size to be paid to the Bitcoin miners. HIGHLY recommended to leave undefined and use ‘feeTxConfirmTarget’ instead for dynamic fee estimates.
feeTxConfirmTarget number No Calculate fees per kilobyte, targeting transaction confirmation in this number of blocks. Default: 2, Minimum: 1, Maximum: 1000.
maxFeeRate number No An upper bound for the fee rate in satoshi per kB. Useful to set as a safety measure when using dynamic fees.
minConfirms number No only choose unspent inputs with a certain number of confirmations. We recommend setting this to 1 and using enforceMinConfirmsForChange.
enforceMinConfirms ForChange boolean No Defaults to false. When constructing a transaction, minConfirms will only be enforced for unspents not originating from the wallet.
instant boolean No set to true to request that the transaction be sent with BitGo’s instant guarantee against double-spends (fees may apply).
forceChangeAtEnd boolean No Forces the change address to be the last output.
changeAddress address (string) No Specifies the change address instead of creating a new one.
noSplitChange boolean No Set to true to disable automatic change splitting for purposes of unspent management.
targetWalletUnspents number No Specify a number of target unspents to maintain in the wallet.
validate boolean No Extra verification of the change addresses, which is always done server-side and is redundant client-side (defaults to true).
minUnspentSize number No Minimum amount in satoshis for an unspent to be considered usable. Defaults to 5460 (to combat tx dust spam).
feeSingleKeySourceAddress address (string) No Use this single key address to pay fees
feeSingleKeyWIF private key in WIF No Use the address based on this private key to pay fees

Sign Transaction

bitgo.wallets().get({id: walletId}, function(err, wallet) {
  wallet.getEncryptedUserKeychain({}, function(err, keychain) {
    console.log("Got encrypted user keychain");
    // Decrypt the user key with a passphrase
    keychain.xprv = bitgo.decrypt({ password: walletPassphrase, input: keychain.encryptedXprv });
    var transactionHex = "0100000003f6a05b9ab9d7c62cb70a662a4016cbd4740d1d6d35d3c903e3a74fd9f943d09c0000000017a91...";
    // Unspents Can be obtained from the createTransaction method
    var unspents = [
      {
        "chainPath": "/0/10",
        "redeemScript": "522102f96f3d88ca43810306a7fff2e99da9f052d56a26c73a094237c55b5ec72fead6"
      }
    ];

    wallet.signTransaction({
      transactionHex: transactionHex,
      unspents: unspents,
      keychain: keychain
    },
    function (err, transaction) {
      console.dir(transaction);
    });
  });
});
Available only as a local method (BitGo Express)
WALLETID='2NB5G2jmqSswk7C427ZiHuwuAt1GPs5WeGa'

UNSPENTS='[
    {
    "chainPath": "/0/10",
    "redeemScript": "522102f96f3d88ca43810306a7fff2e99da9f052d56a26c73a094237c55b5ec72fead62102981092615521d2d6a44a652631309b5136f589f6c625dbf94efa3edae74ddd2f2103b08e8933fc38a3eb2dc0616f336910b884f9ad80b4a7984f2d9f9e19759ff01553ae"
    },
    {
    "chainPath": "/0/10",
    "redeemScript": "522102f96f3d88ca43810306a7fff2e99da9f052d56a26c73a094237c55b5ec72fead62102981092615521d2d6a44a652631309b5136f589f6c625dbf94efa3edae74ddd2f2103b08e8933fc38a3eb2dc0616f336910b884f9ad80b4a7984f2d9f9e19759ff01553ae"
    },
    {
    "chainPath": "/0/0",
    "redeemScript": "52210362a0c0e532afd7c72111525ef6157a32550b2308a0afbedef01505ab2f8aa5a5210281c598ce3155665a8578e51ab4033def358644dae5f1c4abb9b9f038867804ef21031414644c53953b0557c4a3a6f9f99c0b033583b67e5c02bf0297906f60d2ee9d53ae"
    }
]'

TRANSACTIONHEX=0100000003f6a05b9ab9d7c62cb70a662a4016cbd4740d1d6d35d3c903e3a74fd9f943d09c0000000017a914b02ad680c6ff1d2fa953720940ff8e3ac6eef37987ffffffff15e66c75b266d2077c45a3370fe0da92c0c20ebe400343bf82ac522fcc8fe60a0000000017a914b02ad680c6ff1d2fa953720940ff8e3ac6eef37987ffffffff3f7d55ff4330a5b8da69abf675c18ff558e9cf04479779a998a00d3029cbe4070100000017a914c38fcf303ad53d925df43d21b45be7b8d0895c9387ffffffff0360e316000000000017a9147bd4d50e34791a6373bfa0175bf2cb9796a08f5587a02526000000000017a914fce3c3bbd6e96dd3b54f689f33fcd12c94e9dd5587308527000000000017a91424808ad9ba7f68ae0460ab3c21f5281ead31814f8700000000

KEYCHAIN='{ "xpub": "xpub661MyMwAqRbcGM9kbvxAfLzr9WwqaVKSqw1dEm16mZmPmigQBrqzVQz314kd9jV68JjpRLCtrRWRpEJqe3FCaN4fuMTZNaDa3uMSjxUaZEj",
            "encryptedXprv": "{\"iv\":\"ToxBefI++Jf7FhRUV7MNFA==\",\"v\":1,\"iter\":10000,\"ks\":256,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"X3Ibf2DfHd8=\",\"ct\":\"ri+99W0cLUpNCgjksZJVl425OGVrJaNJVllaldTjXumD8oxySjGALoj630Qf5xe0WD0DMJjVIAhMwlPz4g6eG6n8a2ZeKRdvfWMhp7PBEdGGCywPbtLNTfbjrS9kfM9bedncp9QXud7fERfH63vorzEP0rUOZJ0=\"}",
            "path": "m",
            "xprv": "xprv9s21ZrQH143K3s5HVuRAJD47bV7MB2bbUi62SNbVDEEQtvMFeKXjwcfZ9otQ4vZMtHzumu9LyFriSFzcjEXJp6eAL4muKaahwxAaiDPWt4R" }'

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"transactionHex\": \"$TRANSACTIONHEX\", \"unspents\": $UNSPENTS, \"keychain\": $KEYCHAIN }" \
http://$BITGO_EXPRESS_HOST:3080/api/v1/wallet/$WALLETID/signtransaction

Sign a multi-sig transaction using a created transaction hex, keychain and unspent information (derivation paths and redeem scripts). Typically used with the output from createTransaction.

Can be performed offline.

This is client-side functionality only in the SDK.

Example Response

{"tx":"0100000003f6a05b9ab9d7c62cb70a662a4016cbd4740d1d6d35d3c903e3a74fd9f943d09c00....."}

HTTP Request

This method is only available client-side.

Parameters

Parameter Type Required Description
transactionHex string Yes The unsigned transaction, in hex string form
unspents array Yes Array of unspents objects, which contain the chainpath and redeemScript.
keychain keychain object Yes The decrypted keychain (object), with available xprv property.
signingKey private key (string) No For legacy safe wallets, the private key string.
validate boolean No Extra verification of signatures (which are always verified server-side), defaults to global configuration.

Send Transaction

TX={raw hex transaction}

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"tx\": \"$TX\", \"otp\": \"0000000\" }" \
https://test.bitgo.com/api/v1/tx/send
bitgo.wallets().get({id: walletId}, function(err, wallet) {
  console.log("Balance is: " + (wallet.balance() / 1e8).toFixed(4));
  wallet.getEncryptedUserKeychain({}, function(err, keychain) {
    if (err) {
      console.log("Error getting encrypted keychain!");
      console.dir(err);
      return process.exit(-1);
    }
    console.log("Got encrypted user keychain");

    // Decrypt the user key with a passphrase
    keychain.xprv = bitgo.decrypt({ password: walletPassphrase, input: keychain.encryptedXprv });

    // Set recipients
    var recipients = {};
    recipients[destinationAddress] = amountSatoshis;
    console.log("Creating transaction");
    wallet.createTransaction({
      recipients: recipients,
      fee: fee
      },
      function(err, transaction) {
        if (err) {
          console.log("Failed to create transaction!");
          console.dir(err);
          return process.exit(-1);
        }

        console.dir(transaction);
        console.log("Signing transaction");
        wallet.signTransaction({
          transactionHex: transaction.transactionHex,
          unspents: transaction.unspents,
          keychain: keychain
        },
        function (err, transaction) {
          if (err) {
            console.log("Failed to sign transaction!");
            console.dir(err);
            return process.exit(-1);
          }

          console.dir(transaction);
          console.log("Sending transaction");
          wallet.sendTransaction({tx: transaction.tx}, function (err, callback) {
            console.log("Transaction sent: " + callback.tx);
          });
        });
      }
    );
  });
});

Send a partially-signed transaction. The server will do one of the following:

HTTP Request

POST /api/v1/tx/send

Example Response

{
  "tx": "01000000022cbc51a1d73a7e8ef3feaf30ad51b08b53cf91c672ba73..",
  "hash": "b3bd8ac76de2340c1159337acdfcaabf08a9470e8157870bd1d846..",
  "status": "accepted",
  "instant": true,
  "instantId": "56651c4c4e82b975616b58647c77fe1dc"
}

BODY Parameters

Parameter Type Required Description
tx Transaction Object Yes The transaction, in hex string form
sequenceId string No A custom user-provided string that can be used to uniquely identify the state of this transaction before and after signing
message string No User-provided string (this does not hit the blockchain)
instant boolean No set to true to request that the transaction be sent with BitGo’s instant guarantee against double-spends (fees may apply).
otp string No A 7 digit code used to bypass a policy with the “getOTP” action type. See Wallet Policy for more details

Response

Returns the sent transaction and its hash in hex-encoded form.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match, or unlock is required.
402 Payment Required The transaction fee in this request seems too low.

Policy/Failure Response

Field Description
error the message from the policy that triggered this pending approval
pendingApproval the pending approval id, which will need to be approved by another user
otp set to true if the policy that fired was a “getOTP” type
triggeredPolicy id of the policy that triggered this pending approval
status the transaction status

Get Instant Guarantee

INSTANTID=564ea1fa95f4344c6db00773d1277160

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/instant/$INSTANTID
bitgo.instantGuarantee({ id: '56562ee923ab7f3a28d638085ba6955a' }, function(err, result) {
  if (err) {
      console.log("Error getting guarantee!");
      console.dir(err);
      return process.exit(-1);
  }
  console.dir(result);
});

BitGo Instant is built on top of our wallet platform, as a guarantee by BitGo against double spends. As a co-signer on a multi-sig wallet, BitGo will never double-spend an output. We back our promise with a cryptographically signed guarantee on each transaction, enabling receivers to accept funds without the need for any block confirmations.

HTTP Request

GET /api/v1/instant/:id

Example Response

{
    "amount": 600000,
    "createTime": "2015-11-20T04:30:49.894Z",
    "guarantee": "BitGo Inc. guarantees the transaction with hash 8ba08ef2a745246f309ec4eaff5d7652c4fc01e61eebd9aabc1c58996355acd7 or normalized hash 62f76eb48d60a1c46cb74ce42063bd9c0816ca5e17877738a824525c9794ceaf for the USD value of 0.00600000 BTC at Fri Nov 20 2015 04:30:49 GMT+0000 (UTC) until confirmed to a depth of 6 confirms.",
    "id": "564ea1fa95f4344c6db00773d1277160",
    "normalizedHash": "62f76eb48d60a1c46cb74ce42063bd9c0816ca5e17877738a824525c9794ceaf",
    "signature": "1c2ea42ab4b9afdc069441401a1...",
    "state": "open",
    "transactionId": "8ba08ef2a745246f309ec4eaff5d7652c4fc01e61eebd9aabc1c58996355acd7"
}

URL Parameters

Parameter Type Required Description
id string Yes The instant guarantee id to be retrieved.

Response

Returns the instant guarantee message, including the amount and Transaction ID.

Parameter Type Description
amount Number Amount in Satoshis of the instant guarantee
createTime DateTime The time at which the transaction was created
guarantee string The message by BitGo to guarantee the instant transaction
id string The instant guarantee ID on BitGo
transactionId string The hash of the guaranteed transaction
normalizedHash string The hash of the guaranteed transaction without signatures
signature string Cryptographically signed guarantee, to provide an audit record in cases of a dispute
state string The state of a transaction as monitored by BitGo (you do not need to take any action on this)

Verifying BitGo’s Guarantee

BitGo’s guarantee is signed using our corporate signing key, which corresponds to the public Bitcoin address 1BitGo3gxRZ6mQSEH52dvCKSUgVCAH4Rja.

To confirm, verify the guarantee with our signature. Example:

assert(bitcoin.Message.verify('1BitGo3gxRZ6mQSEH52dvCKSUgVCAH4Rja', signature, guarantee, process.config.bitcoin.network));

If the signature is valid, you may accept the transaction instantly without the need for any block information. You can save the guarantee & signature locally to provide an audit record in case of a dispute.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match, or unlock is required.

Get Wallet by Address

Identifies the wallet to which a given address belongs and returns additional information about the address (including balances).

ADDRESS=2NBMGw7K9XiBPfvW3nUQcrANKncmAoLUdDX

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/walletaddress/$ADDRESS
var address = '2NBMGw7K9XiBPfvW3nUQcrANKncmAoLUdDX';
bitgo.getWalletAddress({ address: address }, function(err, result) {
  if (err) { console.log(err); process.exit(-1); }
  console.dir(result);
});

HTTP Request

GET /api/v1/walletaddress/:address

URL Parameters

Parameter Type Required Description
address bitcoin address (string) Yes The address to look up information on

Example response

{
    "address": "3JNUVmyjdLySccafwPSGDfS3dCVEz3Rnpj",
    "balance": 0,
    "chain": 0,
    "index": 7,
    "path": "/0/7",
    "received": 0,
    "redeemScript": "52210306d46ec69fdbf36c0eb1c4fe96ac0417d1375490a6811fdfa6f1dc3c78aad50c2102fb38d7ffb3e354a74b3231eeee6b361c7f3c5ddccac15c7f06e5557f4e6a5318210270467cb619033ef9bcb7cc39d4ce45084418229c0e8aa65821345a222a24a2e453ae",
    "sent": 0,
    "txCount": 0,
    "wallet": "32uFQgny5bgj24nywQPo5cgEUGX6a1PuAp"
}

Response

Returns a wallet address object

Field Description
address The bitcoin address being looked up
balance Current balance (satoshis) in this address
chain The HD chain used to generate this address (0 for user-generated, 1 for change)
index The index in the HD chain used to generate this address
path The HD path of the address on the wallet
received Total amount (satoshis) received on this address
sent Total amount (satoshis) sent on this address
txCount Total number of transactions on this address
redeemScript The redeemScript that may be used to spend funds from this P2SH address
wallet The base address (wallet ID) of the wallet this address is on

Freeze Wallet

WALLETID='2N8ryDAob6Qn8uCsWvkkQDhyeCQTqybGUFe'
DURATION='4000'
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"duration\": \"$DURATION\" }" \
https://test.bitgo.com/api/v1/wallet/$WALLETID/freeze
bitgo.wallets().get({ "id": walletId }, function(err, wallet) {
  bitgo.unlock({ otp: otp }, function(err) {
    if (err) {
      console.dir(err);
      throw new Error("Could not unlock!");
    }
    wallet.freeze({ "duration": 4000 }, function(err, result) {
      console.dir(result);
    });
  });
});

Example Response

{
  "time" : "2016-04-01T03:51:39.779Z",
  "expires" : "2016-04-01T04:58:19.779Z"
}

Prevent all spend activity on a wallet. This call is designed to be used in cases of emergency, and prevent spends for a default of 1 hour.

Parameters

Parameter Type Required Description
duration number No length of time in seconds to freeze spend activity. Defaults to 1 hour.

Response

Field Description
time The date the freeze command was called
expires The date after which spend activity will be allowed

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match, or unlock is required.

Wallet Sharing

A BitGo wallet may be shared between multiple users. All users on a wallet share the same private key (although each individual user may encrypt it separately).

Security on a shared wallet is enforced by BitGo, which requires that users log in and authenticate before co-signing. Wallet permission levels define what an individual user is able to do on a wallet.

Wallet Permissions

Permission Description
View View transactions on the wallet
Spend Initiate transactions on the wallet, which are subject to wallet policy
Admin Change policy and manage users and settings on the wallet

Sharing a wallet

Available only as a local method (BitGo Express)

WALLETID='2N8ryDAob6Qn8uCsWvkkQDhyeCQTqybGUFe'
PASSPHRASE='walletpassphrase'
RECEIVEREMAIL='test@bitgo.com'

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"walletPassphrase\": \"$PASSPHRASE\", \"email\": \"$RECEIVEREMAIL\" }" \
http://$BITGO_EXPRESS_HOST:3080/api/v1/wallet/$WALLETID/simpleshare
bitgo.wallets().get({ "id": walletId }, function(err, wallet) {
    wallet.shareWallet({ email: receiverUser, walletPassphrase: senderPassword, permissions: 'view,spend', skipKeychain: false }, function callback(err, result) {
        console.dir(result);
    });
});

Example Response

{
  "id": "54c594802ebe8510790092958f526f47",
  "walletId": "2MsaMz4tYy5RieZ8qBeW1rhsTpNAXjpofSC",
  "walletLabel": "test2",
  "fromUser": "54c589521758c40e79008e91a7088190",
  "toUser": "5458141599f715232500000530a94fd2",
  "permissions": "view,spend,admin",
  "state": "active",
  "keychain":
   { "xpub": "xpub661MyMwAqRbcFcDmevjhDfSebRy8toH17gJ64a2qAMr5gC4JZRWLUJwPDFeKg6aTMNPa1hYQ3s5kJkDNPMbAw5oQdcjn9N58rYQeUnUozFn",
     "encryptedXprv": "{iv:uoXLSMgfplagVOku...",
     "fromPubKey": "041363164D0521A...",
     "toPubKey": "031D388E7B16FE..",
     "path": "m/999999/26697279/124485569"
   }
}

Sharing a wallet involves giving another user permission to use the wallet through BitGo.

In order for the receiver to use the wallet, we also need to share the private key with them. Each user on BitGo creates a public-private keypair for this purpose during their signup process.

The BitGo SDK does the following client-side to create a new wallet share:

Parameters

Parameter Type Required Description
email string Yes Email of the user to share the wallet with
permissions string Yes Comma-separated list of permissions, e.g. view,spend,admin
walletPassphrase string No Passphrase on the wallet being shared
skipKeychain boolean No Set to true if sharing a wallet with another user who will obtain the keychain out-of-band
disableEmail boolean No Set to true to prevent a notification email sent to the user added
message string No The message to be used for this share.
reshare boolean No Must be explicitly set to true if a user is being reinvited to share a wallet after resetting their password.

Response

Field Description
id The id of the walletShare, used to accept it
walletId The id of the wallet being shared
walletLabel Label of the wallet to present to the user
fromUser BitGo ID of the user sharing the wallet
toUser BitGo ID of the user receiving the wallet
permissions Comma-separated list of permissions that the wallet share will give to the receiving user
keychain The encrypted keychain for the receiver to decrypt (to obtain the private key)

List Wallet Shares

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/walletShare
  bitgo.wallets().listShares({}, function callback(err, result) {
    if (err) {
      throw err;
    }
    console.dir(result);
  });

Gets lists of incoming and outgoing wallet shares for the logged-on account.

HTTP Request

GET /api/v1/walletShare

Example response

{
   "incoming":
   [
     { "id": "54c58f8d2ebe851079008fe3bbd9e50f",
       "walletId": "2N8ryDAob6Qn8uCsWvkkQDhyeCQTqybGUFe",
       "walletLabel": "test1",
       "fromUser": "54c589521758c40e79008e91a7088190",
       "toUser": "5458141599f715232500000530a94fd2",
       "permissions": "view,spend,admin",
       "state": "active" },
     { "id": "54c594802ebe8510790092958f526f47",
       "walletId": "2MsaMz4tYy5RieZ8qBeW1rhsTpNAXjpofSC",
       "walletLabel": "test2",
       "fromUser": "54c589521758c40e79008e91a7088190",
       "toUser": "5458141599f715232500000530a94fd2",
       "permissions": "view,spend,admin",
       "state": "active" }
   ],
   "outgoing": []
}

Response

Each wallet share object returned contains the following fields:

Field Description
id The id of the walletShare, used to accept it
walletId The id of the wallet being shared
walletLabel Label of the wallet to present to the user
fromUser BitGo ID of the user sharing the wallet
toUser BitGo ID of the user receiving the wallet
permissions Comma-separated list of permissions that the wallet share will give to the receiving user

Accept Wallet Share

Available only as a local method (BitGo Express)

SHAREID='54c594802ebe8510790092958f526f47'
NEWPASSPHRASE='receiverpassphrase'
PASSWORD='sharingkeypassword'

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"newWalletPassphrase\": \"$NEWPASSPHRASE\", \"userPassword\": \"$PASSWORD\" }" \
http://$BITGO_EXPRESS_HOST:3080/api/v1/walletshare/$SHAREID/acceptShare
bitgo.wallets().acceptShare(
    { walletShareId: shareId,
      newWalletPassphrase: 'receiverpassphrase',
      userPassword: 'receiverpassword'
    }, function(err, result) {
        console.dir(result);
    }
)

Example Response

{ "state": "accepted", "changed": "true" }

Client-side operation to accept a wallet share. Performs the following steps:

HTTP Request

This method is only available client-side.

Parameters

Parameter Type Required Description
walletShareId bitcoin address (string) Yes The incoming wallet share ID to accept
newWalletPassphrase string No the passphrase to set on the wallet, for use during future spends
userPassword string No the user’s password to decrypt the shared private key
overrideEncryptedXprv string No Set to an alternate encrypted xprv if you wish to store an encrypted xprv received out-of-band

Response

Field Description
state end state of walletShare (should be ‘accepted’)
changed true if successful

Cancel Wallet Share

SHAREID='54c594802ebe8510790092958f526f47'

curl -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/walletshare/$SHAREID
bitgo.wallets().cancelShare({ walletShareId: cancelledWalletShareId }, function(err, result) {
    if (err) { throw err; }
    console.dir(result);
)

Example Response

{ "state": "canceled", "changed": "true" }

Can be used to cancel a pending outgoing wallet share, or reject an incoming share. The share should not have been accepted yet.

HTTP Request

DELETE/api/v1/walletshare/:walletShareId

URL Parameters

Parameter Type Required Description
walletShareId string Yes The Wallet share to update.

Response

Field Description
state new state of walletShare
changed true if successful

Remove Wallet User

After a user has accepted a wallet share, they become a party on a wallet and the wallet share is considered “complete”.

In order to revoke the share after they have accepted, you can remove the user from the wallet.

This may require approval by another wallet administrator if there is more than a single administrator on a wallet.

bitgo.wallets().get({ "id": walletId }, function callback(err, wallet) {
  if (err) {
    throw err;
  }

  wallet.removeUser({ "user": userId }, function callback(err, wallet) {
    if (err) {
      // handle error
    }
    // etc
  });
});
WALLETID=2MvPJ8GMoFFWdUTh6p42FJV6XpmJEVjxv92
USERID=5479ac2bfb1d3e5e71000005d4dc49e3
curl -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLETID/user/$USERID

HTTP Request

DELETE /api/v1/wallet/:walletId/user/:userId

URL Parameters

Parameter Required Description
walletId Yes The ID of the wallet
userId Yes The user id of the user to remove (can be found on the wallet object)

Response

Returns the updated Wallet Model for this wallet, or a Pending Approval object (if approval is required).

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match, or unlock is required.

Wallet Policy

BitGo wallets feature advanced security features such as multi-user or SMS approval of transactions and spending limits. To take advantage of this, a user/developer may add and modify policy rules on a wallet. Rules will trigger an associated action (set by the user). The policy engine will collect all triggered rule results, and perform any triggered actions in the order of deny, getApproval (from another user), or getOTP (sent via SMS to a specified user).

If a wallet carries a balance and there are more than two “admin” users associated with a Wallet, any policy change will require approval by another administrator before it will take effect (if there are no additional “admin” users, this will not be necessary). It is thus highly recommended to create wallets with at least 2 administrators by performing a wallet share. This way, policy can be effective even if a single user is compromised.

For policies with the getOTP action type, successfully sending a transaction will require a 7 digit OTP before the transaction is signed and sent. This action type lets you offer a Two Factor Authentication security option for your own service, without implementing it yourself. The first attempt to send a transaction will fail and send out the code to the phone specified on the rule. Once you acquire the code from the user, make another send transaction call with the otp code included as a parameter in the API call and the transaction will successfully send. See the otp parameter at Sends Coins to Address for further details.

This documentation provides API and SDK coverage of basic BitGo policy involving a single wallet. Further custom policy may be implemented using the webhook policy type, which causes BitGo to call out to a URL endpoint capable of evaluating any custom policy behavior involving external state.

Advanced policy involving multiple wallets may be implemented by contacting BitGo directly.

Get Policy

WALLET=2NEe9QhKPB2gnQLB3hffMuDcoFKZFjHYJYx

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLET/policy
bitgo.wallets().get({ "id": walletId }, function callback(err, wallet) {
  if (err) {
    throw err;
  }

  wallet.getPolicy({}, function callback(err, policy) {
    if (err) {
      // handle error
    }
    console.dir(policy);
  });
});

Example response

{
  "id": "57d73dedd1187a4a7b2bdeebedddcd6b",
  "version": 0,
  "date": "2016-09-12T23:44:45.462Z",
  "rules": [
    {
      "id": "my velocity limit",
      "type": "velocityLimit",
      "action": {
        "type": "getOTP",
        "actionParams": {
          "otpType": "sms",
          "phone": "+15417543010",
          "duration": "3600"
        }
      },
      "condition": {
        "amount": 10000000,
        "timeWindow": 86400,
        "groupTags": [
          ":tag"
        ],
        "excludeTags": []
      }
    },
    {
      "action": {
          "type": "getApproval"
      },
      "condition": {
        "amount": 200000000
      },
      "id": "com.bitgo.limit.velocity.day",
      "type": "velocityLimit"
    }
  ]
}

Gets the policy rules in operation on a wallet.

HTTP Request

GET /api/v1/wallet/:walletId/policy

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID of the wallet

Response

Returns a Wallet Policy object, containing the rules set up on it

Get Policy Status

WALLET=2NEe9QhKPB2gnQLB3hffMuDcoFKZFjHYJYx

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLET/policy/status
bitgo.wallets().get({ "id": walletId }, function callback(err, wallet) {
  if (err) {
    throw err;
  }

  wallet.getPolicyStatus({}, function callback(err, policy) {
    if (err) {
      // handle error
    }
    console.dir(policy);
  });
});

Example response

{
    "statusResults": [
        {
            "policy": "55380d34d0d3b00364a52285f09e23a4",
            "ruleId": "com.bitgo.limit.velocity.day",
            "status": {
                "remaining": 94982419
            }
        },
        {
            "policy": "55380d34d0d3b00364a52285f09e23a4",
            "ruleId": "com.bitgo.limit.tx",
            "status": {
                "remaining": 200000000
            }
        }
    ]
}

HTTP Request

GET /api/v1/wallet/:walletId/policy/status

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID of the wallet

Response

Returns status results as generated by rules active on the wallet policy, including information about the limit usage.

Set Policy Rule

Add or update a rule to a wallet’s policy. A wallet policy’s rules controls the conditions under which BitGo will use its single key to sign a transaction. An email notification will be sent to all wallet users when a policy is updated. This email is NOT sent for the first time policy is added.

WALLETID=2NFj9CHyY8cLKH4UXsivpRa5xkdvAXqqai9

curl -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{ "action" : { "type" : "getApproval" }, "condition": {"type": "velocity", "amount": 10100000000, "timeWindow": 86400, "groupTags": [":tag"], "excludeTags": [] }, "id": "my velocity limit", "type": "velocityLimit" }' \
https://test.bitgo.com/api/v1/wallet/$WALLETID/policy/rule
var walletId = '2MufYDkh6iwNDtyREBeAXcrRDDAopG1RNc2';
bitgo.wallets().get({ "id": walletId }, function callback(err, wallet) {
  if (err) { throw err; }
  // Sets the policy
  var rule = {
    id: "test1",
    type: "velocityLimit"
    action: { type: "getApproval" },
    condition: {
      "type": "velocity",
      "amount": 101*1e8,
      "timeWindow": 24 * 60 * 60,
      "groupTags": [
        ":tag"
      ],
      "excludeTags": []
    }
  };
  wallet.setPolicyRule(rule, function callback(err, wallet) {
    if (err) { throw err; }
    console.dir(wallet.admin.policy);
  });
});

HTTP Request

PUT /api/v1/wallet/:walletId/policy/rule

BODY Parameters

Policy rule objects have a type, a condition, and an action. The type of policy often dictates the condition values.

Parameter Type Required Example
id the id of the policy “custom1”, “anyUniqueRuleId”
type The type of policy See Policy Types
condition The condition for this policy See Policy Types
action The action to take when the condition is false See Policy Action Object

Example response

{
  "policy": {
    "id": "57d73dedd1187a4a7b2bdeebedddcd6b",
    "version": 0,
    "date": "2016-09-13T00:08:30.661Z",
    "rules": [{
      "id": "my velocity limit",
      "type": "velocityLimit",
      "action": {
        "type": "getApproval"
      },
      "condition": {
        "amount": 10100000000,
        "timeWindow": 86400,
        "groupTags": [
          ":tag"
        ],
        "excludeTags": []
      }
    }]
  }
}

Response

Returns the updated Wallet Model object.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.

Policy Object

The aggregate Wallet Policy is an array of Policy Rule Objects. Policy rule objects have a type, a condition, and an action.

Field Description Possible Values
id the id of the policy “com.bitgo.limit.tx”, “custom1”, “anyUniqueRuleId”
type The type of policy “transactionLimit”, “velocityLimit”, “bitcoinAddressWhitelist”, “webhook”
condition The condition for this policy Depends on policy rule type used
action The action to take when the condition is false See policy action object

Policy Type - velocityLimit

A velocityLimit policy rule will trigger when the amount of Bitcoin spent within the specified time window exceeds the specified amount.

Conditions for this include:

Field Description Possible Values
amount The maximum allowed value of all transactions able to be sent during the time window Number of satoshis
timeWindow The interval of time in which to sum transaction spend amounts and compare to the limit Number of seconds
groupTags List of tags specific operations, “:tag” is appropriate is most circumstances string Array
excludeTags Tags which define the group of wallet ids which, if spent to, will exclude that spend from the limit calculation. Also supports :tag to include current tag context string Array

Policy Type - transactionLimit

A transactionLimit policy rule will trigger when a single transaction exceeds the specified amount.

Conditions for this include:

Field Description Possible Values
amount The maximum allowed value of each transaction on the wallet Number of satoshis

Policy Type - bitcoinAddressWhitelist

When active, a Bitcoin address whitelist rule will be triggered whenever any destination Bitcoin address (non-change) of an outgoing transaction is not in the white list.

Conditions for this include:

Field Description Possible Values
add The bitcoin address to add to the whitelist Bitcoin address
remove The bitcoin address to remove from the whitelist Bitcoin address

Example webhook callback (sent to your server, any non-200 response will trigger the policy rule action)

{
    "approvalCount": 0,
    "outputs": [
        {
            "outputAddress": "2N9kNR8iS46WuwekvQVaTUa74w2fbvAXHQn",
            "outputWallet": "2MufYDkh6iwNDtyREBeAXcrRDDAopG1RNc2",
            "value": 24885327
        },
        {
            "outputAddress": "2N8ryDAob6Qn8uCsWvkkQDhyeCQTqybGUFe",
            "outputWallet": "2N8ryDAob6Qn8uCsWvkkQDhyeCQTqybGUFe",
            "value": 10000000
        }
    ],
    "ruleId": "webhookRule1",
    "spendAmount": 10009060,
    "type": "webhook",
    "unsignedRawTx": "0100000001f8de6273285b13f20b59195c4...",
    "walletId": "2MufYDkh6iwNDtyREBeAXcrRDDAopG1RNc2"
}

Policy Type - webhook

When active, a webhook rule will issue a callback to the HTTPS endpoint specified in the condition. The rule will trigger an action if the HTTPS endpoint returns a non-200 (status) response.

Conditions for this rule:

Field Description Possible Values
url The URL to issue the callback to HTTPs endpoint

Body parameters sent in the callback:

Field Description Possible Values
walletId The ID of the wallet from which the transaction is originating “2N8ryDAob6Qn8uCsWvkkQDhyeCQTqybGUFe”
ruleId The ID of the wallet from which the transaction is originating “webhookPolicy1”
outputs Array of output objects containing outputAddress and value [{ “outputAddress”:“2N9kNR8iS46WuwekvQVaTUa74w2fbvAXHQn”, “value”:24885327}]
spendAmount The net spend amount from the wallet, less change (includes fees) 10009060
approvalCount The number of user approvals on the wallet thus far 0
unsignedRawTx The hex string of the half-signed raw transaction “0100000001… 0794c5382a38700000000”
sequenceId The custom sequence ID provided by the sender when creating a transaction “custom1”

Policy Action Object

An action is the action to take when the condition is not met by a transaction.

Field Description Possible Values
type The type of action “deny”, “getApproval”, “getOTP”
actionParams JSON object containing phone/otpType/duration See below
otpType Determines how the code should be sent (must set type === “getOTP”) “sms”
phone The phone number that will receive the code (must set type === “getOTP”) “541-754-3010”, “+498963648018”
duration The time in seconds the OTP should be valid for (must set type === “getOTP”) 3600

Remove Policy Rule

RULEID='test1'
WALLETID='2MvPJ8GMoFFWdUTh6p42FJV6XpmJEVjxv92'

curl -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"id\": \"$RULEID\" }" \
https://test.bitgo.com/api/v1/wallet/$WALLETID/policy/rule
var walletId = '2MufYDkh6iwNDtyREBeAXcrRDDAopG1RNc2';
bitgo.wallets().get({ "id": walletId }, function callback(err, wallet) {
  if (err) { throw err; }
  wallet.removePolicyRule({ "id": ruleId }, function callback(err, wallet) {
    if (err) { throw err; }
    console.dir(wallet.admin.policy);
  });
});

Example Response

{
  "date": "2015-10-29T23:33:20.166Z",
  "id": "5631d2f48cad5fab2c6abe16682372bb",
  "rules": [ ],
  "version": 5
}

Removes a policy rule with the id specified. This may require a secondary approval if there is more than 1 administrator on the wallet.

HTTP Request

DELETE /api/v1/wallet/:walletId/policy/rule

URL Parameters

Parameter Type Required Description
walletId address (string) Yes The base address of the wallet

BODY Parameters

Parameter Type Required Description
id string Yes the id of the policy rule to remove

Response

Returns the updated Wallet Model object.

Pending Approvals

List Pending Approvals

List pending approvals on a wallet or an enterprise by providing either a wallet id or an enterprise in the url. By default, the request returns all the pending approvals for a user.

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/pendingapprovals?enterprise=$ENTID
var enterpriseId = '2MufYDkh6iwNDtyREBeAXcrRDDAopG1RNc2';
bitgo.pendingapprovals().list({
  "enterpriseId": enterpriseId
}, function(err, pendingapprovals) {
  if (err) { throw err; }
  console.dir(pendingapprovals);
});

Example Response

{
   "pendingApprovals": [
       {
           "createDate": "2015-04-28T21:57:52.747Z",
           "creator": "54c2...0c79",
           "enterprise": "54a2...1e88",
           "id": "5540...0633",
           "info": {
               "policyRuleRequest": {
                   "action": "update",
                   "policyChanged": "553e...84c7",
                   "update": {
                       "action": {
                           "type": "getApproval"
                       },
                       "condition": {
                           "amount": 300000000
                       },
                       "id": "com.bitgo.limit.velocity.day",
                       "type": "velocityLimit"
                   }
               },
               "type": "policyRuleRequest"
           },
           "state": "pending"
       }
   ]
}

HTTP Request

GET /api/v1/pendingapprovals

URL Parameters

Parameter Type Required Description
walletId address (string) No The base address of the wallet
enterprise string No The public ID of the enterprise

Response

Returns a list of pending approvals.

Update Pending Approval

Update the state of a pending approval to either ‘approved’ or ‘rejected’.

curl -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN_OTHERENTERPRISEUSER" \
-d '{ "state": "approved", "otp": "0000000" }' \
https://test.bitgo.com/api/v1/pendingapprovals/:PENDINGAPPROVALID
var enterpriseId = '2MufYDkh6iwNDtyREBeAXcrRDDAopG1RNc2';
bitgo.pendingapprovals().list({
  "enterpriseId": enterpriseId
}, function(err, pendingapprovals) {
  if (err) { throw err; }
  var pendingapproval = pendingapprovals[0];
  pendingapproval.approve({
    "walletPassphrase": "pa55w0rd",
    "otp": "0000000"
  }, function(err, res) {
    if (err) { throw err; }
    console.dir(res);
  });
});

Example Response

{
   "createDate": "2015-04-28T21:58:02.416Z",
   "creator": "54c2...0c79",
   "enterprise": "54a2...1e88",
   "id": "5540...10f7",
   "info": {
       "policyRuleRequest": {
           "action": "update",
           "policyChanged": "553e...84c7",
           "update": {
               "action": {
                   "type": "getApproval"
               },
               "condition": {
                   "amount": 300000000
               },
               "id": "com.bitgo.limit.velocity.day",
               "type": "velocityLimit"
           }
       },
       "type": "policyRuleRequest"
   },
   "resolvers": [
       {
           "date": "2015-04-28T22:02:32.395Z",
           "user": "5458...4fd2"
       }
   ],
   "state": "approved"
}

HTTP Request

PUT /api/v1/pendingapprovals/:pendingApprovalId

URL Parameters

Parameter Type Required Description
pendingApprovalId string Yes The ID of the pending approval to be updated.

BODY Parameters

Parameter Type Required Description
state string Yes the new state of the pending approval: ‘approved’, ‘rejected’
otp string Yes the 2-factor-authentication otp code

Response

Returns the updated pending approvals with the new state.

Address Labels

Labels allow you to keep track of addresses with human readable notes. You can add a label to any valid address; the address does not need to be one controlled by the wallet. Address labels are distinct from wallet labels, but they are tied to a wallet so that when you share the wallet with other users they will be also able to view the labels.

List Labels For All Wallets

curl -X GET \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/labels
bitgo.labels({}, function callback(err, labels) {
  if (err) {
    // handle error
  }
  // do something with labels
  console.dir(labels);
});

Get the list of labels for the user

HTTP Request

GET /api/v1/labels

Example response

{
  "labels": [
    {
      "walletId": "2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf",
      "address": "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD",
      "label": "My Favorite Multi-Sig Address"
    },
    {
      "walletId": "2MyWgQ3PMAWPenJnHJUPpVjFDLHhaPkZCz5",
      "address": "msWpfbCKSaz4wvqtqMwfmFkE58mTKxsRFG",
      "label": "Watch-only Address"
    }
  ]
}

Response

Returns an array of Label Model objects.

Field Description
walletId id of the wallet (also the first receiving address)
address the bitcoin address being labeled
label the address label

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.

List Labels For Specific Wallet

WALLET=2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf
curl -X GET \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/labels/$WALLET
var wallets = bitgo.wallets();
var data = {
  "type": "bitcoin",
  "id": "2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf",
};
wallets.get(data, function callback(err, wallet) {
  if (err) {
    // handle error
  }
  // do something with labels
  wallet.labels({}, function (err, labels) {
    if (err) {
      console.log(err);
      process.exit(-1);
    }
    console.dir(labels);
  });
});

Get the list of labels for the wallet

HTTP Request

GET /api/v1/labels/:walletId

Example response

{
  "labels": [
    {
      "walletId": "2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf",
      "address": "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD",
      "label": "My Favorite Multi-Sig Address"
    }
  ]
}

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID and first address of the wallet

Response

Returns an array of Label Model objects.

Field Description
walletId id of the wallet (also the first receiving address)
address the bitcoin address being labeled
label the address label

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.
404 Not Found The wallet could not be found.

Set Label

WALLET=2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf
ADDRESS=2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD
curl -X PUT \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"label\": \"A Noteworthy Label\" }" \
https://test.bitgo.com/api/v1/labels/$WALLET/$ADDRESS
var wallets = bitgo.wallets();
var data = {
  "type": "bitcoin",
  "id": "2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf",
};
wallets.get(data, function callback(err, wallet) {
  if (err) {
      console.log(err);
      process.exit(-1);
  }
  wallet.setLabel({label: "A Noteworthy Label", address: "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD"}, function (err, label) {
    if (err) {
      console.log(err);
      process.exit(-1);
    }
    console.dir(label);
  });
});

Set a label on a specific address and associate it with a specific wallet. Labels are limited to 250 characters in length. Labels cannot be set on a wallet’s first receiving address because it reserved for the wallet’s label.

HTTP Request

PUT /api/v1/labels/:walletId/:address

Example response

{
  "walletId": "2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf",
  "address": "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD",
  "label": "A Noteworthy Label"
}

URL Parameters

Name Type Required Description
walletId bitcoin address (string) Yes id of the wallet (also the first receiving address)
address bitcoin address (string) Yes the bitcoin address being labeled

PUT Parameters

Name Type Required Description
label string Yes the address label

Response

Returns a Label Model object.

Field Description
walletId id of the wallet (also the first receiving address)
address the bitcoin address being labeled
label the address label

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.
404 Not Found The wallet could not be found.

Delete Label

WALLET=2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf
ADDRESS=2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD
curl -X DELETE \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/labels/$WALLET/$ADDRESS
wallet.deleteLabel({address: "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD"}, function (err, label) {
  if (err) {
    // handle error
  }
  console.dir(label);
});

Delete a label from a specific address and wallet.

HTTP Request

DELETE /api/v1/labels/:walletId/:address

Example response

{
  "walletId": "2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf",
  "address": "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD",
  "label": "A Noteworthy Label"
}

URL Parameters

Name Type Required Description
walletId bitcoin address (string) Yes id of the wallet (also the first receiving address)
address bitcoin address (string) Yes the bitcoin address being labeled

Response

Returns a Label Model object of the label that was deleted.

Field Description
walletId id of the wallet (also the first receiving address)
address the bitcoin address being labeled
label the address label

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
401 Unauthorized The authentication parameters did not match.
404 Not Found The wallet or label could not be found.

Tags

Tags are an advanced policy feature for enterprise clients.

Create a tag

HTTP Request

POST /api/v1/tag

BODY Parameters

The tag must have a name and exactly one of either a user, wallet, or enterprise.

Parameter Type Required Description Possible Values
name string Yes The name of the tag.
user id No The user id of the user who owns the tag, which can only be the id of the user adding the tag.
wallet id No The id, not bitcoin address, of the wallet to own the tag.
enterprise id No The id of the enterprise to own the tag.

Response

Returns the tag.

{
  "_id": "[id]",
  "name": "name of tag",
  "user": "[id]"
}

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.

Add a tag to a wallet

HTTP Request

POST /api/v1/wallet/:walletId/tag

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID and first address of the wallet

BODY Parameters

You must specify the id of the tag you are adding to the wallet, and no other parameters are required.

Parameter Type Required Description Possible Values
tag id Yes The id of the tag.

Response

Returns the wallet, tag, and number of wallettxs affected.

{
  "wallet": "[id]",
  "tag": "[id]",
  "walletTxsAffected": 0
}

Errors

Response Description
404 Not Found The tag was not found

Webhook Notifications

Example transaction Webhook callback

POST http://your.server.com/webhook

{
  "type": "transaction",
  "walletId": "2MwLxgWaAGmMT9asT4nAdeewWzPEz3Sn5Eg",
  "hash": "c9a55f32d4b63d02a617eea58873227e4f011d0dfc836cb2e9cab531c4db0c4a"
}

Example pending approval Webhook callback

POST http://your.server.com/webhook
{
  "type": "pendingapproval",
  "pendingApprovalId": "55e79a1b5f9a20da1d3fe5b988a71c93",
  "walletId": "2MwLxgWaAGmMT9asT4nAdeewWzPEz3Sn5Eg",
  "state": "accepted"
}

Webhooks may be setup up to programmatically receive callbacks from BitGo. These may be attached to wallets (in the case of transactions), or to a user (for block notifications). Webhook notifications are triggered when the specified event occurs, such as an incoming transaction.

BitGo servers will make a POST http request to the URL defined with a JSON payload, and expect a HTTP 200 OK. If a successful response is not received, BitGo will attempt to retry the webhook with an increasing delay between each retry.

Developers should take care to ensure that their application succeeds even in the cases of transient network error, or if receive the same webhook twice due to an improper acknowledgement.

Request Schema

The Webhook URL will be called with the following JSON-encoded fields in the HTTP body.

Field Description
type type of Webhook: ‘transaction’, ‘transactionExpire’, ‘transactionRemoved’, ‘block’, and ‘pendingapproval’.
walletId ID of the wallet associated with the webhook event, if this is a wallet webhook.
hash transaction ID, if this is a transaction webhook
pendingApprovalId pending approval ID, if this is a pending approval webhook
state the state of the pending approval (pending, approved, or rejected), if this is a pending approval webhook

Webhook Types

BitGo is currently actively working on webhooks. Please get in touch with us to request more webhook types.

Type Description
transaction Activates when a transaction is seen/confirmed on any receive address of a wallet.
transactionRemoved Activates when a transaction is removed from a user’s wallet due to a reorganization, a conflict with a confirmed transaction, or if a malleated version of the transaction was confirmed.
transactionExpire Activates when a transaction is about to expire. Transactions expire after 2 weeks waiting for a confirmation.
pendingapproval Activates when a pending approval pertaining to a user’s wallet is created, approved, or rejected.
block Activates when a new block is seen on the Bitcoin network.

List Wallet Webhooks

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/wallet/$WALLETID/webhooks
bitgo.wallets().get({ "id": walletId }, function(err, wallet) {
    wallet.listWebhooks({}, function callback(err, result) {
        console.dir(result);
    });
});

Example Response

[
    {
      "walletId": "2NGJP7z9DZwyVjtY32YSoPqgU6cG2QXpjHu",
      "type": "transaction",
      "url": "http://www.yoursite.com/partner/webhooks"
    },
    {
      "walletId": "2NGJP7z9DZwyVjtY32YSoPqgU6cG2QXpjHu",
      "type": "transaction",
      "url": "http://www.company2.com/api/webhooks",
      "numConfirmations": 3
    }
]

Gets list of webhooks set up on the wallet. Currently, the only types of webhooks that can be attached to a wallet are transaction and pendingapproval notifications.

HTTP Request

GET /api/v1/wallet/:walletId/webhooks

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID and first address of the wallet

Response

An array of Webhook objects

Field Description
walletId id of the wallet
type type of Webhook, e.g. transaction
url http/https url for callback requests

Add Wallet Webhooks

WALLETID=2NGJP7z9DZwyVjtY32YSoPqgU6cG2QXpjHu
URL='http://www.yoursite.com/partner/webhooks'

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"url\": \"$URL\", \"type\": \"transaction\" }" \
https://test.bitgo.com/api/v1/wallet/$WALLETID/webhooks
bitgo.wallets().get({ "id": walletId }, function(err, wallet) {
    wallet.addWebhook({ url: url, type: 'transaction' }, function callback(err, result) {
        console.dir(result);
    });
});

Example Response

{
  "walletId": "2NGJP7z9DZwyVjtY32YSoPqgU6cG2QXpjHu",
  "type": "transaction",
  "url": "http://www.yoursite.com/partner/webhooks"
}

Adds a Webhook that will result in a HTTP callback at the specified URL from BitGo when events are triggered. There is a limit of 10 Webhooks of each type per wallet.

There are 2 types of wallet webhooks available: 1. Transaction webhooks will fire on any transaction on the wallet. 2. Pending approval webhooks will fire when an outgoing transaction has triggered policy on the wallet.

HTTP Request

POST /api/v1/wallet/:walletId/webhooks

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID and first address of the wallet

Parameters

Parameter Type Required Description
type string Yes type of Webhook, e.g. transaction or pendingapproval
url string Yes valid http/https url for callback requests
numConfirmations integer No number of confirmations before triggering the transaction webhook. If 0 or unspecified, requests will be sent to the callback endpoint will be called when the transaction is first seen and when it is confirmed.

Response

Field Description
walletId id of the wallet
type type of Webhook, e.g. transaction
url http/https url for callback requests

Remove Wallet Webhooks

WALLETID=2NGJP7z9DZwyVjtY32YSoPqgU6cG2QXpjHu
URL='http://www.yoursite.com/partner/webhooks'

curl -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"url\": \"$URL\", \"type\": \"transaction\" }" \
https://test.bitgo.com/api/v1/wallet/$WALLETID/webhooks
bitgo.wallets().get({ "id": walletId }, function(err, wallet) {
    wallet.removeWebhook({ url: url, type: 'transaction' }, function callback(err, result) {
        console.dir(result);
    });
});

Example Response

{
  "removed": 1
}

Removing a Webhook will cause new events of the specified type to no longer trigger HTTP callbacks to your URLs.

HTTP Request

DELETE /api/v1/wallet/:walletId/webhooks

URL Parameters

Parameter Type Required Description
walletId bitcoin address (string) Yes The ID and first address of the wallet

Parameters

Parameter Type Required Description
type string Yes type of Webhook, e.g. transaction
url string Yes valid http/https url for callback requests to be made at

Response

Field Description
walletId id of the wallet
type type of Webhook, e.g. transaction
url http/https url for callback requests

List User Webhooks

curl -X GET \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
https://test.bitgo.com/api/v1/webhooks
bitgo.listWebhooks({}, function callback(err, result) {
  console.dir(result);
});

Example Response

[
    {
        "type": "block",
        "coin": "bitcoin",
        "url": "https://303fe960.ngrok.com"
    },
    {
        "type": "block",
        "coin": "bitcoin",
        "url": "http://www.yoursite.com/partner/webhooks"
    }
]

Gets list of webhooks attached to the user. Currently, the only type of webhook that can be attached to a user is a block notification.

HTTP Request

GET /api/v1/webhooks

Response

An array of Webhook objects

Field Description
type type of Webhook, e.g. block
coin string
url http/https url for callback requests

Add User Webhooks

URL='https://303fe960.ngrok.com'

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"url\": \"$URL\", \"type\": \"block\", \"coin\": \"bitcoin\" }" \
https://test.bitgo.com/api/v1/webhooks
bitgo.addWebhook({ url: url, type: 'block', coin: 'bitcoin' }, function callback(err, result) {
        console.dir(result);
    });
});

Example Response

{
  "type": "block",
  "type": "bitcoin",
  "url": "http://www.yoursite.com/partner/webhooks"
}

Adds a webhook that will result in a HTTP callback at the specified URL from BitGo when events are triggered. The webhook record is attached to the user account.

HTTP Request

POST /api/v1/webhooks

Parameters

Parameter Type Required Description
type string Yes type of Webhook, e.g. block
coin string No the network token e.g. “bitcoin” or “eth” (defaults to bitcoin)
url string Yes valid http/https url for callback requests

Response

Field Description
type type of Webhook, e.g. block
url http/https url for callback requests

Remove User Webhooks

URL='http://www.yoursite.com/partner/webhooks'

curl -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d "{ \"url\": \"$URL\", \"type\": \"block\" }" \
https://test.bitgo.com/api/v1/webhooks
bitgo.removeWebhook({ url: url, type: 'block' }, function callback(err, result) {
  console.dir(result);
});

Example Response

{
  "removed": 1
}

Removing a Webhook will cause new events of the specified type to no longer trigger HTTP callbacks to your URLs.

HTTP Request

DELETE /api/v1/webhooks

Parameters

Parameter Type Required Description
type string Yes type of Webhook, e.g. transaction
url string Yes valid http/https url for callback requests to be made at

Response

Field Description
type type of Webhook, e.g. transaction
url http/https url for callback requests

Utilities

This section describes utility services provided as part of the BitGo API.

Decrypt

var encryptedString = '{"iv":"n4zHXVTi/Go/riCP8fNs/A==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"zvLyve+4AJU=","ct":"gNMqheicMoD8ZmNzRwuQfWGAh+HA933l"}';
var decryptedString = bitgo.decrypt({ password: "password", input: encryptedString });
// decryptedString = "this is a secret"
Available only as a local method (BitGo Express)

PASSWORD='password'
INPUT='{\"iv\":\"n4zHXVTi/Go/riCP8fNs/A==\",\"v\":1,\"iter\":10000,\"ks\":256,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"zvLyve+4AJU=\",\"ct\":\"gNMqheicMoD8ZmNzRwuQfWGAh+HA933l\"}'

curl -X POST \
-H "Content-Type: application/json" \
-d "{ \"password\": \"$PASSWORD\", \"input\": \"$INPUT\" }" \
http://$BITGO_EXPRESS_HOST:3080/api/v1/decrypt

{ "decrypted" : "this is a secret" }

Client-side function to decrypt an encrypted blob from the BitGo API.

Encrypt

var encryptedString = bitgo.encrypt({ password: "password", input: "this is a secret" });
// encyrptedString = "{\"iv\":\"n4zHXVTi/Go/riCP8fNs/A==\",\"v\":1,\"iter\":10000,\"ks\":256,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"zvLyve+4AJU=\",\"ct\":\"gNMqheicMoD8ZmNzRwuQfWGAh+HA933l\"}"
Available only as a local method (BitGo Express)

PASSWORD='password'
INPUT='this is a secret'

curl -X POST \
-H "Content-Type: application/json" \
-d "{ \"password\": \"$PASSWORD\", \"input\": \"$INPUT\" }" \
http://$BITGO_EXPRESS_HOST:3080/api/v1/encrypt

{ "encrypted" : "{\"iv\":\"U4uRz85ytmlCeTe2P3iOmg==\",\"v\":1,\"iter\":10000,\"ks\":256,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"zvLyve+4AJU=\",\"ct\":\"/tRnUh9LUyI7L5e5LPqpvnPR7RD1CdUi\"}" }

Client-side function to encrypt a string. All data stored with BitGo is encrypted using this API.

Estimate Transaction Fees

bitgo.estimateFee({ numBlocks: 6 }, function callback(err, res) {
  console.dir(res);
});
curl -k https://www.bitgo.com/api/v1/tx/fee?numBlocks=6

Returns the recommended fee rate per kilobyte to confirm a transaction within a target number of blocks. This can be used to construct transactions.

HTTP Request

GET /api/v1/tx/fee?numBlocks=6

Example response

{ "feePerKb": 21949,
    "numBlocks": 6,
    "confidence": 80,
    "multiplier": 1,
    "feeByBlockTarget": {
        "1": 62246,
        "2": 47730,
        "3": 35130,
        "4": 32837,
        "6": 21949,
        "7": 20017,
        "8": 18644,
        "9": 16545,
    }
}

Parameters

Parameter Type Required Description
numBlocks number No The target number of blocks for the transaction to be confirmed. The accepted range is 1 - 1000 and the default value is 2.
maxFee number No The maximum fee in satoshi per kilobyte that will be returned by the fee estimator.
cpfpAware boolean No Indicates that the estimation should account for child-pays-for-parent, default is false.
txSize number No Size of the transaction in bytes, only used in combination with cpfpAware:true.
inputs array of strings No List of txIDs identifying unconfirmed transactions that the desired CPFP transaction will spend outputs from, is only used in combination with cpfpAware:true.

Response

Field Description
confidence Confidence of the estimation as used by BitGo. Do not use estimation if this value is less than 85.
feePerKb The estimated fee rate in satoshis per kilobyte for the requested target number of blocks.
multiplier Multiplier amount used by BitGo to compute the feePerKb. informational only - do not use.
numBlocks The target number of blocks requested for the estimate
feeByBlockTarget List of fee rates for block targets between 1 and 1000. The response only includes the blocks for which the fee rate changes compared to the preceding block.

Market Price Data

bitgo.markets().latest({}, function callback(err, market) {
  if (err) {
    // handle error
  }
  // etc
});
curl -k https://test.bitgo.com/api/v1/market/latest

Get information about the current market

HTTP Request

GET /api/v1/market/latest

Example Market Model response

    {  
      "latest":{  
        "_id":"2017-01-03T00:00:00.000Z",
        "currencies":{  
          "cacheTime":1483464065150,
          "ZAR":{  
            "24h_avg":14166.72,
            "total_vol":68474.29,
            "timestamp":1483464063,
            "last":14233.45,
            "bid":14227.79,
            "ask":14241.92,
            "cacheTime":1483461006210,
            "monthlyLow":10388.73,
            "monthlyHigh":14265.1,
            "prevDayLow":13742.4,
            "prevDayHigh":14265.1,
            "lastHourLow":14126.03,
            "lastHourHigh":14232.02
          },
          "USD":{  
            "24h_avg":1027.58,
            "total_vol":68474.29,
            "timestamp":1483464063,
            "last":1032.42,
            "bid":1032.01,
            "ask":1033.03,
            "cacheTime":1483461006231,
            "monthlyLow":753.08,
            "monthlyHigh":1037.5,
            "prevDayLow":1003.66,
            "prevDayHigh":1037.5,
            "lastHourLow":1024.91,
            "lastHourHigh":1032.6
          },
          "INR":{  
            "24h_avg":70270.03,
            "total_vol":68474.29,
            "timestamp":1483464063,
            "last":70601.02,
            "bid":70572.95,
            "ask":70643.03,
            "cacheTime":1483461004821,
            "monthlyLow":51327.43,
            "monthlyHigh":70797.84,
            "prevDayLow":68392.91,
            "prevDayHigh":70797.84,
            "lastHourLow":70104.36,
            "lastHourHigh":70630.36
          },
          "GBP":{  
            "24h_avg":838.49,
            "total_vol":68474.29,
            "timestamp":1483464063,
            "last":842.44,
            "bid":842.1,
            "ask":842.94,
            "cacheTime":1483461016786,
            "monthlyLow":591.95,
            "monthlyHigh":843.7,
            "prevDayLow":816.89,
            "prevDayHigh":843.7,
            "lastHourLow":836.5,
            "lastHourHigh":842.77
          },
          "EUR":{  
            "24h_avg":986.6,
            "total_vol":68474.29,
            "timestamp":1483464063,
            "last":991.25,
            "bid":990.86,
            "ask":991.84,
            "cacheTime":1483461001800,
            "monthlyLow":703.68,
            "monthlyHigh":996.2,
            "prevDayLow":959.52,
            "prevDayHigh":996.2,
            "lastHourLow":986.51,
            "lastHourHigh":993.91
          },
          "CNY":{  
            "24h_avg":7152.68,
            "total_vol":68474.29,
            "timestamp":1483464063,
            "last":7186.37,
            "bid":7183.51,
            "ask":7190.64,
            "cacheTime":1483462551515,
            "monthlyLow":5183.77,
            "monthlyHigh":7207.67,
            "prevDayLow":6970.52,
            "prevDayHigh":7207.67,
            "lastHourLow":7134.19,
            "lastHourHigh":7187.72
          },
          "CAD":{  
            "24h_avg":1381.13,
            "total_vol":68474.29,
            "timestamp":1483464063,
            "last":1387.63,
            "bid":1387.08,
            "ask":1388.46,
            "cacheTime":1483461014145,
            "monthlyLow":1002.36,
            "monthlyHigh":1392.95,
            "prevDayLow":1348.37,
            "prevDayHigh":1392.95,
            "lastHourLow":1375.99,
            "lastHourHigh":1386.31
          },
          "AUD":{  
            "24h_avg":1421.25,
            "total_vol":68474.29,
            "timestamp":1483464063,
            "last":1427.95,
            "bid":1427.38,
            "ask":1428.8,
            "cacheTime":1483461004781,
            "monthlyLow":1013.22,
            "monthlyHigh":1443.58,
            "prevDayLow":1393.18,
            "prevDayHigh":1443.58,
            "lastHourLow":1418.88,
            "lastHourHigh":1429.53
          }
        },
        "__v":0
      }
    }

Response

Returns a Market Model object. All prices are denominated in the user’s set currency.

Field Description
24h_avg Average market price over the last 24 hours
total_vol 24 hour volume of bitcoins exchanged
timestamp Unix timestamp this data was gathered at
last Latest market price
bid Highest current bid price
ask Lowest current ask price
cachetime Internal value used by BitGo
monthlyLow The lowest monthly market price
monthlyHigh The highest monthly market price
prevDayLow The lowest market price of the previous day
prevDayHigh The highest market price of the previous day
lastHourLow The lowest market price of the last hour
lastHourHigh The highest market price of the last hour

Malware Address List

curl https://www.bitgo.com/api/v1/malware/bitcoin

BitGo maintains a list of addresses known to be used by address-swapping malware. BitGo will refuse to co-sign transactions to these addresses. This API provides the list of addresses which are currently blocked by BitGo. We recommend periodically polling this list (once a day, perhaps), in order to maintain your own block list. Otherwise you may accidentally submit bad transactions to BitGo, if one of your customers is infected and requests a withdrawal.

HTTP Request

GET /api/v1/malware/bitcoin

Example response

{
  "readme": "This is a list of addresses known by BitGo to be tied to bitcoin-stealing malware. BitGo will not co-sign transactions going to these addresses. It is recommended to periodically query this API to update your own internal list of bad addresses, in order to prevent transaction failures.",
  "addresses": [
    {
      "address": "19ZM2pjq6U4jVb283GZkCPNukjeyb2YZ2u"
    },
    {
      "address": "1EZV9ghJ4rCvwtVE27ZUxY6she4GzeEzCf"
    }
  ]
}

Response

Field Description
readme Human-readable explanation of this list
addresses List of { address: xxx } objects

Verify Bitcoin Address

var isValid = bitgo.verifyAddress({ address: "1AJbsFZ64EpEfS5UAjAfcUG8pH8Jn3rn1F" });
Available only as a local method (BitGo Express)

curl -X POST \
-H "Content-Type: application/json" \
-d '{ "address": "2NFasKP9nqHHUBvVHvEGkuHpNA3hjdkUhAV" }' \
http://$BITGO_EXPRESS_HOST:3080/api/v1/verifyaddress

Client-side function to verify that a given string is a valid Bitcoin Address. Supports both v1 addresses (e.g. “1…”) and P2SH addresses (e.g. “3…”).

Returns true if the address is valid.

BitGo Client Version

var version = bitgo.version();

Client-side function to get the version of this BitGo SDK.

Returns a string.

Blockchain Data

BitGo provides a public API for getting blockchain data on addresses and transactions. These APIs do not relate to the concept of BitGo users or wallets. The purpose of this API endpoint is to allow API consumers to get data on non-BitGo addresses and transactions (similar to the concept of txindex and watchonly in the Satoshi client).

For most wallet use cases, developers will want to use the Wallet and Keychain APIs. They support many more operations, such as checking the combined balances of HD wallets, creating addresses, sending transactions, etc.

Get Address

Lookup an address with balance info.

ADDRESS=2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD
curl https://test.bitgo.com/api/v1/address/$ADDRESS
var address = "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD";
bitgo.blockchain().getAddress({ address: address }, function(err, response) {
  if (err) { console.log(err); process.exit(-1); }
  console.dir(response);
});

HTTP Request

GET /api/v1/address/:address

URL Parameters

Parameter Type Required Description
address bitcoin address (string) Yes The bitcoin address

Example response

{
  "address": "2N76BgbTnLJz9WWbXw15gp6K9mE5wrP4JFb",
  "balance": 6900000,
  "confirmedBalance": 6900000
}

Response

Returns address summary information.

Field Description
address The address
balance the balance, including transactions with 0 confirmations
confirmedBalance the confirmed balance

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.
404 Not Found The address was not found

Get Address Transactions

Get transactions for a given address, ordered by reverse block height.

ADDRESS=2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD
curl https://test.bitgo.com/api/v1/address/$ADDRESS/tx
var address = "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD";
bitgo.blockchain().getAddressTransactions({address: address}, function(err, response) {
  if (err) { console.log(err); process.exit(-1); }
  console.log(JSON.stringify(response, null, 4));
});

HTTP Request

GET /api/v1/address/:address/tx

URL Parameters

Parameter Type Required Description
address bitcoin address (string) Yes The bitcoin address

QUERY Parameters

Parameter Type Required Description
skip number No The starting index number to list from. Default is 0.
limit number No Max number of results to return in a single call (default=25, max=250)

Example response

{
    "transactions": [
        {
            "id": "951aea423c6ba55ac4e6aba953c1dc08e4854bcdf07cb505c4c69447a3f9712e",
            "caption": "test sending",
            "date": "2014-11-13T01:47:10.000Z",
            "pending": false,
            "entries": [
                {
                    "account": "2MxrfrSPNhj1yVrC1CqyNRMFR8WtM7XxpS7",
                    "value": 1890000
                },
                {
                    "account": "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD",
                    "value": -6900000
                },
                {
                    "account": "2N91XzUxLrSkfDMaRcwQhe9DauhZMhUoxGr",
                    "value": 5000000
                }
            ]
        },
        {
            "id": "c7e823fe39d1f0a4081bbefe53f67ebf117189b43a92da3225aa2e4247e35c68",
            "date": "2014-11-13T01:07:05.000Z",
            "pending": false,
            "entries": [
                {
                    "account": "muqrFWxvQiN6KTSZcUugxivMre2fCHnFnF",
                    "value": -104350000
                },
                {
                    "account": "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD",
                    "value": 6900000
                },
                {
                    "account": "mrGtgBbfp5jnqK6c4QNcad6WdHYQr67W8N",
                    "value": 97440000
                }
            ]
        }
    ],
    "start": 0,
    "count": 2,
    "total": 2
}

Response

Returns an array of Transaction objects. Each transaction contains summary information about how that transaction affected the net balance of any bitcoin address involved in the transaction.

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.

Get Address Unspent Outputs

Get unspent outputs going into a given address. Ordered by descending block height (unconfirmed transactions first).

ADDRESS=2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD
curl https://test.bitgo.com/api/v1/address/$ADDRESS/unspents
var address = "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD";
bitgo.blockchain().getAddressUnspents({address: address}, function(err, response) {
  if (err) { console.log(err); process.exit(-1); }
  console.log(JSON.stringify(response, null, 4));
});

HTTP Request

GET /api/v1/address/:address/unspents

URL Parameters

Parameter Type Required Description
address bitcoin address (string) Yes The bitcoin address

Example response

{
    "pendingTransactions": false,
    "unspents": [
        {
            "address": "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD",
            "blockHeight": 308023,
            "confirmations": 85670,
            "date": "2015-04-15T23:31:34.918Z",
            "script": "a9147bd4d50e34791a6373bfa0175bf2cb9796a08f5587",
            "tx_hash": "777cb752b4ecaf84fc3716cc5790cd84d7481764b40d496d81d997e04112818d",
            "tx_output_n": 0,
            "value": 3200000
        },
        {
            "address": "2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD",
            "blockHeight": 308749,
            "confirmations": 84944,
            "date": "2015-04-15T23:31:23.919Z",
            "script": "a9147bd4d50e34791a6373bfa0175bf2cb9796a08f5587",
            "tx_hash": "6a75bda7016698abcd903b4b005b9ba306324a8d50bee932237ffde50a5a9eba",
            "tx_output_n": 0,
            "value": 100000
        }
    ]
}

Response

Returns an array of unspent Transaction objects. Each transaction contains the following information

Name Type Description
address string The address with the unspent output
tx_hash number Amount in satoshis of the output unspent
tx_output_n number Amount in satoshis of the output unspent
value number Amount in satoshis of the output unspent
blockheight number The height in which the transaction was seen
confirmations number The number of confirmations for this transaction
date date The datetime the transaction was seen on the network
script string The output bitcoin script in hex format

Errors

Response Description
400 Bad Request The request parameters were missing or incorrect.

Get Transaction Details

TX=af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648
curl https://test.bitgo.com/api/v1/tx/$TX
var txId = 'af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648';
bitgo.blockchain().getTransaction({id: txId}, function(err, response) {
  if (err) { console.log(err); process.exit(-1); }
  console.log(JSON.stringify(response, null, 4));
});

Gets details for a transaction hash

HTTP Request

GET /api/v1/tx/:txid

URL Parameters

Parameter Type Required Description
txid string Yes The transaction ID (hash)

Example response

{
  "blockhash": "000000009249e7d725cc087cb781ade1dbfaf2bd777822948d5fccd4044f8299",
  "confirmations": 16679,
  "date": "2014-11-06T02:22:55.000Z",
  "entries": [
    {
      "account": "2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov",
      "value": 84000000
    },
    {
      "account": "msj42CCGruhRsFrGATiUuh25dtxYtnpbTx",
      "value": -85900000
    },
    {
      "account": "mwahoJcaVuy2TiMtGDZV9PaujFeD9z1a1q",
      "value": 1890000
    }
  ],
  "fee": 10000,
  "height": 306695,
  "hex": "0100000001b6e8b36132d351b3d66b5452d8f4601e2271a7bb52b644397db956a4ffe2a053000000006a4730440220127c4adc1cf985cd884c383e69440ce4d48a0c4fdce6bf9d70faa0ee8092acb80220632cb6c99ded7f261814e602fc8fa8e7fe8cb6a95d45c497846b8624f7d19b3c012103df001c8b58ac42b6cbfc2223b8efaa7e9a1911e529bd2c8b7f90140079034e75ffffffff0200bd01050000000017a914c449a7fafb3b13b2952e064f2c3c58e851bb943087d0d61c00000000001976a914b0379374df5eab8be9a21ee96711712bdb781a9588ac00000000",
  "id": "af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648",
  "inputs": [
    {
      "previousHash": "53a0e2ffa456b97d3944b652bba771221e60f4d852546bd6b351d33261b3e8b6",
      "previousOutputIndex": 0
    }
  ],
  "outputs": [
    {
      "account": "2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov",
      "value": 84000000,
      "vout": 0
    },
    {
      "account": "mwahoJcaVuy2TiMtGDZV9PaujFeD9z1a1q",
      "value": 1890000,
      "vout": 1
    }
  ],
  "pending": false
}

Response

Returns detailed information on a transaction, including net effects on all bitcoin addresses involved in the transaction.

Get Transaction That Spends A Given Output ID

TX=af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648
VOUT=0
curl https://test.bitgo.com/api/v1/tx/input/$TX/$VOUT
var txId = 'af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648';
var vout = 0;
bitgo.blockchain().getTransactionByInput({ txId: txId, vout: vout }, function(err, response) {
  if (err) { console.log(err); process.exit(-1); }
  console.log(JSON.stringify(response, null, 4));
});

Gets details for a transaction that spends a specific output ID of another transaction

HTTP Request

GET /api/v1/tx/input/:txid/:vout

URL Parameters

Parameter Type Required Description
txid string Yes The transaction ID (hash) of the output that was spent
vout number Yes The vout (output position on the parent transaction) of the output that was spent

Example response

{
  transactions:
  [
    {
      "blockhash": "000000009249e7d725cc087cb781ade1dbfaf2bd777822948d5fccd4044f8299",
      "confirmations": 16679,
      "date": "2014-11-06T02:22:55.000Z",
      "entries": [
        {
          "account": "2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov",
          "value": 84000000
        },
        {
          "account": "msj42CCGruhRsFrGATiUuh25dtxYtnpbTx",
          "value": -85900000
        },
        {
          "account": "mwahoJcaVuy2TiMtGDZV9PaujFeD9z1a1q",
          "value": 1890000
        }
      ],
      "fee": 10000,
      "height": 306695,
      "hex": "0100000001b6e8b36132d351b3d66b5452d8f4601e2271a7bb52b644397db956a4ffe2a053000000006a4730440220127c4adc1cf985cd884c383e69440ce4d48a0c4fdce6bf9d70faa0ee8092acb80220632cb6c99ded7f261814e602fc8fa8e7fe8cb6a95d45c497846b8624f7d19b3c012103df001c8b58ac42b6cbfc2223b8efaa7e9a1911e529bd2c8b7f90140079034e75ffffffff0200bd01050000000017a914c449a7fafb3b13b2952e064f2c3c58e851bb943087d0d61c00000000001976a914b0379374df5eab8be9a21ee96711712bdb781a9588ac00000000",
      "id": "af867c86000da76df7ddb1054b273ca9e034e8c89d049b5b2795f9f590f67648",
      "inputs": [
        {
          "previousHash": "53a0e2ffa456b97d3944b652bba771221e60f4d852546bd6b351d33261b3e8b6",
          "previousOutputIndex": 0
        }
      ],
      "outputs": [
        {
          "account": "2NB96fbwy8eoHttuZTtbwvvhEYrBwz494ov",
          "value": 84000000,
          "vout": 0
        },
        {
          "account": "mwahoJcaVuy2TiMtGDZV9PaujFeD9z1a1q",
          "value": 1890000,
          "vout": 1
        }
      ],
      "pending": false
    }
  ]
}

Response

Returns detailed information on a transaction, including net effects on all bitcoin addresses involved in the transaction.

Get Block

BLOCK=00000000000000066fff8a67fbb6fac31e9c4ce5b1eabc279ce53218106aa26a
curl https://test.bitgo.com/api/v1/block/$BLOCK
var blockId = '00000000000000066fff8a67fbb6fac31e9c4ce5b1eabc279ce53218106aa26a';
bitgo.blockchain().getBlock({id: blockId}, function(err, response) {
  if (err) { console.log(err); process.exit(-1); }
  console.log(JSON.stringify(response, null, 4));
});

Gets a Bitcoin block and the transactions within it. You can use ‘latest’ to get the latest block on the bitcoin network.

HTTP Request

GET /api/v1/block/latest

GET /api/v1/block/:blockHeight

GET /api/v1/block/:blockHash

URL Parameters

Parameter Type Required Description
id variable Yes The block hash (string), height (number) or ‘latest’ for the latest block
extended boolean No Set to true to return details on each transaction within the block

Example response

{
    "chainWork": "60359949399610308617",
    "date": "2015-04-15T23:05:50.139Z",
    "fees": 21226,
    "height": 326945,
    "id": "00000000000000066fff8a67fbb6fac31e9c4ce5b1eabc279ce53218106aa26a",
    "merkleRoot": "0b9c0bf5193fece523780bf92e3ad05025371a3d86987005a7316c35c507dcc3",
    "nonce": 924308913,
    "previous": "00000000eecd159babde9b094c6dbf1f4f63028ba100f6f092cacb65f04afc46",
    "value": 66640872300,
    "version": 2,
    "transactions": [
        "e393422e5a0b4c011f511cf3c5911e9c09defdcadbcf16ceb12a47a80e257aaa",
        "fe429dd68ef56613a038238e81b19e2158ef3ad9d9535d1127018bb78ff83537",
        "e1ee8183626b7854c80563d809f85acc6c7cd878de599bee291d0f759a7b2264",
        "dee33ab621e5409c65948d330f01e1adadb533b0f726d80d48e20bb434b4b542",
        "7d83ee2d59e06bc7efe49c647289d98842a7e9ec3b90c3cc965a81df08c08c8f"
    ]
}

Response

Name Type Description
date datetime The timestamp the block was seen on the network
id string Hash of the block
previous string Hash of the previous block in the chain
transactions array Array of transaction hashes (strings) that are in the block

BitGo Instant

BitGo Instant allows sending on-chain transactions which can be credited instantly by recipients, due to a financial guarantee by BitGo against double-spending. Anyone can receive BitGo Instant transactions. In order to send BitGo Instant transactions, you will need either a BitGo KRS wallet, or will need to arrange a collateral agreement with BitGo.

Receiving

In order to credit BitGo Instant transactions instantly, you will need to respect the instant: true property on the transaction objects returned from the List Wallet Transactions and Get Wallet Transaction APIs. Instant transactions will also have a field instantId which can be used to Get the Instant Guarantee on a transaction.

Sending

You will first need a BitGo Instant-compatible wallet. This can be done by creating a KRS-enabled wallet in the web interface, or using the Create Wallet API with a backupXpubProvider specified. If you have an existing non-KRS wallet, it can be upgraded to BitGo Instant-capable by arranging a collateral agreement with BitGo.

In order to send a BitGo Instant transaction, use the instant: true flag on any of the transaction APIs, such as Send Coins to Address or Create Transaction. BitGoD also has the capability to send BitGo Instant transactions through its JSON interface.

BitGo Instant transactions have stricter requirements about the depths of the inputs being spent. This means that the balance of a wallet available for sending a BitGo Instant transaction may be less than the total balance of the wallet. The instantBalance property on the wallet object returned by the Get Wallet API will tell you the available balance for sending a BitGo Instant transaction.

When sending a BitGo Instant transaction, the transaction may fail if you do not have enough confirmed unspents in your wallet, or if the transaction would cause you to exceed the risk limits supported for your wallet. The risk limit is determined by the amount of collateral pledged, or by a risk limit BitGo applies to all wallets served by a particular KRS. You will need to handle potential failures when sending a BitGo Instant transaction, and possibly retry as a standard transaction.

BitGo Instant transactions are provided at no additional cost to any customer on our standard transactional pricing plans, including volume discount plans.

Partner OAuth

BitGo partners may utilize our OAuth endpoints to obtain authorized access and perform actions on behalf of 3rd party BitGo accounts. BitGo complies with the OAuth standard to allow secure access to customer accounts while keeping their passwords safe.

To begin, partners should obtain OAuth application parameters by getting in touch with us. The OAuth flow typically goes as follows:

  1. You redirect users to log into BitGo via our OAuth gateway at https://www.bitgo.com/oauth/authorize. In the parameters of this request, you specify the client id, redirect uri and scope.
  2. The user reaches the BitGo OAuth gateway. We ask them if it’s ok for you to gain access to the requested scope. They log in with their password and 2FA to confirm.
  3. We redirect the user back to your redirect Uri, with a code parameter. This authorization code is valid for use by your client ID only.
  4. You send the authorization code back to your servers and create a request to BitGo servers with the code, client id and secret. We exchange this for an access token.
  5. You use the access token in the Authorization header to make API calls on behalf of the BitGo user.

OAuth Variables

Name Description
Client Id A string (name) of the OAuth application seeking access to 3rd party accounts. This will be public.
Client Secret A secret string, stored on the server of the OAuth consumer, used to convert authorization codes for the client id to access tokens.
Redirect Uris A list of acceptable redirect URIs. When you send users to our OAuth gateway for authorization, we send them back to a Uri on your site with the authorization code.
Scope A list of OAuth scopes. These are the scopes that your application will be allowed to request for from the user.

Scope Values

The scope values define the allowed operations within an OAuth session. These scopes should be provided to the BitGo OAuth gateway such that BitGo may inform the user of your intent and assign you an appropriate authentication code with the requested scope.

Please specify scopes separated using spaces, e.g. “openid profile wallet_view_enterprise wallet_spend_enterprise”.

Note that more powerful scopes do not encompass basic ones, ie. wallet_spend does not encompass wallet_view, so you should request for both.

OAuth Scope Value Description of Allowed Actions
openid Verify the user is logged in and get their User ID
profile Get the user’s profile, including email and phone number
wallet_create Create wallets on behalf of the user
wallet_view_enterprise View wallets created under their enterprise
wallet_spend_enterprise Spend Bitcoin from wallets created under their enterprise
wallet_manage_enterprise Manage and modify settings from wallets created under their enterprise
wallet_view:#WALLETID View a wallet’s transactions and addresses
wallet_spend:#WALLETID Spend Bitcoin from the specific wallet
wallet_manage:#WALLETID Manage and modify settings on the specific wallet
wallet_view_all View all the transactions and addresses for all wallets the user has access to
wallet_freeze_#WALLETID Freeze all spend activity on a specific wallet for a given duration (defaults to 1 hour)
wallet_freeze_all Freeze all spend activity on all of the user’s wallets

3rd Party BitGo Login

Example OAuth gateway redirect to send your users to BitGo OAuth

https://test.bitgo.com/oauth/authorize?client_id=FBExchange&redirect_uri=https%3A%2F%2Ffbexchange.com%2Foauth_redirect&scope=openid%20profile%20wallet_view_enterprise&email=test@bitgo.com&signup=false

The first step in the OAuth flow is to redirect your users to the BitGo OAuth gateway with the Client ID, Scope and Redirect Uri parameters.

Parameters may be sent via GET or POST.

OAuth Request Parameters

Example redirect URL from BitGo sending users back to your site

https://fbexchange.com/oauth_redirect?code=440261e26512877b7ebe86e2740da3030d81e88e
Parameter Required Description
client_id Yes Name of the OAuth application seeking access to 3rd party accounts
redirect_uri Yes Redirect Uri for BitGo to send users back to your site after they have authenticated on BitGo
scope Yes List of requested OAuth scopes, separated by spaces. Your access to the user’s information will be dependent on these scopes
state No opaque string that you contain any custom information you wish to provide. Send back as a parameter in the redirect Uri
signup No boolean value to be used to control if the user defaults to login or sign up when they land on the OAuth gateway at BitGo
email No string value of the email username, used to pre-populate the value
force_email No if set to true, the email field (set above) will be readonly on the user’s client

Our server will redirect

After the user has authorized your application, we will redirect back them to your URL. The redirect will contain the URL parameters:

Parameter Description
code Authorizing code string which you can use (together with your secret) to exchange for an access token

Obtaining Access Tokens

var bitgo = new BitGoJS.BitGo({clientId:clientId, clientSecret:clientSecret});
var authorizationCode = '440261e26512877b7ebe86e2740da3030d81e88e';
bitgo.authenticateWithAuthCode({ authCode: authorizationCode }, function(err, result) {
if (err) {
    console.dir(err);
    throw new Error("Could not auth!");
  }
  console.dir(result);
  bitgo.me({}, function(err, response) {
    if (err) {
      console.dir(err);
      throw new Error("Could not get user!");
    }
    console.dir(response);
  });
});
AUTHORIZATION_CODE='440261e26512877b7ebe86e2740da3030d81e88e'
CLIENT_ID='FBExchange'
CLIENT_SECRET='testclientsecret'
curl -X POST https://test.bitgo.com/oauth/token \
-H "Content-Type: application/json" \
-d  "{ \"client_id\": \"$CLIENT_ID\",
       \"client_secret\": \"$CLIENT_SECRET\",
       \"grant_type\": \"authorization_code\",
       \"code\":\"$AUTHORIZATION_CODE\"
    }"

When your user receives the authorization code, send it to the service backend you wish to use to perform actions on behalf of the user.

You then need to exchange the authentication code for an access token that you can use as you would the rest of the api.

OAuth Token Request Parameters

Parameter Description
client_id A string (name) of the OAuth application seeking access to 3rd party accounts
client_secret A secret string, stored on the server of the OAuth application, issued to you by BitGo
grant_type should be ‘authorization_code’
code The authentication code you received in the redirect from the above user login step

Example response

{
    "token_type":"bearer",
    "access_token":"2dba5167e70d4c18679a9775c57b184951a4fa07",
    "expires_in":3600,
    "expires_at":1418059789,
    "refresh_token":"3f8aa90479b4e3f0ea4544ed302e3bfe91968581",
    "id_token":"eyJ0eXAiOiJIUzI1NiJ96js46Ngvk-uC10YjYcEa4CqIAe-1hX2hYgXq6my...."
}

OAuth Response

Our server will return an access token for use with the API.

The token must be added as a HTTP header to all API calls in the HTTP “Authorization” header:

Authorization: Bearer <your token goes here>

Parameter Description
token_type The type of token e.g. ‘bearer’
access_token The token to be used in the Authorization header for subsequent authorized API requests on behalf of the user
expires_in Number of seconds the token is valid
expires_at Time which the token will expire, in seconds since 1970.
refresh_token Can be used to obtain another access token, if your session is due to expire
id_token openid jwt token containing user profile information, if requested as a scope

OpenID JSON Web Token

If the partner authentication request had an openid profile scope, a id_token in JSON Web Token (JWT) base64-encoded format will be returned in the response to the OAuth access token request above. You should validate the JSON web token is signed with the HS256 algorithm using your client secret (to prove it came from BitGo).

This token will contain user profile information. You should take care to store this information securely so as not to expose your users to scammers or phishing.

Example decrypted id_token (from the above access token response)

{
    "phone_number": "+14085551234",
    "sub": "54583af457fd213c2d00000532cc8e44e6bdf943559be179e9475cfe",
    "phone_number_verified": true,
    "iss": "http://dev-accounts.bitgo.com",
    "email_verified": false,
    "zoneinfo": "US/Pacific",
    "access_token": "09d3dc7a41c86ceff09e383acda4840840bf056d",
    "exp": 1416882424,
    "iat": 1416878824,
    "email": "tester@something.com",
    "aud": "TESTCLIENTID"
}

ID Token Claims

Parameter Format Description
iat seconds since utc time this token was created, in seconds since 1970.
exp seconds since utc expiry time of the token (when to accept it until), in seconds since 1970.
aud string the client id
iss uri string the issue identifier
sub string BitGo unique user id
access_token string access token you received from this request, for verification purposes
email string user email
email_verified boolean if the user email has been verified
phone_number string user phone number
phone_number_verified boolean if the phone number has been verified
zoneinfo TZ time zone information, e.g. US/pacific

Refreshing Access Tokens

// var refreshToken = 'undefined'; // if unset, uses the refresh token saved from a previous authentication request.
var refreshToken = '3f8aa90479b4e3f0ea4544ed302e3bfe91968581' // from above auth request
bitgo.refreshToken({ refreshToken: refreshToken }, function(err, result) {
  if (err) {
    console.dir(err);
    throw new Error("Could not refresh!");
  }
  console.dir(result);
});
REFRESH_TOKEN='3f8aa90479b4e3f0ea4544ed302e3bfe91968581' #from above request
CLIENT_ID='FBExchange'
CLIENT_SECRET='testclientsecret'
curl -X POST https://test.bitgo.com/oauth/token \
-H "Content-Type: application/json" \
-d  "{ \"client_id\": \"$CLIENT_ID\",
       \"client_secret\": \"$CLIENT_SECRET\",
       \"grant_type\": \"refresh_token\",
       \"refresh_token\":\"$REFRESH_TOKEN\"
    }"

The access token obtained in the previous step is typically good for an hour.

To extend a user session, you can request another access token using the request token also sent in the previous step.

Example response

{
    "token_type":"bearer",
    "access_token":"2dba5167e70d4c18679a9775c57b184951a4fa07",
    "expires_in":3600,
    "expires_at":1418059789,
    "refresh_token":"3f8aa90479b4e3f0ea4544ed302e3bfe91968581"
}

Refresh tokens have a lifetime of 2 weeks from creation and are valid for a single use only. A new refresh token is assigned to you each time one is used.

OAuth Token Request Parameters

Parameter Description
client_id A string (name) of the OAuth application seeking access to 3rd party accounts
client_secret A secret string, stored on the server of the OAuth application, issued to you by BitGo
grant_type should be ‘refresh_token’
refresh_token The refresh token received when you exchanged the authorization code for the access token

Examples

BitGo has provided examples of how to perform several common wallet operations using our SDK. The more important ones are covered here.

The examples below (and more!) can be found in the BitGoJS/examples directory in our SDK repository. Please report problems with the examples via email or Git issues.

Obtaining the Wallet ID

When you create your wallet on the BitGo test website, the wallet id is the first receiving address. It is also in the URI when you click on it from the main menu.

Get Wallet Balance

Code Snippet

var bitgo = new BitGoJS.BitGo();

// First, Authenticate
bitgo.authenticate({ username: user, password: password, otp: otp }, function(err, result) {
  console.log("Logged in!" );

  // Get the Balance
  bitgo.wallets().get({type: 'bitcoin', id: id}, function(err, wallet) {
    console.log("Balance is: " + (wallet.balance() / 1e8).toFixed(4));
  });
});
$ node getWalletBalance.js tester@bitgo.com superhardseypassphrase 0000000 2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD

Example output

Logged in!
Balance is: 0.6274

This simple example shows how to authenticate and get the wallet. The balance in bitcoins can be found on the wallet model.

Usage

node getWalletBalance.js <user> <pass> <otp> <walletId>

Parameters

Name Type Required Description
user string Yes username (your email on the test environment)
pass string Yes password on BitGo
otp number Yes the one-time-password (you can use 0000000 in the test environment)
walletId string Yes id of the wallet (also the first receiving address)

List Wallet Transactions

Code Snippet

bitgo.authenticate({ username: user, password: password, otp: otp }, function(err, result) {
  console.log("Logged in!" );

  // Get the wallet
  bitgo.wallets().get({type: 'bitcoin', id: id}, function(err, wallet) {
    console.log("Balance is: " + (wallet.balance() / 1e8).toFixed(4));

    // Get the transactions
    wallet.transactions({}, function(err, result) {
      for (var index = 0; index < result.transactions.length; ++index) {
        var tx = result.transactions[index];
        var value = 0;
        for (var entriesIndex = 0; entriesIndex < tx.entries.length; ++entriesIndex) {
          if (tx.entries[entriesIndex].account === wallet.id()) {
            value += tx.entries[entriesIndex].value;
          }
        }
        var verb = (value > 0) ? 'Received' : 'Sent';
        console.log(tx.id + ': ' + verb + ' ' + (value / 1e8).toFixed(8) + 'BTC on ' + tx.date);
      }
    });
  });
});
$ node listWalletTransactions.js tester@bitgo.com superhardseypassphrase 0000000 2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD

> Example output

Logged in!
Balance is: 0.6274
b9573e0e1d8f22fbfe314760b9abd0b6942132cfb2bd7f9fee9713b545a62689: Received 0.56000000BTC on 2014-11-17T21:20:59.000Z
b3bd8ac76de2340c1159337acdfcaabf08a9470e8157870bd1d84631a0acc67b: Received 0.00010000BTC on 2014-11-17T21:00:58.000Z
7f5d6a27ea832b2d0a9b63ecdbccecaadbd582b5be41d5bdeabcce72243366a3: Received 0.00010000BTC on 2014-11-17T19:57:18.000Z
690b8a83e1685869f6138d9a74776f5f868ffc1121fa22f2086e65400f14ef78: Received 0.00010000BTC on 2014-11-17T19:57:18.000Z

This example shows how to get the list of transactions on a wallet. This may be useful for verifying received transaction IDs.

Usage

node listWalletTransactions.js <user> <pass> <otp> <walletId>

Parameters

Name Type Required Description
user string Yes username (your email on the test environment)
pass string Yes password on BitGo
otp number Yes the one-time-password (you can use 0000000 in the test environment)
walletId bitcoin address (string) Yes id of the wallet (also the first receiving address)

Address Labels

$ node addressLabels.js tester@bitgo.com superhardseypassphrase 0000000

Example output

Enter the wallet ID: 2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD
Which label action do you wish to perform? [list, set, delete]: list
 muYhgJrYZHffyGUmuzETjMcBQZJqFo9Vkg    Secret Stash
 2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD   another label
 2MzjET9tYPPZQtsahFvabhaaPWuDdKn3Dh6   descriptive text
 n1wbb1HeZULZwvtcYMLeFz8J9QD7HkG1pa    watch only address

This example shows how to list, set, and delete labels on addresses.

Usage

node addressLabels.js <user> <pass> <otp>

Parameters

Name Type Required Description
user string Yes username (your email on the test environment)
pass string Yes password on BitGo
otp number Yes the one-time-password (you can use 0000000 in the test environment)

Create Wallet

Code Snippet

  bitgo.wallets().createWalletWithKeychains({"passphrase": password, "label": label, "backupXpubProvider": "keyternal"}, function(err, result) {
    if (err) { console.dir(err); throw new Error("Could not create wallet!"); }
    console.log("New Wallet: " + result.wallet.id());
    console.dir(result.wallet.wallet);

    console.log("BACK THIS UP: ");
    console.log("User keychain encrypted xPrv: " + result.userKeychain.encryptedXprv);
    console.log("Backup keychain xPub: " + result.backupKeychain.xpub);
});
$ node createWallet.js tester@bitgo.com superhardseypassphrase 0000000 'My API wallet'

Example output

New Wallet: 2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf
{ "id": "2NAGz3TDs5HmBU2SEodtWyks9n5KXVCzBTf",
 "label": "testwallet",
 "isActive": true,
 "type": "safehd",
 "private": { "keychains": [{}] },
 "permissions": "admin,spend,view",
 "admin": {},
 "spendingAccount": true,
 "confirmedBalance": 0,
 "balance": 0,
 "pendingApprovals": [] }
BACK THIS UP:
User keychain encrypted xPrv: {"iv":"v2aVEG5A8VwnI+ewS..."}
Backup keychain xPub: xpub6GiRC55CRuv2Fx3ihR9EPCr7gauoJcHqvvdSgQkmMmqMQmvQ1KNSBmKPReryBv8E3qJWkHmCx3cWmLGvbDRzCAoV7HUf8A5LUdRhV46u9h5

Creates a wallet on BitGo. The example performs the following steps:

  1. Authenticates with BitGo
  2. Unlocks the account
  3. Creates the user keychain on the client, encrypts it with the password and sends it to the server.
  4. Creates the backup keychain on the client.
  5. Creates the BitGo keychain on the BitGo server.
  6. Creates the wallet with the corresponding public keys to the keychains above.

Usage

node createWallet.js <user> <pass> <otp> <label>

Parameters

Name Type Required Description
user string Yes username (your email on the test environment)
pass string Yes password on BitGo
otp number Yes the one-time-password (you can use 0000000 in the test environment)
label string Yes the wallet name as shown in the BitGo UI

Send Bitcoins to an Address

Code Snippet

var sendBitcoin = function() {
  // Get the wallet
  bitgo.wallets().get({id: walletId}, function(err, wallet) {
    // Send coins
    wallet.sendCoins({ address: destinationAddress, amount: amountSatoshis, walletPassphrase: walletPassphrase }, function(err, result) {
      console.dir(result);
    });
  });
};

// Authenticate and unlock account to enable sending
bitgo.authenticate({ username: user, password: password, otp: otp }, function(err, result) {
  bitgo.unlock({otp: otp}, function(err) {
    sendBitcoin();
  });
});
$ node sendBitcoin tester@bitgo.com superhardseypassphrase 0000000 2N91XzUxLrSkfDMaRcwQhe9DauhZMhUoxGr superhardseypassphrase 2N4Xz4itCdKKUREiySS7oBzoXUKnuxP4nRD 10000

Example output

{ "tx": "01000000017bc6aca03146d8d10b875781...",
  "hash": "101f1f0f2218b0a0ac9aea1c054fbba7d2e75e09fbeeae7acea0254baa9505b7",
  "fee": 10000 }

Sends Bitcoin to another bitcoin address. The example uses the following steps:

  1. Authenticates with BitGo
  2. Unlocks the account to make it possible to spend coins
  3. Gets the wallet from the server by the provided walletId.
  4. Calls the wallet.sendCoins method, which finds the user key, decrypts it, creates and signs the transaction and sends it to BitGo for signing.

Usage

node sendBitcoin <user> <pass> <otp> <walletId> <walletPassphrase> <destinationAddress> <amountSatoshis>

Parameters

Name Type Required Description
user string Yes username (your email on the test environment)
pass string Yes password on BitGo
otp number Yes the one-time-password (you can use 0000000 in the test environment)
walletId bitcoin address (string) Yes the wallet name as shown in the BitGo UI
walletPassphrase string Yes the passphrase used to encrypt the user’s private key
destinationAddress bitcoin address (string) Yes the destination address of the wallet
amountSatoshis string Yes the number of satoshis to send, e.g. 0.1*1e8 for 0.1 bitcoin

Webhook Oracle Policy

Code Snippet

var setUpPolicyAndSendBitcoin = function() {
  console.log("Getting wallet..");
  bitgo.wallets().get({id: walletId}, function(err, wallet) {
    if (err) { console.log("Error getting wallet!"); console.dir(err); return process.exit(-1); }
    console.log("Balance is: " + (wallet.balance() / 1e8).toFixed(4));
    // Sets the policy
    var rule = {
      id: "webhookRule1",
      type: "webhook",
      action: { type: "deny" },
      condition: { "url": url }
    };
    console.dir(rule);
    console.log("Setting webhook policy rule.. ");
    wallet.setPolicyRule(rule, function callback(err, walletAfterPolicyChange) {
      if (err) { throw err; }
      console.log("New policy: ");
      console.dir(walletAfterPolicyChange.admin.policy);
      wallet.sendCoins({ address: destinationAddress, amount: amountSatoshis, walletPassphrase: walletPassphrase },
      function(err, result) {
        // removing the rule
        wallet.removePolicyRule({id: "webhookRule1"}, function(err, res) { console.log("Removed policy rule"); });
        if (err) { console.log("Error sending coins!"); console.dir(err); }
        if (result) {
          console.dir(result);
        }
      });
    });
  });
};

// Authenticate and unlock account to enable sending
bitgo.authenticate({ username: user, password: password, otp: otp }, function(err, result) {
  bitgo.unlock({otp: otp}, function(err) {
    setUpPolicyAndSendBitcoin();
  });
});
$ node addPolicyWebhookAndSendCoins bencxr@fragnetics.com nicehardpassword 0000000 2MufYDkh6iwNDtyREBeAXcrRDDAopG1RNc2 https://486d7844.ngrok.com/ walletpasw0rd 2N8ryDAob6Qn8uCsWvkkQDhyeCQTqybGUFe 1380000

Example output

Getting wallet..
Balance is: 1.2582
{ id: 'webhookRule1',
  type: 'webhook',
  action: { type: 'deny' },
  condition: { url: 'https://486d7844.ngrok.com/' } }
Setting webhook policy rule..
New policy:
{ id: '5632aa4039cccac60913ea0ed44276c0',
  rules:
   [ { id: 'webhookRule1',
       type: 'webhook',
       action: [Object],
       condition: [Object] } ] }
{ status: 'accepted',
  tx: '0100000001a89f36c0b714878cdd4cddf5...' }
Removed policy rule

Example webhook callback (sent to the URL provided, any non-200 response will trigger the policy denial)

{
    "approvalCount": 0,
    "outputs": [
        {
            "outputAddress": "2N9kNR8iS46WuwekvQVaTUa74w2fbvAXHQn",
            "outputWallet": "2MufYDkh6iwNDtyREBeAXcrRDDAopG1RNc2",
            "value": 24885327
        },
        {
            "outputAddress": "2N8ryDAob6Qn8uCsWvkkQDhyeCQTqybGUFe",
            "outputWallet": "2N8ryDAob6Qn8uCsWvkkQDhyeCQTqybGUFe",
            "value": 10000000
        }
    ],
    "ruleId": "webhookRule1",
    "spendAmount": 10009060,
    "type": "webhook",
    "unsignedRawTx": "0100000001f8de6273285b13f20b59195c4...",
    "walletId": "2MufYDkh6iwNDtyREBeAXcrRDDAopG1RNc2"
}

This example demonstrates how to set up a webhook policy on a wallet capable of executing any custom external logic via a URL endpoint (potentially a script or other program) on the Internet. This allows external state to be mapped into a contract where various users share a single wallet (the URL acts as the “oracle”).

When a transaction is made, the URL provided is hit. If it returns a 200 status, then the transaction will be allowed. If not, then the policy rule is fired and the transaction denied.

  1. Authenticates with BitGo
  2. Unlocks the account to make it possible to spend coins and set policy
  3. Gets the wallet from the server by the provided walletId
  4. Sets up the policy which will cause the URL provided to be hit.
  5. Calls the wallet.sendCoins method, which finds the user key, decrypts it, creates and signs the transaction and sends it to BitGo for signing.
  6. Removes the policy and returns the result.

When testing locally, one can create a URL by first setting up a local server (express or any http server will work), and then running a tool such as ngrok to get a public facing url.

Usage

node addPolicyWebhookAndSendCoins <user> <pass> <otp> <walletId> <url> <walletPassphrase> <destinationAddress> <amountSatoshis>

Parameters

Name Type Required Description
user string Yes username (your email on the test environment)
pass string Yes password on BitGo
otp number Yes the one-time-password (you can use 0000000 in the test environment)
walletId bitcoin address (string) Yes the wallet name as shown in the BitGo UI
url http endpoint (string) Yes the URL to set up the policy with
walletPassphrase string Yes the passphrase used to encrypt the user’s private key
destinationAddress bitcoin address (string) Yes the destination address of the wallet
amountSatoshis string Yes the number of satoshis to send, e.g. 0.1*1e8 for 0.1 bitcoin

Recover Wallet

RecoverWallet is a tool that can recover funds from a BitGo wallet without using the BitGo service. It is provided for demonstration purposes and to prove that BitGo wallets are 100% recoverable even if the BitGo Service is unavailable. It is not expected that this tool would be used for production environments.

Given only the information on a wallet’s keycard, the tool constructs a transaction which moves all of the funds within that wallet to a new account of the user’s choice. This is done without using any BitGo Service APIs.

The RecoverWallet tool is interactive or command line driven.

Usage

node recoverwallet.js –userKey –backupKey –bitgoKey

Parameters

Name Meaning
userKey The user extended private key for the wallet. (Box A from the Wallet KeyCard)
backupKey The backup extended private key for the wallet. (Box B from the Wallet KeyCard)
bitgoKey The bitgo extended public key for the wallet. (Box C from the Wallet KeyCard)
testnet Flag to use testnet instead of the production bitcoin network
nosend Flag to create the transaction but not send it
password The password to use to decrypt the userKey and backupKey
destination The bitcoin address to which you want to send the recovered funds