Solana Pay, Actions & Blinks
Solana Pay, Actions, and Blinks are the embeddable interaction stack for Solana: ways to request value or signatures outside a full custom dApp shell.
They share one idea. A client (wallet, Blink provider, or QR scanner) discovers an intent, optionally fetches a server-built transaction, and asks the user to sign. You own the HTTPS endpoint and instructions; the wallet owns keys and the approve screen.
This page is the section umbrella. Sibling pages cover payment URLs, transaction requests, the Actions HTTP contract, Blinks, implementation, and verification.
Summary
- Solana Pay starts as payment-oriented URLs and QR flows; transaction requests extend that to server-built transactions; Actions generalize the pattern into a standard metadata + transaction API; Blinks package Actions as shareable, embeddable links.
- Insight: Most product growth is not "open our SPA and connect." POS, invoices, social CTAs, governance votes, and one-tap mints need portable intents any compatible wallet can complete without a new deep-link scheme per client.
- Key Concepts: transfer request, transaction request, reference account, Action GET/POST, Action metadata, Blink, unfurl, CORS, base64 wire transaction, simulation, settlement verification.
- When to Use: Checkout and donations, in-person QR, social or campaign CTAs, lightweight on-chain buttons (vote, mint, swap), and any flow where the merchant or protocol should build the transaction the user signs.
- Limitations/Trade-offs: You trade full in-app UX for reach. Hosting, TLS, CORS, rate limits, and phishing resistance become product requirements. Users still must understand what they sign; wallets and Blink clients cannot invent trust for a malicious domain.
- Related Topics: Solana Pay Basics, Transaction Requests, Actions (the spec), Blinks, Building an Action, Security & Verification.
Foundations
Start with Solana Pay as the payment layer.
A transfer request encodes recipient, amount (and optional SPL mint), label, message, and optional reference public keys into a URL wallets understand. Merchants render it as a QR for point of sale or share it for remote checkout. The wallet prefills a transfer; the user signs; the chain settles.
References drive bookkeeping. A unique reference pubkey per order lets your server watch RPC or websockets for a matching transaction and mark the invoice paid without trusting a browser callback alone. Amount and mint still need server-side checks; a matching reference is correlation, not full proof by itself.
Transaction requests lift the same "wallet fetches intent from HTTPS" pattern beyond plain transfers. The merchant endpoint receives the customer's account, builds a versioned transaction with that account as fee payer or required signer, and returns a serialized transaction the wallet can preview and sign. Checkout can swap, mint, or call a custom program in one approval.
Solana Actions generalize transaction-producing endpoints beyond classic merchant pay. The Actions specification defines how clients discover human-readable metadata (title, icon, description, label, and related fields) and how they obtain a base64-encoded transaction for a connected account. Wallets, Blink portals, and social unfurlers speak the same contract.
Blinks (blockchain links) are the distribution layer. A Blink is an Action URL presented through a Blink-aware client or proxy so it unfurls into a rich card: icon, copy, and a button that runs the Action POST flow. The Action remains your HTTPS API; the Blink is how users find and share it on X, Discord, partner sites, and Blink surfaces.
This site builds client and server code with @solana/kit 7.0.0, deploys programs under Agave 4.1.1 / Solana CLI 3.0.10, and often composes instructions from Anchor 0.32.1 programs in Rust 1.91.1. Pay and Actions are mainly TypeScript and HTTP; the programs you invoke still obey Sealevel account and CU rules.
Mechanics & Interactions
Solana Pay transfer path
- Merchant creates a transfer URL (
@solana/payencodeURLor hand-built fields per the Pay spec). - Customer scans a QR or opens the link in a wallet.
- Wallet shows amount, label, and recipient; user signs a transfer (SOL or SPL).
- Merchant monitors the reference (and amount) via RPC until confirmed, then fulfills the order.
Use transfer requests when the action is "send N of asset X to recipient Y" without multi-instruction composition on the server.
Transaction request path
- Wallet opens
https://merchant.example/pay?...(or the transaction-request shape your wallet supports). - Endpoint validates params, loads a blockhash, builds instructions for the connected account, serializes a wire transaction (unsigned, or partially signed only when you intentionally co-sign).
- Wallet simulates and shows the preview; user signs; network executes.
- Merchant verifies settlement via references, balances, program events, or instruction fingerprints.
Transaction requests and Actions overlap heavily. Many products implement Actions (or Action-compatible handlers) and treat Solana Pay transaction requests as the payment-flavored ancestor of the same pattern.
Actions: GET metadata, POST transaction
| Method | Role |
|---|---|
OPTIONS | CORS preflight for browser and extension clients |
GET | Read-only metadata for cards and unfurlers |
POST | Accept { account } (and optional body fields), return { transaction } base64 |
GET must not mutate state. It is cacheable presentation: HTTPS icon, title, description, button label, optional inputs. POST is dynamic per user: insert their pubkey as signer/fee payer, set a fresh blockhash, attach only accounts and instructions required for that CTA.
Clients show your metadata, then POST the connected wallet address. Your server returns a transaction the wallet signs. Optional callbacks report completion; never treat them as sole proof without RPC confirmation.
Blinks: shareable Actions
A Blink client takes an Action URL (often via a provider query such as ?action=https://...) and:
- Fetches Action GET metadata for the unfurl card.
- Renders icon, title, and CTA in the host surface.
- Runs the same POST → sign → submit path as a native Actions client.
Your job remains the Action endpoint: CORS, TLS, accurate metadata, and least-privilege transactions. Blink providers and wallets add allowlists, warnings, and badges; those complement safe construction, they do not replace it.
Building an Action (implementation loop)
Production Actions usually live as route handlers (for example Next.js App Router under app/api/actions/...):
- Scaffold GET, POST, and OPTIONS with Actions CORS headers.
- GET returns stable branding assets on your domain.
- POST parses
account, builds instructions (Kit builders or Codama/IDL helpers for Anchor programs), sets fee payer and blockhash, serializes base64. - Simulate before return when failure would waste attention or hide broken config.
- Observe RPC cost, errors, and signatures server-side with rate limits.
Separate program IDs and RPC URLs for devnet and mainnet-beta. A mainnet Action pointing at a devnet program ID is a common launch bug.
Security and verification as first-class mechanics
- Transport: HTTPS only for Action URLs, icons, and Pay endpoints.
- Origin: users should see the real domain; clone sites steal icons and labels.
- Transaction content: least privilege; no unexpected
SetAuthority, unlimited approvals, or unrelated transfers. - Simulation: wallets simulate; your POST handler should too for known-good paths.
- Settlement: for commerce, confirm on-chain with reference + amount (and mint) before fulfillment.
- Abuse: rate-limit POST, cap fee sponsorship, and avoid open endpoints that build attacker-chosen drains under your brand.
Blink-side verification also covers client registries, domain checks, and unfurl integrity (icon still on your host). Treat unfurl caches as stale-prone; version static asset URLs when branding changes.
Advanced Considerations & Applications
Choosing the right layer
| Need | Prefer | Avoid when |
|---|---|---|
| In-person SOL/SPL payment | Solana Pay transfer + QR | You need multi-ix composition |
| Checkout with swap/mint/custom ix | Transaction request or Action | Plain transfer URL is enough |
| Shareable social CTA | Action + Blink | Offline POS only |
| Full multi-screen product UX | Wallet-adapter dApp | You only need a one-tap CTA |
| High-risk money movement | Escrow program + verified settlement | Trusting client "paid" events alone |
Many teams run both: Solana Pay or Actions for acquisition and POS, and a full dApp for power users. The shared skill is building safe transactions for a customer pubkey.
Product patterns
- Invoices and donations: transfer requests with unique references and short labels.
- Commerce with inventory: transaction request or Action that mints a receipt, burns a coupon PDA, or moves vault funds under program rules.
- Governance and community: vote, claim, or stake CTAs as Blinks.
- DeFi entry points: one swap or deposit ix set with explicit slippage; never hide unlimited approvals behind a "Claim" label.
- Fee sponsorship: optional partial-sign for gasless UX, with hard caps, auth, and monitoring so sponsorship cannot be drained.
Client, stack, and ops
Use @solana/kit 7.0.0 for RPC, addresses, message construction, and wire encoding. Prefer versioned transactions and simulation. For Anchor 0.32.1 programs, generate typed builders (Codama/IDL) so account metas stay correct as programs evolve.
An Action only delivers a transaction the user signs; it does not relax Sealevel checks, PDAs, token rules, or CU limits on the programs you call.
Operationally: CDN-cache stable GET metadata, never cache POST txs across users; rotate blockhashes every POST; log latency and failures without secrets in query strings; if a bad Action ships, take the route offline and rotate assets when phishing clones appear.
Common Misconceptions
- "Solana Pay is only QR codes for SOL." Pay covers transfer and transaction-request flows, including SPL amounts and richer merchant APIs.
- "Actions replace wallets." Actions feed wallets and Blink clients; the user still signs in a wallet context.
- "A Blink is a different on-chain program." A Blink is distribution and unfurl UX around an Action URL; chain state changes only when the signed transaction lands.
- "Green simulation means the merchant can mark paid." Simulation is not settlement. Confirm signatures and balances at your required commitment.
- "GET can create the invoice side effects." GET is for metadata. Creating orders or burning nonces on GET invites caches and crawlers to corrupt state.
- "Wildcard CORS is always fine." Spec clients need CORS, but sensitive or sponsored endpoints still need rate limits, auth, and abuse monitoring.
- "Icon and title prove legitimacy." Phishing clones copy both. Domain inspection and client verification matter more than branding alone.
- "One Action URL can safely mean anything the body asks for." Prefer fixed, audited templates per route (
/vote,/mint,/pay) over open-ended builders. - "Transaction requests and Actions are unrelated." They share server-built transactions; Actions are the broader, social-ready standard.
- "Fee sponsorship is free growth." Uncapped sponsorship is a drain vector. Budget, authenticate, and meter it.
FAQs
What problem do Solana Pay, Actions, and Blinks solve together?
They let users complete on-chain intents (pay, vote, mint, swap) from links, QR codes, and social surfaces without forcing every interaction through a custom multi-page dApp.
When should I use a simple transfer request instead of an Action?
When the intent is a plain SOL or SPL payment to a known recipient and amount, and you do not need multi-instruction logic or social unfurl CTAs. Transfer URLs are the smallest surface area.
What is a reference account in Solana Pay?
A public key included in the payment so your backend can find the matching on-chain transaction and bind it to an order id. Generate a unique reference per checkout session and verify amount server-side.
How do transaction requests differ from transfer requests?
Transfer requests describe a payment the wallet can construct locally. Transaction requests hit your HTTPS API so the server returns a full transaction (swap, mint, custom program, etc.) for the customer to sign.
What must an Actions endpoint implement?
At minimum: CORS/OPTIONS as required by clients, GET metadata for human display, and POST that accepts the user account and returns a base64 transaction. Follow the current Actions specification fields your target wallets support.
Is a Blink a separate API from an Action?
Usually no. The Action is the API. A Blink is how that Action is linked, unfurled, and presented inside Blink-aware apps and providers.
Why do Action icons need HTTPS on my domain?
Clients load icons for cards and unfurls. Hotlinking or HTTP assets break rendering, weaken trust signals, and create supply-chain risk if a third party swaps the image.
Can I build Actions with @solana/kit 7.0.0?
Yes. Kit is the TypeScript stack this site pins for RPC, addresses, and transaction message construction in POST handlers.
Do I need Anchor to ship an Action?
No. Actions are HTTP plus any valid Solana transaction. Anchor 0.32.1 helps when your CTA calls an Anchor program and you want IDL-driven builders; native programs work the same at the wire level.
How should merchants verify that a payment succeeded?
Confirm via RPC (and preferably websockets or an indexer) a transaction that matches reference, amount, mint, and recipient rules at your commitment level. Do not trust client-only callbacks.
What are the highest-risk mistakes in Action POST handlers?
Over-privileged transactions, skipping simulation, uncapped fee sponsorship, missing rate limits, and wrong-cluster program IDs in production.
How do Blinks handle trust for unknown domains?
Clients may warn, allowlist, or show verification badges. Assume users can ignore warnings; keep transactions minimal and domains consistent with your brand.
Should GET metadata be cached at the CDN?
Yes for stable branding, with short TTLs if titles change often. Never cache POST transaction responses across users or time.
What should I read next in this section?
Start with Solana Pay Basics and Transaction Requests, then Actions (the spec) and Blinks. Implement with Building an Action and harden with Security & Verification.
Related
- Solana Pay Basics - transfer URLs, QR flows, references, and payment metadata
- Transaction Requests - server-built transactions for checkout beyond plain transfers
- Actions (the spec) - GET metadata and POST transaction contract
- Blinks - shareable, embeddable Action links and unfurl UX
- Building an Action - endpoints, CORS, metadata, and signing flow end-to-end
- Security & Verification - trust, phishing, simulation, and settlement checks
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, and @solana/kit 7.0.0.