> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blockradar.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Signing

> Sign messages, typed data, and raw transactions with your wallet keys

<Note>
  In a nutshell<br />
  The Blockradar Signing API lets you cryptographically sign plain text messages, structured data (typed data), and raw transactions using your wallet's private keys. Sign messages to prove wallet ownership. Sign transactions built externally (e.g., Jupiter swaps on Solana) without exposing private keys, and optionally broadcast them on-chain.
</Note>

## Prerequisites

Before using the Signing API, ensure you have:

<Steps>
  <Step title="API Key">
    Get your API key from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Developers** to generate one.
  </Step>

  <Step title="Wallet Created">
    Create a master wallet from the [Blockradar Dashboard](https://dashboard.blockradar.co). Navigate to **Wallets** and create one for your target blockchain. You'll need the `walletId` for signing operations.
  </Step>

  <Step title="Environment">
    Choose between **Testnet** (for development) or **Mainnet** (for production). Wallets are isolated per environment.
  </Step>
</Steps>

## How It Works

The Signing API produces a cryptographic signature that proves you control a specific wallet address. The signed output can be verified by any third party without accessing your private keys.

<CardGroup cols={2}>
  <Card title="Message Signing" icon="pen">
    Sign plain text messages to prove wallet ownership. Works on all supported blockchains: EVM, Tron, Solana, and Stellar.
  </Card>

  <Card title="Typed Data Signing" icon="file-signature">
    Sign structured data following the EIP-712 standard. Used for gasless approvals (EIP-2612 Permit) and authorized transfers (EIP-3009). EVM-only.
  </Card>

  <Card title="Transaction Signing" icon="file-contract">
    Sign raw transactions built externally. Build a swap on Jupiter, a contract call via ethers.js, or a TronWeb transfer, then send the unsigned tx and get it signed without exposing private keys.
  </Card>

  <Card title="Transaction Broadcast" icon="tower-broadcast">
    Sign and broadcast a raw transaction in one step. Blockradar signs the transaction and submits it on-chain via a reliable queue with automatic retries.
  </Card>
</CardGroup>

### Common use cases

* **Third-party provider registration**: Prove you own an address when onboarding with services like Iron, Circle, or other DeFi protocols
* **Gasless token approvals**: Sign EIP-2612 Permit messages to authorize token spending without an on-chain transaction
* **Authorized transfers**: Sign EIP-3009 TransferWithAuthorization messages for delegated transfers
* **Off-chain attestations**: Create verifiable proofs of intent or agreement tied to a wallet address
* **External swap execution**: Build a Jupiter swap on Solana, sign it with Blockradar, and broadcast it on-chain
* **Custom contract interactions**: Build any transaction externally and have Blockradar sign and/or submit it

## Master Wallet vs Child Address

The Signing API is available at two levels:

<CardGroup cols={2}>
  <Card title="Master Wallet" icon="wallet">
    Sign using the master wallet's keys. Ideal for treasury-level operations and provider integrations.
  </Card>

  <Card title="Child Address" icon="address-card">
    Sign using a specific child address's keys. Use when the third party requires a signature from a deposit address.
  </Card>
</CardGroup>

### Endpoints

| Operation        | Master Wallet                                     | Child Address                                                           |
| ---------------- | ------------------------------------------------- | ----------------------------------------------------------------------- |
| Sign Message     | `POST /v1/wallets/{walletId}/signing/message`     | `POST /v1/wallets/{walletId}/addresses/{addressId}/signing/message`     |
| Sign Typed Data  | `POST /v1/wallets/{walletId}/signing/typed-data`  | `POST /v1/wallets/{walletId}/addresses/{addressId}/signing/typed-data`  |
| Sign Transaction | `POST /v1/wallets/{walletId}/signing/transaction` | `POST /v1/wallets/{walletId}/addresses/{addressId}/signing/transaction` |
| Sign + Broadcast | `POST /v1/wallets/{walletId}/signing/broadcast`   | `POST /v1/wallets/{walletId}/addresses/{addressId}/signing/broadcast`   |

***

## Message Signing

Sign a plain text message with your wallet's private key. The API signs the message, verifies the signature matches the wallet address, and returns both the signature and a transaction record.

### Supported Blockchains

| Blockchain                                                   | Signing Standard                                   | Signature Format                          |
| ------------------------------------------------------------ | -------------------------------------------------- | ----------------------------------------- |
| EVM (Ethereum, Polygon, BSC, Base, Arbitrum, Optimism, Celo) | EIP-191 (personal\_sign)                           | Hex-encoded with `r`, `s`, `v` components |
| Tron                                                         | TronWeb signMessageV2                              | Hex-encoded string                        |
| Solana                                                       | Ed25519                                            | Base58-encoded string                     |
| Stellar                                                      | SEP-53 (Ed25519 over the hashed, prefixed message) | Base64-encoded string                     |

<Note>
  Stellar message signing follows [SEP-53](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0053.md), the Stellar standard for signing arbitrary messages. The signed payload is `SHA-256("Stellar Signed Message:\n" + message)`, signed with the account's Ed25519 key, and the signature is base64-encoded. To verify it, apply the same prefix and hash before checking the signature against the signer's public key. The Stellar CLI `stellar message` command and the SEP-53 helpers in the Stellar SDK do this for you. A raw Ed25519 signature over the unprefixed message will not verify.
</Note>

### Request Parameters

| Parameter   | Type   | Required | Description                                                                        |
| ----------- | ------ | -------- | ---------------------------------------------------------------------------------- |
| `message`   | string | Yes      | The plain text message to sign. Maximum 4,096 characters.                          |
| `reference` | string | No       | Your internal tracking ID. Use for idempotency. Duplicate references are rejected. |
| `metadata`  | object | No       | Custom key-value pairs stored with the transaction record.                         |

### Message Signing Example

<CodeGroup>
  ```bash Curl theme={null}
  curl --request POST \
    --url https://api.blockradar.co/v1/wallets/{walletId}/signing/message \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: <api-key>' \
    --data '{
      "message": "Please sign this message to verify your wallet ownership for Iron provider registration.",
      "reference": "iron-verification-001",
      "metadata": {
        "provider": "iron",
        "purpose": "wallet-verification"
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    `https://api.blockradar.co/v1/wallets/${walletId}/signing/message`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': apiKey
      },
      body: JSON.stringify({
        message: 'Please sign this message to verify your wallet ownership for Iron provider registration.',
        reference: 'iron-verification-001',
        metadata: {
          provider: 'iron',
          purpose: 'wallet-verification'
        }
      })
    }
  ).then(r => r.json());

  console.log('Signature:', response.data.hash);
  console.log('Signed transaction:', response.data.signedTransaction);
  ```

  ```php PHP theme={null}
  <?php

  $curl = curl_init();

  curl_setopt_array($curl, [
    CURLOPT_URL => "https://api.blockradar.co/v1/wallets/{walletId}/signing/message",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_POSTFIELDS => json_encode([
      "message" => "Please sign this message to verify your wallet ownership for Iron provider registration.",
      "reference" => "iron-verification-001",
      "metadata" => [
        "provider" => "iron",
        "purpose" => "wallet-verification"
      ]
    ]),
    CURLOPT_HTTPHEADER => [
      "Content-Type: application/json",
      "x-api-key: <api-key>"
    ],
  ]);

  $response = curl_exec($curl);
  curl_close($curl);

  echo $response;
  ```
</CodeGroup>

### EVM Response

```json theme={null}
{
  "message": "Message signed successfully",
  "statusCode": 200,
  "data": {
    "id": "770f9100-7338-4823-b1ce-3658fc67db09",
    "hash": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b",
    "status": "SUCCESS",
    "type": "SIGNED",
    "senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "signedTransaction": {
      "r": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e2133",
      "s": "0x5aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b3",
      "v": 27,
      "signature": "0xdb095e6cbf...b31b"
    },
    "reference": "iron-verification-001",
    "metadata": {
      "provider": "iron",
      "purpose": "wallet-verification"
    },
    "confirmed": true,
    "createdAt": "2025-03-02T19:00:52.000Z"
  }
}
```

### Tron / Solana / Stellar Response

For Tron, Solana, and Stellar, the `signedTransaction` object contains only the `signature` field (no `r`, `s`, `v` components):

```json theme={null}
{
  "message": "Message signed successfully",
  "statusCode": 200,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "hash": "3xYkZ9...",
    "status": "SUCCESS",
    "type": "SIGNED",
    "senderAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRT9Y",
    "recipientAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRT9Y",
    "signedTransaction": {
      "signature": "3xYkZ9..."
    },
    "reference": "tron-verification-001",
    "confirmed": true,
    "createdAt": "2025-03-02T19:00:52.000Z"
  }
}
```

### Response Fields

| Field               | Description                                                                                                                    |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `id`                | Unique transaction ID for the signing record                                                                                   |
| `hash`              | The cryptographic signature. For EVM: hex string. For Tron: hex string. For Solana: base58 string. For Stellar: base64 string. |
| `status`            | Always `SUCCESS` for completed signatures                                                                                      |
| `type`              | Always `SIGNED` for signing transactions                                                                                       |
| `senderAddress`     | The wallet address that produced the signature                                                                                 |
| `signedTransaction` | Signature components. EVM includes `r`, `s`, `v`, and full `signature`. Tron, Solana, and Stellar include `signature` only.    |
| `reference`         | Your provided reference string (if any)                                                                                        |
| `metadata`          | Your provided metadata object (if any)                                                                                         |

***

## Typed Data Signing (EVM Only)

Sign structured data following the EIP-712 standard. This is used for gasless approvals, delegated transfers, and other on-chain authorization flows that require a structured signature.

<Warning>
  Typed data signing is only available for EVM-compatible blockchains (Ethereum, Polygon, BSC, Base, Arbitrum, Optimism, Celo). Tron, Solana, and Stellar do not support EIP-712.
</Warning>

### Supported Standards

| Standard                             | Use Case                                                                  |
| ------------------------------------ | ------------------------------------------------------------------------- |
| EIP-712                              | Generic structured data signing                                           |
| EIP-2612 (Permit)                    | Gasless token approvals. Approve spending without an on-chain transaction |
| EIP-3009 (TransferWithAuthorization) | Delegated transfers. Authorize a transfer that a third party submits      |

### Request Parameters

| Parameter | Type   | Required | Description                                                                               |
| --------- | ------ | -------- | ----------------------------------------------------------------------------------------- |
| `domain`  | object | Yes      | EIP-712 domain separator. Includes `name`, `version`, `chainId`, and `verifyingContract`. |
| `types`   | object | Yes      | Type definitions for the structured data.                                                 |
| `message` | object | Yes      | The data to sign, conforming to the type definitions.                                     |

### EIP-2612 Permit Example

<CodeGroup>
  ```bash Curl theme={null}
  curl --request POST \
    --url https://api.blockradar.co/v1/wallets/{walletId}/signing/typed-data \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: <api-key>' \
    --data '{
      "domain": {
        "name": "USD Coin",
        "version": "2",
        "chainId": 11155111,
        "verifyingContract": "0xa0b86a33e6441b8c4c8c0c077bcdd28571685701"
      },
      "types": {
        "Permit": [
          { "name": "owner", "type": "address" },
          { "name": "spender", "type": "address" },
          { "name": "value", "type": "uint256" },
          { "name": "nonce", "type": "uint256" },
          { "name": "deadline", "type": "uint256" }
        ]
      },
      "message": {
        "owner": "0x742d35cc6634c0532925a3b8d4c9db96c4b4d8b6",
        "spender": "0x8ba1f109551bd432803012645aac136c4c8c8c0c",
        "value": "1000000000",
        "nonce": "0",
        "deadline": "1641081600"
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    `https://api.blockradar.co/v1/wallets/${walletId}/signing/typed-data`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': apiKey
      },
      body: JSON.stringify({
        domain: {
          name: 'USD Coin',
          version: '2',
          chainId: 11155111,
          verifyingContract: '0xa0b86a33e6441b8c4c8c0c077bcdd28571685701'
        },
        types: {
          Permit: [
            { name: 'owner', type: 'address' },
            { name: 'spender', type: 'address' },
            { name: 'value', type: 'uint256' },
            { name: 'nonce', type: 'uint256' },
            { name: 'deadline', type: 'uint256' }
          ]
        },
        message: {
          owner: '0x742d35cc6634c0532925a3b8d4c9db96c4b4d8b6',
          spender: '0x8ba1f109551bd432803012645aac136c4c8c8c0c',
          value: '1000000000',
          nonce: '0',
          deadline: '1641081600'
        }
      })
    }
  ).then(r => r.json());

  console.log('Signature:', response.data.hash);
  console.log('r:', response.data.signedTransaction.r);
  console.log('s:', response.data.signedTransaction.s);
  console.log('v:', response.data.signedTransaction.v);
  ```
</CodeGroup>

### Typed Data Response

```json theme={null}
{
  "message": "Typed data signed successfully",
  "statusCode": 200,
  "data": {
    "id": "770f9100-7338-4823-b1ce-3658fc67db09",
    "hash": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b",
    "status": "SUCCESS",
    "type": "SIGNED",
    "senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "signedTransaction": {
      "r": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e2133",
      "s": "0x5aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b3",
      "v": 27,
      "signature": "0xdb095e6cbf...b31b"
    },
    "confirmed": true,
    "createdAt": "2025-03-02T19:00:52.000Z"
  }
}
```

### Domain Object Fields

| Field               | Type   | Required | Description                                                        |
| ------------------- | ------ | -------- | ------------------------------------------------------------------ |
| `name`              | string | Yes      | The name of the signing domain (e.g., the token name or dApp name) |
| `version`           | string | Yes      | The version of the domain                                          |
| `chainId`           | number | Yes      | The chain ID. Must match the wallet's blockchain network.          |
| `verifyingContract` | string | Yes      | The contract address that will verify the signature                |
| `salt`              | string | No       | Optional domain salt for EIP-712 v4                                |

<Warning>
  Chain ID validation<br />
  The `chainId` in your domain object must match the chain ID of the wallet's blockchain network. If they don't match, the API returns a `400 Chain ID mismatch` error.
</Warning>

***

## Child Address Signing

Sign messages, typed data, transactions, or broadcast using a specific child address instead of the master wallet. All four signing operations are available for child addresses:

<CodeGroup>
  ```bash Curl theme={null}
  curl --request POST \
    --url https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/signing/message \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: <api-key>' \
    --data '{
      "message": "Verify ownership of deposit address for provider onboarding.",
      "reference": "address-verify-001"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    `https://api.blockradar.co/v1/wallets/${walletId}/addresses/${addressId}/signing/message`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': apiKey
      },
      body: JSON.stringify({
        message: 'Verify ownership of deposit address for provider onboarding.',
        reference: 'address-verify-001'
      })
    }
  ).then(r => r.json());

  console.log('Signature:', response.data.hash);
  ```
</CodeGroup>

<Tip>
  Child address signing follows the same request and response format as master wallet signing. The only difference is the endpoint URL, which includes the `addressId`.
</Tip>

***

## Webhook Events

Signing operations trigger a webhook with the transaction record:

| Event            | Description                                                                                                                                             |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `signed.success` | Signing completed successfully. For message/typed data/transaction sign, this fires immediately. For broadcast, this fires after on chain confirmation. |
| `signed.failed`  | Transaction broadcast failed after all retries were exhausted. Only applies to the `/broadcast` endpoint.                                               |

### Webhook Payload (Message or Typed Data Signing)

```json theme={null}
{
  "event": "signed.success",
  "data": {
    "id": "770f9100-7338-4823-b1ce-3658fc67db09",
    "reference": "iron-verification-001",
    "senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "hash": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b",
    "confirmed": true,
    "status": "SUCCESS",
    "type": "SIGNED",
    "createdChannel": "api",
    "reason": "Message signed",
    "network": "testnet",
    "chainId": 11155111,
    "metadata": {
      "provider": "iron",
      "purpose": "wallet-verification"
    },
    "signedTransaction": {
      "r": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e2133",
      "s": "0x5aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b3",
      "v": 27,
      "signature": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b"
    },
    "amount": null,
    "amountUSD": "0.00",
    "fee": null,
    "feeUSD": null,
    "currency": "USD",
    "createdAt": "2025-03-02T19:00:52.000Z",
    "updatedAt": "2025-03-02T19:00:52.000Z",
    "wallet": {
      "id": "d236a191-c1d4-423c-a439-54ce6542ca41",
      "name": "Ethereum Master Wallet",
      "address": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
      "isActive": true,
      "status": "ACTIVE",
      "network": "testnet"
    },
    "asset": null,
    "blockchain": {
      "id": "85ffc132-3972-4c9e-99a5-5cf0ccb688bf",
      "name": "ethereum",
      "symbol": "eth",
      "slug": "ethereum",
      "isEvmCompatible": true,
      "tokenStandard": "ERC20"
    },
    "beneficiary": null
  }
}
```

### Webhook Payload (Transaction Signing)

For transaction signing, the `signedTransaction` field is a string (not an object). The format depends on the chain.

```json theme={null}
{
  "event": "signed.success",
  "data": {
    "id": "782942da-48b0-416b-924b-8f657ae637a7",
    "reference": "52TQawmiqYpNiWD2Ks0P",
    "senderAddress": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446",
    "recipientAddress": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446",
    "hash": "0xac4c73ca084608ac6b981e54db948dc80c15b4ea3ffd0c9f5781f3af7ad6fe51",
    "confirmed": true,
    "status": "SUCCESS",
    "type": "SIGNED",
    "createdChannel": "api",
    "reason": "Transaction signed",
    "network": "testnet",
    "chainId": 11155111,
    "metadata": null,
    "signedTransaction": "0x02f87383aa36a763843b9aca008459682f0082520894000000000000000000000000000000000000dead865af3107a400080c080a0b760...",
    "amount": null,
    "amountUSD": "0.00",
    "fee": null,
    "feeUSD": null,
    "currency": "USD",
    "createdAt": "2026-03-19T13:34:24.937Z",
    "updatedAt": "2026-03-19T13:34:24.937Z",
    "wallet": {
      "id": "3f9aca5c-38ee-4e1d-ab67-c084a2e37bb2",
      "name": "Ethereum Wallet",
      "address": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446",
      "isActive": true,
      "status": "ACTIVE",
      "network": "testnet"
    },
    "asset": null,
    "blockchain": {
      "id": "85ffc132-3972-4c9e-99a5-5cf0ccb688bf",
      "name": "ethereum",
      "symbol": "eth",
      "slug": "ethereum",
      "isEvmCompatible": true,
      "tokenStandard": "ERC20"
    },
    "beneficiary": null
  }
}
```

### Webhook Payload (Broadcast Success)

After the broadcast queue confirms the transaction on chain, you receive this webhook. The `hash` field is updated to the on chain transaction hash and `confirmed` changes to `true`.

```json theme={null}
{
  "event": "signed.success",
  "data": {
    "id": "f3efdbaa-a1f8-4365-b3b4-768413c9a92b",
    "reference": "docs-test-broadcast",
    "senderAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
    "recipientAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
    "hash": "5bKNw9RX8aXkrK1VEHg5aPa1xtckpShPyenSRET4mUBXh5uCkWLFV5MhGRi4cMACDJvFn6VfkoKb75Pk4KYw6xtw",
    "confirmed": true,
    "status": "SUCCESS",
    "type": "SIGNED",
    "createdChannel": "api",
    "reason": "Transaction signed and broadcast",
    "network": "testnet",
    "chainId": 103,
    "metadata": null,
    "signedTransaction": "AeWpW65y80rSu+TU0CSrcvFNovyDiybKRjSskCpfffAFLM0GIYzx...",
    "amount": null,
    "amountUSD": "0.00",
    "fee": null,
    "feeUSD": null,
    "currency": "USD",
    "createdAt": "2026-03-19T13:35:09.921Z",
    "updatedAt": "2026-03-19T13:35:09.921Z",
    "wallet": {
      "id": "c72a6f21-6ab5-48ad-9f99-fd90a2d6d311",
      "name": "Solana Testnet Wallet",
      "address": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
      "isActive": true,
      "status": "ACTIVE",
      "network": "testnet"
    },
    "asset": null,
    "blockchain": {
      "id": "196badf5-380f-4480-ab4a-d0e4304e91f0",
      "name": "solana",
      "symbol": "sol",
      "slug": "solana",
      "isEvmCompatible": false,
      "tokenStandard": null
    },
    "beneficiary": null
  }
}
```

### Webhook Payload (Broadcast Failed)

If the broadcast fails permanently after all retry attempts, you receive this webhook. The `status` is `FAILED` and `confirmed` remains `false`.

```json theme={null}
{
  "event": "signed.failed",
  "data": {
    "id": "f3efdbaa-a1f8-4365-b3b4-768413c9a92b",
    "reference": "docs-test-broadcast",
    "senderAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
    "recipientAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
    "hash": "5bKNw9RX8aXkrK1VEHg5aPa1xtckpShPyenSRET4mUBXh5uCkWLFV5MhGRi4cMACDJvFn6VfkoKb75Pk4KYw6xtw",
    "confirmed": false,
    "status": "FAILED",
    "type": "SIGNED",
    "createdChannel": "api",
    "reason": "Transaction broadcast failed",
    "network": "testnet",
    "chainId": 103,
    "metadata": null,
    "signedTransaction": "AeWpW65y80rSu+TU0CSrcvFNovyDiybKRjSskCpfffAFLM0GIYzx...",
    "amount": null,
    "amountUSD": "0.00",
    "fee": null,
    "feeUSD": null,
    "currency": "USD",
    "createdAt": "2026-03-19T13:35:09.921Z",
    "updatedAt": "2026-03-19T13:35:09.921Z",
    "wallet": {
      "id": "c72a6f21-6ab5-48ad-9f99-fd90a2d6d311",
      "name": "Solana Testnet Wallet",
      "address": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
      "isActive": true,
      "status": "ACTIVE",
      "network": "testnet"
    },
    "asset": null,
    "blockchain": {
      "id": "196badf5-380f-4480-ab4a-d0e4304e91f0",
      "name": "solana",
      "symbol": "sol",
      "slug": "solana",
      "isEvmCompatible": false,
      "tokenStandard": null
    },
    "beneficiary": null
  }
}
```

***

## Transaction Signing

Sign a raw, unsigned transaction built externally. You build the transaction using any SDK (ethers.js, TronWeb, Solana web3.js, Jupiter API), then send the serialized unsigned transaction to Blockradar for signing and/or broadcasting, without needing to build or manage your own infrastructure or blockchain nodes.

### Supported Blockchains and Formats

| Blockchain | `transaction` field format                                                      | How to build                                                                                                                                                                                 |
| ---------- | ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Solana     | Base64 of `VersionedTransaction.serialize()`                                    | Jupiter API `/swap` response, or `@solana/web3.js` TransactionMessage                                                                                                                        |
| EVM        | JSON string of `{to, value, data, nonce, chainId, gasLimit, maxFeePerGas, ...}` | `ethers.js` populateTransaction()                                                                                                                                                            |
| Tron       | JSON string of TronWeb transaction object `{txID, raw_data, raw_data_hex}`      | `tronWeb.transactionBuilder.triggerSmartContract()`                                                                                                                                          |
| Stellar    | Base64 of the transaction envelope XDR (`transaction.toXDR()`)                  | `@stellar/stellar-sdk` `TransactionBuilder`, then `.toXDR()`. Soroban transactions must be simulated and assembled first — see [Stellar Soroban Transactions](#stellar-soroban-transactions) |

### Request Parameters

| Parameter     | Type   | Required | Description                                                            |
| ------------- | ------ | -------- | ---------------------------------------------------------------------- |
| `transaction` | string | Yes      | The serialized unsigned transaction. Format depends on the blockchain. |
| `reference`   | string | No       | Your internal tracking ID.                                             |
| `metadata`    | object | No       | Custom key-value pairs stored with the transaction record.             |

### Transaction Signing Example (Solana + Jupiter)

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { Connection, PublicKey, VersionedTransaction } from '@solana/web3.js';

  // Step 1: Build the swap transaction via Jupiter API
  const quoteResponse = await fetch(
    'https://quote-api.jup.ag/v6/quote?inputMint=SOL&outputMint=USDC&amount=1000000&slippageBps=50'
  ).then(r => r.json());

  const swapResponse = await fetch('https://quote-api.jup.ag/v6/swap', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      quoteResponse,
      userPublicKey: walletAddress, // Your Blockradar wallet's Solana address
      wrapAndUnwrapSol: true,
    })
  }).then(r => r.json());

  // Step 2: Send the unsigned transaction to Blockradar for signing
  const signResponse = await fetch(
    `https://api.blockradar.co/v1/wallets/${walletId}/signing/transaction`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': apiKey
      },
      body: JSON.stringify({
        transaction: swapResponse.swapTransaction, // Base64 VersionedTransaction
        reference: 'jupiter-swap-001'
      })
    }
  ).then(r => r.json());

  console.log('Signed tx:', signResponse.data.signedTransaction);
  console.log('Hash:', signResponse.data.hash);
  ```

  ```bash Curl theme={null}
  curl --request POST \
    --url https://api.blockradar.co/v1/wallets/{walletId}/signing/transaction \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: <api-key>' \
    --data '{
      "transaction": "<base64 unsigned VersionedTransaction>",
      "reference": "jupiter-swap-001"
    }'
  ```
</CodeGroup>

### Transaction Signing Example (EVM)

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { ethers } from 'ethers';

  // Step 1: Build the unsigned transaction
  const provider = new ethers.providers.JsonRpcProvider('https://rpc.sepolia.org');
  const nonce = await provider.getTransactionCount(walletAddress);
  const feeData = await provider.getFeeData();

  const unsignedTx = JSON.stringify({
    to: '0xRecipientAddress',
    value: ethers.utils.parseEther('0.01').toHexString(),
    nonce,
    chainId: 11155111, // Sepolia
    gasLimit: ethers.utils.hexlify(21000),
    maxFeePerGas: feeData.maxFeePerGas.toHexString(),
    maxPriorityFeePerGas: feeData.maxPriorityFeePerGas.toHexString(),
    type: 2,
  });

  // Step 2: Send to Blockradar for signing
  const signResponse = await fetch(
    `https://api.blockradar.co/v1/wallets/${walletId}/signing/transaction`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': apiKey
      },
      body: JSON.stringify({
        transaction: unsignedTx,
        reference: 'eth-transfer-001'
      })
    }
  ).then(r => r.json());

  // The signed transaction can be broadcast via any RPC
  // await provider.sendTransaction(signResponse.data.signedTransaction);
  ```

  ```bash Curl theme={null}
  curl --request POST \
    --url https://api.blockradar.co/v1/wallets/{walletId}/signing/transaction \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: <api-key>' \
    --data '{
      "transaction": "{\"to\":\"0xRecipient\",\"value\":\"0x2386F26FC10000\",\"nonce\":0,\"chainId\":11155111,\"gasLimit\":\"0x5208\",\"maxFeePerGas\":\"0x59682F00\",\"maxPriorityFeePerGas\":\"0x3B9ACA00\",\"type\":2}",
      "reference": "eth-transfer-001"
    }'
  ```
</CodeGroup>

### Sign-Only Response (EVM)

```json theme={null}
{
  "statusCode": 200,
  "message": "Transaction signed successfully",
  "data": {
    "id": "782942da-48b0-416b-924b-8f657ae637a7",
    "reference": "52TQawmiqYpNiWD2Ks0P",
    "senderAddress": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446",
    "recipientAddress": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446",
    "hash": "0xac4c73ca084608ac6b981e54db948dc80c15b4ea3ffd0c9f5781f3af7ad6fe51",
    "confirmed": true,
    "status": "SUCCESS",
    "type": "SIGNED",
    "createdChannel": "api",
    "reason": "Transaction signed",
    "network": "testnet",
    "chainId": 11155111,
    "metadata": null,
    "signedTransaction": "0x02f87383aa36a763843b9aca008459682f0082520894000000000000000000000000000000000000dead865af3107a400080c080a0b760...",
    "amount": null,
    "amountUSD": "0.00",
    "fee": null,
    "feeUSD": null,
    "currency": "USD",
    "createdAt": "2026-03-19T13:34:24.937Z",
    "updatedAt": "2026-03-19T13:34:24.937Z",
    "wallet": {
      "id": "3f9aca5c-38ee-4e1d-ab67-c084a2e37bb2",
      "name": "Ethereum Wallet",
      "address": "0xC887a3Cb8E7AbA4A77D7275AD4B242f71cbd5446",
      "isActive": true,
      "status": "ACTIVE",
      "network": "testnet"
    },
    "asset": null,
    "blockchain": {
      "id": "85ffc132-3972-4c9e-99a5-5cf0ccb688bf",
      "name": "ethereum",
      "symbol": "eth",
      "slug": "ethereum",
      "isEvmCompatible": true,
      "tokenStandard": "ERC20"
    },
    "beneficiary": null
  }
}
```

### Sign-Only Response (Solana)

```json theme={null}
{
  "statusCode": 200,
  "message": "Transaction signed successfully",
  "data": {
    "id": "02f404a5-d13e-4bcf-8ad5-c5f51c04fa49",
    "reference": "qZmQqDiIp9owMzQJcDbv",
    "senderAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
    "recipientAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
    "hash": "TjphHHAzjhRBn8t1qhhTRWpUxvkATBnzeRBB8fonWkYpR1gDh4t99rmgah3hrwoCbD3L9Ex1a7SYjjX2TePio3s",
    "confirmed": true,
    "status": "SUCCESS",
    "type": "SIGNED",
    "createdChannel": "api",
    "reason": "Transaction signed",
    "network": "testnet",
    "chainId": 103,
    "metadata": null,
    "signedTransaction": "ARcO4DT2IYg/wemCZy4iYXVRzlGruYHUTGqIcbWI/uWeWet6MNZKVVvUF4yT5GQjRqrb1QD1TaAoflyXXatxzAaAAQABA...",
    "amount": null,
    "amountUSD": "0.00",
    "fee": null,
    "feeUSD": null,
    "currency": "USD",
    "createdAt": "2026-03-19T13:38:45.326Z",
    "updatedAt": "2026-03-19T13:38:45.326Z",
    "wallet": {
      "id": "c72a6f21-6ab5-48ad-9f99-fd90a2d6d311",
      "name": "Solana Testnet Wallet",
      "address": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
      "isActive": true,
      "status": "ACTIVE",
      "network": "testnet"
    },
    "asset": null,
    "blockchain": {
      "id": "196badf5-380f-4480-ab4a-d0e4304e91f0",
      "name": "solana",
      "symbol": "sol",
      "slug": "solana",
      "isEvmCompatible": false,
      "tokenStandard": null
    },
    "beneficiary": null
  }
}
```

### Sign-Only Response (Tron)

```json theme={null}
{
  "statusCode": 200,
  "message": "Transaction signed successfully",
  "data": {
    "id": "af44218f-d38b-472b-9834-49f461a20fd4",
    "reference": "J6RugzxXI6cdpeMXrhh",
    "senderAddress": "TMUZSkS3aF1pZxnTokWikUQH7SYt3bNb6G",
    "recipientAddress": "TMUZSkS3aF1pZxnTokWikUQH7SYt3bNb6G",
    "hash": "3180f971f692a78f62050278149d746abd946fbd1797a414f5ad0d5ed45c902b",
    "confirmed": true,
    "status": "SUCCESS",
    "type": "SIGNED",
    "createdChannel": "api",
    "reason": "Transaction signed",
    "network": "testnet",
    "chainId": 3448148188,
    "metadata": null,
    "signedTransaction": "{\"visible\":false,\"txID\":\"3180f971f692a78f...\",\"raw_data\":{\"contract\":[{\"parameter\":{\"value\":{\"to_address\":\"418840e6c55b9ada...\",\"owner_address\":\"417e3682ec8f5b98...\",\"amount\":1000000},\"type_url\":\"type.googleapis.com/protocol.TransferContract\"},\"type\":\"TransferContract\"}],\"ref_block_bytes\":\"513f\",\"ref_block_hash\":\"08c7d5da0ddd12fb\",\"expiration\":1773927585000,\"timestamp\":1773927525000},\"signature\":[\"d5adac23f23414083ef4f93b995a4a18...\"]}",
    "amount": null,
    "amountUSD": "0.00",
    "fee": null,
    "feeUSD": null,
    "currency": "USD",
    "createdAt": "2026-03-19T13:38:47.096Z",
    "updatedAt": "2026-03-19T13:38:47.096Z",
    "wallet": {
      "id": "c4bbebea-6cec-4021-b842-ffead75fd0f1",
      "name": "Tron Wallet",
      "address": "TMUZSkS3aF1pZxnTokWikUQH7SYt3bNb6G",
      "isActive": true,
      "status": "ACTIVE",
      "network": "testnet"
    },
    "asset": null,
    "blockchain": {
      "id": "fa91a922-3838-45f6-8a88-a4c771e1443a",
      "name": "tron",
      "symbol": "trx",
      "slug": "tron",
      "isEvmCompatible": false,
      "tokenStandard": "TRC20"
    },
    "beneficiary": null
  }
}
```

<Note>
  For transaction signing, `signedTransaction` is a **string**, not an object. This is different from message signing where it returns an object with signature components like `r`, `s`, `v`.
</Note>

### `signedTransaction` Format by Chain

| Chain   | Type   | Format                                                                      | What to do with it                                                                                                                                                                                                                                       |
| ------- | ------ | --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Solana  | string | Base64 encoded bytes of the signed VersionedTransaction                     | Decode to bytes and pass to `connection.sendRawTransaction()`                                                                                                                                                                                            |
| EVM     | string | Hex string starting with `0x` containing the RLP encoded signed transaction | Pass directly to `eth_sendRawTransaction` or `provider.sendTransaction()`                                                                                                                                                                                |
| Tron    | string | JSON string of the signed transaction object containing a `signature` array | Parse with `JSON.parse()` and pass to `tronWeb.trx.sendRawTransaction()`                                                                                                                                                                                 |
| Stellar | string | Base64 of the signed transaction envelope XDR                               | Classic transactions: submit via Horizon `server.submitTransaction(TransactionBuilder.fromXDR(...))`. Soroban transactions: submit via Soroban RPC `server.sendTransaction(...)` — Horizon will reject them. Or use the `/broadcast` endpoint for either |

### `hash` Field by Chain

| Chain   | Format                        | How it is derived                                                                  |
| ------- | ----------------------------- | ---------------------------------------------------------------------------------- |
| Solana  | Base58 string                 | First signature from the signed transaction                                        |
| EVM     | Hex string starting with `0x` | Keccak256 hash of the signed transaction bytes                                     |
| Tron    | Hex string                    | The `txID` field from the transaction object, computed during transaction building |
| Stellar | Hex string                    | SHA-256 transaction hash (`transaction.hash()`) over the signed envelope           |

***

## Transaction Broadcast

Sign **and** broadcast a raw transaction in one step. Blockradar signs the transaction, then submits it on-chain via a reliable queue with automatic retries. The API returns immediately with `PENDING` status. You'll receive a `signed.success` or `signed.failed` webhook when the on-chain result is confirmed.

<Warning>
  Broadcast requires testnet/mainnet funds in the wallet to pay gas fees. The transaction must be valid and not expired (Solana blockhashes expire in \~90 seconds).
</Warning>

### Stellar Soroban Transactions

The signing endpoints accept Stellar Soroban transactions — a [Stellar Asset Contract](https://developers.stellar.org/docs/tokens/stellar-asset-contract) transfer or a custom contract invocation — in addition to classic transactions. Pass the same base64 transaction envelope XDR format; Blockradar detects Soroban transactions automatically and submits them via Soroban RPC instead of Horizon.

Two Stellar rules to follow:

1. **Simulate and assemble before signing.** A Soroban transaction must be simulated against Soroban RPC and assembled with the simulation results (resource footprint and fees) before it is signed. Submitting an unassembled transaction fails on-chain.
2. **Rebuild on stale sequence.** If the wallet's sequence number has moved by submission time, the API returns an error stating the transaction is stale (`tx_bad_seq`) and must be rebuilt and re-signed. Build a fresh transaction with the current sequence number and try again.

```javascript JavaScript theme={null}
import {
  rpc,
  TransactionBuilder,
  Networks,
  Contract,
  Address,
  nativeToScVal
} from '@stellar/stellar-sdk';

