Retry a transfer batch's failed recipients

Sends the batch's failed recipients again, from the same source wallet, and no other recipient.

POST/v1/payments/transfer-batches/{batchId}/retryRun in dashboard

A failed recipient was not paid: its transaction never reached the network or the network rejected it. Recipients still pending or processing may land and are never sent again. Each resent recipient keeps its row and links to its new chunk transfer.

Takes no body and requires an Idempotency-Key. A retry with the same key sends nothing again: while its response is stored, it returns that saved response, and after a server error or once the response has expired, the batch as it stands. Read the batch's current state with GET /v1/payments/transfer-batches/{batchId}, and use a new key for each retry you mean to send.

Any credential that may send from the batch's wallet can retry it. Each recipient is paid the address the batch recorded for it. Only recipients that are still failed are ever sent, so a retry under a new key never pays anyone twice.

Returns 409, sending nothing: TRANSFER_BATCH_NOTHING_TO_RETRY when the batch has no failed recipients (while it is processing, its unsent recipients become failed only once its request can no longer send them), TRANSFER_BATCH_RETRY_CLAIMED when a concurrent retry claimed them first, and TRANSFER_BATCH_DESTINATION_CHANGED (details.recipientIds) when a failed recipient's counterparty account has changed its address since (send that recipient in a new batch). A native SOL retry is refused with 409 AMOUNT_BELOW_RENT_MINIMUM, as create is, when a failed recipient would still be paid less than the rent-exempt minimum at an address with no account; its recipients stay failed.

Requires an API key with the transfer_batches.execute action.

Path parameters

  • batchId · string · required · min length 1 · example xbatch_example

    Transfer batch identifier.

Headers

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

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

  • Idempotency-Key · string · required

    Use a unique 1–255 printable ASCII key per operation. Reuse it with the same request on retries. An in-flight attempt returns 409; a changed request returns 422. Retry and recovery rules.

