Coinbax API

Transactions

Payment operations and lifecycle management

View as Markdown

List transactions with filters

GET/api/v1/transactionsX-API-Key

Query parameters

  • pagenumber

    Page number

  • limitnumber

    Items per page

  • statusenum

    Filter by status

    "pending" · "risk_review" · "pending_user_action" · "escrowed" · "in_review" · "disputed" · "completed" · "refunded" · "failed" · "rescinded"
  • fromAddressstring

    Filter by sender blockchain address

  • toAddressstring

    Filter by receiver blockchain address

  • dateFromstring

    Filter by date from (ISO 8601)

  • dateTostring

    Filter by date to (ISO 8601)

  • customerIdstring

    Filter by customer ID

  • walletAddressstring

    Filter by wallet address (matches fromAddress OR toAddress)

Responses

200List of transactions

Response follows the unified success / data / meta / error envelope.

curl https://api-staging.coinbax.com/api/v1/transactions \
  -H "X-API-Key: $COINBAX_API_KEY"
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions', {
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
  },
});
const result = await response.json();

Create a new transaction

POST/api/v1/transactionsX-API-Key

Request body

  • fromAddressstringrequired

    Sender blockchain address

  • toAddressstringrequired

    Receiver blockchain address

  • amountnumberrequired

    Transaction amount (minimum 0.01, maximum 1,000,000)

  • currencyenum"USDC" · "USDT" · "ETH" · "MockUSDC" · "USDG"

    Currency type

  • blockchainNetworkenum"ethereum" · "base" · "solana" · "optimism" · "arbitrum" · "base-sepolia" · "ethereum-sepolia" · "optimism-sepolia" · "arbitrum-sepolia" · "solana-devnet" · "solana-testnet"

    Blockchain network. Defaults to the environment's Base network when omitted ('base' on production, 'base-sepolia' on local/staging). Mainnet names sent to local/staging are coerced to their testnet counterpart (e.g. base → base-sepolia); testnet names sent to production are rejected with TESTNET_NOT_ALLOWED_IN_PRODUCTION.

  • orchestrationTypeenum"raw" · "coinbax"

    Orchestration type: raw (direct blockchain) or coinbax (smart contract escrow)

  • templateIdstring (uuid)

    Template ID from coinbax-library. The template will be fetched from the library service.

  • contractTemplateIdstring (uuid)

    Contract template ID (alias for templateId, for backward compatibility)

  • templateobject

    Complete template data embedded in request (optional, prefer using templateId instead)

    • TemplateDto
      • templateIdstringrequired

        Template ID from coinbax-library

      • templateNamestringrequired

        Template name

      • templateVersionstringrequired

        Template version

      • controlsarray of TemplateControlDtorequired

        Array of controls to execute

        array of TemplateControlDto
        • idstringrequired

          Control ID

        • typestringrequired

          Control type (e.g., TimeDelay, TwoFactorAuth, ComplianceCheck)

        • namestringrequired

          Control name

        • executionPhasestringrequired

          Execution phase (PRE_ESCROW, POST_ESCROW, POST_RELEASE)

        • executionOrdernumberrequired

          Execution order within the phase

        • configobjectrequired

          Control configuration

          object

          Control configuration

        • isRequiredboolean

          Whether this control is required for the transaction

        • isActiveboolean

          Whether this control is active

  • metadataobject

    Additional metadata about the transaction

    object

    Additional metadata about the transaction

  • billingConfigobject

    Billing configuration from workspace (passed by coinbax-core)

    • BillingConfigDto
      • feeTypeenumrequired"percentage" · "fixed" · "tiered"

        Type of fee calculation

      • feePercentagenumber

        Fee percentage in basis points (100 = 1%). Required for percentage type.

      • fixedFeeAmountnumber

        Fixed fee amount in smallest currency unit. Required for fixed type.

      • tieredFeesarray of TieredFeeDto

        Array of tiered fee configurations. Required for tiered type.

        array of TieredFeeDto
        • minAmountnumberrequired

          Minimum transaction amount for this tier

        • maxAmountnumberrequired

          Maximum transaction amount for this tier

        • feePercentagenumberrequired

          Fee percentage in basis points (100 = 1%)

      • feeWalletAddressstringrequired

        Coinbax fee collection wallet address

      • currencystringrequired

        Currency for fee collection

      • isActivebooleanrequired

        Whether billing is active for this workspace

  • quoteIdstring (uuid)

    FeeQuote id from a prior /transactions/quote call. Required when the workspace has BILLING_ENABLED=true (Phase 1 cutover).

  • signerTypeenum"custodial" · "external_wallet"

    Signer type: custodial (Coinbax signs) or external_wallet (User signs via MetaMask)

  • customerIdstring

    Customer ID for external wallet transactions (Transmitter users)

  • idempotencyKeystring

    Idempotency key to prevent duplicate transaction creation. If provided, a transaction with the same key will return the existing transaction instead of creating a new one.

Responses

201Transaction created successfully
  • rescindobject

    Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.

    • TransactionRescindInfo
      • allowedbooleanrequired

        Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.

      • deadlineobjectrequired

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

        object

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

      • requiresReasonbooleanrequired

        Whether the rescind endpoint requires a non-empty `reason` field in the request body.

      • notifyRecipientbooleanrequired

        Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.

