Files
cfw-autumn/apps/docs/mintlify/api-reference/billing/attach.mdx

457 lines
18 KiB
Plaintext

---
title: "Attach"
openapi: "openapi POST /v1/billing.attach"
---
import { DynamicParamField } from "/components/dynamic-param-field.jsx";
import { DynamicResponseField } from "/components/dynamic-response-field.jsx";
import { DynamicResponseExample } from "/components/dynamic-response-example.jsx";
<Note>
The attach endpoint subscribes a customer to a plan. It handles new
subscriptions, upgrades, and downgrades automatically. For modifying an
existing subscription (like changing quantities or canceling), use
[update](/api-reference/billing/billingUpdate) instead.
</Note>
### Common Use Cases
<CodeGroup>
```typescript Subscribe to a plan
const response = await autumn.billing.attach({
customerId: "cus_123",
planId: "pro_plan",
});
if (response.paymentUrl) {
// Redirect customer to checkout
window.location.href = response.paymentUrl;
}
```
```typescript Custom pricing
const response = await autumn.billing.attach({
customerId: "cus_123",
planId: "enterprise_plan",
customize: {
price: {
amount: 999, // $999
interval: "month",
},
},
});
```
```typescript Attach plan with prepaid quantities
const response = await autumn.billing.attach({
customerId: "cus_123",
planId: "team_plan",
featureQuantities: [{ featureId: "seats", quantity: 5 }],
});
```
```typescript Pass metadata to Stripe subscription
const response = await autumn.billing.attach({
customerId: "cus_123",
planId: "pro_plan",
checkoutSessionParams: {
subscriptionData: {
metadata: {
userId: "internal-user-id",
source: "upgrade-flow",
},
},
},
});
```
</CodeGroup>
### Stripe checkout session params
Use `checkoutSessionParams` to pass additional data to the Stripe checkout session. Values you provide are deep-merged with Autumn's internal parameters, so your fields are preserved alongside ones Autumn sets automatically (like `trial_end` or internal metadata).
This is useful for attaching custom metadata to the Stripe subscription created during checkout — for example, linking subscriptions to internal user IDs or tracking the source of the purchase.
### Body Parameters
<DynamicParamField body="customer_id" type="string" required>
The ID of the customer to attach the plan to.
</DynamicParamField>
<DynamicParamField body="entity_id" type="string">
The ID of the entity to attach the plan to.
</DynamicParamField>
<DynamicParamField body="plan_id" type="string" required>
The ID of the plan.
</DynamicParamField>
<DynamicParamField body="feature_quantities" type="object[]">
If this plan contains prepaid features, use this field to specify the quantity of each prepaid feature. This quantity includes the included amount and billing units defined when setting up the plan.
<Expandable title="properties">
<DynamicParamField body="feature_id" type="string" required>
The ID of the feature to set quantity for.
</DynamicParamField>
<DynamicParamField body="quantity" type="number">
The quantity of the feature.
</DynamicParamField>
<DynamicParamField body="adjustable" type="boolean">
Whether the customer can adjust the quantity.
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="version" type="number">
The version of the plan to attach.
</DynamicParamField>
<DynamicParamField body="customize" type="object">
Customize the plan to attach. Can override the price, items, free trial, or a combination.
<Expandable title="properties">
<DynamicParamField body="price" type="object | null">
Base price configuration for a plan.
<Expandable title="properties">
<DynamicParamField body="amount" type="number" required>
Base price amount for the plan.
</DynamicParamField>
<DynamicParamField body="interval" type="'one_off' | 'week' | 'month' | 'quarter' | 'semi_annual' | 'year'" required>
Billing interval (e.g. 'month', 'year').
</DynamicParamField>
<DynamicParamField body="interval_count" type="number">
Number of intervals per billing cycle. Defaults to 1.
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="items" type="object[]">
Override the items in the plan.
<Expandable title="properties">
<DynamicParamField body="feature_id" type="string" required>
The ID of the feature to configure.
</DynamicParamField>
<DynamicParamField body="included" type="number">
Number of free units included. Balance resets to this each interval for consumable features.
</DynamicParamField>
<DynamicParamField body="unlimited" type="boolean">
If true, customer has unlimited access to this feature.
</DynamicParamField>
<DynamicParamField body="reset" type="object">
Reset configuration for consumable features. Omit for non-consumable features like seats.
<Expandable title="properties">
<DynamicParamField body="interval" type="'one_off' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'semi_annual' | 'year'" required>
Interval at which balance resets (e.g. 'month', 'year'). For consumable features only.
</DynamicParamField>
<DynamicParamField body="interval_count" type="number">
Number of intervals between resets. Defaults to 1.
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="price" type="object">
Pricing for usage beyond included units. Omit for free features.
<Expandable title="properties">
<DynamicParamField body="amount" type="number">
Price per billing_units after included usage. Either 'amount' or 'tiers' is required.
</DynamicParamField>
<DynamicParamField body="tiers" type="object[]">
Tiered pricing. Either 'amount' or 'tiers' is required.
<Expandable title="properties">
<DynamicParamField body="to" type="number" required />
<DynamicParamField body="amount" type="number" />
<DynamicParamField body="flat_amount" type="number" />
</Expandable>
</DynamicParamField>
<DynamicParamField body="tier_behavior" type="'graduated' | 'volume'" />
<DynamicParamField body="interval" type="'one_off' | 'week' | 'month' | 'quarter' | 'semi_annual' | 'year'" required>
Billing interval. For consumable features, should match reset.interval.
</DynamicParamField>
<DynamicParamField body="interval_count" type="number">
Number of intervals per billing cycle. Defaults to 1.
</DynamicParamField>
<DynamicParamField body="billing_units" type="number">
Units per price increment. Usage is rounded UP when billed (e.g. billing_units=100 means 101 rounds to 200).
</DynamicParamField>
<DynamicParamField body="billing_method" type="'prepaid' | 'usage_based'" required>
'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go.
</DynamicParamField>
<DynamicParamField body="max_purchase" type="number">
Max units purchasable beyond included. E.g. included=100, max_purchase=300 allows 400 total.
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="proration" type="object">
Proration settings for prepaid features. Controls mid-cycle quantity change billing.
<Expandable title="properties">
<DynamicParamField body="on_increase" type="'bill_immediately' | 'prorate_immediately' | 'prorate_next_cycle' | 'bill_next_cycle'" required>
Billing behavior when quantity increases mid-cycle.
</DynamicParamField>
<DynamicParamField body="on_decrease" type="'prorate' | 'prorate_immediately' | 'prorate_next_cycle' | 'none' | 'no_prorations'" required>
Credit behavior when quantity decreases mid-cycle.
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="rollover" type="object">
Rollover config for unused units. If set, unused included units carry over.
<Expandable title="properties">
<DynamicParamField body="max" type="number">
Max rollover units. Omit for unlimited rollover.
</DynamicParamField>
<DynamicParamField body="max_percentage" type="number">
Maximum rollover as a percentage (0-100) of included + prepaid grant. Mutually exclusive with max.
</DynamicParamField>
<DynamicParamField body="expiry_duration_type" type="'month' | 'forever'" required>
When rolled over units expire.
</DynamicParamField>
<DynamicParamField body="expiry_duration_length" type="number">
Number of periods before expiry.
</DynamicParamField>
</Expandable>
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="free_trial" type="object | null">
Free trial configuration for a plan.
<Expandable title="properties">
<DynamicParamField body="duration_length" type="number" required>
Number of duration_type periods the trial lasts.
</DynamicParamField>
<DynamicParamField body="duration_type" type="'day' | 'month' | 'year'">
Unit of time for the trial ('day', 'month', 'year').
</DynamicParamField>
<DynamicParamField body="card_required" type="boolean">
If true, payment method required to start trial. Customer is charged after trial ends.
</DynamicParamField>
</Expandable>
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="invoice_mode" type="object">
Invoice mode creates a draft or open invoice and sends it to the customer, instead of charging their card immediately. This uses Stripe's send_invoice collection method.
<Expandable title="properties">
<DynamicParamField body="enabled" type="boolean" required>
When true, creates an invoice and sends it to the customer instead of charging their card immediately. Uses Stripe's send_invoice collection method.
</DynamicParamField>
<DynamicParamField body="enable_plan_immediately" type="boolean">
If true, enables the plan immediately even though the invoice is not paid yet.
</DynamicParamField>
<DynamicParamField body="finalize" type="boolean">
If true, finalizes the invoice so it can be sent to the customer. If false, keeps it as a draft for manual review.
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="proration_behavior" type="'prorate_immediately' | 'none'">
How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges.
</DynamicParamField>
<DynamicParamField body="redirect_mode" type="'always' | 'if_required' | 'never'">
Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects.
</DynamicParamField>
<DynamicParamField body="subscription_id" type="string">
A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan.
</DynamicParamField>
<DynamicParamField body="discounts" type="object[]">
List of discounts to apply. Each discount can be an Autumn reward ID, Stripe coupon ID, or Stripe promotion code.
<Expandable title="properties">
<DynamicParamField body="reward_id" type="string">
The ID of the reward to apply as a discount.
</DynamicParamField>
<DynamicParamField body="promotion_code" type="string">
The promotion code to apply as a discount.
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="success_url" type="string">
URL to redirect to after successful checkout.
</DynamicParamField>
<DynamicParamField body="new_billing_subscription" type="boolean">
Only applicable when the customer has an existing Stripe subscription. If true, creates a new separate subscription instead of merging into the existing one.
</DynamicParamField>
<DynamicParamField body="billing_cycle_anchor" type="any">
Reset the billing cycle anchor immediately with 'now'.
</DynamicParamField>
<DynamicParamField body="plan_schedule" type="'immediate' | 'end_of_cycle'">
When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are scheduled.
</DynamicParamField>
<DynamicParamField body="starts_at" type="integer">
Unix timestamp in milliseconds for when the attached plan should start. Future dates create a scheduled subscription.
</DynamicParamField>
<DynamicParamField body="checkout_session_params" type="object">
Additional parameters to pass into the creation of the Stripe checkout session.
</DynamicParamField>
<DynamicParamField body="custom_line_items" type="object[]">
Custom line items that override the auto-generated proration invoice. Only valid for immediate plan changes (eg. upgrades or one off plans).
<Expandable title="properties">
<DynamicParamField body="amount" type="number" required>
Amount in dollars for this line item (e.g. 10.50). Can be negative for credits.
</DynamicParamField>
<DynamicParamField body="description" type="string" required>
Description for the line item.
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="processor_subscription_id" type="string">
The processor subscription ID to link. Use this to attach an existing Stripe subscription instead of creating a new one.
</DynamicParamField>
<DynamicParamField body="carry_over_balances" type="object">
Whether to carry over balances from the previous plan.
<Expandable title="properties">
<DynamicParamField body="enabled" type="boolean" required>
Whether to carry over balances from the previous plan.
</DynamicParamField>
<DynamicParamField body="feature_ids" type="string[]">
The IDs of the features to carry over balances from. If left undefined, all features will be carried over.
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="carry_over_usages" type="object">
Whether to carry over usages from the previous plan.
<Expandable title="properties">
<DynamicParamField body="enabled" type="boolean" required>
Whether to carry over usages from the previous plan.
</DynamicParamField>
<DynamicParamField body="feature_ids" type="string[]">
The IDs of the features to carry over usages for. If left undefined, all consumable features will be carried over.
</DynamicParamField>
</Expandable>
</DynamicParamField>
<DynamicParamField body="metadata.{key}" type="string">
Key-value metadata to attach to the Stripe subscription, invoice, and checkout session created during this attach flow. Keys prefixed with 'autumn_' are reserved and will be stripped.
</DynamicParamField>
<DynamicParamField body="no_billing_changes" type="boolean">
If true, skips any billing changes for the attach operation.
</DynamicParamField>
<DynamicParamField body="enable_plan_immediately" type="boolean">
If true, the customer's plan is activated immediately even when payment is deferred (invoice mode) or pending (Stripe checkout). For Stripe checkout, the customer_product is inserted before the customer completes the hosted form.
</DynamicParamField>
### Response
<DynamicResponseField name="customer_id" type="string">
The ID of the customer.
</DynamicResponseField>
<DynamicResponseField name="entity_id" type="string">
The ID of the entity, if the plan was attached to an entity.
</DynamicResponseField>
<DynamicResponseField name="invoice" type="object">
Invoice details if an invoice was created. Only present when a charge was made.
<Expandable title="properties">
<DynamicResponseField name="status" type="string | null">
The status of the invoice (e.g., 'paid', 'open', 'draft').
</DynamicResponseField>
<DynamicResponseField name="stripe_id" type="string">
The Stripe invoice ID.
</DynamicResponseField>
<DynamicResponseField name="total" type="number">
The total amount of the invoice in cents.
</DynamicResponseField>
<DynamicResponseField name="currency" type="string">
The three-letter ISO currency code (e.g., 'usd').
</DynamicResponseField>
<DynamicResponseField name="hosted_invoice_url" type="string | null">
URL to the hosted invoice page where the customer can view and pay the invoice.
</DynamicResponseField>
</Expandable>
</DynamicResponseField>
<DynamicResponseField name="payment_url" type="string | null">
URL to redirect the customer to complete payment. Null if no payment action is required.
</DynamicResponseField>
<DynamicResponseField name="required_action" type="object">
Details about any action required to complete the payment. Present when the payment could not be processed automatically.
<Expandable title="properties">
<DynamicResponseField name="code" type="'3ds_required' | 'payment_method_required' | 'payment_failed'">
The type of action required to complete the payment.
</DynamicResponseField>
<DynamicResponseField name="reason" type="string">
A human-readable explanation of why this action is required.
</DynamicResponseField>
</Expandable>
</DynamicResponseField>
<ResponseExample>
```json 200
{
"customer_id": "cus_123",
"payment_url": "https://checkout.stripe.com/..."
}
```
</ResponseExample>