---
title: Billing Portal
api: POST /auth/billing-portal
description: "Get a Stripe Customer Portal URL for managing subscription, updating payment methods, or reactivating a cancelled account."
---

> **For AI agents:** the complete documentation index is at [llms.txt](https://docs.boringmarketing.com/llms.txt). Append `.md` to any page URL for its markdown version.

Returns a short-lived Stripe Customer Portal URL. Open it in a browser to manage the subscription attached to the caller's account — update payment methods, download invoices, cancel, or **reactivate** a cancelled subscription.

<Note>
This is the only authenticated endpoint a **cancelled** user can reach. All billable endpoints (`/brands/*`, `/track/*`, pipeline triggers, content endpoints) return `403` for cancelled users with a Siren action pointing here. Reactivating through the portal re-enables the account and preserves the original API key — no rotation required.
</Note>

<Note>
**Path split.** The returned `portal_url` is a Stripe-hosted web page — there is no API equivalent.

**If you're a human:** open it directly.

**If you're an agent:** surface the URL to your human operator (email, chat, CLI prompt) and wait for them to complete the action; the portal cannot be driven headlessly. Because the URL expires within minutes, fetch it fresh at the moment of handoff, not ahead of time.
</Note>

## Response

```json
{
  "portal_url": "https://billing.stripe.com/p/session/live_..."
}
```

The URL is generated by Stripe and expires within minutes. Do not cache it — call the endpoint fresh each time the user needs to open the portal.

## Errors

| Status | Meaning |
|---|---|
| `400` | No Stripe customer record attached to this user. This shouldn't happen on a self-serve account — contact support. |
| `401` | Missing or invalid `X-API-Key` header. |
| `502` | Stripe Customer Portal session creation failed (upstream Stripe error). Retry. |

## Example

<CodeGroup>
```bash cURL
curl -X POST \
  -H "X-API-Key: $BM_API_KEY" \
  https://api.boringmarketing.com/auth/billing-portal
```

```python Python
resp = httpx.post(
    "https://api.boringmarketing.com/auth/billing-portal",
    headers={"X-API-Key": api_key},
)
print(resp.json()["portal_url"])
```
</CodeGroup>

## When to call this

- **Upgrading / downgrading tier.** Direct the user to the portal after a `402 upgrade_required` Siren action.
- **Updating payment method.** When a Stripe webhook marks the account `past_due`, surface the portal URL to the user.
- **Reactivating a cancelled subscription.** A cancelled user calling any billable endpoint receives a `403` with `next_actions` pointing at `/auth/billing-portal` and `/auth/checkout`. The portal path preserves the existing account and API key; the checkout path creates a fresh subscription.
- **Downloading invoices.** The portal exposes the full invoice history from Stripe.
