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

# Python/FastAPI Integration

> Take your first payment from a Python or FastAPI app in five minutes — Macropay handles tax, PCI, and disputes as merchant of record.

Macropay is your **merchant of record**: when a customer checks out, Macropay is the legal seller. That means we calculate and remit sales tax and VAT worldwide, keep card data inside a PCI DSS Level 1 compliant vault, and own the chargeback process — so your Python service only ever touches a checkout URL and a webhook.

This guide wires up a working integration end to end: install the SDK, mint a checkout, verify a signed webhook in FastAPI, and read back orders. Budget about five minutes.

## What you'll need

* A [Macropay account](https://macropay.ai/signup) with an organization
* Python 3.9 or newer
* An [organization access token](/integrate/authentication) (the `macropay_oat_…` credential)

<Info>
  Run everything against the [sandbox](https://sandbox.macropay.ai/start) first. It mirrors production behavior — webhooks, signatures, the lot — without moving real money.
</Info>

## 1. Install and authenticate

Pick your package manager:

<CodeGroup>
  ```bash pip theme={null}
  pip install macropay
  ```

  ```bash uv theme={null}
  uv add macropay
  ```

  ```bash poetry theme={null}
  poetry add macropay
  ```
</CodeGroup>

Export your sandbox token and webhook secret so they stay out of source control:

```bash theme={null}
export MACROPAY_ACCESS_TOKEN="macropay_oat_your_token_here"
export MACROPAY_WEBHOOK_SECRET="whsec_your_secret_here"
```

## 2. Initialize the client

Point the client at `sandbox` while you build. The `curl` tab below reuses the same environment variable for the raw-HTTP examples throughout this guide.

<CodeGroup>
  ```py Python theme={null}
  import os

  from macropay import Macropay

  client = Macropay(
      access_token=os.environ["MACROPAY_ACCESS_TOKEN"],
      server="sandbox",
  )
  ```

  ```bash curl theme={null}
  export MACROPAY_ACCESS_TOKEN="macropay_oat_your_token_here"
  # Every curl example below reuses this variable
  ```
</CodeGroup>

## 3. Create a checkout session

Create a product once in the [dashboard](https://macropay.ai) — a one-time license, a monthly plan, whatever you're selling — then generate a hosted checkout per customer. Macropay's hosted page handles card entry, 3-D Secure, tax collection, and localization for you.

<CodeGroup>
  ```py Python theme={null}
  # Sell a "Pro" plan and bounce the buyer back to your app afterward
  checkout = client.checkouts.create(
      product_id="prod_xxx",
      success_url="https://your-app.com/thanks",
  )

  # Redirect the customer to the hosted checkout
  print(f"Send the customer to: {checkout.url}")
  ```

  ```bash curl theme={null}
  curl -X POST https://sandbox-api.macropay.ai/v1/checkouts/ \
    -H "Authorization: Bearer $MACROPAY_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "product_id": "prod_xxx",
      "success_url": "https://your-app.com/thanks"
    }'
  ```
</CodeGroup>

<Tip>
  The `success_url` is only a redirect — never the place to provision access. Tax may still be settling and the payment can fail asynchronously. Treat the **webhook** in the next step as your single source of truth.
</Tip>

## 4. Verify and handle webhooks

Macropay signs every webhook using the [Standard Webhooks](https://www.standardwebhooks.com/) spec, so you can verify authenticity before trusting a payload. Install the verifier:

```bash theme={null}
pip install standardwebhooks
```

Here's a complete FastAPI endpoint that checks the signature, then fans out on event type:

```py theme={null}
# webhook.py
import os

from fastapi import FastAPI, HTTPException, Request
from standardwebhooks.webhooks import Webhook

app = FastAPI()

webhook = Webhook(os.environ["MACROPAY_WEBHOOK_SECRET"])


@app.post("/api/webhooks/macropay")
async def handle_webhook(request: Request):
    body = (await request.body()).decode("utf-8")

    headers = {
        "webhook-id": request.headers.get("webhook-id"),
        "webhook-timestamp": request.headers.get("webhook-timestamp"),
        "webhook-signature": request.headers.get("webhook-signature"),
    }

    try:
        payload = webhook.verify(body, headers)
    except Exception:
        raise HTTPException(status_code=401, detail="Invalid signature")

    event_type = payload["type"]
    data = payload["data"]

    if event_type == "order.paid":
        # Payment cleared — provision the purchase now
        print(f"Order paid: {data['id']}")

    elif event_type == "subscription.created":
        # New recurring customer — grant entitlements
        print(f"Subscription started: {data['id']}")

    elif event_type == "subscription.canceled":
        # Recurring access ended — revoke entitlements
        print(f"Subscription canceled: {data['id']}")

    return {"status": "ok"}
```

<Warning>
  Register the endpoint in the dashboard under **Settings → Webhooks** and copy its signing secret into `MACROPAY_WEBHOOK_SECRET`. For local development, tunnel the route with [ngrok](https://ngrok.com) and point the dashboard at the public URL.
</Warning>

The full catalog of events you can subscribe to lives in the [webhook events reference](/integrate/webhooks/events).

## 5. Read back orders, subscriptions, and customers

With money flowing, query your data directly from the SDK. Amounts are integers in the smallest currency unit (cents), so divide by 100 to display.

<CodeGroup>
  ```py Python theme={null}
  # Recent orders
  orders = client.orders.list()
  for order in orders.result:
      print(f"Order {order.id}: {order.status} — ${order.amount / 100:.2f}")

  # Active subscriptions
  subscriptions = client.subscriptions.list()
  for sub in subscriptions.result:
      print(f"Subscription {sub.id}: {sub.status}")

  # A single customer
  customer = client.customers.get(customer_id="cust_xxx")
  print(f"Customer: {customer.email}")
  ```

  ```bash curl theme={null}
  # Recent orders
  curl https://sandbox-api.macropay.ai/v1/orders/ \
    -H "Authorization: Bearer $MACROPAY_ACCESS_TOKEN"

  # Active subscriptions
  curl https://sandbox-api.macropay.ai/v1/subscriptions/ \
    -H "Authorization: Bearer $MACROPAY_ACCESS_TOKEN"

  # A single customer
  curl https://sandbox-api.macropay.ai/v1/customers/cust_xxx \
    -H "Authorization: Bearer $MACROPAY_ACCESS_TOKEN"
  ```
</CodeGroup>

## 6. Test the full loop in sandbox

<Steps>
  <Step title="Open the checkout">
    Run the script from step 3 and open the returned `checkout.url` in a browser.
  </Step>

  <Step title="Pay with a test card">
    Use `4242 4242 4242 4242` with any future expiry and any CVC, then complete the purchase.
  </Step>

  <Step title="Confirm the webhook">
    Watch your FastAPI logs — an `order.paid` event should arrive and pass signature verification.
  </Step>
</Steps>

## Go to production

When the sandbox loop works, switch over:

| Sandbox                        | Production                                   |
| ------------------------------ | -------------------------------------------- |
| `macropay_oat_…` sandbox token | Production access token                      |
| `server="sandbox"`             | `server="production"` (or omit the argument) |
| `sandbox-api.macropay.ai`      | `api.macropay.ai`                            |
| ngrok webhook URL              | Your production domain                       |

That's the whole footprint. Because Macropay is the merchant of record, there's no separate tax engine to integrate, no PCI questionnaire to fill out, and no dispute workflow to build — those stay on our side of the line.

## Where to go next

<CardGroup cols={2}>
  <Card title="Bill for AI usage" icon="microchip" href="/guides/ai-billing">
    Meter tokens, activity, or agent outcomes and bill on real consumption
  </Card>

  <Card title="Webhook event reference" icon="bell" href="/integrate/webhooks/events">
    Every event type you can subscribe to
  </Card>

  <Card title="Python SDK reference" icon="python" href="/integrate/sdk/python">
    Full method and model documentation
  </Card>

  <Card title="Self-serve customer portal" icon="user" href="/guides/customer-portal">
    Let customers manage plans, invoices, and payment methods
  </Card>
</CardGroup>