{
  "rescind": {
    "allowed": true,
    "deadline": "2026-06-15T12:00:00.000Z",
    "requiresReason": false,
    "notifyRecipient": true
  }
}
409Duplicate transaction detected within time window

Response follows the unified success / data / meta / error envelope.

429Transaction rate limit exceeded (max 10/minute per sender)

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "toAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "amount": 100.5,
  "currency": "USDC",
  "blockchainNetwork": "base",
  "orchestrationType": "raw",
  "templateId": "550e8400-e29b-41d4-a716-446655440000",
  "contractTemplateId": "550e8400-e29b-41d4-a716-446655440000",
  "template": {
    "templateId": "550e8400-e29b-41d4-a716-446655440000",
    "templateName": "2FA Escrow",
    "templateVersion": "1.0.0",
    "controls": [
      {
        "id": "control-123",
        "type": "TwoFactorAuth",
        "name": "Two-Factor Authentication",
        "executionPhase": "PRE_ESCROW",
        "executionOrder": 1,
        "config": {
          "method": "sms",
          "phoneNumber": "+1234567890"
        }
      }
    ]
  },
  "metadata": {
    "orderId": "order_789",
    "productName": "Premium Widget"
  },
  "billingConfig": {
    "feeType": "percentage",
    "feePercentage": 30,
    "feeWalletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "currency": "USDC",
    "isActive": true
  },
  "quoteId": "550e8400-e29b-41d4-a716-446655440000",
  "signerType": "custodial",
  "customerId": "cust_abc123",
  "idempotencyKey": "tx_unique_key_12345"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "toAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "amount": 100.5,
    "currency": "USDC",
    "blockchainNetwork": "base",
    "orchestrationType": "raw",
    "templateId": "550e8400-e29b-41d4-a716-446655440000",
    "contractTemplateId": "550e8400-e29b-41d4-a716-446655440000",
    "template": {
      "templateId": "550e8400-e29b-41d4-a716-446655440000",
      "templateName": "2FA Escrow",
      "templateVersion": "1.0.0",
      "controls": [
        {
          "id": "control-123",
          "type": "TwoFactorAuth",
          "name": "Two-Factor Authentication",
          "executionPhase": "PRE_ESCROW",
          "executionOrder": 1,
          "config": {
            "method": "sms",
            "phoneNumber": "+1234567890"
          }
        }
      ]
    },
    "metadata": {
      "orderId": "order_789",
      "productName": "Premium Widget"
    },
    "billingConfig": {
      "feeType": "percentage",
      "feePercentage": 30,
      "feeWalletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
      "currency": "USDC",
      "isActive": true
    },
    "quoteId": "550e8400-e29b-41d4-a716-446655440000",
    "signerType": "custodial",
    "customerId": "cust_abc123",
    "idempotencyKey": "tx_unique_key_12345"
  }),
});
const result = await response.json();

Money-at-risk: count + age of funds stuck in non-terminal states

GET/api/v1/transactions/at-riskX-API-Key

Responses

200Per-status (escrowed/in_review/pending_user_action/disputed) count, total amount, oldest age, and >24h/>72h aged counts

Response follows the unified success / data / meta / error envelope.

curl https://api-staging.coinbax.com/api/v1/transactions/at-risk \
  -H "X-API-Key: $COINBAX_API_KEY"
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/at-risk', {
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
  },
});
const result = await response.json();

List transaction batches with filters

GET/api/v1/transactions/batchX-API-Key

Returns a paginated list of multi-recipient batches scoped to the calling platform. Legs are not embedded — fetch a single batch via GET /transactions/batch/:id for that.

Query parameters

  • pagenumber

    Page number

  • limitnumber

    Items per page

  • statusenum

    Filter by batch status

    "pending_user_action" · "submitted" · "completed" · "failed"
  • fromAddressstring

    Filter by sender blockchain address

  • dateFromstring

    Filter by date from (ISO 8601)

  • dateTostring

    Filter by date to (ISO 8601)

  • customerIdstring

    Filter by customer ID

Responses

200Paginated list of batches

Response follows the unified success / data / meta / error envelope.

curl https://api-staging.coinbax.com/api/v1/transactions/batch \
  -H "X-API-Key: $COINBAX_API_KEY"
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/batch', {
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
  },
});
const result = await response.json();

Create a multi-recipient transaction batch

POST/api/v1/transactions/batchX-API-Key

Creates a parent batch row plus one Transaction leg per recipient in a single DB transaction. The client (e.g., SafeSend) then signs and submits `WorkspaceEscrow.batchCreateEscrow` with each leg's UUID as the on-chain `transactionId`. Per-leg `EscrowCreated` events flow through the existing event monitor and transition each leg from PENDING_USER_ACTION to ESCROWED individually.

