# Burn Tokens

Source: https://developers.bitgo.com/docs/mint-redeem-tokens

## Overview

You can burn tokens by creating an order with the token as the source and the funding asset as the destination. Burning permanently removes tokens from circulation and returns the equivalent backing asset, keeping reserves 1:1.

All burn orders go through validation, authorization, and reconciliation controls to ensure that redeemed tokens are fully removed from supply and align with reserve balances.

## Prerequisites

* [Get Started](/docs/get-started-intro)
  * Access token must have either the `wallet_spend` or `wallet_spend_all` scopes.
  * User role must have spend permissions.
* [Add a wallet user](/docs/wallets-users-add)
* [Accept the Minting Services Terms](/docs/accept-mint-terms)
* [Deposit Assets](/docs/deposit-assets)

## Cookbook

Want the steps without the walkthrough? Expand the cookbook below:

<Cookbook slug="mint-api-burn-order" title="Burn Tokens" />
<Cookbook slug="mint-api-track-orders" title="Track Orders" />

## 1. Configure HMAC

The Mint API uses BitGo v2 [HMAC](/docs/hmac) authentication. To generate the `hmac` header dynamically, create an environment with the variable `BITGO_ACCESS_TOKEN` set to your access token, then add the following pre-request script:

```js JavaScript
const crypto = require('crypto-js');

const rawToken = pm.environment.get('BITGO_ACCESS_TOKEN');
const url = new URL(pm.request.url.toString());

// Include query params in the path (auth-service uses x-original-uri, which includes them).
const urlPath = url.pathname + url.search;

// GET requests have no body; POST/PUT and others need compact JSON.
let body = '';
if (pm.request.method !== 'GET' && pm.request.body && pm.request.body.raw) {
  body = JSON.stringify(JSON.parse(pm.request.body.raw));
}

const timestamp = Date.now().toString();

// v2 HMAC subject: timestamp|urlPath|body
const subject = [timestamp, urlPath, body].join('|');
const hmac = crypto.HmacSHA256(subject, rawToken).toString(crypto.enc.Hex);
const tokenHash = crypto.SHA256(rawToken).toString(crypto.enc.Hex);

pm.request.headers.upsert({ key: 'Authorization', value: 'Bearer ' + tokenHash });
pm.request.headers.upsert({ key: 'auth-timestamp', value: timestamp });
pm.request.headers.upsert({ key: 'bitgo-auth-version', value: '2.0' });
pm.request.headers.upsert({ key: 'hmac', value: hmac });
```

## 2. List Supported Tokens

View the tokens available to your enterprise, including burn minimums, fees, and your role for each token. The response includes the chain-scoped asset IDs you need when choosing an asset pair and creating the order.


> Endpoint: [Get supported tokens for an enterprise](/reference/mintv1enterprisesupportedtokensget)

```shell cURL
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"

curl -X GET \
  "https://app.bitgo-test.com/api/mint/v1/enterprise/$ENTERPRISE_ID/supported-tokens" \
  -H 'accept: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
```

#### Step Result

```json JSON
{
  "tokens": [
    {
      "token": "usd1",
      "assets": [
        "sol:usd1",
        "eth:usd1",
        "bsc:usd1"
      ],
      "type": "stablecoin",
      "minimumMintAmount": "1.5",
      "minimumBurnAmount": "1.5",
      "mintFeeBps": "5",
      "burnFeeBps": "5",
      "description": "A stablecoin backed by US dollar reserves",
      "role": "issuer",
      "issuerOrdersEnabled": true,
      "name": "USD1"
    }
  ]
}
```

## 3. List Asset Pairs

List the available asset pairs for your enterprise and find the pair where `source` is the token you want to burn and `destination` is the funding asset you want to receive.

> Endpoint: [Get supported asset pairs](/reference/mintv1enterpriseassetpairsget)

```shell cURL
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"
export COIN="<ASSET_ID>"

curl -X GET \
  "https://app.bitgo-test.com/api/mint/v1/enterprise/$ENTERPRISE_ID/asset-pairs" \
  -H 'accept: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
```

#### Step Result

```json JSON
{
  "assetPairs": [
    {
      "source": { 
        "asset": "sol:usd1", 
        "minimumAmount": "100", 
        "decimals": 2 
      },
      "destination": { 
        "asset": "tfiatusd", 
        "decimals": 2 
      },
      "fee": { 
        "basisPoints": "10" 
      }
    }
  ]
}
```

## 4. Calculate Base Units

Express the amount of tokens to burn in base units. Use the `source.decimals` value from the previous step to convert your full-unit amount to base units.

**Formula:** Base Units = Amount * 10<sup>Decimals</sup>

**Example (token):** A redemption of 100 tokens occurs for an asset with 6 decimals:

