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

# Stripe API

> tRPC endpoints for Stripe payments and subscriptions

# Stripe API

Launch provides type-safe tRPC endpoints for all Stripe operations. These endpoints handle payment intents, checkout sessions, and product management.

## Available Endpoints

### `stripe.getProducts`

Fetches all active products and prices from your Stripe account.

```typescript theme={null}
const { data } = trpc.stripe.getProducts.useQuery();

// Returns
{
  products: [
    {
      id: "prod_xxx",
      name: "Pro Yearly",
      description: "Annual subscription",
      prices: [
        { id: "price_xxx", unit_amount: 9999, recurring: { interval: "year" } },
      ],
    },
  ];
}
```

### `stripe.createPaymentIntent`

Creates a payment intent for one-time purchases.

```typescript theme={null}
const mutation = trpc.stripe.createPaymentIntent.useMutation();

const { clientSecret } = await mutation.mutateAsync({
  amount: 999, // Amount in cents
  currency: "usd",
  description: "Pro Lifetime Access",
});
```

### `stripe.createCheckoutSession`

Creates a checkout session for subscriptions.

```typescript theme={null}
const mutation = trpc.stripe.createCheckoutSession.useMutation();

const { url } = await mutation.mutateAsync({
  priceId: "price_xxx",
  mode: "subscription",
  successUrl: "myapp://success",
  cancelUrl: "myapp://cancel",
});
```

### `stripe.getSubscriptionStatus`

Returns the current Stripe subscription for the authenticated user (if any), plus
the local subscription record used for display.

```typescript theme={null}
const { data } = trpc.stripe.getSubscriptionStatus.useQuery();

// Returns
{
  hasSubscription: true,
  subscription: { id: "sub_xxx", status: "active", cancel_at_period_end: false },
  localSubscription: {
    id: "sub_xxx",
    status: "active",
    cancelAtPeriodEnd: false,
    currentPeriodEnd: "2026-01-23T12:34:56.000Z",
  },
}
```

### `stripe.cancelSubscription`

Schedules a subscription to cancel at period end.

```typescript theme={null}
const mutation = trpc.stripe.cancelSubscription.useMutation();
await mutation.mutateAsync();
```

### `stripe.resumeSubscription`

Resumes a subscription that was scheduled to cancel at period end.

```typescript theme={null}
const mutation = trpc.stripe.resumeSubscription.useMutation();
await mutation.mutateAsync();
```

### `stripe.changeSubscriptionPlan`

Switches between subscription prices (monthly ↔ annual). Upgrades take effect
immediately with proration; downgrades take effect at renewal.

```typescript theme={null}
const mutation = trpc.stripe.changeSubscriptionPlan.useMutation();
await mutation.mutateAsync({
  priceId: "price_new",
});
```

## API Structure

**Location:** `apps/api/src/routers/stripe.ts`

```typescript theme={null}
export const stripeRouter = router({
  getProducts: publicProcedure.query(async () => {
    // Fetch products from Stripe
  }),

  createPaymentIntent: protectedProcedure
    .input(
      z.object({
        amount: z.number(),
        currency: z.string(),
        description: z.string().optional(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      // Create payment intent
    }),

  createCheckoutSession: protectedProcedure
    .input(
      z.object({
        priceId: z.string(),
        mode: z.enum(["subscription", "payment"]),
        successUrl: z.string(),
        cancelUrl: z.string(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      // Create checkout session
    }),

  getSubscriptionStatus: protectedProcedure.query(async ({ ctx }) => {
    // Return Stripe subscription and local subscription record
  }),

  cancelSubscription: protectedProcedure.mutation(async ({ ctx }) => {
    // Set cancel_at_period_end to true
  }),

  resumeSubscription: protectedProcedure.mutation(async ({ ctx }) => {
    // Set cancel_at_period_end to false
  }),

  changeSubscriptionPlan: protectedProcedure
    .input(z.object({ priceId: z.string() }))
    .mutation(async ({ input, ctx }) => {
      // Swap subscription price with proration rules
    }),
});
```

## Authentication

* `getProducts` - Public, no authentication required
* `createPaymentIntent` - Protected, requires authenticated user
* `createCheckoutSession` - Protected, requires authenticated user
* `getSubscriptionStatus` - Protected, requires authenticated user
* `cancelSubscription` - Protected, requires authenticated user
* `resumeSubscription` - Protected, requires authenticated user
* `changeSubscriptionPlan` - Protected, requires authenticated user

## Customer Management

When a user makes their first payment, a Stripe customer is automatically created and linked to their account:

```typescript theme={null}
// Automatic customer creation
const customer = await stripe.customers.create({
  email: user.email,
  name: user.name,
  metadata: { userId: user.id },
});
```

## Error Handling

All endpoints return structured errors:

```typescript theme={null}
try {
  await mutation.mutateAsync({ ... });
} catch (error) {
  // error.message contains Stripe error details
  Alert.alert("Payment Failed", error.message);
}
```

## Test Checklist

* `stripe.getProducts` returns products
* `stripe.createPaymentIntent` returns a client secret
* `stripe.createCheckoutSession` returns a valid URL
* `stripe.getSubscriptionStatus` returns subscription info (if subscribed)
* `stripe.cancelSubscription` sets `cancel_at_period_end`
* `stripe.resumeSubscription` clears `cancel_at_period_end`
* `stripe.changeSubscriptionPlan` swaps price with correct proration

## Troubleshooting

If API calls fail, verify Stripe keys in `apps/api/.env` (copy from
`apps/api/example.env` first) and restart the API.

## Remove / Disable

To disable payments while you configure Stripe, set:

`apps/mobile/features/feature-registry.tsx` → `featureFlags.payments = false`

For production removal guidance, see [Removing Features](/essentials/removing-features).

## Next Steps

<CardGroup cols={2}>
  <Card title="Webhooks" icon="webhook" href="/payments/stripe-webhooks">
    Handle asynchronous payment events.
  </Card>

  <Card title="Database Schema" icon="database" href="/payments/database-schema">
    View the database models for payment data.
  </Card>
</CardGroup>