Request body

  • fromAddressstringrequired

    Sender blockchain address (one signer for the whole batch).

  • legsarray of CreateBatchLegDtorequired

    Per-recipient legs (1..MAX_BATCH_LEGS).

    array of CreateBatchLegDto
    • toAddressstringrequired

      Receiver blockchain address for this leg.

    • amountnumberrequired

      Per-leg amount (minimum 0.01, maximum 1,000,000).

    • metadataobject

      Per-leg metadata (e.g., recipient name from the address book). Distinct from batch-level metadata.

      object

      Per-leg metadata (e.g., recipient name from the address book). Distinct from batch-level metadata.

  • currencyenum"USDC" · "USDT" · "ETH" · "MockUSDC" · "USDG"

    Currency type — shared by every leg in the batch.

  • blockchainNetworkstring

    Blockchain network. The set of accepted values mirrors `CreateTransactionDto.blockchainNetwork`, including the env-aware default ('base' on production, 'base-sepolia' on local/staging), non-prod coercion of mainnet names, and production rejection of testnet names.

  • orchestrationTypeenum"raw" · "coinbax"

    Orchestration type for every leg.

  • signerTypeenum"custodial" · "external_wallet"

    Signer type. Must be `external_wallet` in B1 — custodial batch sends are not supported in this phase.

  • templateIdstring (uuid)

    Template ID from coinbax-library. Stored on the batch in B1; control execution against the template is wired in B2.

  • customerIdstring

    Customer ID for external-wallet flows (Transmitter, SafeSend).

  • idempotencyKeystring

    Idempotency key — if provided, an existing batch with the same key is returned instead of creating a new one.

  • metadataobject

    Batch-level metadata (distinct from per-leg metadata).

    object

    Batch-level metadata (distinct from per-leg metadata).

  • templateobject

    Embedded template (alternative to `templateId`, deprecated for consistency with `CreateTransactionDto`).

    • TemplateDto
      • templateIdstringrequired

        Template ID from coinbax-library

      • templateNamestringrequired

        Template name

      • templateVersionstringrequired

        Template version

      • controlsarray of TemplateControlDtorequired

        Array of controls to execute

        array of TemplateControlDto
        • idstringrequired

          Control ID

        • typestringrequired

          Control type (e.g., TimeDelay, TwoFactorAuth, ComplianceCheck)

        • namestringrequired

          Control name

        • executionPhasestringrequired

          Execution phase (PRE_ESCROW, POST_ESCROW, POST_RELEASE)

        • executionOrdernumberrequired

          Execution order within the phase

        • configobjectrequired

          Control configuration

          object

          Control configuration

        • isRequiredboolean

          Whether this control is required for the transaction

        • isActiveboolean

          Whether this control is active

Responses

201Batch created successfully (legs included in `legs`)
object
{}
400Invalid request — empty/oversized `legs`, malformed addresses, unsupported `signerType`, or template validation failure

Response follows the unified success / data / meta / error envelope.

403Customer approval required or sender not approved

Response follows the unified success / data / meta / error envelope.

429Transaction rate limit exceeded

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/batch \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "legs": [
    {
      "toAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
      "amount": 100.5,
      "metadata": {
        "recipientLabel": "Alice",
        "orderId": "order_789"
      }
    }
  ],
  "currency": "USDC",
  "blockchainNetwork": "base",
  "orchestrationType": "raw",
  "signerType": "external_wallet",
  "templateId": "550e8400-e29b-41d4-a716-446655440000",
  "customerId": "cust_abc123",
  "idempotencyKey": "batch_unique_key_12345",
  "metadata": {
    "source": "safesend",
    "uiVersion": "1.2.3"
  },
  "template": {
    "templateId": "550e8400-e29b-41d4-a716-446655440000",
    "templateName": "2FA Escrow",
    "templateVersion": "1.0.0",
    "controls": [
      {
        "id": "control-123",
        "type": "TimeDelay",
        "name": "Payment Hold Period",
        "executionPhase": "PRE_ESCROW",
        "executionOrder": 1,
        "config": {
          "delayMinutes": 5
        },
        "isRequired": true,
        "isActive": true
      }
    ]
  }
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/batch', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "legs": [
      {
        "toAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
        "amount": 100.5,
        "metadata": {
          "recipientLabel": "Alice",
          "orderId": "order_789"
        }
      }
    ],
    "currency": "USDC",
    "blockchainNetwork": "base",
    "orchestrationType": "raw",
    "signerType": "external_wallet",
    "templateId": "550e8400-e29b-41d4-a716-446655440000",
    "customerId": "cust_abc123",
    "idempotencyKey": "batch_unique_key_12345",
    "metadata": {
      "source": "safesend",
      "uiVersion": "1.2.3"
    },
    "template": {
      "templateId": "550e8400-e29b-41d4-a716-446655440000",
      "templateName": "2FA Escrow",
      "templateVersion": "1.0.0",
      "controls": [
        {
          "id": "control-123",
          "type": "TimeDelay",
          "name": "Payment Hold Period",
          "executionPhase": "PRE_ESCROW",
          "executionOrder": 1,
          "config": {
            "delayMinutes": 5
          },
          "isRequired": true,
          "isActive": true
        }
      ]
    }
  }),
});
const result = await response.json();

Get a transaction batch by ID

GET/api/v1/transactions/batch/{id}X-API-Key

Returns the parent batch row plus all child Transaction legs. Each leg carries its own status, escrowId, and per-recipient metadata; per-leg listing of just the legs is also reachable via GET /transactions?batchId=…

Path parameters

  • idstringrequired

Responses

200Batch details with legs
object
{}
404Batch not found

Response follows the unified success / data / meta / error envelope.

curl https://api-staging.coinbax.com/api/v1/transactions/batch/<id> \
  -H "X-API-Key: $COINBAX_API_KEY"
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/batch/<id>', {
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
  },
});
const result = await response.json();

Manually cancel an unsubmitted batch

POST/api/v1/transactions/batch/{id}/cancelX-API-Key

