> ## Documentation Index
> Fetch the complete documentation index at: https://docs.base.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscriptions Overview

> Accept recurring USDC payments using spend permissions on Base

export const Button = ({children, disabled, variant = "primary", size = "medium", iconName, roundedFull = false, className = '', fullWidth = false, onClick = undefined}) => {
  const variantStyles = {
    primary: 'bg-blue text-black border border-blue hover:bg-blue-80 active:bg-[#06318E] dark:text-white',
    secondary: 'bg-white border border-white text-palette-foreground hover:bg-zinc-15 active:bg-zinc-30',
    outlined: 'bg-transparent text-white border border-white hover:bg-white hover:text-black active:bg-[#E3E7E9]'
  };
  const sizeStyles = {
    medium: 'text-md px-4 py-2 gap-3',
    large: 'text-lg px-6 py-4 gap-5'
  };
  const sizeIconRatio = {
    medium: '0.75rem',
    large: '1rem'
  };
  const classes = ['text-md px-4 py-2 whitespace-nowrap', 'flex items-center justify-center', 'disabled:opacity-40 disabled:pointer-events-none', 'transition-all', variantStyles[variant], sizeStyles[size], roundedFull ? 'rounded-full' : 'rounded-lg', fullWidth ? 'w-full' : 'w-auto', className];
  const buttonClasses = classes.filter(Boolean).join(' ');
  const iconSize = sizeIconRatio[size];
  return <button type="button" disabled={disabled} className={buttonClasses} onClick={onClick}>
      <span>{children}</span>
      {iconName && <Icon name={iconName} width={iconSize} height={iconSize} color="currentColor" />}
    </button>;
};

export const BaseBanner = ({content = null, id, dismissable = true}) => {
  const LOCAL_STORAGE_KEY_PREFIX = 'cb-docs-banner';
  const [isVisible, setIsVisible] = useState(false);
  const onDismiss = () => {
    localStorage.setItem(`${LOCAL_STORAGE_KEY_PREFIX}-${id}`, 'false');
    setIsVisible(false);
  };
  useEffect(() => {
    const storedValue = localStorage.getItem(`${LOCAL_STORAGE_KEY_PREFIX}-${id}`);
    setIsVisible(storedValue !== 'false');
  }, []);
  if (!isVisible) {
    return null;
  }
  return <div className="fixed bottom-0 left-0 right-0 bg-white py-8 px-4 lg:px-12 z-50 text-black dark:bg-black dark:text-white border-t dark:border-gray-95">
      <div className="flex items-center max-w-8xl mx-auto">
        {typeof content === 'function' ? content({
    onDismiss
  }) : content}
        {dismissable && <button onClick={onDismiss} className="flex-shrink-0 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors" aria-label="Dismiss banner">
          ✕
        </button>}
      </div>
    </div>;
};

