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.
Search across all documentation pages
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.
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.
@solana/pay encodeURL or hand-built fields per the Pay spec).Use transfer requests when the action is "send N of asset X to recipient Y" without multi-instruction composition on the server.
https://merchant.example/pay?... (or the transaction-request shape your wallet supports).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.
| 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.
A Blink client takes an Action URL (often via a provider query such as ?action=https://...) and:
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.
Production Actions usually live as route handlers (for example Next.js App Router under app/api/actions/...):
account, builds instructions (Kit builders or Codama/IDL helpers for Anchor programs), sets fee payer and blockhash, serializes base64.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.
SetAuthority, unlimited approvals, or unrelated transfers.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.
| 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.
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.
/vote, /mint, /pay) over open-ended builders.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 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.
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.
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.
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.
Usually no. The Action is the API. A Blink is how that Action is linked, unfurled, and presented inside Blink-aware apps and providers.
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.
Yes. Kit is the TypeScript stack this site pins for RPC, addresses, and transaction message construction in POST handlers.
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.
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.
Over-privileged transactions, skipping simulation, uncapped fee sponsorship, missing rate limits, and wrong-cluster program IDs in production.
Clients may warn, allowlist, or show verification badges. Assume users can ignore warnings; keep transactions minimal and domains consistent with your brand.
Yes for stable branding, with short TTLs if titles change often. Never cache POST transaction responses across users or time.
Start with Solana Pay Basics and Transaction Requests, then Actions (the spec) and Blinks. Implement with Building an Action and harden with Security & Verification.
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.
Reviewed by Chris St. John·Last updated Jul 15, 2026