# Settle

Source: https://developers.bitgo.com/docs/crypto-as-a-service-settle

## Overview

Settlements on the Go Network enable you to settle multi-asset trades between Go Accounts, off chain. Assets never leave BitGo cold storage, minimizing counterparty risk, and because settlements are off chain, they're quicker and less expensive than on-chain transactions.

> 📘 **Note**
>
> Ticker symbols of assets in Go Accounts use a different naming convention than the ticker symbols used in on-chain wallets. Assets in Go Accounts prepend `ofc` to the ticker symbol, indicating that the asset is off chain. For example, testnet bitcoin within a Go Account is `ofctbc`, whereas in other on-chain wallet types it's `tbtc4`.

## Prerequisites

* [Get Started](/docs/get-started-intro)
* [Create Go Accounts](/docs/crypto-as-a-service-go-accounts)
* [Fund Go Accounts](/docs/crypto-as-a-service-fund-go-accounts)

## Cookbook

Need just the steps? Expand the cookbook below to get started:

<Cookbook slug="caas-settle" title="Settle" />

## 1. Add a Connection

Add connections to Go Accounts you find in the directory by passing the `targetListingEntryId`. If the directory doesn't list a Go Account, you can still add connection if you know the wallet ID of the partner Go Account.

>Endpoint: [Add a Go Account Connection](/reference/v1postconnectionroute)

```shell cURL (Listed)
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export LISTING_ENTRY_ID="<LISTING_ENTRY_ID>"
export LOCAL_LISTING_ENTRY_DESCRIPTION="<LOCAL_LISTING_ENTRY_DESCRIPTION>"
export TARGET_LISTING_ENTRY_ID="<TARGET_LISTING_ENTRY_ID>"

curl -X POST \
  https://app.bitgo-test.com/api/address-book/v1/connections \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "listingEntryId": "'"$LISTING_ENTRY_ID"'",
    "localListingEntryDescription": "'"$LOCAL_LISTING_ENTRY_DESCRIPTION"'",
    "targetListingEntryId": "'"$TARGET_LISTING_ENTRY_ID"'"
  }'
```
```shell cURL (Unlisted)
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export WALLET_ID="<THEIR_GO_ACCOUNT_WALLET_ID>"

curl -X POST \
  https://app.bitgo-test.com/api/address-book/v1/connections \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{"walletId": "'"$WALLET_ID"'"}'
```
```js JavaScript (Listed)
import { BitGoAPI } from '@bitgo/sdk-api';
import { coins } from '@bitgo/sdk-core';
import { CreateAddressBookConnectionParams } from '@bitgo/sdk-core/src/bitgo/address-book';
import * as dotenv from 'dotenv';

const OFC_WALLET_ID = process.env.OFC_WALLET_ID;

const bitgo = new BitGoAPI({
  accessToken: process.env.TESTNET_ACCESS_TOKEN,
  env: 'test',
  customRootURI: 'https://app.bitgo-test.com',
});

const coin = 'ofc';
bitgo.register(coin, coins.Ofc.createInstance);

async function main() {
  const wallet = await bitgo.coin('ofc').wallets().get({ id: OFC_WALLET_ID });
  const addressBook = wallet.toAddressBook();

  const listing = await addressBook.getListing();
  // Check if the wallet's listing exists and has entries
  if (!listing.listingEntries || listing.listingEntries.length === 0) {
    throw new Error(`Wallet with ID ${OFC_WALLET_ID} does not have any address book listing entries.`);
  }
  const listingEntry = listing.listingEntries[0];

  const directory = await addressBook.getListingEntryDirectory();
  // Check if the directory has any entries to connect with
  if (!directory.listingEntries || directory.listingEntries.length === 0) {
    throw new Error('The address book directory is empty. No available entries to connect with.');
  }
  const targetListingEntry = directory.listingEntries[0];

  const body: CreateAddressBookConnectionParams = {
    listingEntryId: listingEntry.id, // We now know this exists
    targetListingEntryId: targetListingEntry.id, // We now know this exists
    localListingEntryDescription: 'My description of the connection',
  };

  const connection = await addressBook.createConnection(body);

  console.log('Address Book Connection:', connection);
}

main().catch((e) => console.error(e));
```
```js JavaScript (Unlisted)
import { BitGoAPI } from '@bitgo/sdk-api';
import { coins } from '@bitgo/sdk-core';
import { CreateAddressBookConnectionParams } from '@bitgo/sdk-core/dist/src/bitgo/address-book';
import * as dotenv from 'dotenv';

dotenv.config();

const OFC_WALLET_ID = process.env.OFC_WALLET_ID;

const bitgo = new BitGoAPI({
  accessToken: process.env.TESTNET_ACCESS_TOKEN,
  env: 'test',
  customRootURI: 'https://app.bitgo-test.com',
});

const coin = 'ofc';
bitgo.register(coin, coins.Ofc.createInstance);

async function main() {
  const wallet = await bitgo.coin(coin).wallets().get({ id: OFC_WALLET_ID });
  const addressBook = wallet.toAddressBook();

  const listing = await addressBook.getListing();
    
  if (!listing.listingEntries || listing.listingEntries.length === 0) {
    throw new Error(`Wallet with ID ${OFC_WALLET_ID} does not have any address book listing entries.`);
  }
  const listingEntry = listing.listingEntries[0];
  
  const body: CreateAddressBookConnectionParams = {
    listingEntryId: listingEntry.id, // my listing entry id for the wallet
    walletId: '', // ofc wallet with whom I was to add to the address book.
    localListingName: 'Manual Wallet Name',
    localListingEntryDescription: 'My description of the connection',
  };

  const connection = await addressBook.createConnection(body);

  console.log('Address Book Connection:', connection);
}

main().catch((e) => console.error(e));
```

