Spend Permissions let you designate a trusted spender that can spend tokens on behalf of your Smart Account. After you sign the permission, the spender can initiate token spending within the limits you define. You can define limits based on token, time period, and amount.Spend Permissions utilize the Spend Permission Manager contract deployed on Base and other networks.Some use cases this feature enables:
Subscription payments - Enable recurring payments for SaaS, content subscriptions, or membership fees
Agentic payments - Control your agent’s spending limits for autonomous operations
Algorithmic trading - Allow trading bots to execute trades within predefined limits
Automated payouts - Schedule regular distributions or reward payments
Allowance management - Give team members or family controlled access to funds
There are two parties involved in a Spend Permission:
Account - The smart account that creates the Spend Permission and approves it onchain.
Spender - The entity that can spend tokens on behalf of the account within the limits defined by a Spend Permission. Can be a Smart Account or a regular account.
Spender - The entity that can spend tokens on behalf of the account.
Token - The token that the Spend Permission is for. Use "eth" or "usdc" as shortcuts (Base and Base Sepolia only), or provide an ERC-20 contract address for other tokens.
Allowance - The amount of the token the spender is allowed to spend, in the token’s smallest unit (e.g. wei for ETH, 6-decimal units for USDC).
Time period - Use periodInDays for simple daily/weekly limits, or period, start, and end for advanced rolling windows and fixed time ranges.
Salt - A random value to differentiate between permissions with the same parameters. Generated automatically by the SDK.
Extra Data - Arbitrary data for additional information about the permission.
evmSmartAccount is optional. The hook auto-resolves it from the authenticated user’s primary smart account. Pass it explicitly only if the user has multiple smart accounts and you need to target a specific one.
Use useCreateSpendPermission to create a permission. Creating a permission is a user operation that requires gas — use useCdpPaymaster: true on Base or provide a paymasterUrl.
Once a permission is created, the designated spender lists the account’s permissions to find theirs, then calls useSpendPermission to spend within the defined limits.
all_permissions = await cdp.evm.list_spend_permissions( address=smart_account.address,)permissions = [ p for p in all_permissions.spend_permissions if p.permission.spender.lower() == spender.address.lower()]if not permissions: print("No spend permissions found for this spender") exit(1)spend = await spender.use_spend_permission( spend_permission=permissions[0].permission, value=parse_units("0.005", 6), network="base-sepolia",)receipt = await spender.wait_for_user_operation(spend)print(f"Spend completed: {receipt}")
// As the account: see all permissions you've grantedconst permissions = await cdp.evm.listSpendPermissions({ address: smartAccount.address,});console.log("Permissions granted:", permissions);// As the spender: query the account's permissions and filter by your addressconst allPermissions = await cdp.evm.listSpendPermissions({ address: "0xAccountAddress",});const myPermissions = allPermissions.spendPermissions.filter( (p) => p.permission.spender.toLowerCase() === spender.address.toLowerCase());
# As the account: see all permissions you've grantedpermissions = await cdp.evm.list_spend_permissions( address=smart_account.address,)print("Permissions granted:", permissions)# As the spender: query the account's permissions and filter by your addressall_permissions = await cdp.evm.list_spend_permissions( address="0xAccountAddress",)my_permissions = [ p for p in all_permissions.spend_permissions if p.permission.spender.lower() == spender.address.lower()]