Marks a batch FAILED and propagates the same status to every leg. Allowed only while the batch is in `pending_user_action` (the user hasn't signed `batchCreateEscrow` yet, or is parked awaiting verification). Once the on-chain tx is in flight, use per-leg refund/dispute endpoints instead. Idempotent on already-FAILED batches. Fires a `transaction.batch.failed` webhook on success.

Path parameters

  • idstringrequired

Request body

  • reasonstring

    Human-readable reason recorded on the batch metadata. Surfaces in audit logs and the cancel webhook payload. Truncated at 500 chars.

Responses

200Batch cancelled (or was already FAILED — idempotent)
object
{}
400Batch is in a state that cannot be cancelled (submitted / completed)

Response follows the unified success / data / meta / error envelope.

404Batch not found

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/batch/<id>/cancel \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Sender closed the tab before signing batchCreateEscrow"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/batch/<id>/cancel', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "reason": "Sender closed the tab before signing batchCreateEscrow"
  }),
});
const result = await response.json();

Record the on-chain batchCreateEscrow transaction hash

POST/api/v1/transactions/batch/{id}/submit-escrow-hashX-API-Key

Stores the shared on-chain transaction hash on the batch + every leg, and advances the batch to `submitted`. Per-leg `EscrowCreated` events drive each leg from `pending_user_action` to `escrowed` independently via the existing event monitor.

Path parameters

  • idstringrequired

Request body

  • transactionHashstringrequired

    On-chain transaction hash for the `batchCreateEscrow` call. Shared by every leg in the batch (one signature, one tx).

Responses

200Hash recorded, batch advanced to submitted
object
{}
400Batch is in a non-submittable state (already terminal, or still awaiting verification), or the request is for a custodial batch

Response follows the unified success / data / meta / error envelope.

404Batch not found

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/batch/<id>/submit-escrow-hash \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "transactionHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/batch/<id>/submit-escrow-hash', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "transactionHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
  }),
});
const result = await response.json();

Verify a 2FA code against a pending batch control

POST/api/v1/transactions/batch/{id}/verify-2faX-API-Key

Accepts the verification code the sender received and clears the batch's `awaitingControlVerification` flag once every PRE_ESCROW verification control resolves.

Path parameters

  • idstringrequired

Request body

  • codestringrequired

    6-digit verification code sent via SMS

Responses

200Code accepted, batch updated
object
{}
400Batch not awaiting verification, no pending 2FA control, or invalid/expired code

Response follows the unified success / data / meta / error envelope.

404Batch not found

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/batch/<id>/verify-2fa \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "code": "123456"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/batch/<id>/verify-2fa', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "code": "123456"
  }),
});
const result = await response.json();

Preview platform fee for a transaction

POST/api/v1/transactions/fee-previewX-API-Key

Calculate and preview the platform fee before creating a transaction

Request body

  • amountnumberrequired

    The proposed transaction amount

  • billingConfigobjectrequired

    Billing configuration from workspace

    • BillingConfigDto
      • feeTypeenumrequired"percentage" · "fixed" · "tiered"

        Type of fee calculation

      • feePercentagenumber

        Fee percentage in basis points (100 = 1%). Required for percentage type.

      • fixedFeeAmountnumber

        Fixed fee amount in smallest currency unit. Required for fixed type.

      • tieredFeesarray of TieredFeeDto

        Array of tiered fee configurations. Required for tiered type.

        array of TieredFeeDto
        • minAmountnumberrequired

          Minimum transaction amount for this tier

        • maxAmountnumberrequired

          Maximum transaction amount for this tier

        • feePercentagenumberrequired

          Fee percentage in basis points (100 = 1%)

      • feeWalletAddressstringrequired

        Coinbax fee collection wallet address

      • currencystringrequired

        Currency for fee collection

      • isActivebooleanrequired

        Whether billing is active for this workspace

Responses

200Fee preview calculated successfully
  • originalAmountnumberrequired

    The original transaction amount

  • feeAmountnumberrequired

    The calculated platform fee

  • netAmountnumberrequired

    The net amount after fee deduction

  • feeTypeenumrequired"percentage" · "fixed" · "tiered"

    The type of fee calculation used

  • feeBasisPointsobjectrequired

    The fee rate in basis points (if applicable)

    object

    The fee rate in basis points (if applicable)

  • feePercentageDisplayobjectrequired

    The fee percentage displayed for user

    object

    The fee percentage displayed for user

  • feeWalletAddressstringrequired

    The wallet address for fee collection

  • billingActivebooleanrequired

    Whether billing is currently active

{
  "originalAmount": 100.5,
  "feeAmount": 0.3015,
  "netAmount": 100.1985,
  "feeType": "percentage",
  "feeBasisPoints": 30,
  "feePercentageDisplay": "0.30%",
  "feeWalletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "billingActive": true
}
curl -X POST https://api-staging.coinbax.com/api/v1/transactions/fee-preview \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "amount": 100.5,
  "billingConfig": {
    "feeType": "percentage",
    "feePercentage": 30,
    "fixedFeeAmount": 1,
    "tieredFees": [
      {
        "minAmount": 0,
        "maxAmount": 1000,
        "feePercentage": 30
      }
    ],
    "feeWalletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "currency": "USDC",
    "isActive": true
  }
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/fee-preview', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "amount": 100.5,
    "billingConfig": {
      "feeType": "percentage",
      "feePercentage": 30,
      "fixedFeeAmount": 1,
      "tieredFees": [
        {
          "minAmount": 0,
          "maxAmount": 1000,
          "feePercentage": 30
        }
      ],
      "feeWalletAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
      "currency": "USDC",
      "isActive": true
    }
  }),
});
const result = await response.json();

