Crypto-as-a-Service: Capture Client Fee

Capture client fee from completed trades through Go Account wallet transfer (Ta2Ta). See the Guide.

  1. Subscribe to an organization-level trade webhook to receive real-time notifications when trades complete across your entire platform. This is a one-time setup. Your webhook receives two signals per completed trade: one at trade execution (the trigger for fee capture) and one when settlement completes (informational only). Act on the first signal where status is "completed" and no settleDate is present.

    API Reference

  2. After receiving a trade completion webhook notification, retrieve the full order to get the fields needed for fee calculation: filledQuantity, filledQuoteQuantity, averagePrice, product, and side. The webhook payload contains the accountId and order id. You should check idempotency by tracking processed order identifiers to prevent duplicate fee captures from webhook retries.

    API Reference

  3. Build a wallet transfer for the calculated fee amount from the end-user's Go Account to your collection Go Account. This is an internal ledger movement (book transfer) with no on-chain transaction.

    Important: You must disclose to your end users that you charge a fee on top of the trade execution price.

    Calculate the fee based on trade direction:

    • Buy (fiat to crypto): fee = (filledQuoteQuantity * feeBps / 10000) / averagePrice -- denominated in the base token (e.g., BTC). Set COIN to the OFC-prefixed base asset (e.g., ofctbtc4).
    • Sell (crypto to fiat): fee = filledQuoteQuantity * feeBps / 10000 -- denominated in the quote token (e.g., USD). Set COIN to the OFC-prefixed quote asset (e.g., ofctusd).

    API Reference

  4. Sign the transfer payload with the Go Account passphrase. Use BitGo Express in external-signing mode or the JavaScript SDK to ensure your passphrase is never sent over the internet. Initiate this transfer immediately upon trade completion -- delayed or batched processing risks the end-user withdrawing before you capture the fee.

  5. Send the authenticated fee transfer to BitGo. If your enterprise has policy rules configured, the transfer enters a pending state until approved. Once confirmed, your collection Go Account receives the fee. You should display only the net balance (post-fee) to end-users and gate withdrawals until this transfer confirms to prevent a race condition.

    API Reference

// 1. Create Trade Webhook
export ORGANIZATION_ID="<YOUR_ORGANIZATION_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export URL="<YOUR_WEBHOOK_URL>"
export LABEL="<YOUR_WEBHOOK_NAME>"

curl -X POST \
  https://app.bitgo-test.com/api/v2/organization/$ORGANIZATION_ID/webhook \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "type": "tradeOrder",
    "url": "'"$URL"'",
    "label": "'"$LABEL"'"
  }'
// 2. Get Filled Order Details
export ACCOUNT_ID="<END_USER_GO_ACCOUNT_WALLET_ID>"
export ORDER_ID="<ORDER_ID_FROM_WEBHOOK>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"

curl -X GET \
  "https://app.bitgo-test.com/api/prime/trading/v1/accounts/$ACCOUNT_ID/orders/$ORDER_ID" \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
// 3. Build Fee Transfer
export COIN="<OFC_ASSET_ID>"
export WALLET_ID="<END_USER_GO_ACCOUNT_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export FEE_AMOUNT="<CALCULATED_FEE_AMOUNT>"
export COLLECTION_WALLET_ID="<YOUR_COLLECTION_GO_ACCOUNT_WALLET_ID>"

curl -X POST \
  https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/tx/build \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "recipients": [
      {
        "amount": "'"$FEE_AMOUNT"'",
        "walletId": "'"$COLLECTION_WALLET_ID"'"
      }
    ]
}'
// 4. Authenticate Fee Transfer
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export WALLET_PASSPHRASE="<YOUR_GO_ACCOUNT_PASSPHRASE>"

curl -X POST \
  http://$BITGO_EXPRESS_HOST/api/v2/ofc/signPayload \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
   "walletId": "'"$WALLET_ID"'",
   "walletPassphrase": "'"$WALLET_PASSPHRASE"'",
   "payload": "<PAYLOAD_FROM_BUILD_STEP>"
}'
// 5. Send Fee Transfer
curl -X POST \
  https://app.bitgo-test.com/api/v2/$COIN/wallet/$WALLET_ID/tx/send \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "halfSigned": {
      "payload": "<PAYLOAD>",
      "signature": "<SIGNATURE_FROM_AUTH_STEP>"
    }
  }'
Response
// 1. Create Trade Webhook Response
{
  "success": "true",
  "data": {
    "id": "690278897328c7fc41e81887d4b76964",
    "label": "Trade Completion Webhook",
    "created": "2026-03-10T20:26:49.286Z",
    "scope": "organization",
    "organizationId": "68f6af3f2f29893d5863bc0eaf77b3c6",
    "type": "tradeOrder",
    "url": "https://your-platform.com/webhooks/trade",
    "version": 1,
    "state": "active"
  }
}

// 2. Get Filled Order Details Response
{
  "id": "67fd640c-cb6c-4218-80ae-49e79ec15646",
  "accountId": "60e740e7898f7d00064d43769a73dc48",
  "clientOrderId": "myorderid1",
  "time": "2021-08-05T18:05:23.431Z",
  "creationDate": "2021-08-05T18:05:22.286Z",
  "scheduledDate": "2021-08-05T18:05:00.000Z",
  "lastFillDate": "2021-08-05T18:05:23.302Z",
  "completionDate": "2021-08-05T18:05:23.431Z",
  "fundingType": "funded",
  "type": "market",
  "status": "completed",
  "product": "TBTC-TUSD*",
  "side": "buy",
  "quantity": "1000",
  "quantityCurrency": "TUSD*",
  "filledQuantity": "0.02457152",
  "filledQuoteQuantity": "1000",
  "averagePrice": "40697.32"
}

// 3. Build Fee Transfer Response
{
  "payload": "{\"coin\":\"ofctbtc4\",\"recipients\":[{\"address\":\"<COLLECTION_ADDRESS>\",\"amount\":\"<FEE_AMOUNT>\"}],\"fromAccount\":\"60e740e7898f7d00064d43769a73dc48\",\"nonce\":\"d8e5d930-f827-42b1-ad85-40544dad1be6\",\"timestamp\":\"2026-03-10T17:45:56.394Z\",\"feeString\":\"0\"}",
  "feeInfo": { "feeString": "0" },
  "coin": "ofc",
  "token": "ofctbtc4"
}

// 4. Authenticate Fee Transfer Response
{
  "coin": "ofctbtc4",
  "payload": "{\"coin\":\"ofctbtc4\",...}",
  "signature": "20dda1e9558adb297f69020f94cbf4955fabec73478506347dbb5ac8e73b506fc908bbc48bde75b339b99f5de808ed34b2017055c9df198fd1f8b4e524899f9583"
}

// 5. Send Fee Transfer Response
{
  "transfer": {
    "id": "613be001f3de560006842d52251d5d49",
    "coin": "ofctbtc4",
    "wallet": "60e740e7898f7d00064d43769a73dc48",
    "type": "send",
    "state": "signed"
  },
  "status": "signed"
}