# Contracts

Learn how to model negotiated sales agreements with dedicated contract billing.

Use contracts to model negotiated sales agreements that require custom pricing, defined service periods, and mid-deal seat changes while keeping your product catalog clean and avoiding complex [subscription schedules](https://docs.stripe.com/api/subscription_schedules.md).

> This feature is in private preview. You can request early access by filling in the form below.

### Get early access to billing contracts.

Enter your email to request access.

```bash
curl https://docs.stripe.com/preview/register \
  -X POST \
  -H "Content-Type: application/json" \
  -H "Referer: https://docs.stripe.com/billing/contracts" \
  -d '{"email": "EMAIL", "preview": "billing_contracts"}'
```

## Manage contracts in the Dashboard

Use the Dashboard to create, edit, activate, and cancel contracts without writing code. Creating and editing contracts in the Dashboard is in preview and only available in sandboxes. In live mode, you can view contracts, but you can’t create or edit them.

Go to the [Contracts page](https://dashboard.stripe.com/test/contracts) in a sandbox to get started. The Dashboard and API use the same Contract objects, so you can manage a contract with either method.

## Compare contracts and subscriptions

Contracts and [subscriptions](https://docs.stripe.com/api/subscriptions.md) support different billing models and can coexist on the same platform.

|  | Contracts | Subscriptions |
| --- | --- | --- |
| Optimized for | Flexibility, with different terms for each customer | Scale, with the same terms across many customers |
| Pricing | Negotiated rates through overrides on top of catalog pricing | Standard catalog pricing |
| Lifecycle | Defined start and end dates | Recurring with no end date unless canceled |
| Driven by | Sales-led negotiations | Customer self-service |

Contracts and subscriptions use the same [products](https://docs.stripe.com/api/products.md) and [prices](https://docs.stripe.com/api/prices.md). For example, you can reference a product priced at 50 USD per seat per month by both a subscription and a contract, with the contract applying negotiated pricing through overrides.

## Understand how contracts work

Contracts include these building blocks for mapping to a negotiated deal:

- **Pricing lines**: Products from your existing catalog included in the agreement, with quantities and service periods.
- **Pricing overrides**: Negotiated rates that differ from your standard catalog pricing (price override or percentage multiplier).
- **License quantity**: Seat or unit counts that you can change mid-contract period.
- **Billing settings**: Collection method and payment terms specific to the deal.
- **One-time fees**: Fixed charges billed outside the recurring cycle, such as a setup or implementation fee.

### Contracts lifecycle

Contracts move through four statuses:

| Status | Description |
| --- | --- |
| `draft` | Configuration. No billing occurs. |
| `active` | Billing in effect. Invoices generated. |
| `ended` | End date reached. The contract completed its term. |
| `canceled` | Contract canceled before its end date. |

### Create a contract

Create a contract in `draft` status to map your billing cycle to your negotiated sales agreement, then activate it when you’re ready to begin billing.

#### Dashboard

To create a contract in the Dashboard:

1. In a sandbox, go to the [Contracts page](https://dashboard.stripe.com/test/contracts).
2. Click **Create contract**.
3. Enter a contract number, then select a customer and currency.
4. To add a recurring fee, click **Add item**, select an existing product and price, and set the start date, end date, and quantity.
5. To replace a recurring fee’s sticker price, select the fee, click **Schedule price override**, and enter the new amount and the dates it applies to.
6. To apply a discount or markup, click **Add item**, select **Discount** or **Markup**, then enter a percentage and the date range and recurring fees it applies to.
7. Click **Save draft contract**. Stripe saves the contract in `draft` status.

#### API

Create a contract with a pricing line that references an existing product in your catalog:

```curl
curl -X POST https://api.stripe.com/v2/billing/contracts \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-06-24.preview" \
  --json '{
    "currency": "usd",
    "contract_number": "C-2026-0001",
    "pricing_lines": [
        {
            "starts_at": {
                "type": "timestamp",
                "timestamp": "2026-07-01T00:00:00Z"
            },
            "ends_at": {
                "type": "timestamp",
                "timestamp": "2027-07-01T00:00:00Z"
            },
            "pricing": {
                "type": "price",
                "price_details": {
                    "price": "{{PRICE_ID}}",
                    "quantity_changes": [
                        {
                            "effective_at": {
                                "type": "timestamp",
                                "timestamp": "2026-07-01T00:00:00Z"
                            },
                            "set": "12"
                        }
                    ],
                    "pricing_overrides": [
                        {
                            "type": "overwrite_price",
                            "priority": 20,
                            "overwrite_price": {
                                "unit_amount": "100"
                            }
                        }
                    ]
                }
            }
        }
    ],
    "pricing_overrides": [],
    "metadata": {},
    "billing_settings": {
        "billing_profile_details": {
            "customer": "{{CUSTOMER_ID}}"
        },
        "collection_settings_details": {
            "collection_method": "send_invoice"
        },
        "bill_settings_details": {
            "invoice": {
                "time_until_due": {
                    "interval": "month",
                    "interval_count": 1
                }
            }
        }
    }
  }'
```

### Activate a contract

Activate a contract to finalize the draft and create the first invoice when applicable. After activation, the contract `status` changes to `active`.

#### Dashboard

To activate a contract in the Dashboard:

1. Go to the [Contracts page](https://dashboard.stripe.com/test/contracts) and open a draft contract.
2. Click **Activate contract**.
3. Review the amount due and invoice date, then click **Activate contract** to confirm.

#### API

Activate the contract with the following request:

```curl
curl -X POST https://api.stripe.com/v2/billing/contracts/{{BILLINGCONTRACTID_ID}}/activate \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-06-24.preview"
```

### Create a contract with one-time fees

Use one-time fees to bill fixed charges that aren’t tied to the recurring billing cycle, such as setup fees, implementation charges, or one-off professional services. Each one-time fee references a product from your catalog and specifies when to bill.

#### Dashboard

To add a one-time fee when creating a contract in the Dashboard:

1. In the contract editor, click **Add**, then select **One-time fee**.
2. Select an existing product.
3. Enter the **Amount** and **Bill date**.
4. Click **Save draft contract**.

#### API

Include [one-time fees](https://docs.stripe.com/api/v2/billing-contracts/contracts/create.md?api-version=2026-06-24.preview#v2_create_contracts-one_time_fees) when [creating a contract](https://docs.stripe.com/api/v2/billing-contracts/contracts/create.md?api-version=2026-06-24.preview):

```curl
curl -X POST https://api.stripe.com/v2/billing/contracts \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-06-24.preview" \
  --json '{
    "currency": "usd",
    "contract_number": "C-2026-0042",
    "pricing_lines": [
        {
            "starts_at": {
                "type": "timestamp",
                "timestamp": "2026-07-01T00:00:00Z"
            },
            "ends_at": {
                "type": "timestamp",
                "timestamp": "2027-07-01T00:00:00Z"
            },
            "pricing": {
                "type": "price",
                "price_details": {
                    "price": "{{PRICE_ID}}",
                    "quantity_changes": [
                        {
                            "effective_at": {
                                "type": "timestamp",
                                "timestamp": "2026-07-01T00:00:00Z"
                            },
                            "set": "5"
                        }
                    ]
                }
            }
        }
    ],
    "one_time_fees": [
        {
            "product": "{{PRODUCT_ID}}",
            "amount": {
                "value": 50000,
                "currency": "usd"
            },
            "bill_at": {
                "type": "now"
            }
        }
    ],
    "billing_settings": {
        "billing_profile_details": {
            "customer": "{{CUSTOMER_ID}}"
        },
        "collection_settings_details": {
            "collection_method": "send_invoice"
        },
        "bill_settings_details": {
            "invoice": {
                "time_until_due": {
                    "interval": "month",
                    "interval_count": 1
                }
            }
        }
    }
  }'
```

Each one-time fee accepts the following parameters. For full details, see [Create a contract](https://docs.stripe.com/api/v2/billing-contracts/contracts/create.md?api-version=2026-06-24.preview#v2_create_contracts-one_time_fees).

| Parameter | Description |
| --- | --- |
| [product](https://docs.stripe.com/api/v2/billing-contracts/contracts/create.md?api-version=2026-06-24.preview#v2_create_contracts-one_time_fees-product) | The ID of the product for this fee. |
| [amount](https://docs.stripe.com/api/v2/billing-contracts/contracts/create.md?api-version=2026-06-24.preview#v2_create_contracts-one_time_fees-amount) | The amount to bill, with `value` as a non-negative integer in the currency’s [smallest unit](https://docs.stripe.com/currencies.md#minor-units), and `currency` as a three-letter ISO currency code. For example, use `50000` to charge 500 USD. |
| [bill_at](https://docs.stripe.com/api/v2/billing-contracts/contracts/create.md?api-version=2026-06-24.preview#v2_create_contracts-one_time_fees-bill_at) | When to bill this fee. Set `type` to `now` to bill immediately, or `timestamp` with a specific date. |
| [lookup_key](https://docs.stripe.com/api/v2/billing-contracts/contracts/create.md?api-version=2026-06-24.preview#v2_create_contracts-one_time_fees-lookup_key) | An optional user-provided key to identify this fee for later updates or removal. |

To schedule a one-time fee for a future date instead of billing immediately, set `bill_at.type` to `timestamp`:

```curl
curl -X POST https://api.stripe.com/v2/billing/contracts \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-06-24.preview" \
  --json '{
    "currency": "usd",
    "contract_number": "C-2026-0042",
    "one_time_fees": [
        {
            "product": "{{PRODUCT_ID}}",
            "amount": {
                "value": 100000,
                "currency": "usd"
            },
            "bill_at": {
                "type": "timestamp",
                "timestamp": "2026-10-01T00:00:00Z"
            },
            "lookup_key": "implementation_fee"
        }
    ]
  }'
```

### Manage one-time fees on an existing contract

After creating a contract, you can add, update, or remove one-time fees that haven’t been billed.

#### Dashboard

To manage one-time fees in the Dashboard:

1. Go to the [Contracts page](https://dashboard.stripe.com/test/contracts) and open the contract.
2. Click **Edit contract**.
3. To add a fee, click **Add**, select **One-time fee**, and enter its product, amount, and bill date.
4. To change an existing fee, select it in the contract editor and update its details. To remove it, select the fee and click **Remove one-time fee**.
5. Click **Save changes**.

You can’t update or remove a one-time fee that has already been billed on an active contract.

#### API

[Update the contract](https://docs.stripe.com/api/v2/billing-contracts/contracts/update.md?api-version=2026-06-24.preview) with [one_time_fee_actions](https://docs.stripe.com/api/v2/billing-contracts/contracts/update.md?api-version=2026-06-24.preview#v2_update_contracts-one_time_fee_actions) to manage fees.

To add a new one-time fee to an existing contract:

```curl
curl -X POST https://api.stripe.com/v2/billing/contracts/{{BILLINGCONTRACTID_ID}} \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-06-24.preview" \
  --json '{
    "one_time_fee_actions": [
        {
            "type": "add",
            "add": {
                "product": "{{PRODUCT_ID}}",
                "amount": {
                    "value": 25000,
                    "currency": "usd"
                },
                "bill_at": {
                    "type": "now"
                }
            }
        }
    ]
  }'
```

To update an existing one-time fee (by ID or `lookup_key`):

```curl
curl -X POST https://api.stripe.com/v2/billing/contracts/{{BILLINGCONTRACTID_ID}} \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-06-24.preview" \
  --json '{
    "one_time_fee_actions": [
        {
            "type": "update",
            "update": {
                "lookup_key": "implementation_fee",
                "amount": {
                    "value": 150000,
                    "currency": "usd"
                }
            }
        }
    ]
  }'
```

To remove a one-time fee:

```curl
curl -X POST https://api.stripe.com/v2/billing/contracts/{{BILLINGCONTRACTID_ID}} \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-06-24.preview" \
  --json '{
    "one_time_fee_actions": [
        {
            "type": "remove",
            "remove": {
                "lookup_key": "implementation_fee"
            }
        }
    ]
  }'
```

You can’t update or remove a one-time fee that has already been billed on an active contract.

### Cancel a contract

Cancel a contract to end it before the scheduled end date. You can specify whether to generate credit prorations for unused time.

#### Dashboard

To cancel a contract in the Dashboard:

1. Go to the [Contracts page](https://dashboard.stripe.com/test/contracts) and open an active contract.
2. Click the overflow menu (⋯), then select **Cancel contract**.
3. Choose whether to refund the customer for unused time.
4. Click **Cancel contract immediately**.

#### API

Cancel the contract with the following request:

```curl
curl -X POST https://api.stripe.com/v2/billing/contracts/{{BILLINGCONTRACTID_ID}}/cancel \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-06-24.preview" \
  --json '{
    "proration_behavior": "none"
  }'
```

### List invoices for a contract

After activating a contract, Stripe generates [invoices](https://docs.stripe.com/api/invoices.md) according to its pricing and billing terms.

#### Dashboard

To view a contract’s invoices in the Dashboard:

1. Go to the [Contracts page](https://dashboard.stripe.com/test/contracts) and open the contract.
2. Click the **Invoices** tab.
3. Select an invoice to open its invoice details page.

#### API

Use the [contract](https://docs.stripe.com/api/invoices/list.md#list_invoices-contract) parameter to [retrieve all invoices](https://docs.stripe.com/api/invoices/list.md) associated with a specific contract.

```curl
curl -G https://api.stripe.com/v1/invoices \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Version: 2026-06-24.preview" \
  -d "contract={{BILLINGCONTRACTID_ID}}"
```

## Testing

Use [test clocks](https://docs.stripe.com/billing/testing/test-clocks.md) to test your contract setup and simulate the advancement of time. Inspect the invoices and event notifications that Stripe generates as time advances.

### Limitations

Contracts don’t support all subscription features. Notable exceptions include the following.

- **Trials**: Contracts don’t have a trial status. To model a trial period, use pricing overrides to reduce pricing.
- **Discounts**: Contracts don’t support coupons and discounts. To reduce pricing, use pricing overrides.

- **Charge automatically**: Contracts support only `collection_method=send_invoice`. Support for `collection_method=charge_automatically` isn’t enabled for your account.

- **Metered prices**: Contracts only support licensed prices.