#### Step Result

```json JSON
{
  "connections": [
    {
      "ownerListingEntry": {
        "listing": {
          "id": "string",
          "name": "string",
          "description": "string",
          "editable": true
        },
        "id": "string",
        "walletId": "string",
        "coin": "string",
        "type": "GO_ACCOUNT",
        "description": "string",
        "discoverable": true,
        "featured": true,
        "createdAt": "string",
        "updatedAt": "string"
      },
      "targetListingEntry": {
        "listing": {
          "id": "string",
          "name": "string",
          "description": "string",
          "editable": true
        },
        "id": "string",
        "walletId": "string",
        "coin": "string",
        "type": "GO_ACCOUNT",
        "description": "string",
        "discoverable": true,
        "featured": true,
        "createdAt": "string",
        "updatedAt": "string"
      },
      "id": "string", // this is the addressBookConnectionId for settlements
      "type": "DVP",
      "status": "PENDING_DEACTIVATION",
      "label": "string",
      "description": "string",
      "createdBy": "string",
      "updatedBy": "string",
      "createdAt": "string",
      "updatedAt": "string" // this is the addressBookConnectionUpdatedAt for settlements
    }
  ]
}
```

## 2. Create Settlement

The `addressBookConnectionId` and `addressBookConnectionUpdatedAt` timestamp identify your counterparty for the settlement. If you need to find these values, you can call the [Lists counterparty Go Account connections](/reference/v1getcounterpartyconnectionsroute) endpoint.

>Endpoint: [Create settlement](/reference/v1enterpriseaccountsettlementpostroute)

```shell cURL
export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"
export ACCOUNT_ID="<YOUR_ACCOUNT_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export EXTERNAL_ID="<YOUR_EXTERNAL_ID>"
export CONNECTION_ID="<CONNECTION_ID>"
export CONNECTION_UPDATED_AT="<CONNECTION_UPDATED_AT>"
export COUNTERPARTY_ACCOUNT_ID="<COUNTERPARTY_ACCOUNT_ID>"
export CURRENCY="<SENDING_ASSET>"
export QUANTITY="<SENDING_QUANTITY>"

curl -X POST \
  https://app.bitgo-test.com/api/clearing/v1/enterprise/$ENTERPRISE_ID/account/$ACCOUNT_ID/settlement \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "externalId": "'"$EXTERNAL_ID"'",
    "addressBookConnectionId": "'"$CONNECTION_ID"'",
    "addressBookConnectionUpdatedAt": "'"$CONNECTION_UPDATED_AT"'",
    "assetTransfers": [
      {
        "currency": "'"$CURRENCY"'",
        "quantity": "'"$QUANTITY"'"
      }
    ]
  }'
```

#### Step Result

