# Stripe PaymentIntent API (https://www.getfounderhq.com/docs/analytics/revenue/connect-stripe/payment-intent-api)

Attribute payments from your own payment form, built on PaymentIntents. This
takes about ten minutes.

<Callout title="Before you start">
[Connect Stripe](/analytics/revenue/connect-stripe) first. Install the
[web SDK](/analytics/sdks/web) on your checkout page and the
[Node SDK](/analytics/sdks/node) on your server.
</Callout>

FounderHQ treats the PaymentIntent as the transaction. Put the attribution
metadata on the PaymentIntent itself, not on a charge or an invoice.

## 1. Send the visitor IDs to your server

```tsx
// app/checkout/pay-button.tsx
"use client";

import { founderhq } from "@founderhq/events";

export function PayButton({ amountMinor }: { amountMinor: number }) {
  async function startPayment() {
    const identity = founderhq.checkoutMetadata();
    const response = await fetch("/api/payment-intent", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ amountMinor, identity }),
    });
    const { clientSecret } = await response.json();
    // Hand clientSecret to Stripe Elements as you already do.
    console.log(clientSecret);
  }

  return <button onClick={startPayment}>Pay</button>;
}
```

## 2. Create the PaymentIntent with the metadata

```ts
// app/api/payment-intent/route.ts
import Stripe from "stripe";
import { checkoutMetadata } from "@founderhq/events-node";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

export async function POST(request: Request) {
  const { amountMinor, identity } = await request.json();
  const attribution = checkoutMetadata({
    anonymousId: identity.fhq_anonymous_id,
    sessionId: identity.fhq_session_id,
  });

  const intent = await stripe.paymentIntents.create({
    amount: amountMinor,
    currency: "usd",
    automatic_payment_methods: { enabled: true },
    metadata: attribution,
  });

  return Response.json({ clientSecret: intent.client_secret });
}
```

Amounts are in minor units. `4900` is $49.00.

## 3. Know what a refund does

FounderHQ subtracts a refund only when the individual Refund object reaches
`succeeded`. Partial refunds each subtract their own amount. A pending refund
changes nothing.

## Verify

1. Start a payment on your checkout page.
2. In Stripe, open the PaymentIntent. Its metadata shows `fhq_anonymous_id`
   and `fhq_session_id`.
3. Complete the payment with a test card.
4. In FounderHQ, open Revenue. The payment shows the channel that brought the
   buyer.

## Troubleshoot

### The metadata sits on the charge, not the PaymentIntent

FounderHQ reads the PaymentIntent. Move the metadata to the
`paymentIntents.create` call.

### The payment arrives with no channel

The browser sent empty IDs, or this buyer never loaded a page that runs the
SDK. Check that the checkout page itself loads the web SDK.
