Skip to main content
Generate a signed-ready Solana transaction for a supporter to sign and submit to the network. The endpoint resolves the creator by any supported identifier, selects the optimal execution route — direct transfer or Jupiter swap — and returns a Base64-serialized versioned transaction alongside quote metadata. After the supporter signs and submits the transaction, call POST /solana/tips/create to record the tip on Tip Stack.

Request

POST https://tipstack.fun/api/payments/intent
creatorId
string
required
The creator to tip. Accepts a Tip Stack user ID, Solana wallet address, Twitter handle (with or without @), Discord handle, or .sol domain.
amount
number
required
The token amount to send, expressed in human-readable units (e.g. 1.5 for 1.5 SOL or 1.5 USDC). When amountUsd is also provided, amount is ignored.
amountUsd
number
USD amount to send. When provided, overrides amount and is automatically converted to token units using the live Jupiter price feed. Use this for consistent USD-denominated tips regardless of the token the supporter holds.
inputTokenMint
string
required
The Solana mint address of the token the supporter is sending (e.g. So11111111111111111111111111111111111111112 for native SOL or EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v for USDC).
sourceWalletAddress
string
required
The supporter’s wallet public key. This is set as the transaction fee payer and the token source.
tokenSymbol
string
Human-readable symbol for the input token (e.g. SOL, USDC, BONK). Used for display purposes in the response quote and tip record. Does not affect routing.

Response

success
boolean
true when a transaction was successfully generated.
intentId
string
Unique intent identifier prefixed with pi_. Pass this to downstream systems for tracking.
status
string
Always requires_action — the transaction is ready for the supporter to sign but has not been submitted yet.
transaction
string
Base64-encoded, serialized Solana VersionedTransaction. Deserialize this client-side, sign it with the supporter’s wallet, and submit it to the Solana network. See the usage note below.
quote
object
executionMode
string
sync for standard on-chain submission; async when the transaction uses gasless landing (Jito bundles). For async transactions, submit via a Jito-compatible RPC endpoint.
provider
string
The routing engine selected by Tip Stack. One of direct-transfer (no swap needed), jupiter-ultra, or jupiter-v6. The engine is chosen automatically based on the token pair and creator settings.
lastValidBlockHeight
number
The last Solana block height at which this transaction remains valid. If the transaction is not submitted before this block, it will be rejected. Fetch a fresh intent if expiry is reached.
settings
object

Using the transaction

After receiving the response, deserialize the Base64 transaction, request the supporter’s signature, and submit it to Solana. Once you have a confirmed txSignature, call POST /solana/tips/create to record the tip.
TypeScript
import { Transaction, VersionedTransaction, Connection } from '@solana/web3.js';

// 1. Create the intent
const { transaction: txBase64, lastValidBlockHeight } = await fetch(
  'https://tipstack.fun/api/payments/intent',
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      creatorId: 'monalisa.sol',
      amount: 0.1,
      inputTokenMint: 'So11111111111111111111111111111111111111112',
      sourceWalletAddress: supporterWallet.publicKey.toBase58(),
      tokenSymbol: 'SOL',
    }),
  }
).then((r) => r.json());

// 2. Deserialize, sign, and submit
const txBytes = Buffer.from(txBase64, 'base64');
const tx = VersionedTransaction.deserialize(txBytes);
const signedTx = await supporterWallet.signTransaction(tx);

const connection = new Connection('https://api.mainnet-beta.solana.com');
const txSignature = await connection.sendRawTransaction(signedTx.serialize());

// 3. Record the tip
await fetch('https://tipstack.fun/api/solana/tips/create', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    creatorWallet: 'CREATOR_WALLET_ADDRESS',
    tipAmount: 100000000, // 0.1 SOL in lamports
    senderWallet: supporterWallet.publicKey.toBase58(),
    txSignature,
    tokenSymbol: 'SOL',
  }),
});

Example request

JSON
{
  "creatorId": "monalisa.sol",
  "amountUsd": 5,
  "inputTokenMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
  "sourceWalletAddress": "8xRT3m1KZJPHQQaFGpvDJckJcNhHMbDdBfHHVdFGQS7a",
  "tokenSymbol": "USDC"
}

Example response

JSON
{
  "success": true,
  "intentId": "pi_4a1b2c3d4e5f6a7b8c9d0e1f",
  "status": "requires_action",
  "transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAHCx...",
  "quote": {
    "outAmount": "4900000",
    "priceImpactPct": 0.002,
    "amountUsd": 5,
    "tokenSymbol": "USDC"
  },
  "executionMode": "sync",
  "provider": "direct-transfer",
  "lastValidBlockHeight": 289471023,
  "settings": {
    "yieldEnabled": false,
    "gaslessEnabled": false,
    "autoConvertUsdc": true
  }
}
The transaction field is a Base64-encoded, unsigned Solana versioned transaction. You must deserialize it with VersionedTransaction.deserialize(), have the supporter sign it, and submit it yourself. Tip Stack does not submit transactions on your behalf.
Transactions expire at lastValidBlockHeight. If the supporter takes too long to sign, create a fresh intent rather than retrying the expired transaction.