diff --git a/apps/docs/src/app/pages/docs/data/connect.ts b/apps/docs/src/app/pages/docs/data/connect.ts index 8106640..b1646ea 100644 --- a/apps/docs/src/app/pages/docs/data/connect.ts +++ b/apps/docs/src/app/pages/docs/data/connect.ts @@ -17,6 +17,7 @@ import { PAYMENT_LINKS_SUBSECTION } from './payment-links'; import { PRICES_SUBSECTION } from './prices'; import { PRODUCTS_SUBSECTION } from './products'; import { SUBSCRIPTIONS_SUBSECTION } from './subscriptions'; +import { SUBSCRIPTION_ITEMS_SUBSECTION } from './subscription-items'; import { INVOICE_ITEMS_SUBSECTION } from './invoice-items'; import { INVOICES_SUBSECTION } from './invoices'; import { BILLING_SUBSECTION } from './billing'; @@ -64,6 +65,7 @@ export const BILLING_SECTION: DocSection = { INVOICES_SUBSECTION, INVOICE_ITEMS_SUBSECTION, SUBSCRIPTIONS_SUBSECTION, + SUBSCRIPTION_ITEMS_SUBSECTION, ], }; diff --git a/apps/docs/src/app/pages/docs/data/index.ts b/apps/docs/src/app/pages/docs/data/index.ts index afeefd1..388daaf 100644 --- a/apps/docs/src/app/pages/docs/data/index.ts +++ b/apps/docs/src/app/pages/docs/data/index.ts @@ -45,6 +45,7 @@ export * from './connect'; export * from './products'; export * from './prices'; export * from './subscriptions'; +export * from './subscription-items'; export * from './invoice-items'; export * from './invoices'; export * from './billing'; diff --git a/apps/docs/src/app/pages/docs/data/subscription-items.ts b/apps/docs/src/app/pages/docs/data/subscription-items.ts new file mode 100644 index 0000000..592d4d7 --- /dev/null +++ b/apps/docs/src/app/pages/docs/data/subscription-items.ts @@ -0,0 +1,1029 @@ +import { DocSubSection, DocPage, Attribute } from './types'; +import { NODE_INIT, EXPAND_TOOLTIP, BuildEndpointSummaries } from './shared'; +import { GetResourceEventAttributes } from './event-types'; + +export const SUBSCRIPTION_ITEMS_SUBSECTION: DocSubSection = { + id: 'subscriptionitems', + title: 'Subscription Items', + children: [ + { id: 'object', title: 'The Subscription Item object' }, + { id: 'create', title: 'Create a subscription item' }, + { id: 'update', title: 'Update a subscription item' }, + { id: 'retrieve', title: 'Retrieve a subscription item' }, + { id: 'list', title: 'List all subscription items' }, + { id: 'delete', title: 'Delete a subscription item' }, + ], +}; + +// ============================================ +// Shared helpers +// ============================================ + +const DISCOUNT_PARAM_CHILDREN: Attribute[] = [ + { + name: 'coupon', + type: 'string', + description: 'ID of the coupon to create a new discount for.', + }, + { + name: 'discount', + type: 'string', + description: + 'ID of an existing discount on the object (or one of its ancestors) to reuse.', + }, + { + name: 'promotion_code', + type: 'string', + description: 'ID of the promotion code to create a new discount for.', + }, +]; + +const BILLING_THRESHOLD_CHILDREN: Attribute[] = [ + { + name: 'usage_gte', + type: 'integer', + description: + 'Usage threshold that triggers the subscription to create an invoice.', + }, +]; + +const PRICE_DATA_CHILDREN: Attribute[] = [ + { + name: 'currency', + type: 'enum', + required: true, + description: + 'Three-letter currency code, in lowercase. For Zoneless, use usdc.', + enumNote: + 'Difference from Stripe: Use usdc instead of fiat currency codes like usd.', + }, + { + name: 'product', + type: 'string', + required: true, + description: 'The ID of the product that this price will belong to.', + }, + { + name: 'recurring', + type: 'object', + required: true, + description: + 'The recurring components of the price. A subscription item always bills on a recurring price, so this is required here.', + children: [ + { + name: 'interval', + type: 'enum', + required: true, + description: + 'Specifies billing frequency. Either day, week, month or year.', + enumValues: [ + { value: 'day', description: 'Billed daily.' }, + { value: 'week', description: 'Billed weekly.' }, + { value: 'month', description: 'Billed monthly.' }, + { value: 'year', description: 'Billed yearly.' }, + ], + }, + { + name: 'interval_count', + type: 'integer', + description: + 'The number of intervals between subscription billings. For example, interval=month with interval_count=3 bills every 3 months.', + }, + ], + }, + { + name: 'tax_behavior', + type: 'enum', + description: + 'Specifies whether the price is considered inclusive of taxes or exclusive of taxes. One of inclusive, exclusive, or unspecified. Once specified as either inclusive or exclusive, it cannot be changed.', + enumValues: [ + { value: 'exclusive' }, + { value: 'inclusive' }, + { value: 'unspecified' }, + ], + }, + { + name: 'unit_amount', + type: 'integer', + description: + 'A positive integer in the smallest currency unit representing how much to charge. For USDC, this is cents (e.g., 100 = $1 USDC).', + }, + { + name: 'unit_amount_decimal', + type: 'string', + required: true, + requiredText: 'Required unless unit_amount is provided', + description: + 'Same as unit_amount, but accepts a decimal value in the smallest currency unit with at most 12 decimal places. Only one of unit_amount and unit_amount_decimal can be set.', + }, +]; + +// ============================================ +// Shared Data +// ============================================ + +const SUBSCRIPTION_ITEM_OBJECT_JSON = `{ + "id": "si_z_9Km2pQxR4vL8nHw", + "object": "subscription_item", + "billed_until": null, + "billing_thresholds": null, + "created": 1784745601, + "current_period_end": 1787424000, + "current_period_start": 1784745600, + "discounts": [], + "metadata": {}, + "price": { + "id": "price_z_ProMonthly25", + "object": "price", + "active": true, + "billing_scheme": "per_unit", + "created": 1784745600, + "currency": "usdc", + "custom_unit_amount": null, + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": "Pro Plan Price", + "product": "prod_z_oJaYlHpf6YmRzCMm", + "recurring": { + "aggregate_usage": null, + "interval": "month", + "interval_count": 1, + "trial_period_days": null, + "usage_type": "licensed" + }, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "recurring", + "unit_amount": 1000, + "unit_amount_decimal": "1000" + }, + "quantity": 1, + "subscription": "sub_z_1QvK9mR2eZvKYlo2CxH4pN8w", + "tax_rates": [], + "platform_account": "acct_z_Platform123abc" +}`; + +const SUBSCRIPTION_ITEM_UPDATED_JSON = `{ + "id": "si_z_9Km2pQxR4vL8nHw", + "object": "subscription_item", + "billed_until": null, + "billing_thresholds": null, + "created": 1784745601, + "current_period_end": 1787424000, + "current_period_start": 1784745600, + "discounts": [], + "metadata": { + "order_id": "9284" + }, + "price": { + "id": "price_z_ProMonthly25", + "object": "price", + "active": true, + "billing_scheme": "per_unit", + "created": 1784745600, + "currency": "usdc", + "custom_unit_amount": null, + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": "Pro Plan Price", + "product": "prod_z_oJaYlHpf6YmRzCMm", + "recurring": { + "aggregate_usage": null, + "interval": "month", + "interval_count": 1, + "trial_period_days": null, + "usage_type": "licensed" + }, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "recurring", + "unit_amount": 1000, + "unit_amount_decimal": "1000" + }, + "quantity": 3, + "subscription": "sub_z_1QvK9mR2eZvKYlo2CxH4pN8w", + "tax_rates": [], + "platform_account": "acct_z_Platform123abc" +}`; + +const SUBSCRIPTION_ITEM_DELETED_JSON = `{ + "id": "si_z_9Km2pQxR4vL8nHw", + "object": "subscription_item", + "deleted": true +}`; + +const LIST_SUBSCRIPTION_ITEMS_RESPONSE_JSON = `{ + "object": "list", + "url": "/v1/subscription_items", + "has_more": false, + "data": [ + { + "id": "si_z_9Km2pQxR4vL8nHw", + "object": "subscription_item", + "billed_until": null, + "billing_thresholds": null, + "created": 1784745601, + "current_period_end": 1787424000, + "current_period_start": 1784745600, + "discounts": [], + "metadata": {}, + "price": { + "id": "price_z_ProMonthly25", + "object": "price", + "active": true, + "billing_scheme": "per_unit", + "created": 1784745600, + "currency": "usdc", + "custom_unit_amount": null, + "livemode": false, + "lookup_key": null, + "metadata": {}, + "nickname": "Pro Plan Price", + "product": "prod_z_oJaYlHpf6YmRzCMm", + "recurring": { + "aggregate_usage": null, + "interval": "month", + "interval_count": 1, + "trial_period_days": null, + "usage_type": "licensed" + }, + "tax_behavior": "unspecified", + "tiers_mode": null, + "transform_quantity": null, + "type": "recurring", + "unit_amount": 1000, + "unit_amount_decimal": "1000" + }, + "quantity": 1, + "subscription": "sub_z_1QvK9mR2eZvKYlo2CxH4pN8w", + "tax_rates": [], + "platform_account": "acct_z_Platform123abc" + } + ] +}`; + +// ============================================ +// Object Attributes +// ============================================ + +const SUBSCRIPTION_ITEM_ATTRIBUTES: Attribute[] = [ + { + name: 'id', + type: 'string', + description: + 'Unique identifier for the object. Zoneless subscription item IDs are prefixed with si_z_.', + }, + { + name: 'metadata', + type: 'object', + description: + 'Set of key-value pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format.', + }, + { + name: 'price', + type: 'string', + tooltip: EXPAND_TOOLTIP, + description: + 'The price the customer is subscribed to. Use expand[]=price to return the full price object.', + }, + { + name: 'quantity', + type: 'integer', + nullable: true, + description: + 'The quantity of the plan to which the customer should be subscribed. Defaults to 1 when the item is created.', + }, + { + name: 'subscription', + type: 'string', + description: + 'The subscription this subscription_item belongs to.', + }, +]; + +const SUBSCRIPTION_ITEM_MORE_ATTRIBUTES: Attribute[] = [ + { + name: 'object', + type: 'string', + description: + "String representing the object's type. Objects of the same type share the same value.", + }, + { + name: 'billed_until', + type: 'timestamp', + nullable: true, + description: + 'The time period the subscription item has been billed for. Zoneless bills through the parent subscription, so this stays null.', + }, + { + name: 'billing_thresholds', + type: 'object', + nullable: true, + description: + 'Define thresholds at which an invoice will be sent for this subscription item.', + children: BILLING_THRESHOLD_CHILDREN, + }, + { + name: 'created', + type: 'timestamp', + description: + 'Time at which the object was created. Measured in seconds since the Unix epoch.', + }, + { + name: 'current_period_end', + type: 'timestamp', + description: + "The end time of this subscription item's current billing period. Follows the parent subscription's billing cycle and the interval on the item's price.", + }, + { + name: 'current_period_start', + type: 'timestamp', + description: + "The start time of this subscription item's current billing period. Set from the parent subscription's billing cycle anchor.", + }, + { + name: 'discounts', + type: 'array of strings', + description: + 'The discounts applied to the subscription item, as discount IDs. Item discounts are applied before subscription discounts.', + }, + { + name: 'tax_rates', + type: 'array of strings', + nullable: true, + description: + 'The tax rates which apply to this subscription item. When set, the default_tax_rates on the subscription do not apply to this item.', + }, + { + name: 'platform_account', + type: 'string', + description: + "The platform account that owns this resource. For connected account resources, this is the platform's account ID. For the platform's own resources, this equals the account field (self-referential).", + enumNote: + "Zoneless extension: This field is not present in Stripe's API. It enables multi-tenant operation.", + }, +]; + +// ============================================ +// Overview +// ============================================ + +export const SUBSCRIPTION_ITEMS_OVERVIEW_PAGE: DocPage = { + id: 'object', + title: 'The Subscription Item object', + description: + 'Subscription items let a subscription hold more than one price. Each item pairs a price with a quantity, and the subscription bills for all of its items on the same cycle. Items are also added and changed through the items parameter on Subscription create and update.', + stripeDocsUrl: 'https://docs.stripe.com/api/subscription_items', + endpoints: BuildEndpointSummaries(SUBSCRIPTION_ITEMS_SUBSECTION, [ + { method: 'POST', path: '/v1/subscription_items', pageId: 'create' }, + { method: 'POST', path: '/v1/subscription_items/:id', pageId: 'update' }, + { method: 'GET', path: '/v1/subscription_items/:id', pageId: 'retrieve' }, + { method: 'GET', path: '/v1/subscription_items', pageId: 'list' }, + { method: 'DELETE', path: '/v1/subscription_items/:id', pageId: 'delete' }, + ]), + events: GetResourceEventAttributes('subscription_item'), + sections: [ + { + left: [ + { + type: 'callout', + variant: 'info', + title: 'Key concept: ', + text: 'Adding, changing or removing an item emits customer.subscription.updated on the parent subscription. Zoneless does not emit subscription_item.* events.', + html: true, + }, + { type: 'heading', level: 2, text: 'Attributes' }, + { + type: 'attributes', + attributes: SUBSCRIPTION_ITEM_ATTRIBUTES, + moreAttributes: SUBSCRIPTION_ITEM_MORE_ATTRIBUTES, + }, + ], + right: [ + { + type: 'object', + title: 'THE SUBSCRIPTION ITEM OBJECT', + code: SUBSCRIPTION_ITEM_OBJECT_JSON, + }, + ], + }, + ], +}; + +// ============================================ +// Create +// ============================================ + +const CREATE_SUBSCRIPTION_ITEM_PARAMETERS: Attribute[] = [ + { + name: 'subscription', + type: 'string', + required: true, + description: 'The identifier of the subscription to modify.', + }, + { + name: 'metadata', + type: 'object', + description: + 'Set of key-value pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format.', + }, + { + name: 'payment_behavior', + type: 'enum', + description: + 'Controls how to handle payment when a subscription update requires payment and collection_method=charge_automatically.', + enumValues: [ + { + value: 'allow_incomplete', + description: + 'Transition the subscription to past_due if payment fails.', + }, + { + value: 'default_incomplete', + description: + 'Transition the subscription to past_due without attempting payment.', + }, + { + value: 'error_if_incomplete', + description: + 'Return an HTTP 402 error and do not update the subscription.', + }, + { + value: 'pending_if_incomplete', + description: + 'Create a pending update that applies only if the payment succeeds.', + }, + ], + enumNote: + 'Difference from Stripe: Zoneless adds the item immediately and does not attempt a payment for it, so this parameter has no effect.', + }, + { + name: 'price', + type: 'string', + required: true, + requiredText: 'Required unless price_data is provided', + description: 'The ID of the price object.', + }, + { + name: 'proration_behavior', + type: 'enum', + description: + 'Determines how to handle prorations when the billing cycle changes or when an item quantity changes. Defaults to create_prorations.', + enumValues: [ + { value: 'always_invoice' }, + { value: 'create_prorations' }, + { value: 'none' }, + ], + enumNote: + 'Difference from Stripe: Zoneless does not create proration invoice items, so this value is accepted and ignored.', + }, + { + name: 'quantity', + type: 'integer', + description: + "The quantity you'd like to apply to the subscription item you're creating. Defaults to 1.", + }, +]; + +const CREATE_SUBSCRIPTION_ITEM_MORE_PARAMETERS: Attribute[] = [ + { + name: 'billing_thresholds', + type: 'object', + description: + 'Define thresholds at which an invoice will be sent for this item. Pass an empty string to remove previously-defined thresholds.', + expandable: true, + children: BILLING_THRESHOLD_CHILDREN, + }, + { + name: 'discounts', + type: 'array of objects', + description: + 'The coupons and promotion codes to redeem into discounts for the subscription item. Exactly one of coupon, discount, or promotion_code must be specified per entry.', + expandable: true, + children: DISCOUNT_PARAM_CHILDREN, + }, + { + name: 'price_data', + type: 'object', + description: + 'Data used to generate a new Price object inline. Unlike invoice item price_data, recurring is required.', + expandable: true, + children: PRICE_DATA_CHILDREN, + }, + { + name: 'proration_date', + type: 'timestamp', + description: + 'Only used when proration_behavior creates prorations. Zoneless does not create prorations, so this value is accepted and ignored.', + }, + { + name: 'tax_rates', + type: 'array of strings', + description: + 'The tax rates which apply to the subscription item. When set, the default_tax_rates on the subscription do not apply to this item.', + }, +]; + +export const SUBSCRIPTION_ITEMS_CREATE_PAGE: DocPage = { + id: 'create', + title: 'Create a subscription item', + description: + 'Adds a new item to an existing subscription. No existing items will be changed or replaced.', + stripeDocsUrl: 'https://docs.stripe.com/api/subscription_items/create', + endpoints: [{ method: 'POST', path: '/v1/subscription_items' }], + sections: [ + { + left: [ + { type: 'heading', level: 2, text: 'Parameters' }, + { + type: 'attributes', + attributes: CREATE_SUBSCRIPTION_ITEM_PARAMETERS, + moreAttributes: CREATE_SUBSCRIPTION_ITEM_MORE_PARAMETERS, + }, + { type: 'heading', level: 2, text: 'Returns' }, + { + type: 'paragraph', + text: 'The created subscription item object is returned if successful. Otherwise, this call raises an error.', + }, + ], + right: [ + { + type: 'code', + endpoint: { method: 'POST', path: '/v1/subscription_items' }, + tabs: [ + { + id: 'curl', + label: 'cURL', + code: `curl https://api.yourdomain.com/v1/subscription_items \\ + -H "x-api-key: sk_live_z_YOUR_API_KEY" \\ + -d subscription=sub_z_1QvK9mR2eZvKYlo2CxH4pN8w \\ + -d price=price_z_ProMonthly25 \\ + -d quantity=3`, + }, + { + id: 'node', + label: 'Node.js', + code: `${NODE_INIT} + +const subscriptionItem = await zoneless.subscriptionItems.create({ + subscription: 'sub_z_1QvK9mR2eZvKYlo2CxH4pN8w', + price: 'price_z_ProMonthly25', + quantity: 3, +});`, + }, + ], + }, + { + type: 'object', + title: 'RESPONSE', + code: SUBSCRIPTION_ITEM_OBJECT_JSON, + }, + ], + }, + ], +}; + +// ============================================ +// Update +// ============================================ + +const UPDATE_SUBSCRIPTION_ITEM_PARAMETERS: Attribute[] = [ + { + name: 'metadata', + type: 'object', + description: + 'Set of key-value pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format. Individual keys can be unset by posting an empty value to them. All keys can be unset by posting an empty value to metadata.', + }, + { + name: 'payment_behavior', + type: 'enum', + description: + 'Controls how to handle payment when a subscription update requires payment and collection_method=charge_automatically.', + enumValues: [ + { + value: 'allow_incomplete', + description: + 'Transition the subscription to past_due if payment fails.', + }, + { + value: 'default_incomplete', + description: + 'Transition the subscription to past_due without attempting payment.', + }, + { + value: 'error_if_incomplete', + description: + 'Return an HTTP 402 error and do not update the subscription.', + }, + { + value: 'pending_if_incomplete', + description: + 'Create a pending update that applies only if the payment succeeds.', + }, + ], + enumNote: + 'Difference from Stripe: Zoneless applies the change immediately and does not attempt a payment for it, so this parameter has no effect.', + }, + { + name: 'price', + type: 'string', + description: + 'The ID of the price object. Changing the price resets quantity to 1 unless the same request sends a quantity.', + }, + { + name: 'proration_behavior', + type: 'enum', + description: + 'Determines how to handle prorations when the billing cycle changes or when an item quantity changes. Defaults to create_prorations.', + enumValues: [ + { value: 'always_invoice' }, + { value: 'create_prorations' }, + { value: 'none' }, + ], + enumNote: + 'Difference from Stripe: Zoneless does not create proration invoice items, so this value is accepted and ignored.', + }, + { + name: 'quantity', + type: 'integer', + description: + 'The quantity you would like to apply to the subscription item.', + }, +]; + +const UPDATE_SUBSCRIPTION_ITEM_MORE_PARAMETERS: Attribute[] = [ + { + name: 'billing_thresholds', + type: 'object', + description: + 'Define thresholds at which an invoice will be sent for this item. Pass an empty string to remove previously-defined thresholds.', + expandable: true, + children: BILLING_THRESHOLD_CHILDREN, + }, + { + name: 'discounts', + type: 'array of objects', + description: + 'The coupons, promotion codes and existing discounts which apply to the subscription item. Item discounts are applied before subscription discounts. Pass an empty string to remove previously-defined discounts. Exactly one of coupon, discount, or promotion_code must be specified per entry.', + expandable: true, + children: DISCOUNT_PARAM_CHILDREN, + }, + { + name: 'off_session', + type: 'boolean', + description: + 'Indicates that you intend to make future payments with the payment method collected for this subscription. Zoneless does not charge the item change, so this value is accepted and ignored.', + }, + { + name: 'price_data', + type: 'object', + description: + 'Data used to generate a new Price object inline. Unlike invoice item price_data, recurring is required.', + expandable: true, + children: PRICE_DATA_CHILDREN, + }, + { + name: 'proration_date', + type: 'timestamp', + description: + 'Only used when proration_behavior creates prorations. Zoneless does not create prorations, so this value is accepted and ignored.', + }, + { + name: 'tax_rates', + type: 'array of strings', + description: + 'The tax rates which apply to the subscription item. When set, the default_tax_rates on the subscription do not apply to this item. Pass an empty string to remove previously-defined tax rates.', + }, +]; + +export const SUBSCRIPTION_ITEMS_UPDATE_PAGE: DocPage = { + id: 'update', + title: 'Update a subscription item', + description: + 'Updates the price or quantity of an item on a current subscription. Metadata is merged into the values already on the item; every other field is replaced.', + stripeDocsUrl: 'https://docs.stripe.com/api/subscription_items/update', + endpoints: [{ method: 'POST', path: '/v1/subscription_items/:id' }], + sections: [ + { + left: [ + { type: 'heading', level: 2, text: 'Parameters' }, + { + type: 'attributes', + attributes: UPDATE_SUBSCRIPTION_ITEM_PARAMETERS, + moreAttributes: UPDATE_SUBSCRIPTION_ITEM_MORE_PARAMETERS, + }, + { type: 'heading', level: 2, text: 'Returns' }, + { + type: 'paragraph', + text: 'The updated subscription item object is returned upon success. Otherwise, this call raises an error.', + }, + ], + right: [ + { + type: 'code', + endpoint: { method: 'POST', path: '/v1/subscription_items/:id' }, + tabs: [ + { + id: 'curl', + label: 'cURL', + code: `curl https://api.yourdomain.com/v1/subscription_items/si_z_9Km2pQxR4vL8nHw \\ + -H "x-api-key: sk_live_z_YOUR_API_KEY" \\ + -d quantity=3`, + }, + { + id: 'node', + label: 'Node.js', + code: `${NODE_INIT} + +const subscriptionItem = await zoneless.subscriptionItems.update( + 'si_z_9Km2pQxR4vL8nHw', + { + quantity: 3, + } +);`, + }, + ], + }, + { + type: 'object', + title: 'RESPONSE', + code: SUBSCRIPTION_ITEM_UPDATED_JSON, + }, + ], + }, + ], +}; + +// ============================================ +// Retrieve +// ============================================ + +export const SUBSCRIPTION_ITEMS_RETRIEVE_PAGE: DocPage = { + id: 'retrieve', + title: 'Retrieve a subscription item', + description: 'Retrieves the subscription item with the given ID.', + stripeDocsUrl: 'https://docs.stripe.com/api/subscription_items/retrieve', + endpoints: [{ method: 'GET', path: '/v1/subscription_items/:id' }], + sections: [ + { + left: [ + { type: 'heading', level: 2, text: 'Parameters' }, + { type: 'paragraph', text: 'No parameters.' }, + { type: 'heading', level: 2, text: 'Returns' }, + { + type: 'paragraph', + text: 'Returns a subscription item if a valid subscription item ID was provided. Raises an error otherwise.', + }, + ], + right: [ + { + type: 'code', + endpoint: { method: 'GET', path: '/v1/subscription_items/:id' }, + tabs: [ + { + id: 'curl', + label: 'cURL', + code: `curl https://api.yourdomain.com/v1/subscription_items/si_z_9Km2pQxR4vL8nHw \\ + -H "x-api-key: sk_live_z_YOUR_API_KEY"`, + }, + { + id: 'node', + label: 'Node.js', + code: `${NODE_INIT} + +const subscriptionItem = await zoneless.subscriptionItems.retrieve( + 'si_z_9Km2pQxR4vL8nHw' +);`, + }, + ], + }, + { + type: 'object', + title: 'RESPONSE', + code: SUBSCRIPTION_ITEM_OBJECT_JSON, + }, + ], + }, + ], +}; + +// ============================================ +// List +// ============================================ + +const LIST_SUBSCRIPTION_ITEMS_PARAMETERS: Attribute[] = [ + { + name: 'subscription', + type: 'string', + required: true, + description: + 'The identifier of the subscription whose items to return. This parameter is required.', + }, + { + name: 'limit', + type: 'integer', + description: + 'A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10.', + }, +]; + +const LIST_SUBSCRIPTION_ITEMS_MORE_PARAMETERS: Attribute[] = [ + { + name: 'ending_before', + type: 'string', + description: + 'A cursor for use in pagination. ending_before is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with si_z_bar, your subsequent call can include ending_before=si_z_bar in order to fetch the previous page of the list.', + }, + { + name: 'starting_after', + type: 'string', + description: + 'A cursor for use in pagination. starting_after is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with si_z_foo, your subsequent call can include starting_after=si_z_foo in order to fetch the next page of the list.', + }, +]; + +export const SUBSCRIPTION_ITEMS_LIST_PAGE: DocPage = { + id: 'list', + title: 'List all subscription items', + description: + 'Returns the items on a subscription. Items are returned sorted by creation date, with the earliest created items appearing first.', + stripeDocsUrl: 'https://docs.stripe.com/api/subscription_items/list', + endpoints: [{ method: 'GET', path: '/v1/subscription_items' }], + sections: [ + { + left: [ + { type: 'heading', level: 2, text: 'Parameters' }, + { + type: 'attributes', + attributes: LIST_SUBSCRIPTION_ITEMS_PARAMETERS, + moreAttributes: LIST_SUBSCRIPTION_ITEMS_MORE_PARAMETERS, + }, + { type: 'heading', level: 2, text: 'Returns' }, + { + type: 'paragraph', + text: 'A dictionary with a data property that contains an array of up to limit subscription items, starting after subscription item starting_after. Each entry in the array is a separate subscription item object. If no more items are available, the resulting array will be empty.', + html: true, + }, + ], + right: [ + { + type: 'code', + endpoint: { method: 'GET', path: '/v1/subscription_items' }, + tabs: [ + { + id: 'curl', + label: 'cURL', + code: `curl -G https://api.yourdomain.com/v1/subscription_items \\ + -H "x-api-key: sk_live_z_YOUR_API_KEY" \\ + -d subscription=sub_z_1QvK9mR2eZvKYlo2CxH4pN8w \\ + -d limit=3`, + }, + { + id: 'node', + label: 'Node.js', + code: `${NODE_INIT} + +const subscriptionItems = await zoneless.subscriptionItems.list({ + subscription: 'sub_z_1QvK9mR2eZvKYlo2CxH4pN8w', + limit: 3, +});`, + }, + ], + }, + { + type: 'object', + title: 'RESPONSE', + code: LIST_SUBSCRIPTION_ITEMS_RESPONSE_JSON, + }, + ], + }, + ], +}; + +// ============================================ +// Delete +// ============================================ + +const DELETE_SUBSCRIPTION_ITEM_PARAMETERS: Attribute[] = [ + { + name: 'clear_usage', + type: 'boolean', + description: + 'Delete all usage for the given subscription item. Zoneless removes the item immediately, so this value is accepted and ignored.', + }, + { + name: 'payment_behavior', + type: 'enum', + description: + 'Controls how to handle payment when a subscription update requires payment and collection_method=charge_automatically.', + enumValues: [ + { + value: 'allow_incomplete', + description: + 'Transition the subscription to past_due if payment fails.', + }, + { + value: 'default_incomplete', + description: + 'Transition the subscription to past_due without attempting payment.', + }, + { + value: 'error_if_incomplete', + description: + 'Return an HTTP 402 error and do not update the subscription.', + }, + { + value: 'pending_if_incomplete', + description: + 'Create a pending update that applies only if the payment succeeds.', + }, + ], + enumNote: + 'Difference from Stripe: Zoneless deletes the item immediately, so this parameter has no effect.', + }, + { + name: 'proration_behavior', + type: 'enum', + description: + 'Determines how to handle prorations when the billing cycle changes or when an item quantity changes. Defaults to create_prorations.', + enumValues: [ + { value: 'always_invoice' }, + { value: 'create_prorations' }, + { value: 'none' }, + ], + enumNote: + 'Difference from Stripe: Zoneless does not create proration invoice items, so this value is accepted and ignored.', + }, + { + name: 'proration_date', + type: 'timestamp', + description: + 'Only used when proration_behavior creates prorations. Zoneless does not create prorations, so this value is accepted and ignored.', + }, +]; + +export const SUBSCRIPTION_ITEMS_DELETE_PAGE: DocPage = { + id: 'delete', + title: 'Delete a subscription item', + description: + 'Removes an item from the subscription. Removing an item does not cancel the subscription.', + stripeDocsUrl: 'https://docs.stripe.com/api/subscription_items/delete', + endpoints: [{ method: 'DELETE', path: '/v1/subscription_items/:id' }], + sections: [ + { + left: [ + { type: 'heading', level: 2, text: 'Parameters' }, + { + type: 'attributes', + attributes: DELETE_SUBSCRIPTION_ITEM_PARAMETERS, + }, + { type: 'heading', level: 2, text: 'Returns' }, + { + type: 'paragraph', + text: "An object with the deleted subscription item's ID and a deleted flag upon success. Otherwise, this call raises an error, such as if the subscription item has already been deleted.", + }, + ], + right: [ + { + type: 'code', + endpoint: { method: 'DELETE', path: '/v1/subscription_items/:id' }, + tabs: [ + { + id: 'curl', + label: 'cURL', + code: `curl -X DELETE https://api.yourdomain.com/v1/subscription_items/si_z_9Km2pQxR4vL8nHw \\ + -H "x-api-key: sk_live_z_YOUR_API_KEY"`, + }, + { + id: 'node', + label: 'Node.js', + code: `${NODE_INIT} + +const deleted = await zoneless.subscriptionItems.del( + 'si_z_9Km2pQxR4vL8nHw' +);`, + }, + ], + }, + { + type: 'object', + title: 'RESPONSE', + code: SUBSCRIPTION_ITEM_DELETED_JSON, + }, + ], + }, + ], +}; + +export const SUBSCRIPTION_ITEMS_PAGES: DocPage[] = [ + SUBSCRIPTION_ITEMS_OVERVIEW_PAGE, + SUBSCRIPTION_ITEMS_CREATE_PAGE, + SUBSCRIPTION_ITEMS_UPDATE_PAGE, + SUBSCRIPTION_ITEMS_RETRIEVE_PAGE, + SUBSCRIPTION_ITEMS_LIST_PAGE, + SUBSCRIPTION_ITEMS_DELETE_PAGE, +]; diff --git a/apps/docs/src/app/pages/docs/docs-catalog.ts b/apps/docs/src/app/pages/docs/docs-catalog.ts index 43766fb..637559a 100644 --- a/apps/docs/src/app/pages/docs/docs-catalog.ts +++ b/apps/docs/src/app/pages/docs/docs-catalog.ts @@ -43,6 +43,7 @@ import { QUICKSTART_PAGE, SELF_HOSTING_PAGE, SUBSCRIPTIONS_PAGES, + SUBSCRIPTION_ITEMS_PAGES, TOPUPS_PAGES, TRANSFERS_PAGES, WEBHOOK_ENDPOINTS_PAGES, @@ -83,6 +84,7 @@ export const docPageGroups: Record = { products: PRODUCTS_PAGES, prices: PRICES_PAGES, subscriptions: SUBSCRIPTIONS_PAGES, + subscriptionitems: SUBSCRIPTION_ITEMS_PAGES, invoiceitems: INVOICE_ITEMS_PAGES, invoices: INVOICES_PAGES, billing: BILLING_PAGES,