@usethrottle/subscriptions 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md CHANGED
@@ -31,6 +31,18 @@ Direct customer-scoped browser tokens are intentionally not in v1 because the AP
31
31
 
32
32
  ## Conventions
33
33
 
34
+ - **`changePlan()` vs `update()` (since 3.0.0 — D19).** `changePlan()` is a real plan
35
+ change: `POST /api/v1/subscriptions/{id}/change-plan`, prorated and charged
36
+ immediately when `effective: 'now'`. `update()` is the old PATCH-style term
37
+ edit — rename a plan, correct the cadence or amount on the row, no proration,
38
+ no charge. Before 3.0.0, `changePlan()` silently WAS `update()` (a naming
39
+ trap: merchants calling `changePlan()` to upgrade never got the charge). Do
40
+ not re-merge these two.
41
+ - `changeQuantity()`, `retryCharge()`, `waivePeriod()`, `recordUsage()`, and
42
+ `listUsage()` mirror the REST API 1:1 (`change-quantity`, `retry-charge`,
43
+ `waive-period`, `usage` POST + GET). `listUsage()`'s route answers
44
+ `{ items: [...] }`, not the usual `{ data, meta }` envelope — read `items`
45
+ directly off `requestEnvelope()`, never `request()`'s data-unwrap.
34
46
  - Keep API payloads camelCase on writes because the live Fastify validators expect camelCase.
35
47
  - `create()` accepts either `customerId` or `externalCustomerId`; resolve external ids to Throttle customer rows before posting to `/api/v1/subscriptions`.
36
48
  - Normalize both camelCase and snake_case response fields. Some OpenAPI schemas use snake_case while service rows currently serialize camelCase.