const server = new rpc.Server('https://soroban-testnet.stellar.org');
const account = await server.getAccount(walletAddress); // your Blockradar wallet address

// Build a Stellar Asset Contract transfer (USDC)
const contract = new Contract(usdcContractId);
const tx = new TransactionBuilder(account, {
  fee: '1000000',
  networkPassphrase: Networks.TESTNET
})
  .addOperation(
    contract.call(
      'transfer',
      Address.fromString(walletAddress).toScVal(),
      Address.fromString(recipientAddress).toScVal(), // G..., M..., or C...
      nativeToScVal('1000000', { type: 'i128' }) // 0.1 USDC (7 decimals)
    )
  )
  .setTimeout(300)
  .build();

// Simulate and assemble — required for Soroban transactions
const simulation = await server.simulateTransaction(tx);
const assembled = rpc.assembleTransaction(tx, simulation).build();

// Blockradar signs and submits via Soroban RPC
const response = await fetch(
  `https://api.blockradar.co/v1/wallets/${walletId}/signing/broadcast`,
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': apiKey
    },
    body: JSON.stringify({
      transaction: assembled.toXDR(),
      reference: 'soroban-usdc-transfer-001'
    })
  }
).then(r => r.json());
```

<Warning>
  If a Soroban transaction is submitted on-chain but confirmation polling times out, the response includes the transaction hash with the message `Soroban transaction submitted but not yet confirmed`. Reconcile the outcome by looking up that hash — do not rebuild and resubmit, as the original transaction may still confirm and cause a double spend.
</Warning>

### Request

Same parameters as transaction signing:

| Parameter     | Type   | Required | Description                          |
| ------------- | ------ | -------- | ------------------------------------ |
| `transaction` | string | Yes      | The serialized unsigned transaction. |
| `reference`   | string | No       | Your internal tracking ID.           |
| `metadata`    | object | No       | Custom key-value pairs.              |

### Broadcast Example

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Build the unsigned tx (same as sign-only examples above)
  const unsignedTx = swapResponse.swapTransaction; // Jupiter base64 tx

  // Sign + broadcast in one call
  const broadcastResponse = await fetch(
    `https://api.blockradar.co/v1/wallets/${walletId}/signing/broadcast`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': apiKey
      },
      body: JSON.stringify({
        transaction: unsignedTx,
        reference: 'jupiter-swap-broadcast-001'
      })
    }
  ).then(r => r.json());

  console.log('Status:', broadcastResponse.data.status); // "PENDING"
  console.log('Transaction ID:', broadcastResponse.data.id);
  // Wait for webhook: signed.success or signed.failed
  ```

  ```bash Curl theme={null}
  curl --request POST \
    --url https://api.blockradar.co/v1/wallets/{walletId}/signing/broadcast \
    --header 'Content-Type: application/json' \
    --header 'x-api-key: <api-key>' \
    --data '{
      "transaction": "<base64 unsigned VersionedTransaction>",
      "reference": "jupiter-swap-broadcast-001"
    }'
  ```
</CodeGroup>

### Broadcast Response (Solana Example, immediate)

```json theme={null}
{
  "statusCode": 200,
  "message": "Transaction signed and broadcast initiated",
  "data": {
    "id": "f3efdbaa-a1f8-4365-b3b4-768413c9a92b",
    "reference": "docs-test-broadcast",
    "senderAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
    "recipientAddress": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
    "hash": "5bKNw9RX8aXkrK1VEHg5aPa1xtckpShPyenSRET4mUBXh5uCkWLFV5MhGRi4cMACDJvFn6VfkoKb75Pk4KYw6xtw",
    "confirmed": false,
    "status": "PENDING",
    "type": "SIGNED",
    "createdChannel": "api",
    "reason": "Transaction signed and broadcast",
    "network": "testnet",
    "chainId": 103,
    "metadata": null,
    "signedTransaction": "AeWpW65y80rSu+TU0CSrcvFNovyDiybKRjSskCpfffAFLM0GIYzx...",
    "amount": null,
    "amountUSD": "0.00",
    "fee": null,
    "feeUSD": null,
    "currency": "USD",
    "createdAt": "2026-03-19T13:35:09.921Z",
    "updatedAt": "2026-03-19T13:35:09.921Z",
    "wallet": {
      "id": "c72a6f21-6ab5-48ad-9f99-fd90a2d6d311",
      "name": "Solana Testnet Wallet",
      "address": "HKqZUT3wuyJrsPYmrYPcGduDdjXZTggbLrNsF9WHMvbw",
      "isActive": true,
      "status": "ACTIVE",
      "network": "testnet"
    },
    "asset": null,
    "blockchain": {
      "id": "196badf5-380f-4480-ab4a-d0e4304e91f0",
      "name": "solana",
      "symbol": "sol",
      "slug": "solana",
      "isEvmCompatible": false,
      "tokenStandard": null
    },
    "beneficiary": null
  }
}
```

### Broadcast Lifecycle

The transaction goes through these states:

| Status    | Meaning                                                                        |
| --------- | ------------------------------------------------------------------------------ |
| `PENDING` | Transaction signed, broadcast queued. You receive this in the HTTP response.   |
| `SUCCESS` | Transaction confirmed on-chain. Webhook `signed.success` is sent.              |
| `FAILED`  | Broadcast failed after all retries exhausted. Webhook `signed.failed` is sent. |

<Tip>
  The broadcast queue retries up to 10 times with 5-minute intervals. For Solana, if the blockhash expires, retries will not help. You'll need to rebuild the transaction with a fresh blockhash. For Stellar, a stale sequence number (`tx_bad_seq`) similarly requires rebuilding and re-signing the transaction.
</Tip>

***

## Complete Flow Example

Here's a full implementation for signing a message and submitting the signature to a third-party provider:

```javascript theme={null}
async function signAndVerifyWithProvider(walletId, providerMessage) {
  const apiKey = process.env.BLOCKRADAR_API_KEY;
  const baseUrl = 'https://api.blockradar.co/v1';

  // Step 1: Sign the message
  const signResponse = await fetch(
    `${baseUrl}/wallets/${walletId}/signing/message`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': apiKey
      },
      body: JSON.stringify({
        message: providerMessage,
        reference: `provider-verify-${Date.now()}`
      })
    }
  ).then(r => r.json());

  if (signResponse.statusCode !== 200) {
    throw new Error(`Signing failed: ${signResponse.message}`);
  }

  const { hash, senderAddress } = signResponse.data;

  // Step 2: Submit the signature to the third-party provider
  // The provider can verify the signature matches the wallet address
  // without accessing your private keys
  return {
    address: senderAddress,
    signature: hash,
    message: providerMessage
  };
}