Create a fee quote for a pending transaction

POST/api/v1/transactions/quoteX-API-Key

Returns a 120-second-TTL quote with platform fee, workspace fee, gas pass-through (if applicable), and total charged. Pass the returned `quoteId` to `POST /transactions` to lock the rate.

Request body

  • amountUsdstringrequired

    USD principal amount

  • assetstringrequired
  • networkstringrequired

    Canonical network identifier

Responses

200Quote created successfully
  • quoteIdstring (uuid)required
  • expiresAtstring (date-time)required
  • amountUsdstringrequired
  • platformFeeUsdstringrequired
  • workspaceFeeUsdobjectrequired
    object
  • gasPassThroughUsdobjectrequired
    object
  • totalOnTopUsdstringrequired
  • totalChargedUsdstringrequired
  • gasCapExceededbooleanrequired
{
  "quoteId": "9f8b7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
  "expiresAt": "2026-01-15T12:00:00.000Z",
  "amountUsd": "1000.00",
  "platformFeeUsd": "2.500000",
  "workspaceFeeUsd": "5.000000",
  "gasPassThroughUsd": null,
  "totalOnTopUsd": "7.500000",
  "totalChargedUsd": "1007.500000",
  "gasCapExceeded": false
}
404Workspace has no ACTIVE PricingPlan / WorkspaceFeeSchedule. Operator intervention required.

Response follows the unified success / data / meta / error envelope.

422Gas-cap exceeded and PricingPlan.onGasCapBreach=BLOCK. The caller can retry later if gas drops.

Response follows the unified success / data / meta / error envelope.

503Transient: gas oracle / FX / coinbax-core unreachable. Retry.

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/quote \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "amountUsd": "1000.00",
  "asset": "USDC",
  "network": "base"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/quote', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "amountUsd": "1000.00",
    "asset": "USDC",
    "network": "base"
  }),
});
const result = await response.json();

Get transaction statistics

GET/api/v1/transactions/statsX-API-Key

Responses

200Transaction statistics

Response follows the unified success / data / meta / error envelope.

curl https://api-staging.coinbax.com/api/v1/transactions/stats \
  -H "X-API-Key: $COINBAX_API_KEY"
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/stats', {
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
  },
});
const result = await response.json();

Get sanitized template + controls config for a template ID

GET/api/v1/transactions/template-configX-API-Key

Returns public-safe summaries of each active control on a template. Used by pre-confirmation surfaces (e.g. SafeSend) to render "What protects your send" panels and to enforce client-side AmountLimit min/max. Sanitized: only a hand-picked subset of each control config is returned — policy/implementation fields are NOT exposed.

Query parameters

  • templateIdstringrequired

Responses

200Template config retrieved
  • templateIdstringrequired

    Template UUID.

  • templateNamestringrequired

    Template name (e.g. "Transmitter P2P").

  • templateVersionstringrequired

    Template version string from the library (e.g. "1.0.0").

  • controlsarray of TemplateControlSummaryrequired

    Active controls on the template, sanitized to a small set of public-safe fields per type. See TemplateControlSummary.

    array of TemplateControlSummary
    • typestringrequired

      Control type. Tolerates the upstream `ChainlysisSanctions` typo alongside the corrected `ChainalysisSanctions` for now (see PR #74).

    • phasestringrequired

      Execution phase: PRE_ESCROW, POST_ESCROW, PRE_RELEASE, or POST_RELEASE.

    • namestringrequired

      Human-readable control name (from the template, e.g. "Sanctions Screening").

    • isRequiredbooleanrequired

      Whether this control is required (vs. optional — driven by `metadata.optional` on the template control).

    • minAmountnumber

      AmountLimit: minimum allowed amount per send (inclusive).

    • maxAmountnumber

      AmountLimit: maximum allowed amount per send (inclusive).

    • currencystring

      AmountLimit: currency the limits are denominated in (e.g. "USD", "USDC").

    • delayAmountnumber

      TimeDelay: hold-period duration amount.

    • delayUnitenum"seconds" · "minutes" · "hours" · "days"

      TimeDelay: unit for `delayAmount`.

    • allowSenderRescindboolean

      TimeDelay: whether the sender can rescind/cancel during the hold window.

    • userConfigurableboolean

      TimeDelay: whether the user can pick a delay value per transaction (vs. always the template default). When true, the frontend should render `options` as selectable presets. When false or absent, the frontend renders the template default as a read-only display.

    • optionsarray of string

      TimeDelay: allowed preset values (when `userConfigurable` is true) using compact duration notation: `Nm` minutes, `Nh` hours, `Nd` days. Frontend parses and renders these as picker chips. Empty / absent means no template-defined presets — frontend may fall back to its own defaults.

      array of string
      string
    • sanctionsListsarray of string

      ChainlysisSanctions / ChainalysisSanctions: which sanctions lists the screening checks (e.g. OFAC, SDN, EU).

      array of string
      string
    • checksSenderboolean

      ChainlysisSanctions / ChainalysisSanctions: whether the sender wallet is screened.

    • checksRecipientboolean

      ChainlysisSanctions / ChainalysisSanctions: whether the recipient wallet is screened.

    • verificationRequiredboolean

      TwilioSMS: whether the SMS-verification step is mandatory (vs. lookup-only).

{
  "templateId": "a1b2c3d4-e5f6-4a5b-8c9d-1234567890ab",
  "templateName": "Transmitter P2P",
  "templateVersion": "1.0.0",
  "controls": [
    {
      "type": "AmountLimit",
      "phase": "PRE_ESCROW",
      "name": "Amount Limit Check",
      "isRequired": true,
      "minAmount": 1,
      "maxAmount": 1000000,
      "currency": "USD",
      "delayAmount": 24,
      "delayUnit": "hours",
      "allowSenderRescind": true,
      "userConfigurable": true,
      "options": [
        "5m",
        "30m",
        "24h",
        "48h",
        "7d"
      ],
      "sanctionsLists": [
        "OFAC",
        "SDN",
        "EU"
      ],
      "checksSender": true,
      "checksRecipient": true,
      "verificationRequired": true
    }
  ]
}
404Template not found

Response follows the unified success / data / meta / error envelope.

curl https://api-staging.coinbax.com/api/v1/transactions/template-config?templateId=<templateId> \
  -H "X-API-Key: $COINBAX_API_KEY"
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/template-config?templateId=<templateId>', {
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
  },
});
const result = await response.json();

