Prepare vs Execute

Understand SDP's two signing modes for onchain transactions.

Every SDP mutation endpoint that produces a Solana transaction supports two signing modes. The mode you choose determines who signs and submits the transaction.

Execute mode (default)

When you call a mutation endpoint without the /prepare suffix, SDP handles everything:

  1. Builds the transaction
  2. Signs it using your configured custody provider
  3. Submits it to Solana
  4. Returns the confirmed result with a transaction signature
curl -X POST https://api.solana.com/v1/issuance/tokens/tok_abc123/mint \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: mint-001" \
  -d '{
    "mint": {
      "destination": "7xKXz...9fGh",
      "amount": "1000000"
    }
  }'
const response = await fetch(
  "https://api.solana.com/v1/issuance/tokens/tok_abc123/mint",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer sk_test_...",
      "Content-Type": "application/json",
      "Idempotency-Key": "mint-001",
    },
    body: JSON.stringify({
      mint: { destination: "7xKXz...9fGh", amount: "1000000" },
    }),
  }
);
const { data } = await response.json();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.solana.com/v1/issuance/tokens/tok_abc123/mint"))
    .header("Authorization", "Bearer sk_test_...")
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", "mint-001")
    .POST(HttpRequest.BodyPublishers.ofString("""
        {
          "mint": {
            "destination": "7xKXz...9fGh",
            "amount": "1000000"
          }
        }"""))
    .build();

When to use execute mode:

  • You trust SDP's custody provider with signing
  • You want the simplest integration (one API call)
  • Backend-to-backend workflows where you don't need user signatures

Prepare mode

When you add /prepare to a mutation endpoint, SDP builds the transaction but returns it unsigned:

curl -X POST https://api.solana.com/v1/issuance/tokens/tok_abc123/mint/prepare \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "mint": {
      "destination": "7xKXz...9fGh",
      "amount": "1000000"
    },
    "options": { "simulate": true }
  }'
const response = await fetch(
  "https://api.solana.com/v1/issuance/tokens/tok_abc123/mint/prepare",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer sk_test_...",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      mint: { destination: "7xKXz...9fGh", amount: "1000000" },
      options: { simulate: true },
    }),
  }
);
const { data } = await response.json();
// data.preparedTransaction.serialized — base64 transaction to sign
// data.simulation — { success, unitsConsumed, logs }
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.solana.com/v1/issuance/tokens/tok_abc123/mint/prepare"))
    .header("Authorization", "Bearer sk_test_...")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("""
        {
          "mint": {
            "destination": "7xKXz...9fGh",
            "amount": "1000000"
          },
          "options": { "simulate": true }
        }"""))
    .build();

When to use prepare mode:

  • You manage your own keys (hardware wallet, multisig, etc.)
  • You need user approval before signing (wallet pop-up flow)
  • You want to simulate the transaction before committing
  • Regulatory requirements mandate specific signing infrastructure

Signing a prepared transaction

After receiving the serialized transaction:

  1. Decode the base64 string into a transaction object
  2. Sign with the required private key(s)
  3. Submit to Solana via sendRawTransaction
  4. Confirm the transaction using confirmTransaction

Submit before lastValidBlockHeight expires. If the blockhash expires, call /prepare again for a fresh transaction.

Simulation

Prepare endpoints accept options.simulate: true to dry-run the transaction before you sign. The simulation returns:

  • success — whether the transaction would succeed
  • unitsConsumed — compute units used
  • logs — program execution logs
  • error — error details if simulation fails

Endpoints that support both modes

ResourceExecutePrepare
Deploy tokenPOST .../deployPOST .../deploy/prepare
MintPOST .../mintPOST .../mint/prepare
BurnPOST .../burnPOST .../burn/prepare
Force-burnPOST .../force-burnPOST .../force-burn/prepare
SeizePOST .../seizePOST .../seize/prepare
Update authorityPOST .../authorityPOST .../authority/prepare
TransferPOST https://api.solana.com/v1/payments/transfersPOST https://api.solana.com/v1/payments/transfers/prepare

Issuance paths are prefixed with https://api.solana.com/v1/issuance/tokens/{tokenId}. Transfer flows use the concrete payments mutation paths POST https://api.solana.com/v1/payments/transfers and POST https://api.solana.com/v1/payments/transfers/prepare.

Idempotency

Both modes support the Idempotency-Key header. For execute mode, the key prevents duplicate submissions. For prepare mode, the key ensures you get the same prepared transaction if you retry the request.

Is this page helpful?