* Amount: 100
* Decimals: 6
* Calculation: 100 * 10⁶ = 100,000,000
* Result: 100,000,000 base units

```shell Shell
# Calculate programmatically  
DECIMALS=6  # From assets API response for stablecoin
AMOUNT_BASE_UNITS=$(($AMOUNT_IN_FULL_UNITS * 10**$DECIMALS))
echo "Amount in base units: $AMOUNT_BASE_UNITS"
```
```js JavaScript
const fromAmount = (100 * Math.pow(10, stablecoinAsset.decimals)).toString(); // 100 stablecoin in base units
```

## 5. Create Burn Order

> Endpoint: [Create an order](/reference/mintv1enterpriseorderscreate)

```shell cURL
```shell cURL
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"
export COIN="<ASSET_ID>"
export SOURCE_WALLET_ID="<YOUR_WALLET_ID>"
export DESTINATION_WALLET_ID="<DESTINATION_WALLET_ID>"

curl -X POST \
  "https://app.bitgo-test.com/enterprise/$ENTERPRISE_ID/orders" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "x-enterprise-id: $ENTERPRISE_ID" \
  -H 'Content-Type: application/json' \
  -d '{
    "idempotencyKey": "<YOUR_UNIQUE_KEY>",
    "source": {
      "asset":    "<ASSET_ID>",
      "amount":   "100000000",
      "walletId": "'"$SOURCE_WALLET_ID"'",
      "type":     "GO_ACCOUNT"
    },
    "destination": {
      "asset":    "<ASSET_ID>",
      "type":     "GO_ACCOUNT",
      "walletId": "'"$DESTINATION_WALLET_ID"'"
    }
  }'
```

<Accordion title="Burn Status Lifecycle">

| Status | Description |
| :--- | :--- |
| `CREATED` | Order created and awaiting the token deposit. |
| `CONFIRMED_DEPOSIT` | Token deposit detected. |
| `PROCESSING` | The burn is being executed and settled. |
| `FULFILLED` | Tokens burned and the funding asset delivered to the destination. |
| `FAILED` | The order could not be completed. |
| `CANCELLED` | The order was cancelled. |

</Accordion>

#### Step Result

```json JSON
{
  "id": "95bdbd9c-9cdc-41a4-ae70-165387b7aa51",
  "userId": "user-123",
  "status": "CREATED",
  "enterpriseId": "67bc4ae090e8af8f9b412d3d67e85252",
  "source":      { 
    "asset": "tfiatusd", 
    "amount": "100000000", 
    "type": "GO_ACCOUNT", 
    "walletId": "67bc4b03..." 
    },
  "destination": { 
    "asset": "hteth:usd1", 
    "type": "GO_ACCOUNT", 
    "address": "0x123456789abcdef123456789abcdef123456789a",
    "walletId": "67bc4b038f5408faefbfc8edcf6e6577",
    "transferId": "6437d9f07d6a87000613e6c06e4218d3",
    },
  "createdAt": "string",
  "updatedAt": "string",
  "idempotencyKey": "mint-order-2025-04-04-001",
  "depositInstructions": {
    "type": "GO_ACCOUNT",
    "asset": "string",
    "sequenceId": "order-deposit:95bdbd9c-9cdc-41a4-ae70-165387b7aa51",
    "address": "0x123456789abcdef123456789abcdef123456789a"
  },
  "createdAt": "2025-04-04T09:25:48.216Z",
  "updatedAt": "2025-04-04T09:25:48.216Z"
}
```

## 6. Send Burn Order

The following example shows the minimum required parameters for burning an asset.

> Endpoint: [Send Transaction](/reference/expresswalletsendcoins)

```shell cURL
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>"
export COIN="<ASSET_ID>"
export WALLET_ID="<YOUR_WALLET_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"
export WALLET_PASSPHRASE="<YOUR_WALLET_PASSPHRASE>"
export SEQUENCE_ID="<ORDER_ID>"

curl -X POST \
  http://$BITGO_EXPRESS_HOST/api/v2/$COIN/wallet/$WALLET_ID/sendcoins \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "address": "'"$ADDRESS"'",
    "amount": "'"$AMOUNT"'",
    "walletPassphrase": "'"$WALLET_PASSPHRASE"'",
    "sequenceId": "'"$SEQUENCE_ID"'" // This is the id from the Create Mint Order results.
}'
```
```js JavaScript
const wallet = await bitgo.coin('$COIN').wallets().get({ id: walletId });
  await wallet.sendMany({
    recipients: [{ address: treasuryWalletId, amount: fromAmount }],
    sequenceId: order.id,
    walletPassphrase,
  });
