# Stripe codes and credits

Codes used at Stripe Checkout credited without a key, and with a restricted key, coupons, promotion codes and rewards given for you.

If you take payments with Stripe, a friend can use their referrer's code at
Stripe Checkout and the sale is still credited, a friend's discount can be a
real Stripe coupon, and a free month or credit can be given for you. There are
two levels, and the first needs nothing from you.

## Without a key

The integration you connected on the program's **Integration** tab (the signing
secret and the events you send us) already does most of it. Add three events
to the endpoint in Stripe: `promotion_code.created`, `promotion_code.updated`
and `customer.discount.created`.

- When one of your promotion codes in Stripe has the same text as one of the
  program's discount codes (ignoring case), Bolt Claw remembers its id for
  **that program only**. The same code text in another merchant's Stripe never
  credits anybody of yours.
- A `checkout.session.completed` carrying that promotion code, or a subscription
  whose `customer.discount.created` names it, is credited to the code's referrer
  when no link brought the customer first. The link still wins over a code.
- Codes made in Stripe before you connected are matched the first time they are
  used, or paste their `promo_…` ids in the program's **Codes** list.

**Choose Snapshot, not Thin.** Stripe can send events as a full snapshot or as a
thin notice with no data. A thin event carries nothing to credit, so Bolt Claw
answers it `200`, records it, and the Integration tab says
`payload_format: thin` until you switch the endpoint to Snapshot.

## With a restricted key

For coupons, promotion codes and rewards given for you, add a **restricted**
key on the Integration tab's **Codes and credits** card. It is opt-in and you
can remove it at any time; without it, everything falls back to the keyless
behaviour above.

- Only a restricted key is accepted: one that starts `rk_`, live or test. A full
  secret key (one that starts `sk_`) is refused, with the reason: it can do anything in your account,
  and Bolt Claw should never hold that.
- Give it exactly these permissions: **Coupons** write, **Promotion codes**
  write, **Customers** write (balance credit), **Subscriptions** write (free
  periods), **Checkout Sessions** read (line items, for rates per product).
- On save, one harmless read checks it works. It is then sealed, and never
  returned, logged or repeated in an error, not even in part. The card shows
  only whether a key is set, live or test, and since when
  (`codes_and_credits` on the integration).
- It is set and removed in the dashboard only, never through the API: a
  credential should not pass through a script or a chat with an assistant.

What it unlocks:

- **Create codes in Stripe.** One coupon made from the friend's discount rule,
  named so your checkout shows where it came from ("Referral: 20% off for 3
  months"), then a promotion code for every active code of the program. Run it
  from the Codes list, or `POST /v1/referrals/programs/{id}/stripe-codes`. A
  code Stripe already has with the same text is linked, not made again, and
  every call carries an `Idempotency-Key` built from our own id, so running it
  twice makes nothing twice. Deactivating a code here deactivates it there.
- **Rewards given for you**, for sales your Stripe reported (a sale reported through
  the API stays yours to give). A ready `credit` grant becomes a negative balance
  transaction on the customer (credit their next invoice uses); a ready
  `free_period` of months becomes a 100%-off coupon on their subscription for
  that many months, and one of days extends their trial. Each grant is sent to
  Stripe once (`Idempotency-Key: bc-grant-<id>`); anything Stripe refuses comes
  back to your Grants list as `ready` with the reason, in our words.
- **Line items for one-time checkouts**, so a [reward rule](https://boltclaw.ai/docs/rewards) that
  pays per product sees what was bought.

```bash
curl -X POST https://api.boltclaw.ai/v1/referrals/programs/$PROGRAM_ID/stripe-codes \
  -H "Authorization: Bearer $BOLTCLAW_KEY" -H "Idempotency-Key: sync-codes-1"
```

```json
{ "coupon": "bcref-p20-m3", "created": 12, "linked": 3, "failed": 0 }
```

An AI assistant must always ask a person before it does this: it changes what
your customers pay. Without a key, or without a friend's discount rule, the
answer is `409`.

## Errors from Stripe

A Stripe error is never forwarded. Each becomes one fixed sentence: the key was
refused, the key lacks a permission, the object no longer exists, Stripe
refused the request, it already exists, Stripe is limiting requests, or Stripe
could not be reached. What you see on the card or the grant is always one of
those.

<!-- https://boltclaw.ai/docs/referral-stripe-codes as markdown. Generated from openapi.yaml; API version 1.22.0. -->
<!-- Every /docs page answers as markdown: add .md to its path, or send Accept: text/markdown. -->
