Create a transaction

Guides

Create a transaction

Create an outgoing transaction from an existing BroSettlement wallet. A successful `POST` accepts the transaction for processing; it does not mean that the transaction is already final on-chain.

Before you begin

You need:

  • An ACTIVE wallet and its walletId
  • An asset currently returned by GET /api/v1/assets
  • A valid destination address for the selected chain
  • Enough availableBalance for the amount and any applicable network fee
  • An initialized MPC setup and a healthy Co-Signer
  • An API key with the withdrawals:create scope
  • A unique X-Idempotency-Key
  • An optional but recommended unique clientReference from your system

1. Check the wallet and available balance

Read the wallet and its balances before creating the transaction:

text
GET /api/v1/wallets/{walletId}
GET /api/v1/wallets/{walletId}/balances

Use availableBalance for the spendability check. Do not assume that the posted balance is fully available when part of it is reserved.

2. Convert the amount to atomic units

Send amountAtomic as a base-10 string in the asset’s smallest unit. Never use a floating-point number for an amount.

For example, if USDT uses 6 decimals:

text
1.00 USDT = "1000000"

Read the current decimals and chain availability from the Assets API instead of hard-coding them.

3. Build the request body

json
{
  "clientReference": "withdrawal-4821",
  "walletId": "wallet-id",
  "asset": "USDT",
  "toAddress": "destination-address",
  "amountAtomic": "1000000"
}

clientReference can connect the BroSettlement transaction to your order, payout, or withdrawal record. It must be unique when supplied.

Use chainParams only when the current API schema requires chain-specific settings. Do not copy parameters between chains.

4. Sign and send the exact request

bash
curl https://brosettlement-staging-api.brolabel.io/api/v1/transactions \
  -X POST \
  -H "X-Api-Key-Id: 11111111-2222-4333-8444-555555555555" \
  -H "X-Api-Timestamp: 1785402000" \
  -H "X-Api-Nonce: 37c19dc0-8247-4a56-8193-beca10dce927" \
  -H "X-Api-Signature: base64_ed25519_signature" \
  -H "X-Api-Body-Hash: sha256_of_exact_body" \
  -H "X-Idempotency-Key: 018f4df0-5a7f-7352-bd4a-5fd069c2a0c2" \
  -H "Content-Type: application/json" \
  -d '{"clientReference":"withdrawal-4821","walletId":"wallet-id","asset":"USDT","toAddress":"destination-address","amountAtomic":"1000000"}'

Calculate the body hash from the exact body bytes sent by the HTTP client. Sign the canonical six-line string using the exact POST method, request target /api/v1/transactions, body hash, timestamp, nonce, and API key ID.

5. Store the accepted transaction

A successful request returns 201 Created with a transaction detail object. Store at least:

  • id
  • walletId
  • type
  • status
  • chain
  • asset
  • amountAtomic
  • clientReference
  • createdAt and updatedAt

The initial status is normally PENDING. Persist the BroSettlement transaction id before returning success from your own workflow.

6. Track the transaction to a terminal state

Listen for transaction.created, transaction.updated, transaction.confirmed, transaction.failed, and transaction.failed_on_chain. Reconcile each event against:

text
GET /api/v1/transactions/{transactionId}

Treat REST as the source of truth. Do not mark a payout complete from the 201 response alone. Terminal statuses are CONFIRMED, FAILED, and FAILED_ON_CHAIN.

Retry safely

If the result of the original request is unknown, retry with the same X-Idempotency-Key and the identical request body. Changing the body while reusing the key produces an IDEMPOTENCY_CONFLICT.

Do not create a new idempotency key until you have checked the original transaction by id, clientReference, or the transaction list.

Common errors

Error codeWhat to check
INSUFFICIENT_AVAILABLE_BALANCECheck the spendable amount and applicable network fee.
INVALID_ADDRESSValidate the destination against the selected chain.
UNSUPPORTED_ASSET or UNSUPPORTED_CHAINRefresh the current asset and chain catalog.
WITHDRAWALS_BLOCKEDStop retries and resolve the organization or wallet restriction.
CLIENT_REFERENCE_CONFLICTReuse the existing transaction or generate a genuinely new business reference.
IDEMPOTENCY_CONFLICTRetry only with the exact original request.
UPSTREAM_UNAVAILABLEKeep the original idempotency key and retry with backoff.

Transactions API

Review the complete request and response schema, filters, statuses, and balance effects.

WebSocket events

Implement resumable, idempotent lifecycle event processing.

API conventions

Review canonical signing, idempotency, retries, errors, and request tracing.