Responses

  • 200 Failed recipients resent

    • data · object · required

      Transfer batch response payload.

      • batch · object · required

        Transfer batch details.

        • id · string · required · example xbatch_example

          Transfer batch identifier.

        • organizationId · string · required · min length 1 · example org_example

          Organization identifier.

        • projectId · string · required · min length 1 · example prj_example

          Project identifier for the transfer batch.

        • externalId · string | null · required · example payroll_2026_06_30

          Caller-provided batch correlation ID.

        • sourceCustodyWalletId · string | null · required · example cwlt_example

          Exact source SDP Wallet ID, or null for unresolved legacy batches.

        • sourceProviderWalletId · string · required · min length 1 · example privy_wallet_123

          Source Provider wallet ID retained as evidence.

        • sourceAddress · string · required · min length 32 · max length 44 · example So11111111111111111111111111111111111111112

          Source custody wallet address.

        • token · string · required · example SOL

          Token symbol or mint address.

        • status · string · required · one of pending, processing, confirmed, failed, partially_failed, archived · example processing

          Transfer batch status.

        • totalAmount · string | null · required · example 1000.00

          Total requested batch amount in UI units, when computed.

        • recipientCount · integer · required · example 20

          Number of recipient rows in the batch.

        • transactionCount · integer · required · example 1

          Number of Solana transaction chunks for the batch.

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

          ISO 8601 timestamp.

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

          ISO 8601 timestamp.

      • recipients · object[]

        Recipient rows for the batch, included on detail responses.

        • id · string · required

          Transfer batch recipient identifier.

        • batchId · string · required

          Parent transfer batch identifier.

        • transferId · string | null · required · min length 1 · example xfr_example

          Payment transfer chunk that settled this recipient, once assigned.

        • externalId · string | null · required · example payroll_row_001

          Caller-provided recipient correlation ID.

        • counterpartyId · string · required · example cpty_example

          Counterparty identifier for the recipient.

        • counterpartyAccountId · string · required · example cpacct_example

          Counterparty account identifier for the recipient.

        • destination · string · required · min length 32 · max length 44 · example So11111111111111111111111111111111111111112

          Resolved Solana destination address.

        • amount · string · required · example 100.00

          Token amount in UI units (decimal string).

        • status · string · required · one of pending, processing, confirmed, failed, archived · example pending

          Transfer batch recipient status.

        • error · string | null · required

          Recipient-level failure reason, when available. A recipient the source wallet could not fund reads "The wallet used for this payment does not have enough funds. Add funds and try again."

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

          ISO 8601 timestamp.

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

          ISO 8601 timestamp.

      • transfers · object[]

        Payment transfer chunk records associated with this batch.

        • fireblocks · object

          Native Fireblocks transfer tracking. A processing payment may await approval in Fireblocks; network fees are paid by its source vault. A missing transaction ID means submission is still being reconciled. Do not create a replacement payment while its outcome is unknown.

          • transactionId · string | null · required

          • status · string · required

          • subStatus · string | null · required

        • id · string · required · min length 1 · example xfr_example

          Transfer identifier (SDP record ID, not the on-chain signature).

        • organizationId · string · required · min length 1 · example org_example

          Organization identifier.

        • custodyWalletId · string | null · required · example cwlt_example

          Exact SDP Wallet ID associated with the persisted transfer, or null for unresolved legacy and observed rows.

        • providerWalletId · string · required · min length 1 · example privy_wallet_123

          Provider wallet ID retained as evidence; not an execution selector.

        • projectId · string · min length 1 · example prj_example

          Project identifier for the transfer.

        • type · string · required · example transfer

          Transfer type.

        • kind · string · required

          Dashboard transaction kind derived from the transfer type and originating Payments resource.

        • direction · string · required · one of inbound, outbound · example outbound

          Transfer direction.

        • status · string · required · example confirmed

          Transfer status.

        • signature · string | null · required · example sig_example

          Solana transaction signature (tx id/hash).

        • serializedTx · string | null · required · min length 1 · example base64_tx_example

          Base64-encoded transaction payload, if available. Always null for transfer batch chunks, whose signed bytes stay server-side.

        • slot · integer | null · required · example 123456

          Slot number, if confirmed.

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

          Block time, if confirmed.

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

          When SDP confirmed the transfer on chain.

        • fee · integer | null · required · example 0

          Network fee the source wallet paid, in lamports: 0 when SDP sponsored the transaction, null when not known.

        • error · string | null · required · example Signature failed

          Error message if the transaction failed.

        • initiatedBy · object

          Initiator that triggered the transfer.

          • type · string · required · one of api_key, user, system · example api_key

            Initiator type.

          • id · string

            Initiator identifier if applicable.

          • display · string

            Human-friendly label for the initiator.

        • source · string · min length 32 · max length 44 · example So11111111111111111111111111111111111111112

          Source wallet address.

        • destination · string · min length 32 · max length 44 · example So11111111111111111111111111111111111111112

          Destination wallet address.

        • memo · string · max length 256

          Optional memo for the transfer.

        • token · string

          Token symbol or mint address.

        • amount · string · example 100.00

          Token amount in UI units (decimal string).

        • counterpartyId · string · example cpty_example

          Counterparty tied to the transfer record, when available.

        • counterpartyDisplayName · string · example Acme Studio

          Current display name of the counterparty tied to the transfer.

        • risk · object

          Optional risk evaluation for the transfer.

          • provider · string · required · example trm

            Risk scoring provider.

          • score · string · required · example 0.12

            Provider-specific risk score.

          • level · string · required · one of low, medium, high, unknown · example low

            Risk level classification.

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

            Timestamp when risk was evaluated.

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

          Creation timestamp.

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

          Last update timestamp.

    • 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.execute 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.

  • 409 Conflict

    Same fields as 400.

  • 422 Unprocessable Entity

    Same fields as 400.

  • 500 Internal Server Error

    Same fields as 400.

  • 502 Bad Gateway

    Same fields as 400.

  • 503 Service Unavailable

    Same fields as 400.

