> ## 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.

# subscription.subscribe

> Create USDC subscriptions with spend permissions on Base network

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>
  The `subscribe` function creates recurring USDC subscriptions using spend permissions on the Base network. This enables you to charge users periodically without requiring approval for each transaction. **No fees for merchants or users.**
</Info>

## Parameters

<ParamField body="recurringCharge" type="string" required>
  Amount of USDC to charge per period (e.g., "10.50"). Maximum 6 decimal places.
</ParamField>

<ParamField body="subscriptionOwner" type="string" required>
  Ethereum address that will be the spender (your application's address).

  **Pattern:** `^0x[0-9a-fA-F]{40}$`
</ParamField>

<ParamField body="periodInDays" type="number">
  The period in days for the subscription (e.g., 30 for monthly). Default: 30
</ParamField>

<ParamField body="testnet" type="boolean">
  Set to true to use Base Sepolia testnet instead of mainnet. Default: false
</ParamField>

<ParamField body="requireBalance" type="boolean">
  Check if the payer's wallet has sufficient USDC balance before creating the subscription. If true, subscription creation will fail if the payer doesn't have enough balance to cover the recurring charge. Default: true
</ParamField>

<ParamField body="telemetry" type="boolean">
  Whether to enable telemetry logging. Default: true
</ParamField>

## Returns

<ResponseField name="result" type="SubscriptionResult">
  Subscription details on success. The function throws an error on failure.

  <Expandable title="SubscriptionResult properties">
    <ResponseField name="id" type="string">
      The subscription ID (permission hash) - use this to manage the subscription.
    </ResponseField>

    <ResponseField name="subscriptionOwner" type="Address">
      Address that controls the subscription (your application).
    </ResponseField>

    <ResponseField name="subscriptionPayer" type="Address">
      Address that will be charged (the user).
    </ResponseField>

    <ResponseField name="recurringCharge" type="string">
      Recurring charge amount in USD.
    </ResponseField>

    <ResponseField name="periodInDays" type="number">
      Period in days for the subscription.
    </ResponseField>
  </Expandable>
</ResponseField>

## Errors

The `subscribe` function throws an error when subscription creation fails. The error object contains a message explaining what went wrong.

<RequestExample>
  ```typescript Basic Subscription theme={null}
  import { base } from '@base-org/account';

  try {
    const subscription = await base.subscription.subscribe({
      recurringCharge: "9.99",
      subscriptionOwner: "0xYourSubscriptionOwnerWallet",
      periodInDays: 30
    });
    
    console.log(`Subscription ID: ${subscription.id}`);
    console.log(`Payer: ${subscription.subscriptionPayer}`);
    console.log(`Monthly charge: $${subscription.recurringCharge}`);
  } catch (error) {
    console.error(`Subscription failed: ${error.message}`);
  }
  ```

  ```typescript Weekly Subscription on Testnet theme={null}
  try {
    const subscription = await base.subscription.subscribe({
      recurringCharge: "2.99",
      subscriptionOwner: "0xYourSubscriptionOwnerWallet",
      periodInDays: 7,  // Weekly billing
      testnet: true     // Use Base Sepolia
    });
    
    console.log(`Created weekly subscription: ${subscription.id}`);
    console.log(`Charging ${subscription.recurringCharge} every ${subscription.periodInDays} days`);
  } catch (error) {
    console.error(`Failed to create subscription: ${error.message}`);
  }
  ```

  ```typescript Annual Subscription theme={null}
  try {
    const subscription = await base.subscription.subscribe({
      recurringCharge: "99.99",
      subscriptionOwner: "0xYourSubscriptionOwnerWallet",
      periodInDays: 365,  // Annual billing
      testnet: false
    });
    
    console.log(`Annual subscription created!`);
    console.log(`ID: ${subscription.id}`);
    console.log(`Annual charge: $${subscription.recurringCharge}`);
  } catch (error) {
    console.error(`Subscription creation failed: ${error.message}`);
  }
  ```
</RequestExample>

<ResponseExample>
  ```typescript Success Response theme={null}
  {
    id: "0x71319cd488f8e4f24687711ec5c95d9e0c1bacbf5c1064942937eba4c7cf2984",
    subscriptionOwner: "0xYourSubscriptionOwnerWallet",
    subscriptionPayer: "0x742d35Cc4Bf53E0e6C42E5d9F0A8D2F6D8A8B7C9",
    recurringCharge: "9.99",
    periodInDays: 30
  }
  ```

  ```typescript Error (thrown) theme={null}
  {
    "code": 4001,
    "message": "User rejected the request",
    "stack": "Error: User rejected the request\n    at getEthProviderError..."
  }
  ```
</ResponseExample>

## Error Handling

Always wrap calls to `subscribe` in a try-catch block:

```typescript theme={null}
try {
  const subscription = await base.subscription.subscribe({
    recurringCharge: "19.99",
    subscriptionOwner: "0xYourSubscriptionOwnerWallet",
    periodInDays: 30
  });
  // Subscription created successfully
  saveSubscriptionId(subscription.id); // Save for future charges
} catch (error) {
  // Handle subscription failure
  console.error(`Failed to create subscription: ${error.message}`);
}
```

<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>
)}
/>