Get transaction by ID

GET/api/v1/transactions/{id}X-API-Key

Path parameters

  • idstringrequired

Responses

200Transaction details
  • rescindobject

    Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.

    • TransactionRescindInfo
      • allowedbooleanrequired

        Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.

      • deadlineobjectrequired

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

        object

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

      • requiresReasonbooleanrequired

        Whether the rescind endpoint requires a non-empty `reason` field in the request body.

      • notifyRecipientbooleanrequired

        Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.

{
  "rescind": {
    "allowed": true,
    "deadline": "2026-06-15T12:00:00.000Z",
    "requiresReason": false,
    "notifyRecipient": true
  }
}
404Transaction not found

Response follows the unified success / data / meta / error envelope.

curl https://api-staging.coinbax.com/api/v1/transactions/<id> \
  -H "X-API-Key: $COINBAX_API_KEY"
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>', {
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
  },
});
const result = await response.json();

Authorize release of an external-wallet escrow

POST/api/v1/transactions/{id}/authorize-releaseX-API-Key

Runs the PRE_RELEASE controls and records the aggregate result on-chain for an external-wallet (SafeSend) COINBAX escrow, so the sender wallet (releaseEarly / releaseAfterDelay) can release without the escrow's PRE_RELEASE gate reverting. Call this immediately BEFORE the on-chain release write. An early (pre-window) release waives the time-delay hold; a required non-time control failure auto-rejects the escrow and refunds the sender (do not then attempt an on-chain release).

Path parameters

  • idstringrequired

Request body

  • earlyboolean

    Advisory hint that the sender intends an early (pre-window) release. The server authoritatively infers early vs after-delay from the escrow release time and ignores this value for the decision.

Responses

200Release authorized (PRE_RELEASE attested Passed), or the escrow was rejected + refunded because a required control failed (see `rejected`).

Response follows the unified success / data / meta / error envelope.

400Not an external-wallet COINBAX escrow, not in ESCROWED status, or missing on-chain escrow id

Response follows the unified success / data / meta / error envelope.

404Transaction not found

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/<id>/authorize-release \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "early": true
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>/authorize-release', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "early": true
  }),
});
const result = await response.json();

Get bit execution status for transaction

GET/api/v1/transactions/{id}/bit-statusX-API-Key

Path parameters

  • idstringrequired

Responses

200Bit execution status retrieved successfully
  • transactionIdstringrequired

    Transaction ID

  • awaitingVerificationbooleanrequired

    Whether transaction is awaiting verification

  • controlsarray of objectrequired

    Array of control execution results

    array of object
    • controlIdstring
    • controlTypestring
    • phasestring
    • successboolean
    • isRequiredboolean
    • durationMsnumber
    • dataobject
      object
    • executedAtstring (date-time)
  • successbooleanrequired

    Overall success status

  • nextActionstring

    Next action required (if any)

  • messagestringrequired

    Human-readable status message

{
  "transactionId": "123e4567-e89b-12d3-a456-426614174000",
  "awaitingVerification": false,
  "controls": [
    {
      "controlId": "control-uuid",
      "controlType": "TimeDelay",
      "phase": "PRE_ESCROW",
      "success": true,
      "isRequired": true,
      "durationMs": 125,
      "data": {},
      "executedAt": "2026-01-15T12:00:00.000Z"
    }
  ],
  "success": true,
  "nextAction": "verify_2fa",
  "message": "All controls executed successfully"
}
404Transaction not found

Response follows the unified success / data / meta / error envelope.

curl https://api-staging.coinbax.com/api/v1/transactions/<id>/bit-status \
  -H "X-API-Key: $COINBAX_API_KEY"
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>/bit-status', {
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
  },
});
const result = await response.json();

Cancel pre-escrow transaction the user never signed for

POST/api/v1/transactions/{id}/cancelX-API-Key

Marks a transaction in PENDING_USER_ACTION as FAILED with userCancelled=true. No on-chain action — funds were never escrowed. Use this when the user rejects the wallet popup and does not intend to retry; rejects with 400 if the transaction has already advanced to ESCROWED (use /refund or /rescind instead) or is already terminal.