Example request

IDEMPOTENCY_KEY=$(uuidgen)
curl -X POST 'https://api-beta.solana.com/v1/payments/transfer-batches/xbatch_example/retry' \
  -H "Authorization: Bearer $SDP_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY"
// Reuse this key when you retry this request.
const idempotencyKey = crypto.randomUUID();
const res = await fetch("https://api-beta.solana.com/v1/payments/transfer-batches/xbatch_example/retry", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SDP_API_KEY}`,
    "Idempotency-Key": idempotencyKey
  }
});
import os, requests, uuid

# Reuse this key when you retry this request.
idempotency_key = str(uuid.uuid4())
r = requests.post("https://api-beta.solana.com/v1/payments/transfer-batches/xbatch_example/retry",
  headers={"Authorization": f"Bearer {os.environ['SDP_API_KEY']}", "Idempotency-Key": idempotency_key})

Example responses

JSON
{
  "data": {
    "batch": {
      "id": "xbatch_example",
      "organizationId": "org_example",
      "projectId": "prj_example",
      "externalId": "payroll_2026_06_30",
      "sourceCustodyWalletId": "cwlt_example",
      "sourceProviderWalletId": "privy_wallet_123",
      "sourceAddress": "So11111111111111111111111111111111111111112",
      "token": "SOL",
      "status": "processing",
      "totalAmount": "1000.00",
      "recipientCount": 20,
      "transactionCount": 1,
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-01-01T00:00:00.000Z"
    },
    "recipients": [
      {
        "id": "_example",
        "batchId": "batch_example",
        "transferId": "xfr_example",
        "externalId": "payroll_row_001",
        "counterpartyId": "cpty_example",
        "counterpartyAccountId": "cpacct_example",
        "destination": "So11111111111111111111111111111111111111112",
        "amount": "100.00",
        "status": "pending",
        "error": "example",
        "createdAt": "2025-01-01T00:00:00.000Z",
        "updatedAt": "2025-01-01T00:00:00.000Z"
      }
    ],
    "transfers": [
      {
        "fireblocks": {
          "transactionId": "transaction_example",
          "status": "example",
          "subStatus": "example"
        },
        "id": "xfr_example",
        "organizationId": "org_example",
        "custodyWalletId": "cwlt_example",
        "providerWalletId": "privy_wallet_123",
        "projectId": "prj_example",
        "type": "transfer",
        "kind": "example",
        "direction": "outbound",
        "status": "confirmed",
        "signature": "sig_example",
        "serializedTx": "base64_tx_example",
        "slot": 123456,
        "blockTime": "2025-01-01T00:00:00.000Z",
        "confirmedAt": "2025-01-01T00:00:00.000Z",
        "fee": 0,
        "error": "Signature failed",
        "initiatedBy": {
          "type": "api_key"
        },
        "source": "So11111111111111111111111111111111111111112",
        "destination": "So11111111111111111111111111111111111111112",
        "amount": "100.00",
        "counterpartyId": "cpty_example",
        "counterpartyDisplayName": "Acme Studio",
        "risk": {
          "provider": "trm",
          "score": "0.12",
          "level": "low",
          "evaluatedAt": "2025-01-01T00:00:00.000Z"
        },
        "createdAt": "2025-01-01T00:00:00.000Z",
        "updatedAt": "2025-01-02T00:00:00.000Z"
      }
    ]
  },
  "meta": {
    "requestId": "req_example",
    "timestamp": "2025-01-01T00:00:00.000Z"
  }
}
JSON
{
  "error": {
    "code": "INSUFFICIENT_PERMISSIONS",
    "message": "Missing action: transfer_batches.execute",
    "details": {
      "action": "transfer_batches.execute"
    }
  },
  "meta": {
    "requestId": "req_example"
  }
}

Error responses use the standard error shape.