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

# Stripe Billing

> Automatically creates a Stripe Subscription Schedule when a commercial proposal is signed, including one-off setup fees and multi-phase recurring plans.

## Overview

The Stripe Billing integration transforms a signed Qwoty order into a Stripe Subscription Schedule. Each pricing plan phase becomes a Stripe phase with its own items, billing frequency, and duration. One-off charges (setup fees, hardware, onboarding) are attached as invoice items on the first billing cycle. Discounts are applied as native Stripe coupons at the item, phase, or add-invoice-item level.

If the order contains a start delay, the integration automatically creates a trial period of that duration before billing begins.

## Authentication

<Steps>
  <Step title="Access your Stripe Dashboard">
    Go to [dashboard.stripe.com](https://dashboard.stripe.com) and sign in.
  </Step>

  <Step title="Create a restricted API key">
    Navigate to **Developers → API keys → Create restricted key**.

    Grant write access to: **Customers**, **Subscriptions**, **Subscription Schedules**, **Invoices**, **Tax rates**, **Coupons**.
  </Step>

  <Step title="Copy the secret key">
    Copy the key starting with `sk_live_` (or `sk_test_` for testing).
  </Step>

  <Step title="Paste into the integration settings">
    Paste the key into the **Workspace API token** field below.
  </Step>
</Steps>

<Warning>
  If you use multiple Stripe accounts (one per business unit), set **Token scope** to `business_unit` and provide one key per business unit ID.
</Warning>

## Settings

### Authentication

| Key                   | Default     | Description                                                                              |
| --------------------- | ----------- | ---------------------------------------------------------------------------------------- |
| `token_scope`         | `workspace` | `workspace` — one global key. `business_unit` — one key per business unit. **Required.** |
| `workspace_api_token` | —           | Stripe secret key (if `token_scope = workspace`). **Required.**                          |

### Billing

| Key                 | Default                | Description                                                                                                                                                                                                                                                |
| ------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `collection_method` | `charge_automatically` | How Stripe collects payment. `charge_automatically` charges the customer's saved payment method. `send_invoice` sends an invoice by email.                                                                                                                 |
| `days_until_due`    | `30`                   | Days the customer has to pay (only used when `collection_method = send_invoice`).                                                                                                                                                                          |
| `payment_behavior`  | `allow_incomplete`     | Behavior if the first payment fails. `allow_incomplete` — creates the subscription in `incomplete` status. `default_incomplete` — `incomplete` only if payment is required. `error_if_incomplete` — returns an error and does not create the subscription. |

### Taxes

| Key        | Default  | Description                                                                                                                                                           |
| ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tax_mode` | `manual` | `automatic` — Stripe Tax computes tax rates automatically (requires Stripe Tax activation). `manual` — tax rates are taken from the Qwoty order and synced to Stripe. |

<Note>
  When `tax_mode = automatic`, no tax rates from Qwoty are sent to Stripe. Stripe Tax must be configured in your Stripe Dashboard.
</Note>

### Trial

| Key                  | Default          | Description                                                                                                                                                                                     |
| -------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `trial_end_behavior` | `create_invoice` | What happens if the customer has no payment method when the trial ends. `create_invoice` — generates an invoice anyway. `pause` — pauses the subscription. `cancel` — cancels the subscription. |

<Note>
  A trial is created automatically when the order's billing start type is `sign_day` with a `delay_days > 0`. The trial lasts exactly `delay_days` days.
</Note>

### Post-creation

| Key           | Default | Description                                                                                                  |
| ------------- | ------- | ------------------------------------------------------------------------------------------------------------ |
| `post_action` | `none`  | Action after the schedule is created. `none` — nothing. `send_email` — sends a confirmation email via Qwoty. |

## Output

### What gets created in Stripe

**1. Customer** (if not already linked)

The integration looks up the customer by their Qwoty ID (stored in Stripe metadata), then by email. If not found, a new Stripe customer is created and the Stripe ID is written back to Qwoty (`external_ids.accounting`).

**2. Coupons** (one per unique discount amount)

For each discount in the order, the integration looks up an existing Stripe coupon with the ID `qwoty_{orderId}_{amountCents}_{currency}_{duration}` before creating a new one. All Qwoty coupons are prefixed with `qwoty_` for easy identification in your Stripe Dashboard.

**3. Tax rates** (manual mode only)

Tax rates are resolved via `external_ids.accounting` on each tax entry. If not found, the integration searches Stripe by percentage and country, then creates a new tax rate if absent.

**4. Subscription Schedule**

| CPQ source              | Stripe field               | Notes          |
| ----------------------- | -------------------------- | -------------- |
| Customer resolved       | `customer`                 |                |
| `start.type = sign_day` | `start_date = "now"`       |                |
| `start.type = date`     | `start_date`               | Unix timestamp |
| Last phase `forever`    | `end_behavior = "release"` | Auto-renews    |
| Last phase with end     | `end_behavior = "cancel"`  | Cancels at end |
| `order.id`              | `metadata.quote_id`        |                |
| `order.quote_number`    | `metadata.quote_number`    |                |
| `order.opportunity_id`  | `metadata.opportunity_id`  | If set         |

**Phases** — one per CPQ plan phase:

| CPQ source                 | Stripe field | Notes                             |
| -------------------------- | ------------ | --------------------------------- |
| `end.duration`             | `iterations` | Converted to billing cycle count  |
| `end.date`                 | `end_date`   | Unix timestamp                    |
| `end.forever`              | *(absent)*   | Last phase, unlimited             |
| `delay_days > 0` (phase 0) | `trial_end`  | Unix timestamp, now + delay\_days |

**Items per phase** — one per billable line item:

| CPQ source                | Stripe field                   | Notes                       |
| ------------------------- | ------------------------------ | --------------------------- |
| `product.name`            | `price_data.product_data.name` |                             |
| `amounts.unit_price`      | `price_data.unit_amount`       | Gross price × 100 (cents)   |
| `billing_frequency`       | `price_data.recurring`         | interval + interval\_count  |
| `amounts.discount_amount` | `items[M].discounts[0].coupon` | Coupon `duration = forever` |
| Tax resolved              | `default_tax_rates[]`          | Manual mode only            |

**One-off items** (from product sections, added to phase 0):

| CPQ source                | Stripe field                               | Notes                    |
| ------------------------- | ------------------------------------------ | ------------------------ |
| `product.name`            | `price_data.product_data.name`             |                          |
| `amounts.unit_price`      | `price_data.unit_amount`                   | Gross price × 100        |
| `amounts.discount_amount` | `add_invoice_items[M].discounts[0].coupon` | Coupon `duration = once` |
| Global discounts          | `phases[0].discounts[0].coupon`            | Coupon `duration = once` |
| Tax resolved              | `add_invoice_items[M].tax_rates[]`         | Manual mode only         |

### Example — 2-phase subscription with setup fee

A Qwoty order with one setup fee and two 12-month recurring phases produces:

```text theme={null}
Subscription Schedule
├── start_date: now
├── end_behavior: cancel
├── Phase 1 (12 iterations)
│   ├── add_invoice_items
│   │   └── "Setup Fee" — 1 400 € HT
│   └── items
│       └── "Licence Enterprise" — 490 €/month × 10 seats
│           └── coupon: qwoty_xxx_4900_eur_forever (-49 €/month)
└── Phase 2 (12 iterations)
    └── items
        └── "Licence Enterprise" — 590 €/month × 10 seats
```

<Note>
  All prices are sent as gross amounts (HT). Tax is applied by Stripe at invoice generation time, either automatically (Stripe Tax) or via the resolved tax rates.
</Note>