```

#### Step Result

```json JSON
{
  "coin": "ofchteth:usd1",
  "transfers": [
    {
      "id": "transfer_id_12345",
      "coin": "ofchteth:usd1",
      "wallet": "67bc4b03...",
      "value": -10000,
      "baseValue": -10000,
      "state": "unconfirmed",
      "type": "send"
    }
  ]
}
```

## 7. Check Order Status

Retrieve the real-time status and detailed metadata for the burn order. Poll this endpoint until the order reaches `FULFILLED` or `FAILED`.

> Endpoint: [Get an order by ID](/reference/mintv1enterpriseordersget)

```shell cURL
export ENTERPRISE_ID="<YOUR_ENTERPRISE_ID>"
export ORDER_ID="<YOUR_ORDER_ID>"
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>"

curl -X GET \
  "https://app.bitgo-test.com/enterprise/$ENTERPRISE_ID/orders/$ORDER_ID" \
  -H 'accept: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
```

#### Step Result

```json JSON
{
  "timeline": [
    {
      "status": "PROCESSING",
      "timestamp": "2025-04-04T09:25:48.216Z"
    }
  ],
  "transactions": [
    {
      "type": "DEPOSIT",
      "status": "INITIATED",
      "asset": "string",
      "createdAt": "string",
      "updatedAt": "string",
      "transactionHash": "string",
      "transferId": "string",
      "amount": "500000000"
    }
  ],
  "id": "string",
  "userId": "string",
  "type": "BURN",
  "status": "CREATED",
  "enterpriseId": "string",
  "source": {
    "asset": "string",
    "amount": "string",
    "type": "GO_ACCOUNT",
    "walletId": "string"
  },
  "destination": {
    "asset": "string",
    "type": "GO_ACCOUNT",
    "amount": "string",
    "address": "0x123456789abcdef123456789abcdef123456789a",
    "walletId": "67bc4b038f5408faefbfc8edcf6e6577",
    "transferId": "6437d9f07d6a87000613e6c06e4218d3",
    "transactionHash": "0xdeadbeef..."
  },
  "fee": {
    "basisPoints": "5"
  },
  "createdAt": "string",
  "updatedAt": "string",
  "idempotencyKey": "mint-order-2025-04-04-001",
  "depositInstructions": {
    "type": "GO_ACCOUNT",
    "asset": "string",
    "sequenceId": "order-deposit:95bdbd9c-9cdc-41a4-ae70-165387b7aa51",
    "address": "0x123456789abcdef123456789abcdef123456789a"
  },
}
```

## 8. Bulk Fetch Orders by ID (Optional)

Repeat the `id` parameter to fetch a specific set of orders in one call. This is the efficient way to refresh many known orders at once.

> Endpoint: [List orders](/reference/mintv1enterpriseorderslist)

```shell cURL
curl -X GET \
  "https://app.bitgo-test.com/enterprise/$ENTERPRISE_ID/orders" \
  -H 'accept: application/json' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
```

#### Step Result

```json JSON
{
  "orders": [
    {
      "id": "string",
      "userId": "string",
      "type": "BURN",
      "status": "CREATED",
      "enterpriseId": "string",
      "source": {
        "asset": "string",
        "amount": "string",
        "type": "GO_ACCOUNT",
        "walletId": "string"
      },
      "destination": {
        "asset": "string",
        "type": "GO_ACCOUNT",
        "amount": "string",
        "address": "0x123456789abcdef123456789abcdef123456789a",
        "walletId": "67bc4b038f5408faefbfc8edcf6e6577",
        "transferId": "6437d9f07d6a87000613e6c06e4218d3",
        "transactionHash": "0xdeadbeef..."
      },
      "fee": {
        "basisPoints": "5"
      },
      "createdAt": "string",
      "updatedAt": "string",
      "idempotencyKey": "mint-order-2025-04-04-001",
      "depositInstructions": {
        "type": "GO_ACCOUNT",
        "asset": "string",
        "sequenceId": "order-deposit:95bdbd9c-9cdc-41a4-ae70-165387b7aa51",
        "address": "0x123456789abcdef123456789abcdef123456789a"
      },
      "orderMethod": "ISSUER_DIRECT",
      "memo": "string"
    }
  ],
  "total": 142,
  "pageNo": 1,
  "pageSize": 50
}
```

## See Also

* [API Reference: Create an order](/reference/mintv1enterpriseorderscreate)
* [API Reference: Get an order by ID](/reference/mintv1enterpriseordersget)
* [API Reference: Get supported asset pairs](/reference/mintv1enterpriseassetpairsget)
* [API Reference: Get supported tokens for an enterprise](/reference/mintv1enterprisesupportedtokensget)
* [API Reference: List exchange orders](/reference/mintv1enterpriseorderslist)
* [API Reference: Send Transaction](/reference/expresswalletsendcoins)
