<!--
Sitemap:
- [Tempo](/index): Explore Tempo's blockchain documentation, integration guides, and protocol specs. Build low-cost, high-throughput payment applications.
- [Accounts SDK – Getting Started](/accounts/): Set up the Tempo Accounts SDK to create, manage, and interact with accounts on Tempo.
- [Changelog](/changelog)
- [Tempo CLI](/cli/): A single binary for using Tempo Wallet from the terminal, making paid HTTP requests, and running a Tempo node.
- [Tempo Ecosystem Infrastructure](/ecosystem/): Explore Tempo's ecosystem partners providing bridges, wallets, node infrastructure, data analytics, security, and more for building on Tempo.
- [Learn](/learn/): Explore stablecoin use cases and Tempo's payments-optimized blockchain architecture for remittances, payouts, and embedded finance.
- [Tempo Protocol](/protocol/): Technical specifications and reference documentation for the Tempo blockchain protocol, purpose-built for global payments at scale.
- [SDKs](/sdk/): Integrate Tempo into your applications with SDKs for TypeScript, Go, Rust, and Foundry. Build blockchain apps in your preferred language.
- [Tempo CLI](/wallet/): A terminal client for Tempo wallet management, service discovery, and paid HTTP requests via the Machine Payments Protocol.
- [FAQ](/accounts/faq): Frequently asked questions about the Tempo Accounts SDK.
- [Deploying to Production](/accounts/production): Things to consider before deploying your application with the Tempo Accounts SDK to production.
- [Tempo Accounts Server Handlers](/accounts/server/): Configure server-side Tempo Accounts SDK handlers for relaying wallet RPC requests, composing backends, and managing WebAuthn ceremonies.
- [tempo download](/cli/download): Download chain snapshots for faster initial sync of a Tempo node.
- [tempo node](/cli/node): Command reference for running a Tempo node.
- [tempo request](/cli/request): A curl-like HTTP client that handles MPP payment negotiation automatically.
- [tempo wallet](/cli/wallet): Use Tempo Wallet from the terminal — authenticate, check balances, manage access keys, and discover services.
- [Block Explorers](/ecosystem/block-explorers): View transactions, blocks, accounts, and token activity on the Tempo network with block explorers.
- [Bridges & Exchanges](/ecosystem/bridges): Move assets to and from Tempo with cross-chain bridges and access deep DEX liquidity with exchange infrastructure.
- [Data & Analytics](/ecosystem/data-analytics): Query blockchain data on Tempo with indexers, analytics platforms, oracles, and monitoring tools.
- [Node Infrastructure](/ecosystem/node-infrastructure): Connect to Tempo with reliable RPC endpoints and managed node services from infrastructure partners.
- [Issuance & Orchestration](/ecosystem/orchestration): Move money globally between local currencies and stablecoins. Issue, transfer, and manage stablecoins on Tempo.
- [Security & Compliance](/ecosystem/security-compliance): Transaction scanning, threat detection, and compliance infrastructure for Tempo applications.
- [Smart Contract Libraries](/ecosystem/smart-contract-libraries): Build with account abstraction and programmable smart contract wallets on Tempo.
- [Wallets](/ecosystem/wallets): Integrate embedded, custodial, and institutional wallet infrastructure into your Tempo application.
- [!Replace Me!](/guide/_template)
- [Bridge via LayerZero](/guide/bridge-layerzero): Bridge tokens to and from Tempo using LayerZero. Covers Stargate pools and standard OFT adapters with cast commands and TypeScript examples.
- [Bridge via Relay](/guide/bridge-relay): Bridge tokens to and from Tempo using Relay. Includes supported token discovery, curl commands, TypeScript examples with viem, and status tracking.
- [Getting Funds on Tempo](/guide/getting-funds): Bridge assets to Tempo, add funds in Tempo Wallet, or use the faucet on testnet.
- [Stablecoin Issuance](/guide/issuance/): Create and manage your own stablecoin on Tempo. Issue tokens, manage supply, and integrate with Tempo's payment infrastructure.
- [Agentic Payments](/guide/machine-payments/): Make agentic payments using the Machine Payments Protocol (MPP) on Tempo — charge for APIs, MCP tools, and digital content with TIP-20 stablecoins.
- [Tempo Node](/guide/node/): Run your own Tempo node for direct network access. Set up RPC nodes for API access or validator nodes to participate in consensus.
- [Stablecoin Payments](/guide/payments/): Send and receive stablecoin payments on Tempo. Integrate payments with flexible fee options, sponsorship capabilities, and parallel transactions.
- [Connect to Tempo Zones](/guide/private-zones/): Learn how Tempo Zones work alongside the public chain and follow guides for depositing, sending within a zone, routing pathUSD across zones, swapping into betaUSD, and withdrawing.
- [Exchange Stablecoins](/guide/stablecoin-dex/): Trade between stablecoins on Tempo's enshrined DEX. Execute swaps, provide liquidity, and query the onchain orderbook for optimal pricing.
- [Use Tempo Transactions](/guide/tempo-transaction/): Learn how to use Tempo Transactions for configurable fee tokens, fee sponsorship, batch calls, access keys, and concurrent execution.
- [Create & Use Accounts](/guide/use-accounts/): Create and integrate Tempo accounts with the universal Tempo Wallet or domain-bound passkeys.
- [Using Tempo with AI](/guide/using-tempo-with-ai): Give your AI coding agent Tempo documentation context and a wallet for autonomous transactions.
- [Partners](/learn/partners): Discover Tempo's ecosystem of stablecoin issuers, wallets, custody providers, compliance tools, and ramps.
- [What are stablecoins?](/learn/stablecoins): Learn what stablecoins are, how they maintain value through reserves, and the payment use cases they enable for businesses globally.
- [Tempo](/learn/tempo/): Discover Tempo, the payments-first blockchain with instant settlement, predictably low fees, and native stablecoin support.
- [Exchanging Stablecoins](/protocol/exchange/): Tempo's enshrined decentralized exchange for trading between stablecoins with optimal pricing, limit orders, and flip orders for liquidity provision.
- [Transaction Fees](/protocol/fees/): Pay transaction fees in any USD stablecoin on Tempo. No native token required—fees are paid directly in TIP-20 stablecoins with automatic conversion.
- [Tempo RPC Reference](/protocol/rpc/): Reference for Tempo-specific JSON-RPC methods in the tempo, consensus, and admin namespaces, plus modified eth_ behavior.
- [Tempo Improvement Proposals](/protocol/tips/): Browse Tempo Improvement Proposals covering protocol changes, network upgrades, precompiles, transaction formats, and stablecoin standards.
- [Tempo Transactions](/protocol/transactions/): Learn about Tempo Transactions, a new EIP-2718 transaction type with passkey support, fee sponsorship, batching, and concurrent execution.
- [Tempo Zones](/protocol/zones/): Tempo Zones are private execution environments on Tempo Mainnet where balances, transfers, and transaction history are invisible to the public chain.
- [Connect to the Network](/quickstart/connection-details): Connect to Tempo using browser wallets, CLI tools, or direct RPC endpoints. Get chain ID, URLs, and configuration details.
- [Developer Tools](/quickstart/developer-tools): Explore Tempo's developer ecosystem with indexers, embedded wallets, node infrastructure, and analytics partners for building payment apps.
- [EVM Differences](/quickstart/evm-compatibility): Learn how Tempo differs from Ethereum. Understand wallet behavior, fee token selection, VM layer changes, and fast finality consensus.
- [Faucet](/quickstart/faucet): Get free test stablecoins on Tempo Testnet. Connect your wallet or enter any address to receive pathUSD, AlphaUSD, BetaUSD, and ThetaUSD.
- [Integrate Tempo](/quickstart/integrate-tempo): Build on Tempo Testnet. Connect to the network, explore SDKs, and follow guides for accounts, payments, and stablecoin issuance.
- [Predeployed Contracts](/quickstart/predeployed-contracts): Discover Tempo's predeployed system contracts including TIP-20 Factory, Fee Manager, Stablecoin DEX, and standard utilities like Multicall3.
- [Tempo Token List Registry](/quickstart/tokenlist): Query token metadata, icons, and prices on Tempo using the Uniswap Token Lists-compatible API, and submit new tokens via PR to the registry.
- [Contract Verification](/quickstart/verify-contracts): Verify your smart contracts on Tempo using contracts.tempo.xyz. Sourcify-compatible verification with Foundry integration.
- [Wallet Developer Guide](/quickstart/wallet-developers): Integrate Tempo into your wallet. Use Tempo Transactions for fee token selection, fee sponsorship, batching, and concurrent execution.
- [Foundry for Tempo](/sdk/foundry/): Build, test, and deploy smart contracts on Tempo using Foundry. Access Tempo protocol features with forge, cast, anvil, and chisel.
- [Go](/sdk/go/): Build blockchain apps with the Tempo Go SDK. Send transactions, batch calls, and handle fee sponsorship with idiomatic Go code.
- [Python](/sdk/python/): Build blockchain apps with the Tempo Python SDK. Send transactions, batch calls, and handle fee sponsorship using web3.py.
- [Rust](/sdk/rust/): Build blockchain apps with the Tempo Rust SDK using Alloy. Query chains, send transactions, and manage tokens with type-safe Rust code.
- [TypeScript SDKs](/sdk/typescript/): Build blockchain apps with Tempo using Viem and Wagmi. Send transactions, manage tokens, and integrate AMM pools with TypeScript.
- [Tempo Wallet CLI Recipes](/wallet/recipes): Use practical Tempo Wallet CLI recipes for service discovery, paid requests, session management, and funding or transfers.
- [Tempo CLI Reference](/wallet/reference): Complete command and flag reference for tempo wallet and tempo request.
- [Use Tempo Wallet CLI with Agents](/wallet/use-with-agents): Connect Tempo Wallet CLI to your agent and understand the built-in features that make agent-driven paid requests reliable and safe.
- [Adapters](/accounts/api/adapters): Pluggable adapters for the Tempo Accounts SDK Provider.
- [dialog](/accounts/api/dialog): Adapter for the Tempo Wallet dialog, an embedded iframe or popup for account management.
- [Dialog.iframe](/accounts/api/dialog.iframe): Embed the Tempo Wallet auth UI in an iframe dialog element.
- [Dialog.popup](/accounts/api/dialog.popup): Open the Tempo Wallet auth UI in a popup window.
- [Dialog](/accounts/api/dialogs): Dialog modes for embedding the Tempo Wallet.
- [Expiry](/accounts/api/expiry): Utility functions for computing access key expiry timestamps.
- [local](/accounts/api/local): Key-agnostic adapter for defining arbitrary account types and signing mechanisms.
- [Provider](/accounts/api/provider): Create an EIP-1193 provider for managing accounts on Tempo.
- [webAuthn](/accounts/api/webAuthn): Adapter for passkey-based accounts using WebAuthn registration and authentication.
- [WebAuthnCeremony](/accounts/api/webauthnceremony): Pluggable strategy for WebAuthn registration and authentication ceremonies.
- [WebAuthnCeremony.from](/accounts/api/webauthnceremony.from): Create a WebAuthnCeremony from a custom implementation.
- [WebAuthnCeremony.server](/accounts/api/webauthnceremony.server): Server-backed WebAuthn ceremony that delegates to a remote handler.
- [Create & Use Accounts](/accounts/guides/create-and-use-accounts): Choose between universal wallet experiences or domain-bound passkey accounts for your app.
- [eth_fillTransaction](/accounts/rpc/eth_fillTransaction): Fills missing transaction fields and returns wallet-aware metadata.
- [eth_sendTransaction](/accounts/rpc/eth_sendTransaction): Send a transaction from the connected account.
- [eth_sendTransactionSync](/accounts/rpc/eth_sendTransactionSync): Send a transaction and wait for the receipt.
- [personal_sign](/accounts/rpc/personal_sign): Sign a message with the connected account.
- [wallet_authorizeAccessKey](/accounts/rpc/wallet_authorizeAccessKey): Authorize an access key for delegated transaction signing.
- [wallet_connect](/accounts/rpc/wallet_connect): Connect account(s) with optional capabilities like access key authorization.
- [wallet_disconnect](/accounts/rpc/wallet_disconnect): Disconnect the connected account(s).
- [wallet_getBalances](/accounts/rpc/wallet_getBalances): Get token balances for an account.
- [wallet_getCallsStatus](/accounts/rpc/wallet_getCallsStatus): Get the status of a batch of calls sent via wallet_sendCalls.
- [wallet_getCapabilities](/accounts/rpc/wallet_getCapabilities): Get account capabilities for specified chains.
- [wallet_revokeAccessKey](/accounts/rpc/wallet_revokeAccessKey): Revoke a previously authorized access key.
- [wallet_sendCalls](/accounts/rpc/wallet_sendCalls): Send a batch of calls from the connected account.
- [Handler.compose](/accounts/server/handler.compose): Compose multiple server handlers into a single handler.
- [Handler.feePayer (Deprecated)](/accounts/server/handler.feePayer): Deprecated — use Handler.relay with feePayer option instead.
- [Handler.relay](/accounts/server/handler.relay): Server handler that proxies certain RPC requests with wallet-aware enrichment.
- [Handler.webAuthn](/accounts/server/handler.webAuthn): Server-side WebAuthn ceremony handler for registration and authentication.
- [Kv](/accounts/server/kv): Key-value store adapters for server-side persistence.
- [tempoWallet](/accounts/wagmi/tempoWallet): Wagmi connector for the Tempo Wallet dialog.
- [webAuthn](/accounts/wagmi/webAuthn): Wagmi connector for passkey-based WebAuthn accounts.
- [Create a Stablecoin](/guide/issuance/create-a-stablecoin): Create your own stablecoin on Tempo using the TIP-20 token standard. Deploy tokens with built-in compliance features and role-based permissions.
- [Distribute Rewards](/guide/issuance/distribute-rewards): Distribute rewards to token holders using TIP-20's built-in reward mechanism. Allocate tokens proportionally based on holder balances.
- [Manage Your Stablecoin](/guide/issuance/manage-stablecoin): Configure stablecoin permissions, supply limits, and compliance policies. Grant roles, set transfer policies, and control pause/unpause functionality.
- [Mint Stablecoins](/guide/issuance/mint-stablecoins): Mint new tokens to increase your stablecoin's total supply. Grant the issuer role and create tokens with optional memos for tracking.
- [Use Your Stablecoin for Fees](/guide/issuance/use-for-fees): Enable users to pay transaction fees using your stablecoin. Add fee pool liquidity and integrate with Tempo's flexible fee payment system.
- [Agent Quickstart](/guide/machine-payments/agent): Use the tempo CLI to discover services, preview costs, and make paid requests from a terminal or AI agent — no SDK required.
- [Client Quickstart](/guide/machine-payments/client): Set up an MPP client on Tempo. Polyfill fetch to automatically pay for 402 responses with TIP-20 stablecoins.
- [Accept One-Time Payments](/guide/machine-payments/one-time-payments): Charge per request on Tempo using the mppx charge intent. Each request triggers a TIP-20 transfer that settles in ~500ms.
- [Accept Pay-As-You-Go Payments](/guide/machine-payments/pay-as-you-go): Session-based billing on Tempo with MPP payment channels. Clients deposit funds, sign off-chain vouchers, and pay per request without on-chain latency.
- [Server Quickstart](/guide/machine-payments/server): Add payment gating to any HTTP endpoint on Tempo with mppx middleware for Next.js, Hono, Express, and the Fetch API.
- [Accept Streamed Payments](/guide/machine-payments/streamed-payments): Per-token billing over Server-Sent Events on Tempo. Stream content word-by-word and charge per unit using MPP sessions with SSE.
- [Installation](/guide/node/installation): Install Tempo node using pre-built binaries, build from source with Rust, or run with Docker. Get started in minutes with tempoup.
- [Network Upgrades and Releases](/guide/node/network-upgrades): Timeline and details for Tempo network upgrades and important releases for node operators.
- [Running an RPC Node](/guide/node/rpc): Set up and run a Tempo RPC node for API access. Download snapshots, configure systemd services, and monitor node health and sync status.
- [Node Security](/guide/node/security): Security best practices for Tempo node operators, covering key management, network configuration, release verification, and data integrity.
- [System Requirements](/guide/node/system-requirements): Minimum and recommended hardware specs for running Tempo RPC and validator nodes. CPU, RAM, storage, network, and port requirements.
- [Upgrade Cadence](/guide/node/upgrade-cadence): How Tempo schedules and communicates network upgrades, including timelines, notification windows, and what to expect as a node operator.
- [Running a validator node](/guide/node/validator): Overview of running a Tempo validator node.
- [Managing validator keys](/guide/node/validator-keys): Generate, rotate, and recover validator signing keys and shares.
- [Controlling validator lifecycle](/guide/node/validator-lifecycle): Start, stop, register, rotate, deactivate, and transfer ownership of your Tempo validator.
- [Monitoring a validator](/guide/node/validator-monitoring): Monitor validator health with metrics, Grafana dashboards, and log management.
- [Validator Onboarding](/guide/node/validator-setup): Generate signing keys and run your Tempo validator node for the first time.
- [Checking validator status](/guide/node/validator-status): Understand validator state transitions, check your validator's participation status, and query on-chain status.
- [Troubleshooting and FAQ](/guide/node/validator-troubleshooting): Common issues and solutions for Tempo validator operators.
- [Accept a Payment](/guide/payments/accept-a-payment): Accept stablecoin payments in your application. Verify transactions, listen for transfer events, and reconcile payments using memos.
- [Pay Fees in Any Stablecoin](/guide/payments/pay-fees-in-any-stablecoin): Configure users to pay transaction fees in any supported stablecoin. Eliminate the need for a separate gas token with Tempo's flexible fee system.
- [Send a Payment](/guide/payments/send-a-payment): Send stablecoin payments between accounts on Tempo. Include optional memos for reconciliation and tracking with TypeScript, Rust, or Solidity.
- [Send Parallel Transactions](/guide/payments/send-parallel-transactions): Submit multiple transactions concurrently using Tempo's expiring nonce system under-the-hood.
- [Sponsor User Fees](/guide/payments/sponsor-user-fees): Enable gasless transactions by sponsoring fees for your users. Set up a fee payer service and improve UX by removing friction from payment flows.
- [Attach a Transfer Memo](/guide/payments/transfer-memos): Attach 32-byte reference memos to TIP-20 transfers for payment reconciliation, invoice matching, and exchange deposit tracking on Tempo.
- [Use virtual addresses for deposits](/guide/payments/virtual-addresses): Register a virtual-address master, derive deposit addresses offchain, and watch TIP-20 deposits land directly in the registered wallet.
- [Connect to a Zone](/guide/private-zones/connect-to-a-zone): Connect to Tempo Zones on testnet using Zone A and Zone B RPC URLs, chain IDs, and a minimal viem client setup for private flows.
- [Deposit to a Zone](/guide/private-zones/deposit-to-a-zone): Deposit pathUSD from your public-chain balance into Zone A and confirm the resulting zone balance.
- [Send tokens across zones](/guide/private-zones/send-tokens-across-zones): Send pathUSD from Zone A into Zone B by routing a same-token withdrawal through Tempo's L1 router and confirming the target deposit.
- [Send tokens within a zone](/guide/private-zones/send-tokens-within-a-zone): Send pathUSD inside Zone A with a signed zone transfer and confirm the updated zone balance.
- [Swap stablecoins across zones](/guide/private-zones/swap-across-zones): Swap pathUSD from Zone A into betaUSD on Zone B by routing a zone withdrawal through Tempo's L1 router and confirming the target deposit.
- [Withdraw from a Zone](/guide/private-zones/withdraw-from-a-zone): Withdraw pathUSD from Zone A back to your public-chain balance with a direct zone outbox withdrawal.
- [Executing Swaps](/guide/stablecoin-dex/executing-swaps): Learn to execute instant stablecoin swaps on Tempo's DEX. Get price quotes, set slippage protection, and batch approvals with swaps.
- [Managing Fee Liquidity](/guide/stablecoin-dex/managing-fee-liquidity): Add and remove liquidity in the Fee AMM to enable stablecoin fee conversions. Monitor pools, check LP balances, and rebalance reserves.
- [Providing Liquidity](/guide/stablecoin-dex/providing-liquidity): Place limit and flip orders to provide liquidity on the Stablecoin DEX orderbook. Learn to manage orders and set prices using ticks.
- [View the Orderbook](/guide/stablecoin-dex/view-the-orderbook): Inspect Tempo's onchain orderbook using SQL queries. View spreads, order depth, individual orders, and recent trade prices with indexed data.
- [Add Funds to Your Balance](/guide/use-accounts/add-funds): Get test stablecoins on Tempo Testnet using the faucet. Request pathUSD, AlphaUSD, BetaUSD, and ThetaUSD tokens for development and testing.
- [Authorize access keys](/guide/use-accounts/authorize-access-keys): Authorize access keys on Tempo. Use a secondary signing key to send transactions without repeated passkey prompts, with spending limits and expiry for security.
- [Batch Transactions](/guide/use-accounts/batch-transactions): Execute multiple operations atomically in a single Tempo Transaction using native protocol-level batching with one signature and lower gas costs.
- [Connect to Wallets](/guide/use-accounts/connect-to-wallets): Connect your application to EVM-compatible wallets like MetaMask on Tempo. Set up Wagmi connectors and add the Tempo network to user wallets.
- [Embed Passkey Accounts](/guide/use-accounts/embed-passkeys): Create domain-bound passkey accounts on Tempo using WebAuthn for secure, passwordless authentication with biometrics like Face ID and Touch ID.
- [Embed Tempo Wallet](/guide/use-accounts/embed-tempo-wallet): Embed the Tempo Wallet dialog into your application for a universal wallet experience with account management, passkeys, and fee sponsorship.
- [Scheduled Transactions](/guide/use-accounts/scheduled-transactions): Schedule Tempo transactions to execute within a specific time window using validAfter and validBefore timestamps for vesting, offers, and delayed execution.
- [WebAuthn & P256 Signatures](/guide/use-accounts/webauthn-p256-signatures): Sign Tempo transactions with passkeys, Face ID, Touch ID, or hardware security keys using native WebAuthn and P256 signature support on EOA accounts.
- [Onchain FX](/learn/tempo/fx): Access foreign exchange liquidity directly onchain with regulated non-USD stablecoin issuers and multi-currency fee payments on Tempo.
- [Agentic Payments](/learn/tempo/machine-payments): The Machine Payments Protocol (MPP) is an open standard for machine-to-machine payments, co-authored by Stripe and Tempo.
- [Tempo Transactions](/learn/tempo/modern-transactions): Native support for gas sponsorship, batch transactions, scheduled payments, and passkey authentication built into Tempo's protocol.
- [TIP-20 Tokens](/learn/tempo/native-stablecoins): Tempo's stablecoin token standard with payment lanes, stable fees, reconciliation memos, and built-in compliance for regulated issuers.
- [Performance](/learn/tempo/performance): High throughput and sub-second finality built on Reth SDK and Simplex Consensus for payment applications requiring instant settlement.
- [Privacy](/learn/tempo/privacy): Explore Tempo's opt-in privacy features enabling private balances and confidential transfers while maintaining issuer compliance.
- [Power AI agents with programmable money](/learn/use-cases/agentic-commerce): Power autonomous AI agents with programmable stablecoin payments for goods, services, and digital resources in real time.
- [Bring embedded finance to life with stablecoins](/learn/use-cases/embedded-finance): Enable platforms and marketplaces to streamline partner payouts, lower payment costs, and launch rewarding loyalty programs.
- [Send global payouts instantly](/learn/use-cases/global-payouts): Deliver instant, low-cost payouts to contractors, merchants, and partners worldwide with stablecoins, bypassing slow banking rails.
- [Enable true pay-per-use pricing](/learn/use-cases/microtransactions): Enable true pay-per-use pricing with sub-cent payments for APIs, content, IoT services, and machine-to-machine commerce.
- [Stablecoins for Payroll](/learn/use-cases/payroll): Learn how payroll providers can use stablecoins for faster account funding, cheaper cross-border payouts, and embedded wallet revenue.
- [Send money home faster and cheaper](/learn/use-cases/remittances): Send cross-border payments faster and cheaper with stablecoins, eliminating correspondent banks and reducing transfer costs.
- [Move treasury liquidity instantly across borders](/learn/use-cases/tokenized-deposits): Move treasury liquidity instantly across borders with real-time visibility into global cash positions using tokenized deposits.
- [Consensus and Finality](/protocol/blockspace/consensus): Tempo uses Simplex BFT via Commonware for deterministic sub-second finality with Byzantine fault tolerance.
- [Blockspace Overview](/protocol/blockspace/overview): Technical specification for Tempo block structure including header fields, payment lanes, and system transaction ordering.
- [Payment Lane Specification](/protocol/blockspace/payment-lane-specification): Technical specification for Tempo payment lanes ensuring dedicated blockspace for payment transactions with predictable fees during congestion.
- [DEX Balance](/protocol/exchange/exchange-balance): Hold token balances directly on the Stablecoin DEX to save gas costs on trades, receive maker proceeds automatically, and trade more efficiently.
- [Executing Swaps](/protocol/exchange/executing-swaps): Learn how to execute swaps and quote prices on Tempo's Stablecoin DEX with exact-in and exact-out swap functions and slippage protection.
- [Providing Liquidity](/protocol/exchange/providing-liquidity): Provide liquidity on Tempo's DEX using limit orders and flip orders. Earn spreads while facilitating stablecoin trades with price-time priority.
- [Quote Tokens](/protocol/exchange/quote-tokens): Quote tokens determine trading pairs on Tempo's DEX. Each TIP-20 specifies a quote token, with pathUSD available as an optional neutral choice.
- [Stablecoin DEX](/protocol/exchange/spec): Technical specification for Tempo's enshrined DEX with price-time priority orderbook, flip orders, and multi-hop routing for stablecoin trading.
- [Fee AMM Overview](/protocol/fees/fee-amm/): Understand how the Fee AMM automatically converts transaction fees between stablecoins, enabling users to pay in any supported token.
- [Fee Specification](/protocol/fees/spec-fee): Technical specification for Tempo's fee system covering multi-token fee payment, fee sponsorship, token preferences, and validator payouts.
- [Fee AMM Specification](/protocol/fees/spec-fee-amm): Technical specification for the Fee AMM enabling automatic stablecoin conversion for transaction fees with fixed-rate swaps and MEV protection.
- [TIP-20 Rewards](/protocol/tip20-rewards/overview): Built-in reward distribution mechanism for TIP-20 tokens enabling efficient, opt-in proportional rewards to token holders at scale.
- [TIP-20 Rewards Distribution](/protocol/tip20-rewards/spec): Technical specification for the TIP-20 reward distribution system using reward-per-token accumulator pattern for scalable pro-rata rewards.
- [TIP-20 Token Standard](/protocol/tip20/overview): TIP-20 is Tempo's native token standard for stablecoins with built-in fee payment, payment lanes, transfer memos, and compliance policies.
- [TIP20](/protocol/tip20/spec): Technical specification for TIP-20, the optimized token standard extending ERC-20 with memos, rewards distribution, and policy integration.
- [Virtual addresses for TIP-20 deposits](/protocol/tip20/virtual-addresses): Understand how TIP-20 virtual addresses work, why they remove sweep transactions, and how to attribute forwarded deposits on Tempo.
- [TIP-403 Policy Registry](/protocol/tip403/overview): Learn how TIP-403 enables TIP-20 tokens to enforce access control through a shared policy registry with whitelist and blacklist support.
- [Overview](/protocol/tip403/spec): Technical specification for TIP-403, the policy registry system enabling whitelist and blacklist access control for TIP-20 tokens on Tempo.
- [TIP Title](/protocol/tips/_tip_template): Short description for SEO
- [Account Keychain Precompile](/protocol/transactions/AccountKeychain): Technical specification for the Account Keychain precompile managing access keys with expiry timestamps, spending limits, and call-scope restrictions.
- [EIP-4337 Comparison](/protocol/transactions/eip-4337): How Tempo Transactions achieve EIP-4337 goals without bundlers, paymasters, or EntryPoint contracts.
- [EIP-7702 Comparison](/protocol/transactions/eip-7702): How Tempo Transactions extend EIP-7702 delegation with additional signature schemes and native features.
- [Tempo Transaction](/protocol/transactions/spec-tempo-transaction): Technical specification for the Tempo transaction type (EIP-2718) with WebAuthn signatures, parallelizable nonces, gas sponsorship, and batching.
- [T2 Network Upgrade](/protocol/upgrades/t2): Details and timeline for the T2 network upgrade including compound transfer policies, Validator Config V2, permit support for TIP-20, and audit-driven bug fixes.
- [T3 Network Upgrade](/protocol/upgrades/t3): Details and timeline for the T3 network upgrade, including enhanced access keys, signature verification, and virtual addresses.
- [T4 Network Upgrade](/protocol/upgrades/t4): Details and timeline for the T4 network upgrade, including consensus context in the block header and bundled bug fixes.
- [T5 Network Upgrade](/protocol/upgrades/t5): Details and timeline for the T5 network upgrade, including the enshrined TIP-20 escrow channel precompile, DEX improvements, multihop FeeAMM routing, and more.
- [Accounts](/protocol/zones/accounts): Account-scoped access control on Tempo Zones, including private balances, private allowances, and the two-layer privacy model.
- [Tempo Zone Architecture](/protocol/zones/architecture): Architecture of Tempo Zones, including contract layout, sequencer management, chain IDs, and the trust model.
- [Zone Bridging](/protocol/zones/bridging): Deposit and withdraw TIP-20 tokens between Tempo Mainnet and Tempo Zones, including encrypted deposits and composable withdrawal callbacks.
- [Execution & Gas](/protocol/zones/execution): Specification for gas accounting, fee tokens, fixed TIP-20 gas costs, contract creation limits, and token management on Tempo Zones.
- [Zone Proving](/protocol/zones/proving): Batch submission and proof verification for Tempo zones, including the state transition function, ZK and TEE deployment modes, and ancestry proofs.
- [Zone RPC](/protocol/zones/rpc): Authenticated JSON-RPC interface for Tempo Zones with per-account scoping, timing side channel mitigations, and event filtering.
- [Foundry Integration](/sdk/foundry/mpp): Use Foundry tools (cast, forge, anvil, chisel) with MPP-gated RPC endpoints on Tempo — automatic 402 handling with zero config.
- [Signature Verification in Foundry](/sdk/foundry/signature-verifier): Verify secp256k1, P256, and WebAuthn signatures in smart contracts using the TIP-1020 SignatureVerifier precompile with Foundry.
- [Pay for Agent-to-Agent Services](/guide/machine-payments/use-cases/agent-to-agent): Hire agents for coding, design, writing, and email with Auto.exchange and AgentMail via MPP stablecoin payments on Tempo.
- [Pay for AI Models Per Request](/guide/machine-payments/use-cases/ai-model-access): Let your agents call OpenAI, Anthropic, Gemini, Mistral, and other LLMs without API keys using MPP stablecoin payments on Tempo.
- [Pay for Blockchain Data and Analytics](/guide/machine-payments/use-cases/blockchain-data): Query on-chain data from Alchemy, Allium, Nansen, Dune, and Codex using MPP stablecoin payments on Tempo — no API keys required.
- [Pay for Browser Automation and Web Scraping](/guide/machine-payments/use-cases/browser-automation): Run headless browsers, solve CAPTCHAs, and scrape web pages using Browserbase, 2Captcha, and Oxylabs via MPP on Tempo.
- [Pay for Compute and Code Execution](/guide/machine-payments/use-cases/compute-and-code-execution): Run code, deploy containers, and access GPU compute via MPP with stablecoin payments on Tempo — no cloud accounts needed.
- [Pay for Data Enrichment and Lead Generation](/guide/machine-payments/use-cases/data-enrichment-and-leads): Enrich contacts, find emails, profile companies, and generate leads using Apollo, Hunter, Clado, and more via MPP on Tempo.
- [Pay for Financial and Market Data](/guide/machine-payments/use-cases/financial-data): Access stock prices, forex rates, SEC filings, crypto data, and economic indicators via MPP with stablecoin payments on Tempo.
- [Pay for Image, Video, and Audio Generation](/guide/machine-payments/use-cases/image-and-media-generation): Generate images, videos, audio, and speech with fal.ai, OpenAI, Gemini, and Deepgram via MPP stablecoin payments on Tempo.
- [Pay for Maps, Geocoding, and Location Data](/guide/machine-payments/use-cases/location-and-maps): Access Google Maps, Mapbox, weather, and flight data via MPP with stablecoin payments on Tempo — no API keys required.
- [Monetize Your API with Agentic Payments](/guide/machine-payments/use-cases/monetize-your-api): Accept stablecoin payments for your API using MPP on Tempo. Charge per request without requiring signups, billing accounts, or API keys.
- [Pay for Object Storage and Git Repos](/guide/machine-payments/use-cases/storage): Store files and create Git repositories using MPP with stablecoin payments on Tempo — no cloud accounts required.
- [Pay for Translation and Language Services](/guide/machine-payments/use-cases/translation-and-language): Translate text, transcribe audio, and process language using DeepL, Deepgram, and other MPP services with stablecoin payments on Tempo.
- [Pay for Web Search and Research](/guide/machine-payments/use-cases/web-search-and-research): Let agents search the web, extract content, and crawl pages using MPP services like Parallel, Exa, Brave, and Firecrawl with stablecoin payments.
- [Setup](/sdk/typescript/prool/setup): Set up infinite pooled Tempo node instances in TypeScript with Prool for testing and local development of blockchain applications.
-->