Path parameters

  • idstringrequired

Request body

  • reasonstring

    Optional human-readable reason for the cancellation. Surfaced in the transaction.failed webhook and stored on `metadata.cancelReason`.

Responses

200Transaction cancelled successfully
  • rescindobject

    Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.

    • TransactionRescindInfo
      • allowedbooleanrequired

        Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.

      • deadlineobjectrequired

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

        object

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

      • requiresReasonbooleanrequired

        Whether the rescind endpoint requires a non-empty `reason` field in the request body.

      • notifyRecipientbooleanrequired

        Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.

{
  "rescind": {
    "allowed": true,
    "deadline": "2026-06-15T12:00:00.000Z",
    "requiresReason": false,
    "notifyRecipient": true
  }
}
400Transaction not in PENDING_USER_ACTION, or already has an on-chain escrow address

Response follows the unified success / data / meta / error envelope.

404Transaction not found

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/<id>/cancel \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "User dismissed pending tx from SafeSend Active tab"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>/cancel', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "reason": "User dismissed pending tx from SafeSend Active tab"
  }),
});
const result = await response.json();

Complete transaction and release funds

POST/api/v1/transactions/{id}/completeX-API-Key

Path parameters

  • idstringrequired

Request body

  • notestring

    Optional completion note

Responses

200Transaction completed successfully
  • rescindobject

    Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.

    • TransactionRescindInfo
      • allowedbooleanrequired

        Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.

      • deadlineobjectrequired

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

        object

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

      • requiresReasonbooleanrequired

        Whether the rescind endpoint requires a non-empty `reason` field in the request body.

      • notifyRecipientbooleanrequired

        Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.

{
  "rescind": {
    "allowed": true,
    "deadline": "2026-06-15T12:00:00.000Z",
    "requiresReason": false,
    "notifyRecipient": true
  }
}
400Invalid transaction state for completion

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/<id>/complete \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "note": "Service delivered successfully"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>/complete', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "note": "Service delivered successfully"
  }),
});
const result = await response.json();

Refund transaction

POST/api/v1/transactions/{id}/refundX-API-Key

Path parameters

  • idstringrequired

Request body

  • reasonstringrequired

    Reason for refund

Responses

200Transaction refunded successfully
  • rescindobject

    Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.

    • TransactionRescindInfo
      • allowedbooleanrequired

        Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.

      • deadlineobjectrequired

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

        object

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

      • requiresReasonbooleanrequired

        Whether the rescind endpoint requires a non-empty `reason` field in the request body.

      • notifyRecipientbooleanrequired

        Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.

{
  "rescind": {
    "allowed": true,
    "deadline": "2026-06-15T12:00:00.000Z",
    "requiresReason": false,
    "notifyRecipient": true
  }
}
400Invalid transaction state for refund

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/<id>/refund \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Customer request - item not as described"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>/refund', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "reason": "Customer request - item not as described"
  }),
});
const result = await response.json();

Rescind transaction during hold period (sender only)

POST/api/v1/transactions/{id}/rescindX-API-Key

Allows the sender to cancel a transaction during the Payment Hold Period and have funds returned to their wallet. Only available if the TimeDelay control has allowSenderRescind enabled.

Path parameters

  • idstringrequired

Request body

  • reasonstring

    Reason for rescinding the transaction (required if control config has rescindRequiresReason: true)

  • senderWalletstringrequired

    Sender wallet address for authorization verification

Responses

200Transaction rescinded successfully, funds returned to sender
  • rescindobject

    Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.

    • TransactionRescindInfo
      • allowedbooleanrequired

        Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.

      • deadlineobjectrequired

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

        object

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

      • requiresReasonbooleanrequired

        Whether the rescind endpoint requires a non-empty `reason` field in the request body.

      • notifyRecipientbooleanrequired

        Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.

{
  "rescind": {
    "allowed": true,
    "deadline": "2026-06-15T12:00:00.000Z",
    "requiresReason": false,
    "notifyRecipient": true
  }
}
400Transaction cannot be rescinded (not in ESCROWED status, rescind not enabled, or rescind window expired)

Response follows the unified success / data / meta / error envelope.

403Only the sender can rescind a transaction

Response follows the unified success / data / meta / error envelope.

404Transaction not found

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/<id>/rescind \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "Changed my mind about the purchase",
  "senderWallet": "0x1234567890abcdef1234567890abcdef12345678"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>/rescind', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "reason": "Changed my mind about the purchase",
    "senderWallet": "0x1234567890abcdef1234567890abcdef12345678"
  }),
});
const result = await response.json();

Resend 2FA verification code

POST/api/v1/transactions/{id}/resend-2faX-API-Key

Path parameters

  • idstringrequired

Responses

2002FA code resent successfully
  • messagestring
  • expiresInnumber
{
  "message": "2FA code resent successfully",
  "expiresIn": 300
}
400Transaction not awaiting 2FA verification

Response follows the unified success / data / meta / error envelope.

404Transaction not found

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/<id>/resend-2fa \
  -H "X-API-Key: $COINBAX_API_KEY"
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>/resend-2fa', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
  },
});
const result = await response.json();

Retry a failed bit execution

POST/api/v1/transactions/{id}/retry-bit/{bitId}X-API-Key

Path parameters

  • idstringrequired
  • bitIdstringrequired