```json JSON
{
  "approvalRequests": [
    {
      "createdAt": "2019-08-24",
      "updatedAt": "2019-08-24",
      "id": "23d3e6c5-72d2-41e8-9e79-8d7e09a19b74",
      "accountId": "yourAccountId",
      "status": "acknowledged",
      "payload": "{\"nonce\":\"216c7312-5af8-463a-963d-8a91535b7ed5\",\"version\":\"3.0.0\",\"signerAccount\":\"yourAccountId\",\"settlementTransfers\":[{\"id\":\"b5f1ab55-b510-4bf6-92cd-214a7e23321\",\"sourceTradingAccountId\":\"yourAccountId\",\"destinationTradingAccountId\":\"counterpartiesAccountId\",\"currency\":\"$CURRENCY\",\"quantity\":\"$QUANTITY\"}]}",
    },
    {
      "createdAt": "2019-08-24",
      "updatedAt": "2019-08-24",
      "id": "54586c2b-adfd-40bd-8115-ea3a37f3f4df",
      "accountId": "counterpartiesAccountId",
      "status": "initialized",
      "payload":  "{\"nonce\":\"d51a9909-0b25-4ebc-b864-eba6e76e77d1\",\"version\":\"3.0.0\",\"signerAccount\":\"counterpartiesAccountId\",\"settlementTransfers\":[{\"id\":\"b5f1ab55-b510-4bf6-92cd-214a7e23321\",\"sourceTradingAccountId\":\"yourAccountId\",\"destinationTradingAccountId\":\"counterpartiesAccountId\",\"currency\":\"$CURRENCY\",\"quantity\":\"$QUANTITY\"}]}",
    }
  ],
  "settlementTransfers": [
    {
      "id": "b5f1ab55-b510-4bf6-92cd-214a7e23321",
      "sourceTradingAccountId": "yourAccountId",
      "destinationTradingAccountId": "counterpartiesAccountId",
      "currency":"$CURRENCY",
      "quantity":"$QUANTITY"
    }
  ],
  "requesterAccountName": "string",
  "finalizedAt": "2019-08-24",
  "createdAt": "2019-08-24",
  "updatedAt": "2019-08-24",
  "id": "string", // settlementId for signing
  "externalId": "string",
  "notation": "string",
  "requesterAccountId": "string",
  "status": "canceled",
  "type": "direct"
}
```

## 3. Sign Settlement (Optional)

If you're sending assets in the settlement, you must sign the settlement to confirm the transaction. However, if you're only receiving assets in a settlement, signing is optional.

### 3.1 Apply Signature

```js JavaScript
import { BitGoAPI } from '@bitgo/sdk-api';
import { coins } from '@bitgo/sdk-core';

const OFC_WALLET_ID = process.env.OFC_WALLET_ID;
const payload = process.env.PAYLOAD;
const walletPassphrase = process.env.OFC_WALLET_PASSPHRASE;

const bitgo = new BitGoAPI({
  accessToken: process.env.TESTNET_ACCESS_TOKEN,
  env: 'test',
});

const coin = 'ofc';
bitgo.register(coin, coins.Ofc.createInstance);

async function main() {
  const wallet = await bitgo.coin('ofc').wallets().get({ id: OFC_WALLET_ID });

  console.log('Wallet:', wallet);

  const tradingAccount = wallet.toTradingAccount();

  const signature = tradingAccount.signPayload({payload, walletPassphrase});

  console.log('Signature:', signature);
}

main().catch((e) => console.error(e));
```


#### Substep Result

```
"1f2f62b22832940d82819eccc9e2fbcb5339ae863bc9fba4d6cc62f01550fc325a7e007fb8b753d0e862145e716d4a6054f75c2da2b7c2ac5d41679683a4996349"
```

### 3.2 Submit Signed Settlement

>Endpoint: [Sign settlement](/reference/v1postsettlementsigningroute)

```shell cURL
export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"
export ACCOUNT_ID="<YOUR_ACCOUNT_ID>"
export SETTLEMENT_ID="<SETTLEMENT_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export PAYLOAD="<SETTLEMENT_PAYLOAD>"
export SIGNATURE="<YOUR_PUBLIC_KEY>"

curl -X POST \
  https://app.bitgo-test.com/api/clearing/v1/enterprise/$ENTERPRISE_ID/account/$ACCOUNT_ID/settlement/$SETTLEMENT_ID/signing \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "payload": "'"$PAYLOAD"'",
    "signature": "'"$SIGNATURE"'"
  }'
```

#### Substep Result

Signing a settlement places the assets in your Go Account into a `held` state, preventing them from use in other transactions. If your Go Account has an insufficient balance to cover the settlement, then BitGo rejects the request.

> 📘 **Note**
>
> If the signing fails for any reason, the settlement cancels.

```json JSON
{}
```

## 4. Approve Settlement (Optional)

> 📘 **Note**
>
> If you configure an approval requirement for settlements, you can't approve a settlement you initiated - another admin must always approve it.

>Endpoint: [Update Pending Approval](/reference/v2approvalupdate)

```shell cURL
export APPROVAL_ID="<APPROVAL_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export OTP="<YOUR_OTP>"

curl -X PUT \
  https://app.bitgo-test.com/api/v2/pendingApprovals/$APPROVAL_ID \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "state": "approved",
    "otp": "'"$OTP"'"
  }'
```
```js JavaScript
const baseCoin = this.bitgoSDK.coin(initialPendingApproval.coin);
const pendingApproval = await baseCoin.pendingApprovals().get({ id: initialPendingApproval.id });
const result = await pendingApproval.approve(params);
```

#### Step Result

