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

# Polar

> Step-by-step guide to setting up Polar checkout and webhooks

Polar gives you a clean, modern checkout experience with great metadata support. The setup is straightforward -- users pay on Polar's checkout page, then Polar tells your app what happened through a webhook. Let's wire it up.

## What you're setting up

Four things to make Polar work:

1. Products inside Polar
2. Checkout links your users can click
3. A webhook endpoint Polar can call
4. A way for the repo to know what each product means

## Env vars

<CodeGroup>
  ```env Required theme={null}
  NEXT_PUBLIC_PAYMENT_PROVIDER=polar
  NEXT_PUBLIC_CHECKOUT_URL_TEMPLATE=https://...
  POLAR_WEBHOOK_SECRET=...
  ```

  ```env Optional checkout URLs theme={null}
  NEXT_PUBLIC_CHECKOUT_URL_PLAN_SMALL=https://...
  NEXT_PUBLIC_CHECKOUT_URL_PLAN_MEDIUM=https://...
  NEXT_PUBLIC_CHECKOUT_URL_PLAN_LARGE=https://...
  NEXT_PUBLIC_CHECKOUT_URL_CREDITS_SMALL=https://...
  NEXT_PUBLIC_CHECKOUT_URL_CREDITS_LARGE=https://...
  ```

  ```env Optional product map theme={null}
  POLAR_PRODUCT_MAP='{"prod_123":"plan-medium","prod_456":"credits-small"}'
  ```
</CodeGroup>

## Setup

<Steps>
  <Step title="Create products in Polar">
    Head to your [Polar dashboard](https://polar.sh/) and create the products you want to sell.

    For your first setup, keep it simple:

    * One **Medium plan** product
    * One **Small credits** product

    Each product will need to map to a repo purchase type like `plan-medium` or `credits-small`.
  </Step>

  <Step title="Create checkout links">
    Once your products are ready, create hosted checkout links in Polar and add them to `.env.local`:

    ```env theme={null}
    NEXT_PUBLIC_CHECKOUT_URL_PLAN_MEDIUM=https://polar.sh/checkout/...
    NEXT_PUBLIC_CHECKOUT_URL_CREDITS_SMALL=https://polar.sh/checkout/...
    ```

    These are the links your app will use for payment buttons.
  </Step>

  <Step title="Tell the repo what each product means">
    You have two ways to do this. Pick whichever you prefer.

    <Tabs>
      <Tab title="Option A: Metadata (recommended)">
        Add a `type` field to your Polar product or order metadata:

        ```text theme={null}
        type=plan-medium
        ```

        The repo reads this directly. It's the cleanest approach because the payment already says what it is.
      </Tab>

      <Tab title="Option B: Product map in env">
        Keep the mapping in your env vars:

        ```env theme={null}
        POLAR_PRODUCT_MAP='{"prod_123":"plan-medium","prod_456":"credits-small"}'
        ```

        This tells the repo which purchase type belongs to each Polar product.
      </Tab>
    </Tabs>
  </Step>

  <Step title="Add the webhook in Polar">
    In your Polar settings, add this webhook endpoint:

    ```text theme={null}
    https://yourdomain.com/api/payments/polar
    ```

    Then copy the webhook secret into your env:

    ```env theme={null}
    POLAR_WEBHOOK_SECRET=...
    ```

    <Warning>
      If the webhook isn't configured, checkout may succeed in Polar but your app will never know about it. That means credits won't be added and purchases won't be stored.
    </Warning>
  </Step>
</Steps>

## How it works under the hood

When Polar sends a successful webhook:

1. The repo verifies the webhook signature
2. It reads the purchase type from metadata or `POLAR_PRODUCT_MAP`
3. It stores the purchase in the `purchases` table
4. It tries to match the purchase to a user (using external customer ID if available)
5. It updates credits or purchase state

## A quick example

Say you want to sell one credits pack through Polar. Here's everything you'd set:

```env theme={null}
NEXT_PUBLIC_PAYMENT_PROVIDER=polar
NEXT_PUBLIC_CHECKOUT_URL_CREDITS_SMALL=https://polar.sh/checkout/...
POLAR_WEBHOOK_SECRET=...
POLAR_PRODUCT_MAP='{"prod_credits_small":"credits-small"}'
```

Now when a user buys that product:

1. The checkout button sends them to Polar
2. Polar charges them
3. Polar calls your webhook
4. The repo recognizes `credits-small`
5. The repo adds the correct number of credits

Pretty straightforward, right?

## Verify your setup

<Check>
  **Your Polar setup is working if all of these are true:**

  * The app opens the Polar checkout page
  * Polar shows a successful webhook delivery
  * A row appears in your `purchases` table
  * A credits purchase increases the user's credits
  * A plan purchase updates the user's access state
</Check>

<AccordionGroup>
  <Accordion title="Created the product but nothing shows in the app">
    You probably forgot to save the checkout URL in your `.env.local` file. Without it, the app can't build payment buttons.
  </Accordion>

  <Accordion title="Checkout works but purchases aren't recorded">
    You configured checkout but forgot the webhook. The webhook is what tells your app the payment happened -- without it, your app is in the dark.
  </Accordion>

  <Accordion title="Webhook fires but purchase type is unknown">
    Make sure you've mapped the Polar product to a valid purchase type, either via metadata or `POLAR_PRODUCT_MAP`. If neither is set, the repo can't determine what was bought.
  </Accordion>

  <Accordion title="Changed env vars but nothing changed">
    Restart your dev server. Next.js doesn't hot-reload environment variable changes.
  </Accordion>

  <Accordion title="Webhook works locally but not in production">
    Check that the webhook URL in Polar points to your production domain, not `localhost` or a dev tunnel URL.
  </Accordion>
</AccordionGroup>

<Card title="Payments Overview" icon="money-bill" href="/payments">
  Go back to the shared payment architecture and basics.
</Card>
