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

# Payment Flow

> Hosted checkout pages vs building your own payment flow

## Using hosted pages

By default, `billing.attach` returns a `paymentUrl` — just redirect the customer and Autumn handles payment collection, confirmation, and activation.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const response = await autumn.billing.attach({
    customerId: "user_123",
    planId: "pro",
  });

  redirect(response.paymentUrl);
  ```

  ```tsx React theme={null}
  import { useCustomer } from "autumn-js/react";

  const { attach } = useCustomer();

  await attach({ planId: "pro" });
  ```

  ```python Python theme={null}
  response = await autumn.billing.attach(
      customer_id="user_123",
      plan_id="pro",
  )
  # Redirect to response.payment_url
  ```

  ```bash cURL theme={null}
  curl -X POST 'https://api.useautumn.com/v1/billing.attach' \
    -H 'Authorization: Bearer am_sk_...' \
    -H 'Content-Type: application/json' \
    -d '{
      "customer_id": "user_123",
      "plan_id": "pro"
    }'
  ```
</CodeGroup>

New customers without a payment method are sent to **Stripe Checkout**. Existing customers are sent to **Autumn Checkout** to review and confirm. After checkout, the customer is redirected to your `successUrl` (or the default URL in your Autumn dashboard).

## Building your own checkout

For full control over the checkout experience, use `redirectMode: "if_required"`. This charges the saved payment method directly instead of redirecting — the customer is only sent to Stripe Checkout if they don't have a payment method yet.

```mermaid actions={false} theme={null}
graph LR
  A["previewAttach"] --> B["user confirms"] --> C["attach"] --> D{"Payment method?"}
  D -->|Yes| E["Charged"]
  D -->|No| F["Stripe Checkout"]
  E --> G["Plan enabled"]
  F --> G
  style A fill:#f472b622,stroke:#f472b6
  style C fill:#f472b622,stroke:#f472b6
```

### Step 1: Preview the charge

Call `billing.previewAttach` to get line items, totals, and proration details to display in your UI.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const preview = await autumn.billing.previewAttach({
    customerId: "user_123",
    planId: "pro",
  });

  // preview.lineItems  — array of charges and credits
  // preview.total      — net amount in cents
  // preview.currency   — e.g. "usd"
  ```

  ```tsx React theme={null}
  import { useCustomer } from "autumn-js/react";

  const { previewAttach } = useCustomer();

  const preview = await previewAttach({ planId: "pro" });
  ```

  ```python Python theme={null}
  preview = await autumn.billing.preview_attach(
      customer_id="user_123",
      plan_id="pro",
  )
  ```

  ```bash cURL theme={null}
  curl -X POST 'https://api.useautumn.com/v1/billing.preview_attach' \
    -H 'Authorization: Bearer am_sk_...' \
    -H 'Content-Type: application/json' \
    -d '{
      "customer_id": "user_123",
      "plan_id": "pro"
    }'
  ```
</CodeGroup>

<Expandable title="Example response">
  ```json theme={null}
  {
    "customerId": "user_123",
    "lineItems": [
      {
        "title": "Pro Plan",
        "description": "Monthly subscription",
        "amount": 20
      },
      {
        "title": "Credit for Free Plan",
        "description": "Unused time on current plan",
        "amount": -5
      }
    ],
    "total": 15,
    "currency": "usd",
    "nextCycle": {
      "startsAt": 1735689600000,
      "total": 20
    }
  }
  ```
</Expandable>

### Step 2: Confirm and charge

Once the customer confirms, call `billing.attach` with `redirectMode: "if_required"`.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const response = await autumn.billing.attach({
    customerId: "user_123",
    planId: "pro",
    redirectMode: "if_required",
  });

  if (response.paymentUrl) {
    redirect(response.paymentUrl);
  } else {
    showSuccess();
  }
  ```

  ```tsx React theme={null}
  import { useCustomer } from "autumn-js/react";

  const { attach } = useCustomer();

  const response = await attach({
    planId: "pro",
    redirectMode: "if_required",
  });
  ```

  ```python Python theme={null}
  response = await autumn.billing.attach(
      customer_id="user_123",
      plan_id="pro",
      redirect_mode="if_required",
  )

  if response.payment_url:
      redirect(response.payment_url)
  else:
      show_success()
  ```

  ```bash cURL theme={null}
  curl -X POST 'https://api.useautumn.com/v1/billing.attach' \
    -H 'Authorization: Bearer am_sk_...' \
    -H 'Content-Type: application/json' \
    -d '{
      "customer_id": "user_123",
      "plan_id": "pro",
      "redirect_mode": "if_required"
    }'
  ```
</CodeGroup>

## Handling the response

The `billing.attach` response has two key fields:

**`payment_url`** — a URL the customer should be redirected to, or `null` if no redirect is needed.

**`required_action`** — present when payment couldn't be processed automatically. See [Edge Cases](/documentation/customers/edge-cases) for details on handling 3DS, payment failures, and retries.
