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

# Saving cards and the customer portal

> Hosted pages for saving a card, paying an invoice and managing billing

Card details never touch your servers. Bouclay hands the customer to hosted pages, and your gateway takes the card there.

## Save a card with a checkout session

A checkout session saves a card through a small verification charge (₦50 for NGN, one major unit in most other currencies). It is refunded automatically once it settles, and the card stays on file.

```bash theme={null}
curl https://bouclay.com/api/v1/checkout-sessions \
  -H "Authorization: Bearer $BOUCLAY_KEY" \
  -H "Idempotency-Key: add-card-user-42-1" \
  -H "Content-Type: application/json" \
  -d '{
    "customer": "ctm_…",
    "setDefault": true,
    "updateSubscriptions": true,
    "returnUrl": "https://yourapp.com/billing"
  }'
```

1. Redirect the customer to `checkoutUrl`.
2. They come back to `returnUrl` with `checkoutSession=<id>&status=complete` (or `status=failed`) added.
3. Treat the query string as a hint. Confirm with `GET /checkout-sessions/{id}`, or wait for `payment_method.created`.

`setDefault` makes the new card the customer's default. `updateSubscriptions` moves their card-paid subscriptions onto it, the way the portal's "update card" does. A subscription with no card of its own charges the customer's default card.

`returnUrl` must be `https`. Plain `http` is accepted only for local addresses such as `localhost` or `*.test`.

## List and remove cards

`GET /customers/{id}/payment-methods` lists saved cards (brand, last four digits, expiry). `DELETE /customers/{id}/payment-methods/{pm}` removes one.

## Hosted invoice pages

Every invoice has a `hostedUrl`, a page where the customer sees the invoice and pays it, and an `invoicePdfUrl`. Link to them from your app or emails. Bouclay's own invoice and reminder emails use them too.

## The customer portal

The portal is a page where your customer manages their own billing: see their subscriptions, update their card, see and pay invoices, download receipts, check their credit, pause or cancel, and edit their billing details (name, billing emails, TIN and address). You don't build any of it.

When the customer clicks **Manage billing** in your app, make a portal session and redirect them:

```bash theme={null}
curl https://bouclay.com/api/v1/portal-sessions \
  -H "Authorization: Bearer $BOUCLAY_KEY" \
  -H "Idempotency-Key: portal-user-42-1730000000" \
  -H "Content-Type: application/json" \
  -d '{"customer": "ctm_…", "returnUrl": "https://yourapp.com/billing"}'
```

Redirect to `data.url`. Don't store it: the link works for 60 minutes. After that, visiting it sends the customer to `returnUrl` so your app can make a fresh one (or answers `410` when there is no `returnUrl`).

Brand the portal, the hosted pages and Bouclay's emails with your logo and colour under **Billing settings → Branding**.

## Cancellation flow

When a customer cancels in the portal, Bouclay can ask why and make an offer to stay, such as a discount for a few months. Set your reasons and offers in the dashboard under **Subscriptions → Cancellation flow**. When you cancel through the API, pass one of those reasons as `reason` (`crsn_…`) and the customer's own words as `comment`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.