@usethrottle/subscriptions
v1.0.4
Published
React hooks, server proxy helpers, and primitive components for Throttle subscriptions.
Downloads
461
Readme
@usethrottle/subscriptions
Production React hooks, server proxy helpers, and primitive components for Throttle subscriptions.
npm install @usethrottle/subscriptions @usethrottle/checkout-reactWhat it covers
- Subscription lifecycle reads and mutations: list, get, create, update, change plan, pause, resume, cancel.
- Recurring checkout-session creation for subscribe flows.
- Trial eligibility checks for trial-fraud protection.
- Customer payment-method reads for subscription confirmation and buyer portals.
- Buyer-portal proxy helpers so browser code never sees an
sk_*key. - Primitive UI components for status, trial countdowns, and past-due dunning.
Browser usage
Mount the provider with a fetcher that points at your own backend proxy:
'use client';
import { SubscriptionProvider } from '@usethrottle/subscriptions';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<SubscriptionProvider fetcher={(path, init) => fetch(`/api/throttle${path}`, init)}>
{children}
</SubscriptionProvider>
);
}Then use hooks inside your buyer portal:
import {
DunningBanner,
SubscriptionStatusBadge,
useCancelSubscription,
useSubscriptions,
} from '@usethrottle/subscriptions';
export function Subscriptions({ userId }: { userId: string }) {
const { data, isLoading } = useSubscriptions({ externalCustomerId: userId });
const cancel = useCancelSubscription();
if (isLoading) return null;
return data?.data.map((sub) => (
<article key={sub.id}>
<SubscriptionStatusBadge status={sub.status} />
<strong>{sub.planName ?? sub.planReference}</strong>
<DunningBanner subscription={sub} onUpdateCard={() => openUpdateCard(sub)} />
<button onClick={() => cancel.mutate({ id: sub.id, atPeriodEnd: true })}>
Cancel at period end
</button>
</article>
));
}Server proxy helper
For Next.js App Router:
// app/api/throttle/[...path]/route.ts
import { createSubscriptionProxyHandler } from '@usethrottle/subscriptions/server';
import { auth } from '@/lib/auth';
const handler = createSubscriptionProxyHandler({
apiKey: process.env.THROTTLE_SECRET_KEY!,
async getExternalCustomerId() {
const user = await auth();
return user?.id ?? null;
},
});
export { handler as GET, handler as POST, handler as PATCH };The helper allowlists subscription, customer-by-external, trial eligibility, and checkout-session paths. It pins subscription list reads, customer lookups, direct subscription creates, and checkout-session creates to the authenticated buyer's externalCustomerId, and verifies ownership before forwarding subscription mutations.
Payment-method reads are pinned to the authenticated buyer's Throttle customer row.
Server-side API client
You can also use the client directly from backend code:
import { createSubscriptionsClient } from '@usethrottle/subscriptions/server';
const subscriptions = createSubscriptionsClient({
apiKey: process.env.THROTTLE_SECRET_KEY!,
});
await subscriptions.cancel('sub_123', { atPeriodEnd: true });
await subscriptions.listCustomerPaymentMethods('cus_123');create() accepts either a Throttle customerId or your own externalCustomerId. When you pass externalCustomerId, the client resolves the Throttle customer row before calling the subscription create endpoint.
Boundaries
- Customer-scoped browser tokens are not part of v1. Use the proxy helper.
- Payment collection remains in
@usethrottle/checkout-react. - Composite portal layouts are application code; this package ships hooks and primitives.