Responses

200Bit execution retried successfully
  • rescindobject

    Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.

    • TransactionRescindInfo
      • allowedbooleanrequired

        Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.

      • deadlineobjectrequired

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

        object

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

      • requiresReasonbooleanrequired

        Whether the rescind endpoint requires a non-empty `reason` field in the request body.

      • notifyRecipientbooleanrequired

        Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.

{
  "rescind": {
    "allowed": true,
    "deadline": "2026-06-15T12:00:00.000Z",
    "requiresReason": false,
    "notifyRecipient": true
  }
}
400Invalid bit ID or bit cannot be retried

Response follows the unified success / data / meta / error envelope.

404Transaction or bit not found

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/<id>/retry-bit/<bitId> \
  -H "X-API-Key: $COINBAX_API_KEY"
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>/retry-bit/<bitId>', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
  },
});
const result = await response.json();

Submit escrow transaction hash for external wallet (Transmitter) transactions

POST/api/v1/transactions/{id}/submit-escrow-hashX-API-Key

After the user deposits USDC to the escrow contract via MetaMask, submit the transaction hash and escrow ID to confirm the escrow was created

Path parameters

  • idstringrequired

Request body

  • transactionHashstringrequired

    Blockchain transaction hash from user wallet escrow deposit

  • escrowIdstring

    Escrow ID returned by the smart contract (optional - will be detected from blockchain events if not provided)

Responses

200Escrow hash submitted and verified successfully
  • rescindobject

    Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.

    • TransactionRescindInfo
      • allowedbooleanrequired

        Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.

      • deadlineobjectrequired

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

        object

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

      • requiresReasonbooleanrequired

        Whether the rescind endpoint requires a non-empty `reason` field in the request body.

      • notifyRecipientbooleanrequired

        Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.

{
  "rescind": {
    "allowed": true,
    "deadline": "2026-06-15T12:00:00.000Z",
    "requiresReason": false,
    "notifyRecipient": true
  }
}
400Invalid transaction state or escrow verification failed

Response follows the unified success / data / meta / error envelope.

404Transaction not found

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/<id>/submit-escrow-hash \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "transactionHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "escrowId": "0x9876543210abcdef9876543210abcdef9876543210abcdef9876543210abcdef"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>/submit-escrow-hash', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "transactionHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
    "escrowId": "0x9876543210abcdef9876543210abcdef9876543210abcdef9876543210abcdef"
  }),
});
const result = await response.json();

Submit blockchain transaction hash for RAW transaction

POST/api/v1/transactions/{id}/submit-hashX-API-Key

After sending USDC from your wallet, submit the transaction hash to complete the transaction

Path parameters

  • idstringrequired

Request body

  • transactionHashstringrequired

    Blockchain transaction hash from user wallet

Responses

200Transaction hash submitted and verified successfully
  • rescindobject

    Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.

    • TransactionRescindInfo
      • allowedbooleanrequired

        Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.

      • deadlineobjectrequired

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

        object

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

      • requiresReasonbooleanrequired

        Whether the rescind endpoint requires a non-empty `reason` field in the request body.

      • notifyRecipientbooleanrequired

        Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.

{
  "rescind": {
    "allowed": true,
    "deadline": "2026-06-15T12:00:00.000Z",
    "requiresReason": false,
    "notifyRecipient": true
  }
}
400Invalid transaction state or hash verification failed

Response follows the unified success / data / meta / error envelope.

404Transaction not found

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/<id>/submit-hash \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "transactionHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>/submit-hash', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "transactionHash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
  }),
});
const result = await response.json();

Verify 2FA code for transaction

POST/api/v1/transactions/{id}/verify-2faX-API-Key

Path parameters

  • idstringrequired

Request body

  • codestringrequired

    6-digit verification code sent via SMS

Responses

2002FA verified successfully, transaction can proceed
  • rescindobject

    Public-safe summary of the TimeDelay rescind config. Lets clients gate the Cancel/Rescind affordance without a second round-trip. Null when the transaction has no TimeDelay control (RAW orchestration, templates without a hold period). Absent from response on the list endpoint and on legacy api revisions.

    • TransactionRescindInfo
      • allowedbooleanrequired

        Whether the sender is allowed to rescind/cancel the transaction during the hold window. Defaults to true when not explicitly set on the underlying control config.

      • deadlineobjectrequired

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

        object

        ISO 8601 timestamp after which rescind is no longer allowed. Null when the rescind window matches the full hold period.

      • requiresReasonbooleanrequired

        Whether the rescind endpoint requires a non-empty `reason` field in the request body.

      • notifyRecipientbooleanrequired

        Whether the recipient is notified (e.g. via SMS) when a rescind succeeds.

{
  "rescind": {
    "allowed": true,
    "deadline": "2026-06-15T12:00:00.000Z",
    "requiresReason": false,
    "notifyRecipient": true
  }
}
400Invalid or expired verification code

Response follows the unified success / data / meta / error envelope.

404Transaction not found

Response follows the unified success / data / meta / error envelope.

curl -X POST https://api-staging.coinbax.com/api/v1/transactions/<id>/verify-2fa \
  -H "X-API-Key: $COINBAX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "code": "123456"
}'
const response = await fetch('https://api-staging.coinbax.com/api/v1/transactions/<id>/verify-2fa', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.COINBAX_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "code": "123456"
  }),
});
const result = await response.json();