// Usage
signAndVerifyWithProvider(
  'wallet-uuid',
  'I authorize Iron to manage assets on my behalf.'
);
```

***

## Error Responses

<AccordionGroup>
  <Accordion title="Wallet Not Found">
    ```json theme={null}
    {
      "message": "Wallet not found",
      "statusCode": 404
    }
    ```

    The `walletId` does not exist or does not belong to your business.
  </Accordion>

  <Accordion title="Address Not Found">
    ```json theme={null}
    {
      "message": "Address not found",
      "statusCode": 404
    }
    ```

    The `addressId` does not exist or is not associated with the specified wallet.
  </Accordion>

  <Accordion title="Unsupported Blockchain (Typed Data)">
    ```json theme={null}
    {
      "message": "Typed data signing is only supported for EVM blockchains",
      "statusCode": 400
    }
    ```

    Typed data signing (EIP-712) is only available on EVM-compatible chains. Use message signing for Tron, Solana, and Stellar.
  </Accordion>

  <Accordion title="Chain ID Mismatch">
    ```json theme={null}
    {
      "message": "Chain ID mismatch",
      "statusCode": 400
    }
    ```

    The `chainId` in your typed data domain object does not match the wallet's blockchain network.
  </Accordion>

  <Accordion title="Signature Verification Failed">
    ```json theme={null}
    {
      "message": "Signature verification failed",
      "statusCode": 400
    }
    ```

    Internal round-trip verification failed. This indicates a system error. Please contact support.
  </Accordion>

  <Accordion title="Invalid Transaction Format (Solana)">
    ```json theme={null}
    {
      "message": "Invalid transaction format: expected a base64-encoded Solana VersionedTransaction",
      "statusCode": 400
    }
    ```

    The `transaction` field is not valid base64, or the decoded bytes are not a valid Solana VersionedTransaction.
  </Accordion>

  <Accordion title="Invalid Transaction Format (EVM/Tron)">
    ```json theme={null}
    {
      "message": "Invalid transaction format: expected a JSON string",
      "statusCode": 400
    }
    ```

    The `transaction` field is not valid JSON. EVM and Tron transactions must be JSON-stringified objects.
  </Accordion>

  <Accordion title="Invalid Transaction Format (Stellar)">
    ```json theme={null}
    {
      "message": "Invalid transaction format: expected a base64-encoded Stellar transaction envelope XDR",
      "statusCode": 400
    }
    ```

    The `transaction` field is not a valid base64-encoded Stellar transaction envelope XDR. Build the transaction with `@stellar/stellar-sdk` and pass `transaction.toXDR()`.
  </Accordion>
</AccordionGroup>

***

## Best Practices

### Security

* **Use references**: Track signing operations with unique reference IDs for audit trails and idempotency
* **Verify the message**: Before signing, confirm the message content matches what the third-party service expects
* **Limit message length**: Messages are capped at 4,096 characters. Keep messages concise and specific

### Integration

* **No gas fees**: Signing operations are off-chain and do not require native token balance
* **Immediate response**: Signatures are generated synchronously. No polling or webhook waiting required for the signature itself
* **Listen for webhooks**: Use webhooks to maintain an audit trail of all signing events

### Typed Data

* **Match chain IDs**: The `chainId` in your domain must match the wallet's network. Use sandbox (testnet) chain IDs for testing and production (mainnet) chain IDs for live operations
* **Check the contract**: The `verifyingContract` must be the contract that will verify the signature on-chain

### Transaction Signing

* **Build the transaction with the correct sender**: The unsigned transaction must use the wallet or child address public key as the fee payer (Solana) or sender (EVM/Tron). If the key does not match, signing will fail.
* **Solana blockhashes expire quickly**: Solana blockhashes are valid for about 60 to 90 seconds. Build the transaction and call the signing endpoint promptly. If using broadcast, the queue retries will not help once the blockhash expires.
* **EVM nonce management**: Set the nonce correctly. If the nonce is already used, the broadcast will fail. Query the nonce from the chain immediately before building the transaction.
* **Tron expiration**: Tron transactions have a 24 hour expiration window set during building. This gives plenty of time for signing and broadcast.
* **Stellar sequence and time bounds**: Build the transaction with the wallet's current account sequence number and valid time bounds. A stale sequence (`tx_bad_seq`) or expired time bounds cause submission to fail. Build and sign promptly, and set time bounds generously if you plan to broadcast later.
* **Stellar Soroban transactions**: Simulate and assemble the transaction before submitting it for signing — an unassembled Soroban transaction fails on-chain. If a stale sequence error is returned, rebuild with a fresh sequence and re-submit. If a broadcast times out awaiting confirmation, reconcile using the returned transaction hash instead of rebuilding, to avoid a double spend.
* **Sign only vs broadcast**: Use `/signing/transaction` when you want to broadcast the transaction yourself or through another service. Use `/signing/broadcast` when you want Blockradar to handle submission with automatic retries.

***

## API Reference

### Master Wallet Endpoints

| Endpoint                                                                               | Description                          |
| -------------------------------------------------------------------------------------- | ------------------------------------ |
| [Sign Message](/en/api-reference/signing/master-wallet-sign-message)                   | Sign a plain text message            |
| [Sign Typed Data](/en/api-reference/signing/master-wallet-typed-data)                  | Sign EIP-712 structured data         |
| [Sign Transaction](/en/api-reference/signing/master-wallet-sign-transaction)           | Sign a raw transaction               |
| [Broadcast Transaction](/en/api-reference/signing/master-wallet-broadcast-transaction) | Sign and broadcast a raw transaction |

### Child Address Endpoints

| Endpoint                                                                               | Description                                               |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| [Sign Message](/en/api-reference/signing/child-address-sign-message)                   | Sign a plain text message from a child address            |
| [Sign Typed Data](/en/api-reference/signing/child-address-typed-data)                  | Sign EIP-712 structured data from a child address         |
| [Sign Transaction](/en/api-reference/signing/child-address-sign-transaction)           | Sign a raw transaction from a child address               |
| [Broadcast Transaction](/en/api-reference/signing/child-address-broadcast-transaction) | Sign and broadcast a raw transaction from a child address |
