Off-Exchange Settlement: Create Settlements - Partner (Disputes Enabled)
Create settlements for trading activity on your platform and send signed requests to BitGo. Use this cookbook when your integration has disputes enabled. Requires cutoffAt and uses the v2 endpoint. See the Guide.
-
You request a signing payload from BitGo for the settlement. Include
cutoffAt— the ISO 8601 timestamp of the most recent trade in this settlement. BitGo uses it to inform clients of the trading activity in this settlement. This payload must be cryptographically signed with your trading account private key to provide integrity, authenticity, and nonrepudiation. Settlement typically occurs during a pre-determined window, usually once every 24 hours.Prerequisites: Client trading must have occurred on your platform, and you must have allocated and connected clients.
-
You send the signed settlement payload to BitGo using the v2 endpoint to initiate the settlement. Include the same
cutoffAtvalue from Step 1 so the signature covers it. BitGo processes settlement asynchronously after the dispute window ends, so the response has an initialstatusofpending.-
When the dispute window ends, BitGo makes a call to your finalize settlement endpoint. This call includes the final settlement amounts which may differ from the initially posted settlement amounts. There may be prior settlement disputes closing or clients submitting disputes on this current settlement.
-
The settlement enters the top up window, where you can reconcile disputes on your platform.
-
Once the top up window ends, BitGo attempts to process the settlement. If funds in your Go Account are not sufficient to satisfy your liabilities for settlement, the settlement will move to the failed state and the settlement will be retried on a continual basis until the settlement goes through.
-
// 1. Get Signing Payload
curl -X GET http://$BITGO_EXPRESS_HOST/api/network/v1/enterprises/{enterpriseId}/partners/settlements-signing \
-H "Authorization: Bearer v123xyz..." \
-H "Content-Type: application/json" \
-d '{
"externalId": "string",
"notes": "string",
"settlementAmounts": {
"additionalProp": {
"additionalProp": "string"
}
},
"nonce": "string",
"cutoffAt": "2026-03-18T12:00:00.000Z"
}'
// 2. Send Signed Settlement Payload
-H "Content-Type: application/json" \
-d '{
"externalId": "idForSettlementAtPartner",
"notes": "this is a settlement note",
"settlementAmounts": {
"09684b38-49ed-4cf6-a28e-c3a459494c69": {
"BTC": "100",
"ETH": "-200"
},
"136c1c69-8654-484f-8c5f-591b334a084f": {
"XRP": "300",
"BTC": "-400"
}
},
"nonce": "1",
"cutoffAt": "2026-03-18T12:00:00.000Z",
"payload": "<payload string from step 1>",
"signature": "<signature>"
}'
import superagent from 'superagent';
import { BitGoAPI } from '@bitgo/sdk-api';
import { coins } from '@bitgo/sdk-core';
require('dotenv').config({ path: '../../.env' });
const bitgo = new BitGoAPI({
accessToken: process.env.TESTNET_ACCESS_TOKEN,
env: 'test',
});
const coin = 'ofc';
bitgo.register(coin, coins.Ofc.createInstance);
function getWalletPwFromEnv(walletId: string): string {
const name = `WALLET_${walletId}_PASSPHRASE`;
const walletPw = process.env[name];
if (walletPw === undefined) {
throw new Error(`Could not find wallet passphrase ${name} in environment`);
}
return walletPw;
}
async function main() {
const enterpriseId = '<YOUR_ENTERPRISE_ID>';
const walletId = 'xyz123';
const wallet = await bitgo.coin(coin).wallets().get({ id: walletId });
const walletPassphrase = getWalletPwFromEnv(wallet.id());
const tradingAccount = wallet.toTradingAccount();
const settlementBody = {
externalId: 'idForSettlementAtPartner',
notes: 'this is a settlement note',
settlementAmounts: {
'09684b38-49ed-4cf6-a28e-c3a459494c69': {
BTC: '100',
ETH: '-200',
},
'136c1c69-8654-484f-8c5f-591b334a084f': {
XRP: '300',
BTC: '-400',
},
},
nonce: '1',
cutoffAt: '2026-03-18T12:00:00.000Z',
};
// 1. Get Signing Payload
const signingResponse = await superagent
.get(`${process.env.BITGO_EXPRESS_HOST}/api/network/v1/enterprises/${enterpriseId}/partners/settlements-signing`)
.set('Authorization', `Bearer ${process.env.TESTNET_ACCESS_TOKEN}`)
.set('Content-Type', 'application/json')
.send(settlementBody);
const { payload } = signingResponse.body;
// 2. Sign the payload
const signature = tradingAccount.signPayload({
payload,
walletPassphrase,
});
// 3. Send Signed Settlement Payload
const settlementResponse = await superagent
.post(`${process.env.BITGO_EXPRESS_HOST}/api/network/v2/enterprises/${enterpriseId}/partners/settlements`)
.set('Content-Type', 'application/json')
.send({
...settlementBody,
payload,
signature,
});
console.log('Settlement:', settlementResponse.body);
}
// 1. Get Signing Payload Response
{
"payload": "{ \"externalId\": \"idForSettlementAtPartner\", \"settlementAmounts\": { \"09684b38-49ed-4cf6-a28e-c3a459494c69\": { \"BTC\": \"100\", \"ETH\": \"-200\" }, \"136c1c69-8654-484f-8c5f-591b334a084f\": { \"XRP\": \"300\", \"BTC\": \"-400\" } }, \"nonce\": \"1\", \"cutoffAt\": \"2026-03-18T12:00:00.000Z\" }"
}
// 2. Send Signed Settlement Payload Response
{
"settlement": {
"id": "string",
"partnerId": "string",
"externalId": "string",
"status": "pending",
"settlementType": "onchain",
"reconciled": false,
"initiatedBy": "string",
"notes": "string",
"createdAt": "2026-03-18T12:00:00.000Z",
"updatedAt": "2026-03-18T12:00:00.000Z",
"finalizedAt": null,
"rtId": "string",
"lossSLAAlertSent": false,
"gainSLAAlertSent": false,
"cutoffAt": "2026-03-18T12:00:00.000Z",
"disputed": false
}
}