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

# Connect Autumn Billing

> Expose the Autumn Fastify handler, authenticate requests, and pass customer metadata to Autumn.

## Overview

Autumn manages products, usage limits, and Stripe checkout on our behalf. The Fastify server only has to expose one proxy route and identify the current customer. Follow the official [Autumn setup guide](https://docs.useautumn.com/setup#dashboard) to configure products and API keys, then wire the identify handler described below to finish the integration.

<Info>
  Autumn automatically provisions customers when it receives a new `customerId`, so we simply forward the 8call user or organization identifier alongside basic profile metadata.
</Info>

## Prerequisites

* `autumn-js` is installed in both the server and web workspaces.
* The `.env` file contains `AUTUMN_SECRET_KEY` for server-side calls and the frontend is wrapped in `<AutumnProvider>`.
* Supabase auth is configured so `getUserFromRequest` can resolve the authenticated profile.

## Register the Fastify handler

<Steps>
  <Step title="Import the handler">
    Add the `autumn-js` Fastify adapter alongside the existing infrastructure imports.

    ```diff theme={null}
    -import fastifyMultipart from '@fastify/multipart';
    +import fastifyMultipart from '@fastify/multipart';
    +import { autumnHandler } from 'autumn-js/fastify';
    ```
  </Step>

  <Step title="Expose `/api/autumn/*`">
    Mount the handler in `apps/server/index.ts` so every GET or POST request under `/api/autumn` is forwarded to Autumn.

    ```215:244:apps/server/index.ts theme={null}
    fastify.route({
      method: ['GET', 'POST'],
      url: '/api/autumn/*',
      handler: autumnHandler({
        identify: async (request) => {
          const typedRequest = request as FastifyRequest & { user?: ProfileAndOrganization };
          const existingUser = typedRequest.user;
          const user = existingUser ?? (await getUserFromRequest(request));

          if (!user || !user.profile) {
            throw handleNotAuthenticated();
          }

          const nameFallbacks = [
            user.profile.display_name,
            [user.profile.first_name, user.profile.last_name].filter(Boolean).join(' ').trim(),
            user.user_metadata?.name,
            user.user_metadata?.full_name,
          ].filter((value) => Boolean(value && `${value}`.trim()));

          return {
            customerId: user.profile.customer_id ?? user.id,
            customerData: {
              name: nameFallbacks[0] ?? undefined,
              email: user.profile.email ?? user.email,
            },
          };
        },
      }),
    });
    ```

    <Tip>
      `customerId` defaults to the user ID if we have not yet synced the Supabase profile’s `customer_id`. Autumn will create the customer automatically on first contact.
    </Tip>
  </Step>
</Steps>

## Verify the proxy

<Tabs>
  <Tab title="Fetch customer state">
    <RequestExample>
      ```bash theme={null}
      curl -X GET "http://localhost:9000/api/autumn/customer" \
        -H "x-user-token: <supabase-session-token>"
      ```
    </RequestExample>

    <ResponseExample>
      ```json Success theme={null}
      {
        "customer": {
          "id": "user_123",
          "products": [...],
          "features": {...}
        }
      }
      ```
    </ResponseExample>
  </Tab>

  <Tab title="Trigger checkout">
    <RequestExample>
      ```bash theme={null}
      curl -X POST "http://localhost:9000/api/autumn/checkout" \
        -H "x-user-token: <supabase-session-token>" \
        -H "Content-Type: application/json" \
        -d '{"productId":"pro"}'
      ```
    </RequestExample>
  </Tab>
</Tabs>

<AccordionGroup>
  <Accordion title="Troubleshooting">
    * **401 Not authenticated**: Ensure the browser sends an `Authorization` or `x-user-token` header so `getUserFromRequest` can fetch the profile.
    * **Missing customer data**: Confirm the Supabase profile includes `customer_id`, or allow Autumn to create one on first request.
    * **CORS errors from Vite dev**: Add `http://localhost:3000` to the Fastify CORS allowlist if you are proxying from the web app.
  </Accordion>
</AccordionGroup>