Defined in the [Base Account SDK](https://github.com/base/account-sdk)

<Info>
  Base Subscriptions enable recurring USDC payments. Users grant your application permission to charge their account periodically, eliminating the need for manual approvals on each payment. **No fees for merchants or users.**
</Info>

## How Subscriptions Work

<Steps>
  <Step title="User Creates Subscription">
    User approves a spend permission for your application to charge a specific amount periodically.
  </Step>

  <Step title="Application Charges Periodically">
    Your backend charges the subscription when payment is due, up to the permitted amount per period.
  </Step>

  <Step title="Automatic Period Reset">
    The spending limit resets automatically at the start of each new period.
  </Step>

  <Step title="User Can Cancel Anytime">
    Users maintain full control and can revoke the permission at any time.
  </Step>
</Steps>

## Core Functions

<CardGroup cols={3}>
  <Card title="subscribe" icon="credit-card" href="/base-account/reference/base-pay/subscribe">
    Create a new subscription with spend permissions
  </Card>

  <Card title="getStatus" icon="chart-line" href="/base-account/reference/base-pay/getStatus">
    Check subscription status and remaining charges
  </Card>

  <Card title="charge" icon="bolt" href="/base-account/reference/base-pay/charge">
    Charge a subscription from your backend (Node.js only)
  </Card>

  <Card title="revoke" icon="ban" href="/base-account/reference/base-pay/revoke">
    Cancel a subscription from your backend (Node.js only)
  </Card>

  <Card title="getOrCreateSubscriptionOwnerWallet" icon="wallet" href="/base-account/reference/base-pay/getOrCreateSubscriptionOwnerWallet">
    Setup CDP smart wallet for subscription management (Node.js only)
  </Card>

  <Card title="prepareCharge" icon="receipt" href="/base-account/reference/base-pay/prepareCharge">
    Advanced: Prepare transaction calls to charge a subscription
  </Card>

  <Card title="prepareRevoke" icon="code" href="/base-account/reference/base-pay/prepareRevoke">
    Advanced: Prepare transaction calls to revoke a subscription
  </Card>
</CardGroup>

## Type Definitions

```typescript theme={null}
// Subscription creation options
interface SubscriptionOptions {
  recurringCharge: string;
  subscriptionOwner: string;
  periodInDays?: number;
  testnet?: boolean;
  telemetry?: boolean;
}

// Subscription result
interface SubscriptionResult {
  id: string;
  subscriptionOwner: Address;
  subscriptionPayer: Address;
  recurringCharge: string;
  periodInDays: number;
}

// Subscription status
interface SubscriptionStatus {
  isSubscribed: boolean;
  recurringCharge: string;
  remainingChargeInPeriod?: string;
  currentPeriodStart?: Date;
  nextPeriodStart?: Date;
  periodInDays?: number;
}

// Charge options (Node.js backend only)
interface ChargeOptions {
  id: string;
  amount: string | 'max-remaining-charge';
  paymasterUrl?: string;
  recipient?: Address;
  testnet?: boolean;
}

// Charge result
interface ChargeResult {
  id: string;
  amount: string;
  recipient?: Address;
}

// Revoke options (Node.js backend only)
interface RevokeOptions {
  id: string;
  paymasterUrl?: string;
  testnet?: boolean;
}

// Revoke result
interface RevokeResult {
  id: string;
}

// Subscription owner wallet setup (Node.js backend only)
interface GetOrCreateSubscriptionOwnerWalletOptions {
  walletName?: string;
}

interface SubscriptionOwnerWallet {
  address: Address;
  walletName: string;
}

// Charge preparation (advanced)
interface PrepareChargeOptions {
  id: string;
  amount: string | 'max-remaining-charge';
  recipient?: Address;
  testnet?: boolean;
}

type PrepareChargeResult = Array<{
  to: Address;
  data: Hex;
  value: '0x0';
}>;

// Revoke preparation (advanced)
interface PrepareRevokeOptions {
  id: string;
  testnet?: boolean;
}

type PrepareRevokeResult = {
  to: Address;
  data: Hex;
  value: '0x0';
};
```

## Next Steps

<CardGroup cols={3}>
  <Card title="Accept Recurring Payments Guide" icon="book" href="/base-account/guides/accept-recurring-payments">
    Learn how to implement recurring payments with Base Pay
  </Card>

  <Card title="One-Time Payments Guide" icon="book" href="/base-account/guides/accept-payments">
    Learn how to implement one-time payments with Base Pay
  </Card>

  <Card title="Spend Permissions" icon="shield" href="/base-account/improve-ux/spend-permissions">
    Deep dive into Spend Permissions
  </Card>
</CardGroup>

<BaseBanner
  id="privacy-policy"
  dismissable={false}
  content={({ onDismiss }) => (
<div className="flex items-center">
  <div className="mr-2">
    We're updating the Base Privacy Policy, effective July 25, 2025, to reflect an expansion of Base services. Please review the updated policy here:{" "}
    <a
      href="https://docs.base.org/privacy-policy-2025"
      target="_blank"
      className="whitespace-nowrap"
    >
      Base Privacy Policy
    </a>. By continuing to use Base services, you confirm that you have read and understand the updated policy.
  </div>
  <Button onClick={onDismiss}>I Acknowledge</Button>
</div>
)}
/>
