Subscriptions

AuthGate manages the full subscription lifecycle — from plan creation to cancellation. Plans and prices are defined once in the dashboard, and users move through them via your application's UI or directly via the API.


Plans and prices

A plan is a product offering (e.g. "Starter", "Pro", "Enterprise"). Each plan has one or more prices that define the billing interval and amount.

Creating a plan

In the AuthGate dashboard, navigate to Billing → Plans → New Plan. Set:

  • Name — displayed to users (e.g. "Pro")
  • Description — optional marketing copy
  • Features — list of feature flags this plan grants (used for entitlements)

Adding prices

Each plan can have multiple prices for different billing intervals. Three pricing models are supported:

ModelDescription
RecurringFixed amount charged every billing period (monthly or annually)
MeteredCharge based on usage reported during the billing period
TieredPrice per unit changes based on total quantity (volume or graduated)

Example price configuration

{
  "nickname": "Pro Monthly",
  "amount": 2900,
  "currency": "usd",
  "interval": "month",
  "model": "recurring"
}

Amounts are always in the smallest currency unit (cents for USD).


Subscription lifecycle

create → trialing (optional) → active → past_due → canceled

                                     paused
StatusDescription
trialingUser is in a free trial period; no charge yet
activeSubscription is current and paid
past_duePayment failed; grace period before cancellation
pausedSubscription manually paused; no billing occurs
canceledSubscription ended; access should be revoked

Creating a subscription

Subscriptions are created via the checkout flow. Your application redirects users to the hosted checkout session or renders the <CheckoutForm /> component. On success, AuthGate creates the subscription and fires a subscription.created webhook.

See SDK Components for the checkout UI and Billing API Endpoints for the raw API.

Canceling a subscription

Subscriptions can be canceled immediately or at the end of the current billing period. Cancel-at-period-end is the default — users retain access until the period closes.

curl -X POST https://your-authgate-instance.com/api/proxy/billing/subscription/cancel \
  -H "Authorization: Bearer <session_token>" \
  -H "Content-Type: application/json" \
  -d '{ "at_period_end": true }'

Pausing a subscription

Pausing stops the billing cycle without canceling the subscription. The user loses access while paused. Resume resumes billing from the pause date.

curl -X POST https://your-authgate-instance.com/api/proxy/billing/subscription/pause \
  -H "Authorization: Bearer <session_token>"

Plan changes and proration

When a user upgrades or downgrades, AuthGate calculates proration automatically:

  • Upgrade — the user is charged for the remaining days on the new plan, minus a credit for unused days on the old plan
  • Downgrade — a credit is applied toward the next invoice; no immediate charge

Proration is calculated at the moment of the plan change and appears as a line item on the next invoice.


Trial periods

Trials are configured per plan in the dashboard. Set the trial duration in days; new subscribers on that plan automatically receive a trial before their first charge.

  • Users in trialing status have full access to plan features via entitlements
  • No payment method is required to start a trial (configurable)
  • If no payment method is collected and the trial ends, the subscription moves to canceled
  • A subscription.trial_ending webhook fires 3 days before trial expiry

Reading subscriptions in React

Use the useSubscription hook from @auth-gate/react to read the current user's subscription in any client component:

import { useSubscription } from "@auth-gate/react";

function SubscriptionStatus() {
  const { subscription, loading, error } = useSubscription();

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Failed to load subscription.</p>;
  if (!subscription) return <p>No active subscription.</p>;

  return (
    <div>
      <p>Plan: {subscription.plan.name}</p>
      <p>Status: {subscription.status}</p>
      <p>Renews: {new Date(subscription.current_period_end).toLocaleDateString()}</p>
    </div>
  );
}

The hook fetches from GET /api/proxy/billing/subscription and caches the result. It returns null for subscription when the user has no active or trialing subscription.

Was this page helpful?