# Authorize access keys

Send stablecoin payments using an access key: a secondary signing key that lets you transact without repeated passkey prompts. Access keys can be scoped with spending limits and expiry for security.

:::info\[Coming with T5]
After the [T5 network upgrade](/protocol/upgrades/t5), `key_authorization` gains an optional `witness: bytes32` field ([TIP-1053](https://github.com/tempoxyz/tempo/blob/main/tips/tip-1053.md)). "Sign-In with Tempo" style apps can derive a 32-byte witness from their challenge and include it in the access-key authorization, so a single user signature both authorizes the access key and binds to the app's challenge — replacing the current two-prompt flow. No breaking change; existing flows continue to work unchanged.
:::

## Demo

By the end of this guide you will be able to send payments on Tempo using an access key. Notice that no passkey prompt appears when sending a payment.

<Demo.Container name="Send a Payment" footerVariant="source" src="tempoxyz/accounts/tree/main/examples/with-access-key">
  <Connect stepNumber={1} />

  <AddFunds stepNumber={2} />

  <SendPayment stepNumber={3} last />
</Demo.Container>

## Steps

::::steps

### Set up Wagmi & integrate accounts

Ensure that you have set up your project with Wagmi and integrated accounts by following either of the guides:

* [Embed Tempo Wallet](/guide/use-accounts/embed-tempo-wallet)
* [Embed domain-bound Passkeys](/guide/use-accounts/embed-passkeys)

### Authorize an access key

Configure your connector to authorize an access key when the user connects. The access key will be used to sign subsequent transactions without passkey prompts.

<Tabs stateKey="connector">
  <Tab title="Tempo Wallet">
    ```ts twoslash [wagmi.config.ts]
    // @noErrors
    import { createConfig, http } from 'wagmi'
    import { tempo } from 'wagmi/chains'
    import { parseUnits } from 'viem'
    import { Expiry } from 'accounts'
    import { tempoWallet } from 'accounts/wagmi'

    export const config = createConfig({
      chains: [tempo],
      connectors: [
        tempoWallet({
          authorizeAccessKey: () => ({ // [!code hl]
            // When the key expires // [!code hl]
            expiry: Expiry.days(7), // [!code hl]
            // Max spend per token // [!code hl]
            limits: [{ // [!code hl]
              token: '0x20c0000000000000000000000000000000000001', // [!code hl]
              limit: parseUnits('100', 6), // 100 AlphaUSD // [!code hl]
            }], // [!code hl]
            // Tokens & functions the key can call // [!code hl]
            scopes: [{ // [!code hl]
              target: '0x20c0000000000000000000000000000000000001', // AlphaUSD // [!code hl]
              selector: 'transfer(address,uint256)', // [!code hl]
            }], // [!code hl]
          }), // [!code hl]
        }),
      ],
      transports: { [tempo.id]: http() },
    })
    ```
  </Tab>

  <Tab title="Domain-bound WebAuthn">
    ```ts twoslash [wagmi.config.ts]
    // @noErrors
    import { createConfig, http } from 'wagmi'
    import { tempo } from 'wagmi/chains'
    import { parseUnits } from 'viem'
    import { Expiry } from 'accounts'
    import { webAuthn } from 'accounts/wagmi'

    export const config = createConfig({
      chains: [tempo],
      connectors: [
        webAuthn({
          authUrl: '/auth',
          authorizeAccessKey: () => ({ // [!code hl]
            // When the key expires // [!code hl]
            expiry: Expiry.days(7), // [!code hl]
            // Max spend per token // [!code hl]
            limits: [{ // [!code hl]
              token: '0x20c0000000000000000000000000000000000001', // [!code hl]
              limit: parseUnits('100', 6), // 100 AlphaUSD // [!code hl]
            }], // [!code hl]
            // Tokens & functions the key can call // [!code hl]
            scopes: [{ // [!code hl]
              target: '0x20c0000000000000000000000000000000000001', // AlphaUSD // [!code hl]
              selector: 'transfer(address,uint256)', // [!code hl]
            }], // [!code hl]
          }), // [!code hl]
        }),
      ],
      transports: { [tempo.id]: http() },
    })
    ```
  </Tab>
</Tabs>

When the user connects, the connector will authorize an access key with:

* **7-day expiry**: the key automatically becomes invalid after 7 days
* **Scopes**: the key can only call `transfer` on the AlphaUSD token
* **100 AlphaUSD spending limit**: the key can spend up to 100 AlphaUSD

### Add testnet funds

Before you can send a payment, you need to fund your account with `AlphaUSD` (`0x20c000…0001`).

```tsx twoslash [AddFunds.tsx]
// @noErrors
import { Hooks } from 'wagmi/tempo'
import { useConnection } from 'wagmi'

function AddFunds() {
  const { address } = useConnection()
  const { mutate, isPending } = Hooks.faucet.useFundSync()

  return (
    <button onClick={() => mutate({ account: address })} disabled={isPending}>
      Add Funds
    </button>
  )
}
```

:::warning
The `addFunds` Hook only works on testnets as a convenience feature to get
started quickly. For production, you will need to onramp & fund your account manually.
:::

### Send a payment

Now send a payment using `useTransferSync`. Because you authorized an access key in step 2, this transaction will be signed automatically: no passkey prompt.

```tsx twoslash [SendPayment.tsx]
// @noErrors
import { Hooks } from 'wagmi/tempo'
import { parseUnits } from 'viem'

function SendPayment() {
  const transfer = Hooks.token.useTransferSync() // [!code hl]

  return (
    <form onSubmit={
      (event) => {
        event.preventDefault()
        const formData = new FormData(event.target as HTMLFormElement)
        const recipient = formData.get('recipient') as `0x${string}`

        transfer.mutate({ // [!code hl]
          amount: parseUnits('100', 6), // [!code hl]
          to: recipient, // [!code hl]
          token: '0x20c0000000000000000000000000000000000001', // [!code hl]
        }) // [!code hl]
      }
    }>
      <label htmlFor="recipient">Recipient address</label>
      <input type="text" name="recipient" placeholder="0x..." />
      <button type="submit" disabled={transfer.isPending}>
        Send Payment
      </button>
    </form>
  )
}
```

### Display receipt

Display the transaction receipt on success.

```tsx twoslash [SendPayment.tsx]
// @noErrors
import { Hooks } from 'wagmi/tempo'
import { parseUnits } from 'viem'

function SendPayment() {
  const sendPayment = Hooks.token.useTransferSync()

  return (
    <>
      {/* ... your payment form ... */}
      {sendPayment.data && ( // [!code hl]
        <a href={`https://explore.tempo.xyz/tx/${sendPayment.data.receipt.transactionHash}`}> {/* [!code hl] */}
          View receipt {/* [!code hl] */}
        </a> {/* [!code hl] */}
      )} {/* [!code hl] */}
    </>
  )
}
```

### Next steps

Now that you can send payments with access keys:

* Learn about the [Account Keychain specification](/protocol/transactions/AccountKeychain)
* Send a payment [with a specific fee token](/guide/payments/pay-fees-in-any-stablecoin)

::::

## SDKs

### Basic transfer with access key

Send a payment using an access key across different SDKs:

<Tabs stateKey="library">
  <Tab title="Viem">
    :::code-group

    ```ts twoslash [example.ts]
    // @noErrors
    import { parseUnits } from 'viem'
    import { generatePrivateKey } from 'viem/accounts'
    import { Account, Actions, Expiry } from 'viem/tempo'
    import { client } from './viem.config'

    // 1. Create an access key. // [!code hl]
    const accessKey = Account.fromP256(generatePrivateKey(), { // [!code hl]
      access: client.account, // [!code hl]
    }) // [!code hl]

    // 2. Sign a key authorization. // [!code hl]
    const keyAuthorization = await Actions.accessKey.signAuthorization(client, { // [!code hl]
      accessKey, // [!code hl]
      expiry: Expiry.days(7), // [!code hl]
      limits: [{ // [!code hl]
        token: '0x20c0000000000000000000000000000000000001', // [!code hl]
        limit: parseUnits('100', 6), // [!code hl]
      }], // [!code hl]
    }) // [!code hl]

    // 3. Send a transfer with the key authorization. // [!code hl]
    const { receipt } = await client.token.transferSync({
      amount: parseUnits('100', 6),
      to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
      token: '0x20c0000000000000000000000000000000000001',
      keyAuthorization, // [!code hl]
    })
    ```

    ```ts twoslash [viem.config.ts]
    // [!include ~/snippets/viem.config.ts:setup]
    ```

    :::

    <div className="h-4" />

    :::info
    Once you have broadcasted the transaction with `keyAuthorization`, you can reuse the same access key to sign subsequent transactions without the need to pass the key authorization again.
    :::
  </Tab>

  <Tab title="Wagmi (Tempo Wallet)">
    :::code-group

    ```tsx twoslash [example.tsx]
    // @noErrors
    import { Hooks } from 'wagmi/tempo'
    import { parseUnits } from 'viem'

    function SendPayment() {
      const { mutate, isPending } = Hooks.token.useTransferSync() // [!code hl]

      return (
        <button
          onClick={() =>
            mutate({ // [!code hl]
              amount: parseUnits('100', 6), // [!code hl]
              to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb', // [!code hl]
              token: '0x20c0000000000000000000000000000000000001', // [!code hl]
            }) // [!code hl]
          }
          disabled={isPending}
        >
          Send Payment
        </button>
      )
    }
    ```

    ```ts twoslash [wagmi.config.ts]
    // @noErrors
    import { createConfig, http } from 'wagmi'
    import { tempo } from 'wagmi/chains'
    import { parseUnits } from 'viem'
    import { Expiry } from 'accounts'
    import { tempoWallet } from 'accounts/wagmi'

    export const config = createConfig({
      chains: [tempo],
      connectors: [
        tempoWallet({
          authorizeAccessKey: () => ({ // [!code hl]
            // When the key expires // [!code hl]
            expiry: Expiry.days(7), // [!code hl]
            // Max spend per token // [!code hl]
            limits: [{ // [!code hl]
              token: '0x20c0000000000000000000000000000000000001', // [!code hl]
              limit: parseUnits('100', 6), // 100 AlphaUSD // [!code hl]
            }], // [!code hl]
            // Tokens & functions the key can call // [!code hl]
            scopes: [{ // [!code hl]
              target: '0x20c0000000000000000000000000000000000001', // AlphaUSD // [!code hl]
              selector: 'transfer(address,uint256)', // [!code hl]
            }], // [!code hl]
          }), // [!code hl]
        }),
      ],
      transports: { [tempo.id]: http() },
    })
    ```

    :::
  </Tab>

  <Tab title="Wagmi (WebAuthn)">
    :::code-group

    ```tsx twoslash [example.tsx]
    // @noErrors
    import { Hooks } from 'wagmi/tempo'
    import { parseUnits } from 'viem'

    // Same API: the connector handles access key signing automatically
    function SendPayment() {
      const { mutate, isPending } = Hooks.token.useTransferSync() // [!code hl]

      return (
        <button
          onClick={() =>
            mutate({ // [!code hl]
              amount: parseUnits('100', 6), // [!code hl]
              to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb', // [!code hl]
              token: '0x20c0000000000000000000000000000000000001', // [!code hl]
            }) // [!code hl]
          }
          disabled={isPending}
        >
          Send Payment
        </button>
      )
    }
    ```

    ```ts twoslash [wagmi.config.ts]
    // @noErrors
    import { createConfig, http } from 'wagmi'
    import { tempo } from 'wagmi/chains'
    import { parseUnits } from 'viem'
    import { Expiry } from 'accounts'
    import { webAuthn } from 'accounts/wagmi'

    export const config = createConfig({
      chains: [tempo],
      connectors: [
        webAuthn({
          authUrl: '/auth',
          authorizeAccessKey: () => ({ // [!code hl]
            // When the key expires // [!code hl]
            expiry: Expiry.days(7), // [!code hl]
            // Max spend per token // [!code hl]
            limits: [{ // [!code hl]
              token: '0x20c0000000000000000000000000000000000001', // [!code hl]
              limit: parseUnits('100', 6), // 100 AlphaUSD // [!code hl]
            }], // [!code hl]
            // Tokens & functions the key can call // [!code hl]
            scopes: [{ // [!code hl]
              target: '0x20c0000000000000000000000000000000000001', // AlphaUSD // [!code hl]
              selector: 'transfer(address,uint256)', // [!code hl]
            }], // [!code hl]
          }), // [!code hl]
        }),
      ],
      transports: { [tempo.id]: http() },
    })
    ```

    :::
  </Tab>

  <Tab title="Rust">
    :::code-group

    ```rust [example.rs]
    use alloy::primitives::{address, U256};
    use alloy::providers::Provider;
    use alloy::signers::{SignerSync, local::PrivateKeySigner};
    use alloy::sol_types::SolCall;
    use tempo_alloy::contracts::precompiles::ITIP20;
    use tempo_alloy::primitives::transaction::key_authorization::{
        KeyAuthorization, SignedKeyAuthorization, TokenLimit,
    };
    use tempo_alloy::primitives::transaction::tt_signature::{
        KeychainSignature, PrimitiveSignature, SignatureType, TempoSignature,
    };
    use tempo_alloy::rpc::TempoTransactionRequest;

    mod provider;

    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let provider = provider::get_provider().await?;
        let root: PrivateKeySigner = std::env::var("PRIVATE_KEY")?.parse()?;

        let token = address!("0x20c0000000000000000000000000000000000001");
        let recipient = address!("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb");
        let amount = U256::from(100_000_000u64); // 100 AlphaUSD (6 decimals)
        let chain_id = provider.get_chain_id().await?;

        // 1. Create an access key. // [!code hl]
        let access_key = PrivateKeySigner::random(); // [!code hl]

        // 2. Sign a key authorization with the root account. // [!code hl]
        let expiry = std::time::SystemTime::now() // [!code hl]
            .duration_since(std::time::UNIX_EPOCH)? // [!code hl]
            .as_secs() + 7 * 24 * 60 * 60; // 7 days // [!code hl]

        let authorization = KeyAuthorization { // [!code hl]
            chain_id, // [!code hl]
            key_type: SignatureType::Secp256k1, // [!code hl]
            key_id: access_key.address(), // [!code hl]
            expiry: Some(expiry), // [!code hl]
            limits: Some(vec![TokenLimit { // [!code hl]
                token, // [!code hl]
                limit: amount, // [!code hl]
                period: 0, // [!code hl]
            }]), // [!code hl]
            ..Default::default() // [!code hl]
        }; // [!code hl]

        let sig = root.sign_hash_sync(&authorization.signature_hash())?; // [!code hl]
        let key_authorization = SignedKeyAuthorization { // [!code hl]
            authorization, // [!code hl]
            signature: sig.into(), // [!code hl]
        }; // [!code hl]

        // 3. Send a transfer with the key authorization. // [!code hl]
        let call_data = ITIP20::transferCall { // [!code hl]
            to: recipient, // [!code hl]
            amount, // [!code hl]
        }.abi_encode(); // [!code hl]

        let tx = TempoTransactionRequest { // [!code hl]
            key_authorization: Some(key_authorization), // [!code hl]
            ..Default::default() // [!code hl]
        } // [!code hl]
        .with_to(token) // [!code hl]
        .with_input(call_data.into()); // [!code hl]

        let receipt = provider // [!code hl]
            .send_transaction(tx) // [!code hl]
            .await? // [!code hl]
            .get_receipt() // [!code hl]
            .await?; // [!code hl]

        println!("Transfer successful: {:?}", receipt.transaction_hash);

        Ok(())
    }
    ```

    ```rust [provider.rs]
    // [!include ~/snippets/rust-signer-provider.rs:setup]
    ```

    :::
  </Tab>

  <Tab title="Cast">
    ```bash
    # 1. Generate an access key.
    $ cast wallet new
    # Address: 0x9f3a7b2c1d4e5f6a8b0c9d2e3f4a5b6c7d8e9f0a
    # Private key: 0x4c0883a69102937d6231471b5dbb6204fe512961708279f22a3c36f1e24b8e10

    # 2. Authorize the access key on-chain with expiry and limits.
    $ cast keychain auth \
      $ACCESS_KEY_ADDRESS \
      secp256k1 \
      $(date -v+7d +%s) \ # 7-day expiry
      --limit 0x20c0000000000000000000000000000000000001:100000000 \
      --rpc-url $TEMPO_RPC_URL \
      --private-key $ROOT_PRIVATE_KEY

    # 3. Send a transfer with the access key.
    $ cast send \
      0x20c0000000000000000000000000000000000001 \
      "transfer(address,uint256)" \
      0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb \
      100000000 \
      --rpc-url $TEMPO_RPC_URL \
      --tempo.access-key $ACCESS_KEY_PRIVATE_KEY \
      --tempo.root-account $ROOT_ADDRESS
    ```
  </Tab>
</Tabs>

### Periodical payments

Use `period` in spending limits to cap how much an access key can spend per time window. The limit resets automatically after each period, making it ideal for subscriptions and recurring billing.

<Tabs stateKey="library">
  <Tab title="Viem">
    :::code-group

    ```ts twoslash [client.ts]
    // @noErrors
    import { parseUnits } from 'viem'
    import { Actions, Expiry } from 'viem/tempo'
    import { client } from './viem.config'

    // Sign a key authorization with a periodic spending limit.
    const keyAuthorization = await Actions.accessKey.signAuthorization(client, {
      accessKey,
      expiry: Expiry.days(30),
      limits: [{
        token: '0x20c0000000000000000000000000000000000001',
        limit: parseUnits('10', 6), // 10 AlphaUSD // [!code hl]
        period: 60 * 60 * 24 * 7, // resets every 7 days // [!code hl]
      }],
    })
    ```

    ```ts twoslash [server.ts]
    // @noErrors
    import { parseUnits } from 'viem'
    import { client } from './viem.config'

    // Charge the user weekly from the server.
    const { receipt } = await client.token.transferSync({
      account: accessKey,
      amount: parseUnits('10', 6),
      to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
      token: '0x20c0000000000000000000000000000000000001',
      keyAuthorization,
    })
    ```

    ```ts twoslash [viem.config.ts]
    // [!include ~/snippets/viem.config.ts:setup]
    ```

    :::
  </Tab>

  <Tab title="Wagmi (Tempo Wallet)">
    :::code-group

    ```tsx twoslash [client.tsx]
    // @noErrors
    import { parseUnits } from 'viem'
    import { useConnectorClient } from 'wagmi'
    import { Expiry } from 'accounts'

    function Subscribe() {
      const { data: client } = useConnectorClient()

      async function handleSubscribe() {
        await client.request({ // [!code hl]
          method: 'wallet_authorizeAccessKey', // [!code hl]
          params: [{ // [!code hl]
            expiry: Expiry.days(30), // [!code hl]
            limits: [{ // [!code hl]
              token: '0x20c0000000000000000000000000000000000001', // [!code hl]
              limit: parseUnits('10', 6), // 10 AlphaUSD // [!code hl]
              period: 60 * 60 * 24 * 7, // resets every 7 days // [!code hl]
            }], // [!code hl]
            scopes: [{ // [!code hl]
              target: '0x20c0000000000000000000000000000000000001', // [!code hl]
              selector: 'transfer(address,uint256)', // [!code hl]
            }], // [!code hl]
          }], // [!code hl]
        }) // [!code hl]
      }

      return (
        <button onClick={handleSubscribe}>
          Subscribe
        </button>
      )
    }
    ```

    ```ts twoslash [server.ts]
    // @noErrors
    import { parseUnits } from 'viem'
    import { Actions } from 'wagmi/tempo'
    import { config } from './wagmi.config'

    // Charge the user weekly from the server.
    const { receipt } = await Actions.token.transferSync(config, {
      amount: parseUnits('10', 6),
      to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
      token: '0x20c0000000000000000000000000000000000001',
    })
    ```

    ```ts twoslash [wagmi.config.ts]
    // @noErrors
    import { createConfig, http } from 'wagmi'
    import { tempo } from 'wagmi/chains'
    import { tempoWallet } from 'accounts/wagmi'

    export const config = createConfig({
      chains: [tempo],
      connectors: [tempoWallet()],
      transports: { [tempo.id]: http() },
    })
    ```

    :::
  </Tab>

  <Tab title="Wagmi (WebAuthn)">
    :::code-group

    ```tsx twoslash [client.tsx]
    // @noErrors
    import { parseUnits } from 'viem'
    import { useConnectorClient } from 'wagmi'
    import { Expiry } from 'accounts'

    function Subscribe() {
      const { data: client } = useConnectorClient()

      async function handleSubscribe() {
        await client.request({ // [!code hl]
          method: 'wallet_authorizeAccessKey', // [!code hl]
          params: [{ // [!code hl]
            expiry: Expiry.days(30), // [!code hl]
            limits: [{ // [!code hl]
              token: '0x20c0000000000000000000000000000000000001', // [!code hl]
              limit: parseUnits('10', 6), // 10 AlphaUSD // [!code hl]
              period: 60 * 60 * 24 * 7, // resets every 7 days // [!code hl]
            }], // [!code hl]
          }], // [!code hl]
        }) // [!code hl]
      }

      return (
        <button onClick={handleSubscribe}>
          Subscribe
        </button>
      )
    }
    ```

    ```ts twoslash [server.ts]
    // @noErrors
    import { parseUnits } from 'viem'
    import { Actions } from 'wagmi/tempo'
    import { config } from './wagmi.config'

    // Charge the user weekly from the server.
    const { receipt } = await Actions.token.transferSync(config, {
      amount: parseUnits('10', 6),
      to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEbb',
      token: '0x20c0000000000000000000000000000000000001',
    })
    ```

    ```ts twoslash [wagmi.config.ts]
    // @noErrors
    import { createConfig, http } from 'wagmi'
    import { tempo } from 'wagmi/chains'
    import { webAuthn } from 'accounts/wagmi'

    export const config = createConfig({
      chains: [tempo],
      connectors: [webAuthn({ authUrl: '/auth' })],
      transports: { [tempo.id]: http() },
    })
    ```

    :::
  </Tab>
</Tabs>

### Authorize arbitrary public keys

You can also directly authorize a public key:

<Tabs stateKey="library">
  <Tab title="Viem">
    :::code-group

    ```ts twoslash [example.ts]
    // @noErrors
    import { parseUnits } from 'viem'
    import { Account, Actions, Expiry } from 'viem/tempo'
    import { client } from './viem.config'

    // Sign authorization by public key
    const keyAuthorization = await Actions.accessKey.signAuthorization(client, {
      accessKey: { // [!code hl]
        publicKey: '0x...', // [!code hl]
        // address: '0x...', // or address // [!code hl]
        type: 'p256', // [!code hl]
      }, // [!code hl]
      expiry: Expiry.days(7),
      limits: [{
        token: '0x20c0000000000000000000000000000000000001',
        limit: parseUnits('100', 6),
      }],
    })
    ```

    ```ts twoslash [viem.config.ts]
    // [!include ~/snippets/viem.config.ts:setup]
    ```

    :::
  </Tab>

  <Tab title="Wagmi (Tempo Wallet)">
    ```ts twoslash [wagmi.config.ts]
    // @noErrors
    import { createConfig, http } from 'wagmi'
    import { tempo } from 'wagmi/chains'
    import { parseUnits } from 'viem'
    import { Expiry } from 'accounts'
    import { tempoWallet } from 'accounts/wagmi'

    export const config = createConfig({
      chains: [tempo],
      connectors: [
        tempoWallet({
          authorizeAccessKey: () => ({
            publicKey: '0x...', // [!code hl]
            // address: '0x...', // or address // [!code hl]
            expiry: Expiry.days(7),
            limits: [{
              token: '0x20c0000000000000000000000000000000000001',
              limit: parseUnits('100', 6),
            }],
            scopes: [{
              target: '0x20c0000000000000000000000000000000000001',
              selector: 'transfer(address,uint256)',
            }],
          }),
        }),
      ],
      transports: { [tempo.id]: http() },
    })
    ```
  </Tab>

  <Tab title="Wagmi (WebAuthn)">
    ```ts twoslash [wagmi.config.ts]
    // @noErrors
    import { createConfig, http } from 'wagmi'
    import { tempo } from 'wagmi/chains'
    import { parseUnits } from 'viem'
    import { Expiry } from 'accounts'
    import { webAuthn } from 'accounts/wagmi'

    export const config = createConfig({
      chains: [tempo],
      connectors: [
        webAuthn({
          authUrl: '/auth',
          authorizeAccessKey: () => ({
            publicKey: '0x...', // [!code hl]
            // address: '0x...', // or address // [!code hl]
            expiry: Expiry.days(7),
            limits: [{
              token: '0x20c0000000000000000000000000000000000001',
              limit: parseUnits('100', 6),
            }],
          }),
        }),
      ],
      transports: { [tempo.id]: http() },
    })
    ```
  </Tab>
</Tabs>

## Best practices

### Scope to specific tokens and functions

Always define `scopes` to restrict which tokens and functions the access key can call. A key scoped to `transfer` on a specific token cannot be used to call other tokens or functions, even if compromised.

### Set appropriate expiry

Access keys should have a reasonable expiry window. Use `Expiry.days(7)` for interactive sessions or `Expiry.hours(1)` for short-lived operations.

### Use spending limits

Combine scopes with per-token spending limits for defense in depth. Spending limits cap the total amount a key can transfer, while scopes restrict which tokens it can interact with.

## Learning resources

<Cards>
  <Card description="Technical specification for the Account Keychain precompile" to="/protocol/transactions/AccountKeychain" icon="lucide:book-open" title="Account Keychain" />
</Cards>
