Estimate transfer batch

Validates an exact-wallet transfer batch request and estimates transaction chunking and fees.

POST/v1/payments/transfer-batches/estimateRun in dashboard

warnings lists what would make the batch fail: a native SOL amount below the rent-exempt minimum sent to an address with no account, or a source wallet left below the minimum; create refuses those with 409 AMOUNT_BELOW_RENT_MINIMUM. Returns 503 ESTIMATE_NOT_AVAILABLE when Solana RPC cannot price a chunk's fee; the estimate stores nothing, so retry it.

Requires an API key with the transfer_batches.read action.

Headers

  • x-project-id · string · min length 1 · example prj_example

    Required for dashboard sessions. API keys use their assigned project.

Request body

application/json · required

Estimate transaction chunking and fees for a transfer batch.

  • projectId · string · min length 1 · example prj_example

    Project identifier for the transfer batch context.

  • sourceCustodyWalletId · string · required · min length 1 · example cwlt_example

    Exact SDP Wallet ID (id from GET /v1/wallets).

  • token · string · required · example SOL

    Token to transfer. Pass SOL for the native token, a well-known token symbol (e.g. USDC) resolved to the configured cluster's mint, or a base58 SPL mint address. Custom tokens must be specified by their on-chain mint.

  • recipients · object[] · required · min items 1 · max items 500

    Counterparty-account recipients to pay in this batch.

    • externalId · string · min length 1 · max length 256

    • counterpartyId · string · min length 1

    • counterpartyAccountId · string · required · min length 1

    • amount · string · required

  • externalId · string · min length 1 · max length 256 · example payroll_2026_06_30

    Optional: an estimate moves nothing, so it names no payout run. Pass the run's externalId to estimate the batch you will create with it.

Responses

  • 200 Transfer batch estimate

    • data · object · required

      Transfer batch estimate response payload.

      • estimate · object · required

        Transfer batch estimate.

        • recipientCount · integer · required

          Requested recipient count.

        • transactionCount · integer · required

          Estimated number of Solana transaction chunks.

        • estimatedFees · object · required

          Estimated fee components.

          • networkFeeLamports · string · required · example 5000

            Estimated base network fee in lamports.

          • priorityFeeLamports · string · required · example 0

            Estimated priority fee in lamports.

          • tokenAccountRentLamports · string · required · example 0

            Estimated rent needed for newly-created recipient token accounts.

          • sponsored · boolean · required · example true

            Whether SDP sponsors transaction fees for this batch.

        • warnings · object[] · required

          What would make the batch fail. Empty when the batch can be sent as estimated.

          One of:

          • code: "AMOUNT_BELOW_RENT_MINIMUM"

            • code · string · required · always AMOUNT_BELOW_RENT_MINIMUM

              A native SOL recipient's address holds no account and its amount is below the rent-exempt minimum.

            • recipientIndex · integer · required

              Zero-based index of the recipient in the request.

            • minimumAmount · string · required

              The smallest SOL amount the address can receive while it has no account.

            • message · string · required

              Human-readable warning.

          • code: "SOURCE_BELOW_RENT_MINIMUM"

            • code · string · required · always SOURCE_BELOW_RENT_MINIMUM

              The source wallet would be left holding more than nothing but less than the rent-exempt minimum, at the end or after some order of the batch's concurrent transactions.

            • sourceRemainder · string · required

              The SOL the source wallet would be left with.

            • minimumAmount · string · required

              The rent-exempt minimum for a SOL wallet.

            • message · string · required

              Human-readable warning.

    • meta · object · required

      Response metadata.

      • requestId · string · required · min length 1 · example req_example

        Request identifier for tracing.

      • timestamp · string · required · format date-time · example 2025-01-01T00:00:00.000Z

        ISO 8601 timestamp.

  • 400 Bad Request

    • error · object · required

      Standard error payload.

      • code · string · required

        Machine-readable error code.

      • message · string · required

        Human-readable error message.

      • details · object

        Optional error details for debugging.

        • * · any
    • meta · object

      • requestId · string · min length 1 · example req_example

        Request identifier for tracing.

  • 401 Unauthorized

    Same fields as 400.

  • 403 Forbidden. Requires the transfer_batches.read action: an API key must hold it (a module's manage or execute also covers its read), and a signed-in member's organization role must include it. Without it the error is INSUFFICIENT_PERMISSIONS and error.details.action names the action. Any other 403 names its own reason.

    Same fields as 400.

  • 404 Not Found

    Same fields as 400.

  • 500 Internal Server Error

    Same fields as 400.

  • 503 Service Unavailable

    Same fields as 400.

Example request

curl -X POST 'https://api-beta.solana.com/v1/payments/transfer-batches/estimate' \
  -H "Authorization: Bearer $SDP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": "prj_example",
    "sourceCustodyWalletId": "cwlt_example",
    "token": "SOL",
    "recipients": [
      {
        "externalId": "payroll_row_001",
        "counterpartyId": "cpty_example",
        "counterpartyAccountId": "cpacct_example",
        "amount": "25.00"
      }
    ],
    "externalId": "payroll_2026_06_30"
  }'
const res = await fetch("https://api-beta.solana.com/v1/payments/transfer-batches/estimate", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SDP_API_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "projectId": "prj_example",
    "sourceCustodyWalletId": "cwlt_example",
    "token": "SOL",
    "recipients": [
      {
        "externalId": "payroll_row_001",
        "counterpartyId": "cpty_example",
        "counterpartyAccountId": "cpacct_example",
        "amount": "25.00"
      }
    ],
    "externalId": "payroll_2026_06_30"
  })
});
import os, requests

r = requests.post("https://api-beta.solana.com/v1/payments/transfer-batches/estimate",
  headers={"Authorization": f"Bearer {os.environ['SDP_API_KEY']}"},
  json={
    "projectId": "prj_example",
    "sourceCustodyWalletId": "cwlt_example",
    "token": "SOL",
    "recipients": [
      {
        "externalId": "payroll_row_001",
        "counterpartyId": "cpty_example",
        "counterpartyAccountId": "cpacct_example",
        "amount": "25.00"
      }
    ],
    "externalId": "payroll_2026_06_30"
  })

Example responses

JSON
{
  "data": {
    "estimate": {
      "recipientCount": 1,
      "transactionCount": 1,
      "estimatedFees": {
        "networkFeeLamports": "5000",
        "priorityFeeLamports": "0",
        "tokenAccountRentLamports": "0",
        "sponsored": true
      },
      "warnings": [
        {
          "code": "AMOUNT_BELOW_RENT_MINIMUM",
          "recipientIndex": 1,
          "minimumAmount": "example",
          "message": "example"
        }
      ]
    }
  },
  "meta": {
    "requestId": "req_example",
    "timestamp": "2025-01-01T00:00:00.000Z"
  }
}
JSON
{
  "error": {
    "code": "INSUFFICIENT_PERMISSIONS",
    "message": "Missing action: transfer_batches.read",
    "details": {
      "action": "transfer_batches.read"
    }
  },
  "meta": {
    "requestId": "req_example"
  }
}

Error responses use the standard error shape.