@@ -25,6 +25,7 @@ function normalizeSubscription(raw) {
25
25
  paymentsMade: Number(raw?.paymentsMade ?? 0),
26
26
  completedAt: optionalIsoDateString(raw?.completedAt),
27
27
  amount: Number(raw?.amount ?? 0),
28
+ quantity: Number(raw?.quantity ?? 1),
28
29
  currency: optionalString(raw?.currency) ?? "USD",
29
30
  currentPeriodStart: requiredDateString(
30
31
  raw?.currentPeriodStart,
@@ -41,10 +42,47 @@ function normalizeSubscription(raw) {
41
42
  pausedAt: optionalDateString(raw?.pausedAt),
42
43
  cancelledAt: optionalDateString(raw?.cancelledAt),
43
44
  metadata: objectOrEmpty(raw?.metadata),
45
+ renewalIssue: normalizeRenewalIssue(raw?.renewalIssue),
46
+ proration: raw?.proration ? {
47
+ creditCents: raw.proration.creditCents,
48
+ chargedCents: raw.proration.chargedCents,
49
+ fullAmount: raw.proration.fullAmount
50
+ } : void 0,
44
51
  createdAt: optionalDateString(raw?.createdAt) ?? void 0,
45
52
  updatedAt: optionalDateString(raw?.updatedAt) ?? void 0
46
53
  };
47
54
  }
55
+ function normalizeRenewalIssue(raw) {
56
+ if (!raw || typeof raw !== "object") return null;
57
+ return {
58
+ kind: raw.kind,
59
+ reason: raw.reason,
60
+ count: Number(raw.count ?? 0),
61
+ firstAt: optionalString(raw.firstAt) ?? void 0,
62
+ lastAt: requiredString(raw.lastAt, "subscription.renewalIssue.lastAt"),
63
+ message: raw.message ?? "",
64
+ alertedAt: optionalDateString(raw.alertedAt),
65
+ charge: raw.charge ? {
66
+ transactionId: optionalString(raw.charge.transactionId),
67
+ amount: Number(raw.charge.amount ?? 0),
68
+ currency: optionalString(raw.charge.currency) ?? "USD",
69
+ periodStart: optionalString(raw.charge.periodStart) ?? void 0
70
+ } : null
71
+ };
72
+ }
73
+ function normalizeUsageItem(raw) {
74
+ return {
75
+ id: requiredString(raw?.id, "usageItem.id"),
76
+ subscriptionId: requiredString(raw?.subscriptionId, "usageItem.subscriptionId"),
77
+ kind: raw?.kind ?? "",
78
+ unitCount: Number(raw?.unitCount ?? 0),
79
+ unitPriceCents: Number(raw?.unitPriceCents ?? 0),
80
+ totalCents: Number(raw?.totalCents ?? 0),
81
+ periodStart: requiredDateString(raw?.periodStart, "usageItem.periodStart"),
82
+ periodEnd: requiredDateString(raw?.periodEnd, "usageItem.periodEnd"),
83
+ createdAt: requiredDateString(raw?.createdAt, "usageItem.createdAt")
84
+ };
85
+ }
48
86
  function normalizeCustomer(raw) {
49
87
  if (!raw) return null;
50
88
  return {
@@ -240,6 +278,12 @@ var SubscriptionsClient = class {
240
278
  );
241
279
  return normalizeSubscription(data);
242
280
  }
281
+ /**
282
+ * A term-only edit: rename the plan, correct the cadence or the amount on
283
+ * the row — no proration, no charge, no period reset. Mirrors
284
+ * `PATCH /api/v1/subscriptions/{id}`. This is what `changePlan()` did
285
+ * before 3.0.0; use `changePlan()` now for an actual plan change.
286
+ */
243
287
  async update(id, input) {
244
288
  const data = await this.request(
245
289
  "PATCH",
@@ -248,9 +292,92 @@ var SubscriptionsClient = class {
248
292
  );
249
293
  return normalizeSubscription(data);
250
294
  }
251
- changePlan(input) {
295
+ /**
296
+ * A real plan change: prorated and charged immediately when
297
+ * `effective: 'now'`, or scheduled for period end with no charge today.
298
+ * Mirrors `POST /api/v1/subscriptions/{id}/change-plan`. The resolved
299
+ * subscription carries `proration` when the server computed one.
300
+ *
301
+ * This is NOT the old `changePlan()` (a PATCH-style term edit with no
302
+ * proration and no charge) — use `update()` for that.
303
+ */
304
+ async changePlan(input) {
252
305
  const { id, ...body } = input;
253
- return this.update(id, body);
306
+ const data = await this.request(
307
+ "POST",
308
+ `/api/v1/subscriptions/${encodeURIComponent(id)}/change-plan`,
309
+ {
310
+ planReference: body.planReference,
311
+ planName: body.planName,
312
+ interval: body.interval,
313
+ intervalUnit: body.intervalUnit,
314
+ intervalCount: body.intervalCount,
315
+ amount: body.amount,
316
+ effective: body.effective
317
+ }
318
+ );
319
+ return normalizeSubscription(data);
320
+ }
321
+ /**
322
+ * Change the seat quantity: prorated and charged immediately when
323
+ * `effective: 'now'`, or scheduled for period end with no charge today.
324
+ * Mirrors `POST /api/v1/subscriptions/{id}/change-quantity`.
325
+ */
326
+ async changeQuantity(id, input) {
327
+ const data = await this.request(
328
+ "POST",
329
+ `/api/v1/subscriptions/${encodeURIComponent(id)}/change-quantity`,
330
+ { quantity: input.quantity, effective: input.effective }
331
+ );
332
+ return normalizeSubscription(data);
333
+ }
334
+ /**
335
+ * Charge a past-due subscription's card again now, instead of waiting for
336
+ * the next scheduled dunning retry. Mirrors
337
+ * `POST /api/v1/subscriptions/{id}/retry-charge`.
338
+ */
339
+ async retryCharge(id) {
340
+ const data = await this.request(
341
+ "POST",
342
+ `/api/v1/subscriptions/${encodeURIComponent(id)}/retry-charge`
343
+ );
344
+ return normalizeSubscription(data);
345
+ }
346
+ /**
347
+ * Forgive the current past-due period — the merchant is not collecting it.
348
+ * Mirrors `POST /api/v1/subscriptions/{id}/waive-period`.
349
+ */
350
+ async waivePeriod(id, input) {
351
+ const data = await this.request(
352
+ "POST",
353
+ `/api/v1/subscriptions/${encodeURIComponent(id)}/waive-period`,
354
+ { reason: input.reason }
355
+ );
356
+ return normalizeSubscription(data);
357
+ }
358
+ /**
359
+ * Record (upsert) a usage item for the subscription's current billing
360
+ * period. Mirrors `POST /api/v1/subscriptions/{id}/usage`.
361
+ */
362
+ async recordUsage(id, input) {
363
+ const data = await this.request(
364
+ "POST",
365
+ `/api/v1/subscriptions/${encodeURIComponent(id)}/usage`,
366
+ { kind: input.kind, unitCount: input.unitCount, unitPriceCents: input.unitPriceCents }
367
+ );
368
+ return normalizeUsageItem(data);
369
+ }
370
+ /**
371
+ * List usage items recorded for the subscription's current billing period.
372
+ * Mirrors `GET /api/v1/subscriptions/{id}/usage`.
373
+ */
374
+ async listUsage(id) {
375
+ const envelope = await this.requestEnvelope(
376
+ "GET",
377
+ `/api/v1/subscriptions/${encodeURIComponent(id)}/usage`
378
+ );
379
+ const items = envelope.items ?? [];
380
+ return items.map(normalizeUsageItem);
254
381
  }
255
382
  async pause(id) {
256
383
  const data = await this.request(
@@ -356,4 +483,4 @@ export {
356
483
  SubscriptionsClient,
357
484
  createSubscriptionsClient
358
485
  };
359
- //# sourceMappingURL=chunk-C4MXEOJ3.js.map
486
+ //# sourceMappingURL=chunk-YQLHMNZH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/normalize.ts","../src/client.ts"],"sourcesContent":["import { ThrottleError, type ThrottleErrorArgs } from '@usethrottle/errors';\n\n/**\n * Thrown on a non-2xx response from the Throttle Subscriptions API.\n *\n * Extends the shared {@link ThrottleError} so a single\n * `catch (e) { if (e instanceof ThrottleError) … }` covers errors from every\n * Throttle SDK. `instanceof ThrottleSubscriptionsError` keeps working.\n */\nexport class ThrottleSubscriptionsError extends ThrottleError {\n constructor(args: {\n code: string;\n message: string;\n statusCode: number;\n details?: unknown;\n responseHeaders?: ThrottleErrorArgs['responseHeaders'];\n }) {\n super(args);\n this.name = 'ThrottleSubscriptionsError';\n }\n}\n\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\n","import type {\n CheckoutSession,\n Customer,\n CustomerPaymentMethod,\n Pagination,\n Subscription,\n SubscriptionInterval,\n SubscriptionRenewalIssue,\n SubscriptionStatus,\n SubscriptionUsageItem,\n TrialEligibilityResult,\n} from './types';\n\nexport function normalizeSubscription(raw: any): Subscription {\n return {\n id: requiredString(raw?.id, 'subscription.id'),\n workspaceId: optionalString(raw?.workspaceId),\n applicationId: optionalString(raw?.applicationId),\n customerId: requiredString(raw?.customerId, 'subscription.customerId'),\n status: (raw?.status ?? 'active') as SubscriptionStatus,\n planReference: requiredString(raw?.planReference, 'subscription.planReference'),\n planName: optionalString(raw?.planName),\n interval: (raw?.interval ?? 'monthly') as SubscriptionInterval,\n intervalUnit: (optionalString(raw?.intervalUnit) as Subscription['intervalUnit']) ?? null,\n intervalCount: raw?.intervalCount == null ? null : Number(raw.intervalCount),\n totalPayments: raw?.totalPayments == null ? null : Number(raw.totalPayments),\n paymentsMade: Number(raw?.paymentsMade ?? 0),\n completedAt: optionalIsoDateString(raw?.completedAt),\n amount: Number(raw?.amount ?? 0),\n quantity: Number(raw?.quantity ?? 1),\n currency: optionalString(raw?.currency) ?? 'USD',\n currentPeriodStart: requiredDateString(\n raw?.currentPeriodStart,\n 'subscription.currentPeriodStart',\n ),\n currentPeriodEnd: requiredDateString(\n raw?.currentPeriodEnd,\n 'subscription.currentPeriodEnd',\n ),\n trialEnd: optionalDateString(raw?.trialEnd),\n cancelAtPeriodEnd: Boolean(raw?.cancelAtPeriodEnd ?? false),\n failureCount: Number(raw?.failureCount ?? 0),\n lastPaymentAt: optionalDateString(raw?.lastPaymentAt),\n pausedAt: optionalDateString(raw?.pausedAt),\n cancelledAt: optionalDateString(raw?.cancelledAt),\n metadata: objectOrEmpty(raw?.metadata),\n renewalIssue: normalizeRenewalIssue(raw?.renewalIssue),\n proration: raw?.proration\n ? {\n creditCents: raw.proration.creditCents,\n chargedCents: raw.proration.chargedCents,\n fullAmount: raw.proration.fullAmount,\n }\n : undefined,\n createdAt: optionalDateString(raw?.createdAt) ?? undefined,\n updatedAt: optionalDateString(raw?.updatedAt) ?? undefined,\n };\n}\n\nfunction normalizeRenewalIssue(raw: any): SubscriptionRenewalIssue | null {\n if (!raw || typeof raw !== 'object') return null;\n return {\n kind: raw.kind,\n reason: raw.reason,\n count: Number(raw.count ?? 0),\n firstAt: optionalString(raw.firstAt) ?? undefined,\n lastAt: requiredString(raw.lastAt, 'subscription.renewalIssue.lastAt'),\n message: raw.message ?? '',\n alertedAt: optionalDateString(raw.alertedAt),\n charge: raw.charge\n ? {\n transactionId: optionalString(raw.charge.transactionId),\n amount: Number(raw.charge.amount ?? 0),\n currency: optionalString(raw.charge.currency) ?? 'USD',\n periodStart: optionalString(raw.charge.periodStart) ?? undefined,\n }\n : null,\n };\n}\n\nexport function normalizeUsageItem(raw: any): SubscriptionUsageItem {\n return {\n id: requiredString(raw?.id, 'usageItem.id'),\n subscriptionId: requiredString(raw?.subscriptionId, 'usageItem.subscriptionId'),\n kind: raw?.kind ?? '',\n unitCount: Number(raw?.unitCount ?? 0),\n unitPriceCents: Number(raw?.unitPriceCents ?? 0),\n totalCents: Number(raw?.totalCents ?? 0),\n periodStart: requiredDateString(raw?.periodStart, 'usageItem.periodStart'),\n periodEnd: requiredDateString(raw?.periodEnd, 'usageItem.periodEnd'),\n createdAt: requiredDateString(raw?.createdAt, 'usageItem.createdAt'),\n };\n}\n\nexport function normalizeCustomer(raw: any): Customer | null {\n if (!raw) return null;\n return {\n id: requiredString(raw?.id, 'customer.id'),\n externalId: optionalString(raw?.externalId),\n email: optionalString(raw?.email),\n firstName: optionalString(raw?.firstName),\n lastName: optionalString(raw?.lastName),\n phone: optionalString(raw?.phone),\n company: optionalString(raw?.company),\n metadata: objectOrEmpty(raw?.metadata),\n createdAt: optionalDateString(raw?.createdAt) ?? undefined,\n updatedAt: optionalDateString(raw?.updatedAt) ?? undefined,\n };\n}\n\nexport function normalizeCustomerPaymentMethod(raw: any): CustomerPaymentMethod {\n return {\n id: requiredString(raw?.id, 'paymentMethod.id'),\n processor: optionalString(raw?.processor),\n methodType: optionalString(raw?.methodType),\n cardBrand: optionalString(raw?.cardBrand),\n cardLastFour: optionalString(raw?.cardLastFour),\n isDefault: Boolean(raw?.isDefault ?? false),\n isActive: Boolean(raw?.isActive ?? true),\n createdAt: optionalDateString(raw?.createdAt) ?? undefined,\n updatedAt: optionalDateString(raw?.updatedAt) ?? undefined,\n };\n}\n\nexport function normalizeCheckoutSession(raw: any): CheckoutSession {\n const sessionId = raw?.sessionId ?? raw?.id;\n return {\n ...withoutUnderscoreKeys(raw),\n id: optionalString(raw?.id) ?? undefined,\n sessionId: requiredString(sessionId, 'checkoutSession.sessionId'),\n checkoutUrl: optionalString(raw?.checkoutUrl) ?? undefined,\n embedToken: optionalString(raw?.embedToken) ?? undefined,\n expiresAt: optionalDateString(raw?.expiresAt) ?? undefined,\n };\n}\n\nexport function normalizeTrialEligibility(raw: any): TrialEligibilityResult {\n return {\n eligible: Boolean(raw?.eligible),\n reason: raw?.reason,\n };\n}\n\nexport function normalizePagination(raw: any): Pagination | undefined {\n if (!raw) return undefined;\n return {\n cursor: raw.cursor ?? null,\n hasMore: Boolean(raw.hasMore ?? false),\n };\n}\n\nexport function toIso(value: string | Date | undefined): string | undefined {\n if (value === undefined) return undefined;\n return value instanceof Date ? value.toISOString() : value;\n}\n\nfunction requiredString(value: unknown, label: string): string {\n if (typeof value === 'string' && value.length > 0) return value;\n throw new Error(`Invalid Throttle response: missing ${label}`);\n}\n\nfunction optionalString(value: unknown): string | null {\n return typeof value === 'string' ? value : null;\n}\n\nfunction requiredDateString(value: unknown, label: string): string {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && value.length > 0) return value;\n throw new Error(`Invalid Throttle response: missing ${label}`);\n}\n\nfunction optionalDateString(value: unknown): string | null {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && value.length > 0) return value;\n return null;\n}\n\n/**\n * Like `optionalDateString`, but always reserializes to a full ISO string\n * (with milliseconds) rather than passing a raw string through unchanged.\n * `completedAt` is a fresh field with no legacy raw-string callers to stay\n * compatible with, so it normalizes cleanly instead of echoing whatever the\n * API sent.\n */\nfunction optionalIsoDateString(value: unknown): string | null {\n if (value instanceof Date) return value.toISOString();\n if (typeof value === 'string' && value.length > 0) {\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? value : d.toISOString();\n }\n return null;\n}\n\nfunction objectOrEmpty(value: unknown): Record<string, unknown> {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction withoutUnderscoreKeys(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return {};\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).filter(([key]) => !key.includes('_')),\n );\n}\n","import { ThrottleSubscriptionsError } from './errors';\nimport {\n normalizeCheckoutSession,\n normalizeCustomer,\n normalizeCustomerPaymentMethod,\n normalizePagination,\n normalizeSubscription,\n normalizeTrialEligibility,\n normalizeUsageItem,\n toIso,\n} from './normalize';\nimport type {\n ChangePlanInput,\n ChangeQuantityInput,\n CheckoutSession,\n CreateCheckoutSessionInput,\n CreateSubscriptionInput,\n Customer,\n CustomerPaymentMethod,\n ListSubscriptionsParams,\n PaginatedSubscriptions,\n RecordUsageInput,\n Subscription,\n SubscriptionInvoiceRefund,\n SubscriptionUsageItem,\n SubscriptionsClientContract,\n SubscriptionsClientOptions,\n ThrottleEnvelope,\n TrialEligibilityInput,\n TrialEligibilityResult,\n UpdateSubscriptionInput,\n WaivePeriodInput,\n} from './types';\n\nexport class SubscriptionsClient implements SubscriptionsClientContract {\n private readonly apiKey?: string;\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof globalThis.fetch;\n private readonly fetcher?: SubscriptionsClientOptions['fetcher'];\n private readonly timeoutMs: number;\n\n constructor(opts: SubscriptionsClientOptions = {}) {\n const fetchImpl = opts.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('SubscriptionsClient: fetch is required');\n if (!opts.apiKey && !opts.fetcher) {\n throw new Error('SubscriptionsClient: apiKey or fetcher is required');\n }\n\n this.apiKey = opts.apiKey;\n this.baseUrl = (opts.baseUrl ?? 'https://api.usethrottle.dev').replace(/\\/+$/, '');\n this.fetchImpl = fetchImpl;\n this.fetcher = opts.fetcher;\n this.timeoutMs = opts.timeoutMs ?? 30_000;\n }\n\n async request<T = unknown>(method: string, path: string, body?: unknown): Promise<T> {\n const envelope = await this.requestEnvelope<T>(method, path, body);\n if (Object.prototype.hasOwnProperty.call(envelope, 'data')) {\n return envelope.data as T;\n }\n return envelope as T;\n }\n\n async requestEnvelope<T = unknown>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<ThrottleEnvelope<T>> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);\n\n try {\n const init: RequestInit = {\n method,\n headers: {\n 'content-type': 'application/json',\n ...(this.apiKey ? { 'x-api-key': this.apiKey } : {}),\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: ctrl.signal,\n };\n\n const res = this.fetcher\n ? await this.fetcher(path, init)\n : await this.fetchImpl(toAbsoluteUrl(this.baseUrl, path), init);\n\n if (res.status === 204) return { data: undefined as T };\n\n const json = (await res.json().catch(() => ({}))) as ThrottleEnvelope<T>;\n if (!res.ok) {\n throw new ThrottleSubscriptionsError({\n code: json.error?.code ?? 'unknown_error',\n message: json.error?.message ?? `HTTP ${res.status}`,\n statusCode: res.status,\n details: json.error?.details,\n responseHeaders: res.headers,\n });\n }\n return json;\n } finally {\n clearTimeout(timer);\n }\n }\n\n async create(input: CreateSubscriptionInput): Promise<Subscription> {\n const customerId = await this.resolveCustomerId(input.customerId, input.externalCustomerId);\n const data = await this.request<unknown>('POST', '/api/v1/subscriptions', {\n applicationId: input.applicationId,\n customerId,\n planReference: input.planReference,\n planName: input.planName,\n interval: input.interval,\n intervalUnit: input.intervalUnit,\n intervalCount: input.intervalCount,\n totalPayments: input.totalPayments,\n amount: input.amount,\n currency: input.currency,\n currentPeriodStart: toIso(input.currentPeriodStart),\n currentPeriodEnd: toIso(input.currentPeriodEnd),\n trialEnd: toIso(input.trialEnd),\n metadata: input.metadata ?? {},\n orderId: input.orderId,\n });\n return normalizeSubscription(data);\n }\n\n async list(params: ListSubscriptionsParams = {}): Promise<PaginatedSubscriptions> {\n const query = new URLSearchParams();\n setQuery(query, 'customerId', params.customerId);\n setQuery(query, 'externalCustomerId', params.externalCustomerId);\n setQuery(query, 'status', params.status);\n setQuery(query, 'interval', params.interval);\n setQuery(query, 'installment', params.installment);\n setQuery(query, 'q', params.q);\n setQuery(query, 'cursor', params.cursor);\n setQuery(query, 'limit', params.limit);\n setQuery(query, 'sort', params.sort);\n setQuery(query, 'createdAfter', toIso(params.createdAfter));\n setQuery(query, 'createdBefore', toIso(params.createdBefore));\n\n const suffix = query.toString() ? `?${query}` : '';\n const envelope = await this.requestEnvelope<unknown[]>('GET', `/api/v1/subscriptions${suffix}`);\n return {\n data: (envelope.data ?? []).map(normalizeSubscription),\n pagination: normalizePagination(envelope.meta?.pagination),\n };\n }\n\n async get(id: string): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'GET',\n `/api/v1/subscriptions/${encodeURIComponent(id)}`,\n );\n return normalizeSubscription(data);\n }\n\n /**\n * A term-only edit: rename the plan, correct the cadence or the amount on\n * the row — no proration, no charge, no period reset. Mirrors\n * `PATCH /api/v1/subscriptions/{id}`. This is what `changePlan()` did\n * before 3.0.0; use `changePlan()` now for an actual plan change.\n */\n async update(id: string, input: UpdateSubscriptionInput): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'PATCH',\n `/api/v1/subscriptions/${encodeURIComponent(id)}`,\n input,\n );\n return normalizeSubscription(data);\n }\n\n /**\n * A real plan change: prorated and charged immediately when\n * `effective: 'now'`, or scheduled for period end with no charge today.\n * Mirrors `POST /api/v1/subscriptions/{id}/change-plan`. The resolved\n * subscription carries `proration` when the server computed one.\n *\n * This is NOT the old `changePlan()` (a PATCH-style term edit with no\n * proration and no charge) — use `update()` for that.\n */\n async changePlan(input: ChangePlanInput): Promise<Subscription> {\n const { id, ...body } = input;\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/change-plan`,\n {\n planReference: body.planReference,\n planName: body.planName,\n interval: body.interval,\n intervalUnit: body.intervalUnit,\n intervalCount: body.intervalCount,\n amount: body.amount,\n effective: body.effective,\n },\n );\n return normalizeSubscription(data);\n }\n\n /**\n * Change the seat quantity: prorated and charged immediately when\n * `effective: 'now'`, or scheduled for period end with no charge today.\n * Mirrors `POST /api/v1/subscriptions/{id}/change-quantity`.\n */\n async changeQuantity(id: string, input: ChangeQuantityInput): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/change-quantity`,\n { quantity: input.quantity, effective: input.effective },\n );\n return normalizeSubscription(data);\n }\n\n /**\n * Charge a past-due subscription's card again now, instead of waiting for\n * the next scheduled dunning retry. Mirrors\n * `POST /api/v1/subscriptions/{id}/retry-charge`.\n */\n async retryCharge(id: string): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/retry-charge`,\n );\n return normalizeSubscription(data);\n }\n\n /**\n * Forgive the current past-due period — the merchant is not collecting it.\n * Mirrors `POST /api/v1/subscriptions/{id}/waive-period`.\n */\n async waivePeriod(id: string, input: WaivePeriodInput): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/waive-period`,\n { reason: input.reason },\n );\n return normalizeSubscription(data);\n }\n\n /**\n * Record (upsert) a usage item for the subscription's current billing\n * period. Mirrors `POST /api/v1/subscriptions/{id}/usage`.\n */\n async recordUsage(id: string, input: RecordUsageInput): Promise<SubscriptionUsageItem> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/usage`,\n { kind: input.kind, unitCount: input.unitCount, unitPriceCents: input.unitPriceCents },\n );\n return normalizeUsageItem(data);\n }\n\n /**\n * List usage items recorded for the subscription's current billing period.\n * Mirrors `GET /api/v1/subscriptions/{id}/usage`.\n */\n async listUsage(id: string): Promise<SubscriptionUsageItem[]> {\n const envelope = await this.requestEnvelope<{ items?: unknown[] }>(\n 'GET',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/usage`,\n );\n // This route answers `{ items: [...] }`, not the usual `{ data, meta }`\n // envelope, so `request()`'s data-unwrap would just hand back the whole\n // body — read `items` off the raw envelope instead.\n const items = (envelope as unknown as { items?: unknown[] }).items ?? [];\n return items.map(normalizeUsageItem);\n }\n\n async pause(id: string): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/pause`,\n );\n return normalizeSubscription(data);\n }\n\n async resume(id: string): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/resume`,\n );\n return normalizeSubscription(data);\n }\n\n async cancel(\n id: string,\n input: { atPeriodEnd?: boolean; refund?: 'none' | 'prorated' | 'last_cycle' } = {},\n ): Promise<Subscription> {\n const data = await this.request<unknown>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/cancel`,\n { atPeriodEnd: input.atPeriodEnd ?? false, refund: input.refund ?? 'none' },\n );\n return normalizeSubscription(data);\n }\n\n /**\n * Refund one billing cycle.\n *\n * `intent` has no default: refunding money and ending the subscription are\n * separate decisions, and guessing either way is wrong often enough that the\n * API requires the caller to say which one they mean.\n */\n async refundInvoice(\n id: string,\n invoiceId: string,\n input: { intent: 'money_only' | 'refund_and_cancel'; amount?: number; reason?: string },\n ): Promise<SubscriptionInvoiceRefund> {\n return this.request<SubscriptionInvoiceRefund>(\n 'POST',\n `/api/v1/subscriptions/${encodeURIComponent(id)}/invoices/${encodeURIComponent(invoiceId)}/refund`,\n input,\n );\n }\n\n async createCheckoutSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession> {\n const data = await this.request<unknown>('POST', '/api/v1/checkout/sessions', input);\n return normalizeCheckoutSession(data);\n }\n\n async checkTrialEligibility(input: TrialEligibilityInput): Promise<TrialEligibilityResult> {\n const data = await this.request<unknown>('POST', '/api/v1/subscriptions/eligibility-check', {\n paymentMethodId: input.paymentMethodId,\n });\n return normalizeTrialEligibility(data);\n }\n\n async getCustomerByExternalId(externalId: string): Promise<Customer | null> {\n try {\n const data = await this.request<unknown>(\n 'GET',\n `/api/v1/customers/by-external/${encodeURIComponent(externalId)}`,\n );\n return normalizeCustomer(data);\n } catch (err) {\n if (err instanceof ThrottleSubscriptionsError && err.statusCode === 404) return null;\n throw err;\n }\n }\n\n async listCustomerPaymentMethods(customerId: string): Promise<CustomerPaymentMethod[]> {\n const data = await this.request<unknown[]>(\n 'GET',\n `/api/v1/customers/${encodeURIComponent(customerId)}/payment-methods`,\n );\n return (data ?? []).map(normalizeCustomerPaymentMethod);\n }\n\n private async resolveCustomerId(\n customerId?: string,\n externalCustomerId?: string,\n ): Promise<string> {\n if (customerId) return customerId;\n if (!externalCustomerId) {\n throw new ThrottleSubscriptionsError({\n code: 'invalid_request',\n message: 'customerId or externalCustomerId is required',\n statusCode: 400,\n });\n }\n\n const customer = await this.getCustomerByExternalId(externalCustomerId);\n if (!customer) {\n throw new ThrottleSubscriptionsError({\n code: 'customer_not_found',\n message: 'Customer not found',\n statusCode: 404,\n });\n }\n return customer.id;\n }\n}\n\nexport function createSubscriptionsClient(opts: SubscriptionsClientOptions): SubscriptionsClient {\n return new SubscriptionsClient(opts);\n}\n\nfunction toAbsoluteUrl(baseUrl: string, path: string): string {\n if (/^https?:\\/\\//i.test(path)) return path;\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n}\n\nfunction setQuery(query: URLSearchParams, key: string, value: unknown): void {\n if (value === undefined || value === null || value === '') return;\n query.set(key, String(value));\n}\n"],"mappings":"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","names":["ThrottleError"]}
@@ -24,6 +24,8 @@ interface Subscription {
24
24
  /** When the final installment succeeded. Set only on `completed`. */
25
25
  completedAt: string | null;
26
26
  amount: number;
27
+ /** #688 — number of seats. Per-seat price is `amount`; the period charge is `amount × quantity`. Defaults to 1. */
28
+ quantity: number;
27
29
  currency: string;
28
30
  currentPeriodStart: string;
29
31
  currentPeriodEnd: string;
@@ -42,9 +44,42 @@ interface Subscription {
42
44
  taxAddressSnapshot?: SubscriptionTaxAddress | null;
43
45
  /** `checkout` when captured at signup, `manual` once a merchant edited it. */
44
46
  taxAddressSource?: 'checkout' | 'manual' | null;
47
+ /**
48
+ * Set by the renewal job when renewals are failing (`system_error`) or when
49
+ * a card was charged but the renewal could not be recorded (`orphan_charge`
50
+ * — renewals are paused until Throttle support resolves it). `null` when
51
+ * nothing is wrong.
52
+ */
53
+ renewalIssue: SubscriptionRenewalIssue | null;
54
+ /**
55
+ * Present only on the response from `changePlan()` / `changeQuantity()` —
56
+ * how much of the old plan's unused time credited the new charge.
57
+ */
58
+ proration?: SubscriptionProration | null;
45
59
  createdAt?: string;
46
60
  updatedAt?: string;
47
61
  }
62
+ interface SubscriptionRenewalIssue {
63
+ kind: 'system_error' | 'orphan_charge';
64
+ /** Stable code; `message` is its fixed, merchant-safe sentence. */
65
+ reason: 'tax_quote_failed' | 'internal_error' | 'record_failed';
66
+ count: number;
67
+ firstAt?: string;
68
+ lastAt: string;
69
+ message: string;
70
+ alertedAt?: string | null;
71
+ charge?: {
72
+ transactionId: string | null;
73
+ amount: number;
74
+ currency: string;
75
+ periodStart?: string;
76
+ } | null;
77
+ }
78
+ interface SubscriptionProration {
79
+ creditCents?: number;
80
+ chargedCents?: number;
81
+ fullAmount?: number;
82
+ }
48
83
  interface SubscriptionTaxAddress {
49
84
  addressLine1?: string | null;
50
85
  addressLine2?: string | null;
@@ -137,9 +172,52 @@ interface CancelSubscriptionInput {
137
172
  id: string;
138
173
  atPeriodEnd?: boolean;
139
174
  }
140
- interface ChangePlanInput extends UpdateSubscriptionInput {
175
+ /**
176
+ * `changePlan()`'s input, mirroring `POST /api/v1/subscriptions/{id}/change-plan`:
177
+ * a real plan change, prorated and charged when `effective: 'now'`. For the
178
+ * old term-only edit (rename a plan, correct an amount, with no proration or
179
+ * charge), use `update()` instead — see its migration note in the 3.0.0
180
+ * changeset.
181
+ */
182
+ interface ChangePlanInput {
141
183
  id: string;
142
184
  planReference: string;
185
+ planName?: string;
186
+ interval?: SubscriptionInterval;
187
+ intervalUnit?: SubscriptionIntervalUnit;
188
+ intervalCount?: number;
189
+ amount: number;
190
+ /** `'now'` prorates and charges immediately; `'period_end'` schedules it, charging nothing today. */
191
+ effective: 'now' | 'period_end';
192
+ }
193
+ /** `changeQuantity()`'s input, mirroring `POST /api/v1/subscriptions/{id}/change-quantity`. */
194
+ interface ChangeQuantityInput {
195
+ quantity: number;
196
+ /** `'now'` prorates and charges immediately; `'period_end'` schedules it, charging nothing today. */
197
+ effective: 'now' | 'period_end';
198
+ }
199
+ /** `recordUsage()`'s input, mirroring `POST /api/v1/subscriptions/{id}/usage`. */
200
+ interface RecordUsageInput {
201
+ kind: string;
202
+ unitCount: number;
203
+ unitPriceCents: number;
204
+ }
205
+ /** A usage item recorded against a subscription's current billing period. */
206
+ interface SubscriptionUsageItem {
207
+ id: string;
208
+ subscriptionId: string;
209
+ kind: string;
210
+ unitCount: number;
211
+ unitPriceCents: number;
212
+ totalCents: number;
213
+ periodStart: string;
214
+ periodEnd: string;
215
+ createdAt: string;
216
+ }
217
+ /** `waivePeriod()`'s input, mirroring `POST /api/v1/subscriptions/{id}/waive-period`. */
218
+ interface WaivePeriodInput {
219
+ /** Required: the only record of why the period was not collected. */
220
+ reason: string;
143
221
  }
144
222
  interface RecurringIntent {
145
223
  plan: string;
@@ -287,12 +365,17 @@ interface SubscriptionsClientContract {
287
365
  get(id: string): Promise<Subscription>;
288
366
  update(id: string, input: UpdateSubscriptionInput): Promise<Subscription>;
289
367
  changePlan(input: ChangePlanInput): Promise<Subscription>;
368
+ changeQuantity(id: string, input: ChangeQuantityInput): Promise<Subscription>;
290
369
  pause(id: string): Promise<Subscription>;
291
370
  resume(id: string): Promise<Subscription>;
292
371
  cancel(id: string, input?: {
293
372
  atPeriodEnd?: boolean;
294
373
  refund?: 'none' | 'prorated' | 'last_cycle';
295
374
  }): Promise<Subscription>;
375
+ retryCharge(id: string): Promise<Subscription>;
376
+ waivePeriod(id: string, input: WaivePeriodInput): Promise<Subscription>;
377
+ recordUsage(id: string, input: RecordUsageInput): Promise<SubscriptionUsageItem>;
378
+ listUsage(id: string): Promise<SubscriptionUsageItem[]>;
296
379
  createCheckoutSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession>;
297
380
  checkTrialEligibility(input: TrialEligibilityInput): Promise<TrialEligibilityResult>;
298
381
  getCustomerByExternalId(externalId: string): Promise<Customer | null>;
@@ -311,8 +394,50 @@ declare class SubscriptionsClient implements SubscriptionsClientContract {
311
394
  create(input: CreateSubscriptionInput): Promise<Subscription>;
312
395
  list(params?: ListSubscriptionsParams): Promise<PaginatedSubscriptions>;
313
396
  get(id: string): Promise<Subscription>;
397
+ /**
398
+ * A term-only edit: rename the plan, correct the cadence or the amount on
399
+ * the row — no proration, no charge, no period reset. Mirrors
400
+ * `PATCH /api/v1/subscriptions/{id}`. This is what `changePlan()` did
401
+ * before 3.0.0; use `changePlan()` now for an actual plan change.
402
+ */
314
403
  update(id: string, input: UpdateSubscriptionInput): Promise<Subscription>;
404
+ /**
405
+ * A real plan change: prorated and charged immediately when
406
+ * `effective: 'now'`, or scheduled for period end with no charge today.
407
+ * Mirrors `POST /api/v1/subscriptions/{id}/change-plan`. The resolved
408
+ * subscription carries `proration` when the server computed one.
409
+ *
410
+ * This is NOT the old `changePlan()` (a PATCH-style term edit with no
411
+ * proration and no charge) — use `update()` for that.
412
+ */
315
413
  changePlan(input: ChangePlanInput): Promise<Subscription>;
414
+ /**
415
+ * Change the seat quantity: prorated and charged immediately when
416
+ * `effective: 'now'`, or scheduled for period end with no charge today.
417
+ * Mirrors `POST /api/v1/subscriptions/{id}/change-quantity`.
418
+ */
419
+ changeQuantity(id: string, input: ChangeQuantityInput): Promise<Subscription>;
420
+ /**
421
+ * Charge a past-due subscription's card again now, instead of waiting for
422
+ * the next scheduled dunning retry. Mirrors
423
+ * `POST /api/v1/subscriptions/{id}/retry-charge`.
424
+ */
425
+ retryCharge(id: string): Promise<Subscription>;
426
+ /**
427
+ * Forgive the current past-due period — the merchant is not collecting it.
428
+ * Mirrors `POST /api/v1/subscriptions/{id}/waive-period`.
429
+ */
430
+ waivePeriod(id: string, input: WaivePeriodInput): Promise<Subscription>;
431
+ /**
432
+ * Record (upsert) a usage item for the subscription's current billing
433
+ * period. Mirrors `POST /api/v1/subscriptions/{id}/usage`.
434
+ */
435
+ recordUsage(id: string, input: RecordUsageInput): Promise<SubscriptionUsageItem>;
436
+ /**
437
+ * List usage items recorded for the subscription's current billing period.
438
+ * Mirrors `GET /api/v1/subscriptions/{id}/usage`.
439
+ */
440
+ listUsage(id: string): Promise<SubscriptionUsageItem[]>;
316
441
  pause(id: string): Promise<Subscription>;
317
442
  resume(id: string): Promise<Subscription>;
318
443
  cancel(id: string, input?: {
@@ -356,4 +481,4 @@ declare class ThrottleSubscriptionsError extends ThrottleError {
356
481
  });
357
482
  }
358
483
 
359
- export { type TrialEligibilityResult as A, createSubscriptionsClient as B, type CancelSubscriptionInput as C, type DunningBannerProps as D, type ListSubscriptionsParams as L, type MutationState as M, type PaginatedSubscriptions as P, type QueryOptions as Q, type RecurringIntent as R, type Subscription as S, type ThrottleEnvelope as T, type UpdateSubscriptionInput as U, type ChangePlanInput as a, type CheckoutCollectInput as b, type CheckoutCustomerInput as c, type CheckoutSession as d, type CreateCheckoutSessionInput as e, type CreateSubscriptionInput as f, type Customer as g, type CustomerPaymentMethod as h, type Pagination as i, type QueryState as j, type SubscriptionFetcher as k, type SubscriptionInterval as l, type SubscriptionIntervalUnit as m, type SubscriptionInvoiceRefund as n, type SubscriptionProviderProps as o, type SubscriptionSort as p, type SubscriptionStatus as q, type SubscriptionStatusBadgeProps as r, type SubscriptionTaxAddress as s, SubscriptionsClient as t, type SubscriptionsClientContract as u, type SubscriptionsClientOptions as v, ThrottleSubscriptionsError as w, type TrialCountdownProps as x, type TrialEligibilityInput as y, type TrialEligibilityReason as z };
484
+ export { type SubscriptionsClientOptions as A, ThrottleSubscriptionsError as B, type CancelSubscriptionInput as C, type DunningBannerProps as D, type TrialCountdownProps as E, type TrialEligibilityInput as F, type TrialEligibilityReason as G, type TrialEligibilityResult as H, createSubscriptionsClient as I, type ListSubscriptionsParams as L, type MutationState as M, type PaginatedSubscriptions as P, type QueryOptions as Q, type RecordUsageInput as R, type Subscription as S, type ThrottleEnvelope as T, type UpdateSubscriptionInput as U, type WaivePeriodInput as W, type ChangePlanInput as a, type ChangeQuantityInput as b, type CheckoutCollectInput as c, type CheckoutCustomerInput as d, type CheckoutSession as e, type CreateCheckoutSessionInput as f, type CreateSubscriptionInput as g, type Customer as h, type CustomerPaymentMethod as i, type Pagination as j, type QueryState as k, type RecurringIntent as l, type SubscriptionFetcher as m, type SubscriptionInterval as n, type SubscriptionIntervalUnit as o, type SubscriptionInvoiceRefund as p, type SubscriptionProration as q, type SubscriptionProviderProps as r, type SubscriptionRenewalIssue as s, type SubscriptionSort as t, type SubscriptionStatus as u, type SubscriptionStatusBadgeProps as v, type SubscriptionTaxAddress as w, type SubscriptionUsageItem as x, SubscriptionsClient as y, type SubscriptionsClientContract as z };
@@ -24,6 +24,8 @@ interface Subscription {
24
24
  /** When the final installment succeeded. Set only on `completed`. */
25
25
  completedAt: string | null;
26
26
  amount: number;
27
+ /** #688 — number of seats. Per-seat price is `amount`; the period charge is `amount × quantity`. Defaults to 1. */
28
+ quantity: number;
27
29
  currency: string;
28
30
  currentPeriodStart: string;
29
31
  currentPeriodEnd: string;
@@ -42,9 +44,42 @@ interface Subscription {
42
44
  taxAddressSnapshot?: SubscriptionTaxAddress | null;
43
45
  /** `checkout` when captured at signup, `manual` once a merchant edited it. */
44
46
  taxAddressSource?: 'checkout' | 'manual' | null;
47
+ /**
48
+ * Set by the renewal job when renewals are failing (`system_error`) or when
49
+ * a card was charged but the renewal could not be recorded (`orphan_charge`
50
+ * — renewals are paused until Throttle support resolves it). `null` when
51
+ * nothing is wrong.
52
+ */
53
+ renewalIssue: SubscriptionRenewalIssue | null;
54
+ /**
55
+ * Present only on the response from `changePlan()` / `changeQuantity()` —
56
+ * how much of the old plan's unused time credited the new charge.
57
+ */
58
+ proration?: SubscriptionProration | null;
45
59
  createdAt?: string;
46
60
  updatedAt?: string;
47
61
  }
62
+ interface SubscriptionRenewalIssue {
63
+ kind: 'system_error' | 'orphan_charge';
64
+ /** Stable code; `message` is its fixed, merchant-safe sentence. */
65
+ reason: 'tax_quote_failed' | 'internal_error' | 'record_failed';
66
+ count: number;
67
+ firstAt?: string;
68
+ lastAt: string;
69
+ message: string;
70
+ alertedAt?: string | null;
71
+ charge?: {
72
+ transactionId: string | null;
73
+ amount: number;
74
+ currency: string;
75
+ periodStart?: string;
76
+ } | null;
77
+ }
78
+ interface SubscriptionProration {
79
+ creditCents?: number;
80
+ chargedCents?: number;
81
+ fullAmount?: number;
82
+ }
48
83
  interface SubscriptionTaxAddress {
49
84
  addressLine1?: string | null;
50
85
  addressLine2?: string | null;
@@ -137,9 +172,52 @@ interface CancelSubscriptionInput {
137
172
  id: string;
138
173
  atPeriodEnd?: boolean;
139
174
  }
140
- interface ChangePlanInput extends UpdateSubscriptionInput {
175
+ /**
176
+ * `changePlan()`'s input, mirroring `POST /api/v1/subscriptions/{id}/change-plan`:
177
+ * a real plan change, prorated and charged when `effective: 'now'`. For the
178
+ * old term-only edit (rename a plan, correct an amount, with no proration or
179
+ * charge), use `update()` instead — see its migration note in the 3.0.0
180
+ * changeset.
181
+ */
182
+ interface ChangePlanInput {
141
183
  id: string;
142
184
  planReference: string;
185
+ planName?: string;
186
+ interval?: SubscriptionInterval;
187
+ intervalUnit?: SubscriptionIntervalUnit;
188
+ intervalCount?: number;
189
+ amount: number;
190
+ /** `'now'` prorates and charges immediately; `'period_end'` schedules it, charging nothing today. */
191
+ effective: 'now' | 'period_end';
192
+ }
193
+ /** `changeQuantity()`'s input, mirroring `POST /api/v1/subscriptions/{id}/change-quantity`. */
194
+ interface ChangeQuantityInput {
195
+ quantity: number;
196
+ /** `'now'` prorates and charges immediately; `'period_end'` schedules it, charging nothing today. */
197
+ effective: 'now' | 'period_end';
198
+ }
199
+ /** `recordUsage()`'s input, mirroring `POST /api/v1/subscriptions/{id}/usage`. */
200
+ interface RecordUsageInput {
201
+ kind: string;
202
+ unitCount: number;
203
+ unitPriceCents: number;
204
+ }
205
+ /** A usage item recorded against a subscription's current billing period. */
206
+ interface SubscriptionUsageItem {
207
+ id: string;
208
+ subscriptionId: string;
209
+ kind: string;
210
+ unitCount: number;
211
+ unitPriceCents: number;
212
+ totalCents: number;
213
+ periodStart: string;
214
+ periodEnd: string;
215
+ createdAt: string;
216
+ }
217
+ /** `waivePeriod()`'s input, mirroring `POST /api/v1/subscriptions/{id}/waive-period`. */
218
+ interface WaivePeriodInput {
219
+ /** Required: the only record of why the period was not collected. */
220
+ reason: string;
143
221
  }
144
222
  interface RecurringIntent {
145
223
  plan: string;
@@ -287,12 +365,17 @@ interface SubscriptionsClientContract {
287
365
  get(id: string): Promise<Subscription>;
288
366
  update(id: string, input: UpdateSubscriptionInput): Promise<Subscription>;
289
367
  changePlan(input: ChangePlanInput): Promise<Subscription>;
368
+ changeQuantity(id: string, input: ChangeQuantityInput): Promise<Subscription>;
290
369
  pause(id: string): Promise<Subscription>;
291
370
  resume(id: string): Promise<Subscription>;
292
371
  cancel(id: string, input?: {
293
372
  atPeriodEnd?: boolean;
294
373
  refund?: 'none' | 'prorated' | 'last_cycle';
295
374
  }): Promise<Subscription>;
375
+ retryCharge(id: string): Promise<Subscription>;
376
+ waivePeriod(id: string, input: WaivePeriodInput): Promise<Subscription>;
377
+ recordUsage(id: string, input: RecordUsageInput): Promise<SubscriptionUsageItem>;
378
+ listUsage(id: string): Promise<SubscriptionUsageItem[]>;
296
379
  createCheckoutSession(input: CreateCheckoutSessionInput): Promise<CheckoutSession>;
297
380
  checkTrialEligibility(input: TrialEligibilityInput): Promise<TrialEligibilityResult>;
298
381
  getCustomerByExternalId(externalId: string): Promise<Customer | null>;
@@ -311,8 +394,50 @@ declare class SubscriptionsClient implements SubscriptionsClientContract {
311
394
  create(input: CreateSubscriptionInput): Promise<Subscription>;
312
395
  list(params?: ListSubscriptionsParams): Promise<PaginatedSubscriptions>;
313
396
  get(id: string): Promise<Subscription>;
397
+ /**
398
+ * A term-only edit: rename the plan, correct the cadence or the amount on
399
+ * the row — no proration, no charge, no period reset. Mirrors
400
+ * `PATCH /api/v1/subscriptions/{id}`. This is what `changePlan()` did
401
+ * before 3.0.0; use `changePlan()` now for an actual plan change.
402
+ */
314
403
  update(id: string, input: UpdateSubscriptionInput): Promise<Subscription>;
404
+ /**
405
+ * A real plan change: prorated and charged immediately when
406
+ * `effective: 'now'`, or scheduled for period end with no charge today.
407
+ * Mirrors `POST /api/v1/subscriptions/{id}/change-plan`. The resolved
408
+ * subscription carries `proration` when the server computed one.
409
+ *
410
+ * This is NOT the old `changePlan()` (a PATCH-style term edit with no
411
+ * proration and no charge) — use `update()` for that.
412
+ */
315
413
  changePlan(input: ChangePlanInput): Promise<Subscription>;
414
+ /**
415
+ * Change the seat quantity: prorated and charged immediately when
416
+ * `effective: 'now'`, or scheduled for period end with no charge today.
417
+ * Mirrors `POST /api/v1/subscriptions/{id}/change-quantity`.
418
+ */
419
+ changeQuantity(id: string, input: ChangeQuantityInput): Promise<Subscription>;
420
+ /**
421
+ * Charge a past-due subscription's card again now, instead of waiting for
422
+ * the next scheduled dunning retry. Mirrors
423
+ * `POST /api/v1/subscriptions/{id}/retry-charge`.
424
+ */
425
+ retryCharge(id: string): Promise<Subscription>;
426
+ /**
427
+ * Forgive the current past-due period — the merchant is not collecting it.
428
+ * Mirrors `POST /api/v1/subscriptions/{id}/waive-period`.
429
+ */
430
+ waivePeriod(id: string, input: WaivePeriodInput): Promise<Subscription>;
431
+ /**
432
+ * Record (upsert) a usage item for the subscription's current billing
433
+ * period. Mirrors `POST /api/v1/subscriptions/{id}/usage`.
434
+ */
435
+ recordUsage(id: string, input: RecordUsageInput): Promise<SubscriptionUsageItem>;
436
+ /**
437
+ * List usage items recorded for the subscription's current billing period.
438
+ * Mirrors `GET /api/v1/subscriptions/{id}/usage`.
439
+ */
440
+ listUsage(id: string): Promise<SubscriptionUsageItem[]>;
316
441
  pause(id: string): Promise<Subscription>;
317
442
  resume(id: string): Promise<Subscription>;
318
443
  cancel(id: string, input?: {
@@ -356,4 +481,4 @@ declare class ThrottleSubscriptionsError extends ThrottleError {
356
481
  });
357
482
  }
358
483
 
359
- export { type TrialEligibilityResult as A, createSubscriptionsClient as B, type CancelSubscriptionInput as C, type DunningBannerProps as D, type ListSubscriptionsParams as L, type MutationState as M, type PaginatedSubscriptions as P, type QueryOptions as Q, type RecurringIntent as R, type Subscription as S, type ThrottleEnvelope as T, type UpdateSubscriptionInput as U, type ChangePlanInput as a, type CheckoutCollectInput as b, type CheckoutCustomerInput as c, type CheckoutSession as d, type CreateCheckoutSessionInput as e, type CreateSubscriptionInput as f, type Customer as g, type CustomerPaymentMethod as h, type Pagination as i, type QueryState as j, type SubscriptionFetcher as k, type SubscriptionInterval as l, type SubscriptionIntervalUnit as m, type SubscriptionInvoiceRefund as n, type SubscriptionProviderProps as o, type SubscriptionSort as p, type SubscriptionStatus as q, type SubscriptionStatusBadgeProps as r, type SubscriptionTaxAddress as s, SubscriptionsClient as t, type SubscriptionsClientContract as u, type SubscriptionsClientOptions as v, ThrottleSubscriptionsError as w, type TrialCountdownProps as x, type TrialEligibilityInput as y, type TrialEligibilityReason as z };
484
+ export { type SubscriptionsClientOptions as A, ThrottleSubscriptionsError as B, type CancelSubscriptionInput as C, type DunningBannerProps as D, type TrialCountdownProps as E, type TrialEligibilityInput as F, type TrialEligibilityReason as G, type TrialEligibilityResult as H, createSubscriptionsClient as I, type ListSubscriptionsParams as L, type MutationState as M, type PaginatedSubscriptions as P, type QueryOptions as Q, type RecordUsageInput as R, type Subscription as S, type ThrottleEnvelope as T, type UpdateSubscriptionInput as U, type WaivePeriodInput as W, type ChangePlanInput as a, type ChangeQuantityInput as b, type CheckoutCollectInput as c, type CheckoutCustomerInput as d, type CheckoutSession as e, type CreateCheckoutSessionInput as f, type CreateSubscriptionInput as g, type Customer as h, type CustomerPaymentMethod as i, type Pagination as j, type QueryState as k, type RecurringIntent as l, type SubscriptionFetcher as m, type SubscriptionInterval as n, type SubscriptionIntervalUnit as o, type SubscriptionInvoiceRefund as p, type SubscriptionProration as q, type SubscriptionProviderProps as r, type SubscriptionRenewalIssue as s, type SubscriptionSort as t, type SubscriptionStatus as u, type SubscriptionStatusBadgeProps as v, type SubscriptionTaxAddress as w, type SubscriptionUsageItem as x, SubscriptionsClient as y, type SubscriptionsClientContract as z };