```json JSON
{
    "id": "65529448bd87efe59c3b0156ddfce867",
    "coin": "tbtc4",
    "wallet": "654ec786c07fe8dc0dcfe03916ec5bb0",
    "enterprise": "62c5ae8174ac860007aff138a2d74df7",
    "creator": "62ab90e06dfda30007974f0a52a12995",
    "createDate": "2023-11-13T21:25:28.022Z",
    "info": {
        "type": "transactionRequest",
        "transactionRequest": {
            "requestedAmount": "10000",
            "fee": 20451,
            "sourceWallet": "654ec786c07fe8dc0dcfe03916ec5bb0",
            "policyUniqueId": "654ec786c07fe8dc0dcfe03f",
            "recipients": [
                {
                    "address": "2N1UvKhtSHLUa9YomSH7n9YMFCkMG2pbmsQ",
                    "amount": "10000",
                    "_id": "65529448bd87efe59c3b0158"
                }
            ],
            "coinSpecific": {
                "tbtc4": {
                    "txHex": "010000000001010e4d3af014f9efe311062965d561b67f78a1759e7016605cd506ddd7041762d50000000023220020510ded26d712922bbb61bc68ef6766f836a03527820cbdc8b1551914eb467dafffffffff02102700000000000017a9145a581567fd2a630e61e34a696ab3bb887972886d87ad0f010000000000225120850d0ab466d15cb1565dd528d4d9709f3e46f41d41fe6d94aa01378e626983990500483045022100db45a8d94ee2144f7e29baa855d94a2bf0120707a7ab2fc93734ed94af972c460220558d00b91275aafc7805dfaaf9ab796adbe9f4e66dc467f7eb93b790671a323201000069522103c10ac628c880629ed0fd2a0563a898f4882baca45e15668a4d3064cf1ea379882103e56f84be4460080618ef869bb7b07096880760f748ba23efab533c2359f923bd21020ae81372264b5eac5c9dc7fe0b9a32bad00771c3a2c71f6e2c971823c3182ed653ae00000000"
                }
            },
            "validTransaction": "010000000001010e4d3af014f9efe311062965d561b67f78a1759e7016605cd506ddd7041762d50000000023220020510ded26d712922bbb61bc68ef6766f836a03527820cbdc8b1551914eb467dafffffffff02102700000000000017a9145a581567fd2a630e61e34a696ab3bb887972886d87ad0f010000000000225120850d0ab466d15cb1565dd528d4d9709f3e46f41d41fe6d94aa01378e626983990400483045022100db45a8d94ee2144f7e29baa855d94a2bf0120707a7ab2fc93734ed94af972c460220558d00b91275aafc7805dfaaf9ab796adbe9f4e66dc467f7eb93b790671a323201473044022049e20c0073f42c9636408efc6c833ebf0e1a8ef13e8cb818dde2f4e2af7f7b7f022000cb3a321d65605b9d51d7f87e34306169607646c8d54a44011b021eff3dbe500169522103c10ac628c880629ed0fd2a0563a898f4882baca45e15668a4d3064cf1ea379882103e56f84be4460080618ef869bb7b07096880760f748ba23efab533c2359f923bd21020ae81372264b5eac5c9dc7fe0b9a32bad00771c3a2c71f6e2c971823c3182ed653ae00000000",
            "validTransactionHash": "5ea8d2b93997ed9fa3597a2f3113817c8216f573a0278c2533bb5db50fdb0dff"
        }
    },
    "state": "approved",
    "scope": "wallet",
    "userIds": [
        "62ab90e06dfda30007974f0a52a12995",
        "621d08a634ad8a0007fcddffd7c429cc"
    ],
    "approvalsRequired": 1,
    "singleRunResults": [
        {
            "ruleId": "Custody Enterprise Transaction ID Verification",
            "triggered": false,
            "_id": "65529448bd87efe59c3b0157"
        }
    ],
    "resolvers": [
        {
            "user": "621d08a634ad8a0007fcddffd7c429cc",
            "date": "2023-11-13T21:44:27.794Z",
            "resolutionType": "pending"
        }
    ]
}
```

## See Also

* [API Reference: Add a Go Account connection](/reference/v1postconnectionroute)
* [API Reference: Lists counterparty Go Account connections](/reference/v1getcounterpartyconnectionsroute)
* [API Reference: Create a listing entry for your enterprises Go Account](/reference/v1postlistingentryroute)
* [API Reference: Create enterprise listing](/reference/v1postlistingroute)
* [API Reference: Create settlement](/reference/v1enterpriseaccountsettlementpostroute)
* [API Reference: Sign settlement](/reference/v1postsettlementsigningroute)
* [API Reference: Update Pending Approval](/reference/v2approvalupdate)
* [API Reference: Update settlement approval request](/reference/v1approvalrequestputroute)
