@openrails/billing-ui 0.234.0 → 0.235.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +39 -2
  2. package/README.md +18 -14
  3. package/dist/account/account-billing.d.ts +6 -3
  4. package/dist/account/change-card-dialog.d.ts +5 -2
  5. package/dist/account/payment-methods-panel.d.ts +6 -3
  6. package/dist/client/client.d.ts +28 -17
  7. package/dist/client/errors.d.ts +1 -4
  8. package/dist/client/generated/error-codes.d.ts +1 -1
  9. package/dist/client/generated/routes.d.ts +42 -28
  10. package/dist/client/generated/wire.d.ts +100 -35
  11. package/dist/client/index.d.ts +2 -2
  12. package/dist/client/types.d.ts +42 -12
  13. package/dist/{client-CWX6QpLa.js → client-BpzCZes3.js} +45 -34
  14. package/dist/client-BpzCZes3.js.map +1 -0
  15. package/dist/client.js +1 -1
  16. package/dist/{config-DZ97SQG2.js → config-qLcHvK0Q.js} +13 -13
  17. package/dist/config-qLcHvK0Q.js.map +1 -0
  18. package/dist/i18n/context.d.ts +1 -1
  19. package/dist/i18n/messages.d.ts +1 -1
  20. package/dist/index.js +184 -177
  21. package/dist/index.js.map +1 -1
  22. package/dist/locales/de.js +5 -4
  23. package/dist/locales/de.js.map +1 -1
  24. package/dist/locales/en.d.ts +5 -4
  25. package/dist/locales/en.js +5 -4
  26. package/dist/locales/en.js.map +1 -1
  27. package/dist/locales/es.js +5 -4
  28. package/dist/locales/es.js.map +1 -1
  29. package/dist/locales/ja.js +5 -4
  30. package/dist/locales/ja.js.map +1 -1
  31. package/dist/locales/ko.js +5 -4
  32. package/dist/locales/ko.js.map +1 -1
  33. package/dist/locales/zh.js +5 -4
  34. package/dist/locales/zh.js.map +1 -1
  35. package/dist/react/context.d.ts +6 -5
  36. package/dist/react/hooks.d.ts +10 -10
  37. package/dist/react.js +1 -1
  38. package/dist/styles.css +1 -1
  39. package/package.json +2 -2
  40. package/dist/client-CWX6QpLa.js.map +0 -1
  41. package/dist/config-DZ97SQG2.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,9 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## Checkout saves a new card under its PSP
4
+
5
+ - Inside a `BillingProvider`, `Checkout` saved a new card with the session
6
+ option's id as `psp_id`, which `POST /me/payment-methods` refuses
7
+ (`invalid_param`); it now sends the option's `psp_id`.
8
+
9
+ ## A default card per currency
10
+
11
+ - `setDefaultPaymentMethod({currency, paymentMethodId})` (`PUT
12
+ /me/default-payment-methods/{currency}`) replaces
13
+ `setCollectionPaymentMethod`: the default card pays the currency's invoices
14
+ and every subscription in it without its own card. `usePaymentMethods()`
15
+ has `setDefault` for `setCollection`, `PaymentMethod.default_currencies`
16
+ replaces `collection_currencies`, and the `payment_method.default_changed`
17
+ change replaces `payment_method.collection_changed`.
18
+ - `AccountBilling` and `PaymentMethodsPanel` take `defaultCurrency` (was
19
+ `collectionCurrency`) and offer "Make default".
20
+ - `setSubscriptionPaymentMethod(id, null)` and `setPaymentMethod(id, null)`
21
+ make a subscription follow the default card; `Subscription.payment_method_id`
22
+ is its own card, null when it follows. The change-card dialog offers "Your
23
+ default card" and opens on any card subscription (`collection_policy`).
24
+
3
25
  ## The customer's summary
4
26
 
5
- - `getAccount()` reads `GET /me`: the balance per currency, the card that
6
- pays each currency, and the unread notice count.
27
+ - `getAccount()` reads `GET /me`: the balance per currency, the default card
28
+ of each currency, and the unread notice count.
7
29
  - `Invoice.delinquent`: overdue past grace; new usage in its currency is
8
30
  refused until it is paid.
9
31
 
@@ -14,6 +36,21 @@
14
36
  final retry, and whether it waits for a new card. Null unless the
15
37
  subscription is `past_due` or `awaiting_method`.
16
38
 
39
+ ## Subscription changes and seats
40
+
41
+ - `changeTier` and `previewTierChange` are `changeSubscription(id,
42
+ { priceId?, quantity?, idempotencyKey, signature? })` and
43
+ `previewSubscriptionChange(id, { priceId?, quantity? })`, on
44
+ `POST /me/subscriptions/{id}/change[/preview]`. `TierChange` and
45
+ `TierChangePreview` are `SubscriptionChange` and `SubscriptionChangePreview`:
46
+ no `action`, a `quantity`. `useSubscriptions().changeTier` is
47
+ `changeSubscription`, its pending state `change`, and its host event
48
+ `subscription.changed`.
49
+ - `Subscription` has `quantity`: the seats of a per-seat price, null
50
+ otherwise; `scheduled_change.quantity` is the seats the next renewal bills. The `tier_change_*` codes are
51
+ `subscription_change_*`, and `quantity_not_allowed` refuses seats on a price
52
+ without them.
53
+
17
54
  ## The public catalog is under /catalog
18
55
 
19
56
  - `listProducts()` reads `GET /catalog/products` (was `GET /products`).
package/README.md CHANGED
@@ -21,10 +21,11 @@ session document, billing fields, browser-autofill behavior, and the checkout
21
21
  request schema.
22
22
 
23
23
  The package lives in the OpenRails repository and shares its version: each
24
- OpenRails release `vX.Y.Z` attaches `openrails-billing-ui-X.Y.Z.tgz`.
24
+ OpenRails release `vX.Y.Z` publishes `@openrails/billing-ui@X.Y.Z` to npm, with
25
+ provenance.
25
26
 
26
27
  ```sh
27
- pnpm add https://github.com/open-rails/openrails/releases/download/vX.Y.Z/openrails-billing-ui-X.Y.Z.tgz
28
+ pnpm add @openrails/billing-ui@X.Y.Z
28
29
  ```
29
30
 
30
31
  ## Checkout
@@ -125,7 +126,7 @@ const billing = createBillingClient({ baseUrl: "/billing/v1", fetch: auth.authFe
125
126
  <BillingProvider client={billing} onChange={() => queryClient.invalidateQueries({ queryKey: ["billing"] })}>
126
127
  <AccountBilling
127
128
  plansHref="/plans"
128
- collectionCurrency="USD" // offers "Use for invoices"
129
+ defaultCurrency="USD" // offers "Make default"
129
130
  sendSolanaTransaction={(tx) => wallet.signAndSend(tx)} // signs a Solana cancel
130
131
  />
131
132
  </BillingProvider>
@@ -150,28 +151,31 @@ routes; `GET /config` is always served.
150
151
  | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
151
152
  | `listProducts()` (each product embeds its prices on sale) | `GET /catalog/products` |
152
153
  | `getConfig()` (capabilities, `currencies`, `payment` with PSPs, `solana.network` and tokens; `client.currencies` is the pinned registry) | `GET /config` |
153
- | `previewTierChange(id, priceId)` | `POST /me/subscriptions/{id}/change-tier/preview` |
154
- | `changeTier(id, { priceId, idempotencyKey, signature? })` | `POST /me/subscriptions/{id}/change-tier` |
154
+ | `previewSubscriptionChange(id, { priceId?, quantity? })` | `POST /me/subscriptions/{id}/change/preview` |
155
+ | `changeSubscription(id, { priceId?, quantity?, idempotencyKey, signature? })` | `POST /me/subscriptions/{id}/change` |
155
156
  | `listSolanaTokens({ priceId, wallet })` | `GET /solana/tokens` |
156
157
 
157
158
  ```ts
158
- const preview = await billing.previewTierChange(sub.id, price.id) // amount_due_now, effective
159
- const change = await billing.changeTier(sub.id, {
160
- priceId: price.id,
159
+ const preview = await billing.previewSubscriptionChange(sub.id, { quantity: 5 }) // amount_due_now, effective
160
+ const change = await billing.changeSubscription(sub.id, {
161
+ quantity: 5,
161
162
  idempotencyKey,
162
163
  })
163
164
  ```
164
165
 
165
- - `changeTier` is a money write. Mint one `idempotencyKey` per attempt and
166
+ - A change moves to another price of the tier group (`priceId`), to other
167
+ seats of a per-seat price (`quantity`), or both. More seats and an upgrade
168
+ charge now; fewer seats and a downgrade apply at the next renewal.
169
+ - `changeSubscription` is a money write. Mint one `idempotencyKey` per attempt and
166
170
  reuse it until the change resolves (`status: "processing"`, a
167
- `tier_change_in_flight` refusal naming `metadata.operation_id`, a 5xx or a
171
+ `subscription_change_in_flight` refusal naming `metadata.operation_id`, a 5xx or a
168
172
  lost response), so OpenRails replays the stored result instead of charging
169
173
  twice. `requires_action` carries `operation_id` for `authenticatePayment`;
170
174
  replay the same key afterwards.
171
175
  - A rail that needs the customer's own step answers `requires_action` with a
172
176
  `next_action`. Solana's is `solana_sign_transactions`:
173
177
  `signWalletAction(change.next_action, send)` signs and sends its
174
- transactions and returns the signature; repeat `changeTier` with the same
178
+ transactions and returns the signature; repeat `changeSubscription` with the same
175
179
  key and `signature`. `cancelSubscription(id, { reason, signature? })` works
176
180
  the same way: its answer is the subscription, unchanged and carrying
177
181
  `next_action` until the signed cancel lands. The hooks run this when given
@@ -215,11 +219,11 @@ provider:
215
219
  - `renderSubscriptionFooter={(s) => ...}` adds host content under a
216
220
  subscription row; `useBillingRefresh()` refetches after host-side changes.
217
221
  - Hooks: `useSubscriptions` (`cancel`, `resume`, `setPaymentMethod`,
218
- `changeTier`, per-row `pending`, `nextCursor`), `usePaymentMethods` (`add`,
219
- `remove`, `setCollection`), `usePayments` (cursor pages), `useProducts` (the
222
+ `changeSubscription`, per-row `pending`, `nextCursor`), `usePaymentMethods` (`add`,
223
+ `remove`, `setDefault`), `usePayments` (cursor pages), `useProducts` (the
220
224
  catalog).
221
225
  Actions resolve to `null` or a `BillingError`; they never throw.
222
- `changeTier` resolves to the `TierChange` instead of `null`. Cancel, resume
226
+ `changeSubscription` resolves to the `SubscriptionChange` instead of `null`. Cancel, resume
223
227
  and the card change answer the subscription, which replaces the row.
224
228
  - Money is exact: `/me` amounts are int64 native-unit strings, scaled by the
225
229
  OpenRails currency registry (`currencies` option to extend it).
@@ -4,8 +4,11 @@ import { PaymentMethodsPanelProps } from './payment-methods-panel';
4
4
  import { SubscriptionsPanelProps } from './subscriptions-panel';
5
5
  export interface AccountBillingProps {
6
6
  cardSetupReturnURL?: PaymentMethodsPanelProps["cardSetupReturnURL"];
7
- /** Offers to make a card the one that collects this currency's invoices. */
8
- collectionCurrency?: string;
7
+ /**
8
+ * Offers to make a card the default for this currency: it pays the
9
+ * currency's invoices and every subscription in it without its own card.
10
+ */
11
+ defaultCurrency?: string;
9
12
  /** Billing country to preselect when adding a card. */
10
13
  defaultCountry?: string;
11
14
  sendSolanaTransaction?: SendSolanaTransaction;
@@ -16,4 +19,4 @@ export interface AccountBillingProps {
16
19
  className?: string;
17
20
  }
18
21
  /** Subscriptions, payment methods and history in one column. */
19
- export declare function AccountBilling({ cardSetupReturnURL, collectionCurrency, defaultCountry, sendSolanaTransaction, plansHref, renderSubscriptionFooter, historyPageSize, appearance, className, }: AccountBillingProps): import("react").JSX.Element;
22
+ export declare function AccountBilling({ cardSetupReturnURL, defaultCurrency, defaultCountry, sendSolanaTransaction, plansHref, renderSubscriptionFooter, historyPageSize, appearance, className, }: AccountBillingProps): import("react").JSX.Element;
@@ -7,8 +7,11 @@ export interface ChangeCardDialogProps {
7
7
  name: string;
8
8
  onOpenChange: (open: boolean) => void;
9
9
  pending: boolean;
10
- /** Resolves null on success; the dialog then closes. */
11
- onConfirm: (paymentMethodId: string) => Promise<BillingError | null>;
10
+ /**
11
+ * The subscription's own card, or null to follow the default card. Resolves
12
+ * null on success; the dialog then closes.
13
+ */
14
+ onConfirm: (paymentMethodId: string | null) => Promise<BillingError | null>;
12
15
  appearance?: CheckoutAppearance;
13
16
  }
14
17
  export declare function ChangeCardDialog({ subscription, name, onOpenChange, pending, onConfirm, appearance, }: ChangeCardDialogProps): React.JSX.Element;
@@ -3,8 +3,11 @@ import * as React from "react";
3
3
  export interface PaymentMethodsPanelProps {
4
4
  /** Return target after off-page card verification; see `SavePaymentMethod`. */
5
5
  cardSetupReturnURL?: (setupId: string) => string;
6
- /** Offers to make a card the one that collects this currency's invoices. */
7
- collectionCurrency?: string;
6
+ /**
7
+ * Offers to make a card the default for this currency: it pays the
8
+ * currency's invoices and every subscription in it without its own card.
9
+ */
10
+ defaultCurrency?: string;
8
11
  /** Billing country to preselect when adding a card. */
9
12
  defaultCountry?: string;
10
13
  appearance?: CheckoutAppearance;
@@ -14,4 +17,4 @@ export interface PaymentMethodsPanelProps {
14
17
  * The customer's saved cards. "Add card" offers each PSP of the merchant's
15
18
  * payment setup (`GET /config`) that saves a card in the page.
16
19
  */
17
- export declare function PaymentMethodsPanel({ cardSetupReturnURL, collectionCurrency, defaultCountry, appearance, className, }: PaymentMethodsPanelProps): React.JSX.Element;
20
+ export declare function PaymentMethodsPanel({ cardSetupReturnURL, defaultCurrency, defaultCountry, appearance, className, }: PaymentMethodsPanelProps): React.JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { CheckoutSource } from '../source';
2
- import { Account, CardSetup, CheckoutSessionLink, PublicConfig, PaymentAuthentication, CurrencyScales, Invoice, ListPage, NewCard, NextAction, Page, Payment, PaymentMethod, Product, SolanaToken, Subscription, TierChange, TierChangePreview } from './types';
2
+ import { Account, CardSetup, CheckoutSessionLink, PublicConfig, PaymentAuthentication, CurrencyScales, Invoice, ListPage, NewCard, NextAction, Page, Payment, PaymentMethod, Product, SolanaToken, Subscription, SubscriptionChange, SubscriptionChangePreview } from './types';
3
3
  export interface BillingClientOptions {
4
4
  /** OpenRails embedded mount. Default "/billing/v1". */
5
5
  baseUrl?: string;
@@ -35,7 +35,15 @@ export interface ListOptions {
35
35
  cursor?: string;
36
36
  signal?: AbortSignal;
37
37
  }
38
- /** A cursor list read: pass the previous page's `next_cursor` for the next. */
38
+ /**
39
+ * A subscription change: another price of its tier group, other seats of a
40
+ * per-seat price, or both. A quantity for a price that is not per seat is
41
+ * refused (`quantity_not_allowed`).
42
+ */
43
+ export interface SubscriptionChangeInput {
44
+ priceId?: string;
45
+ quantity?: number;
46
+ }
39
47
  export interface CursorOptions {
40
48
  limit?: number;
41
49
  cursor?: string | null;
@@ -81,23 +89,23 @@ export declare function createBillingClient(options?: BillingClientOptions): {
81
89
  }): Promise<Subscription>;
82
90
  /** Undoes a scheduled cancel before the period ends. */
83
91
  resumeSubscription(subscriptionId: string): Promise<Subscription>;
84
- setSubscriptionPaymentMethod(subscriptionId: string, paymentMethodId: string): Promise<Subscription>;
85
- /** What `changeTier` would charge now and at the next renewal. */
86
- previewTierChange(subscriptionId: string, priceId: string, signal?: AbortSignal): Promise<TierChangePreview>;
92
+ /** Gives the subscription its own card; `null` makes it follow the default. */
93
+ setSubscriptionPaymentMethod(subscriptionId: string, paymentMethodId: string | null): Promise<Subscription>;
94
+ /** What `changeSubscription` would charge now and at the next renewal. */
95
+ previewSubscriptionChange(subscriptionId: string, change: SubscriptionChangeInput, signal?: AbortSignal): Promise<SubscriptionChangePreview>;
87
96
  /**
88
- * Moves the subscription to another price of its tier group: an upgrade
89
- * charges the saved card now, a downgrade applies at period end.
90
- * `idempotencyKey` identifies this attempt; reuse it until the change
91
- * resolves (`processing`, a `tier_change_in_flight` refusal or a lost
92
- * response) so the stored result replays instead of charging twice. A
93
- * wallet next action (Solana) is completed with `signWalletAction` and
94
- * the change repeated with `signature`.
97
+ * Moves the subscription to another price of its tier group, to other
98
+ * seats of a per-seat price, or both. An upgrade and more seats charge
99
+ * the saved card now; a downgrade and fewer seats apply at period end.
100
+ * Reuse `idempotencyKey` until the change resolves (`processing`, a
101
+ * `subscription_change_in_flight` refusal or a lost response) so the
102
+ * stored result replays instead of charging twice. A Solana wallet next
103
+ * action is completed with `signWalletAction`, then repeated with `signature`.
95
104
  */
96
- changeTier(subscriptionId: string, input: {
97
- priceId: string;
105
+ changeSubscription(subscriptionId: string, input: SubscriptionChangeInput & {
98
106
  idempotencyKey: string;
99
107
  signature?: string;
100
- }): Promise<TierChange>;
108
+ }): Promise<SubscriptionChange>;
101
109
  listPaymentMethods(opts?: CursorOptions): Promise<ListPage<PaymentMethod>>;
102
110
  /**
103
111
  * Stores a card entered in the page with the PSP `psp_id`: a Collect.js
@@ -120,8 +128,11 @@ export declare function createBillingClient(options?: BillingClientOptions): {
120
128
  confirmPaymentAuthentication(operationId: string): Promise<void>;
121
129
  /** `pending` when the provider is still converging (202). */
122
130
  removePaymentMethod(paymentMethodId: string): Promise<"removed" | "pending">;
123
- /** Makes the card the one that collects one currency's invoices. */
124
- setCollectionPaymentMethod(input: {
131
+ /**
132
+ * Makes the card the default for one currency: it pays the currency's
133
+ * invoices and every subscription in it without its own card.
134
+ */
135
+ setDefaultPaymentMethod(input: {
125
136
  currency: string;
126
137
  paymentMethodId: string;
127
138
  }): Promise<void>;
@@ -16,10 +16,7 @@ export declare class BillingError extends Error {
16
16
  constructor(status: number, body: BillingErrorBody);
17
17
  }
18
18
  export declare const isBillingError: (value: unknown) => value is BillingError;
19
- /**
20
- * A server failure (HTTP 5xx) from any client or host source that carries a
21
- * numeric `status`. It is surfaced at once, never retried behind the caller.
22
- */
19
+ /** A server failure (HTTP 5xx) from any client or host source that carries a numeric `status`. */
23
20
  export declare const isServerError: (value: unknown) => boolean;
24
21
  export declare function localError(code: string, message: string): BillingError;
25
22
  export declare function readBillingError(res: Response): Promise<BillingError>;
@@ -1,4 +1,4 @@
1
- export type OpenRailsErrorCode = "access_token_invalid" | "access_token_issuer_unknown" | "access_token_merchant_not_bound" | "admission_captured" | "admission_not_found" | "allowance_meter_not_found" | "allowance_source_in_use" | "allowance_source_invalid" | "already_owned" | "api_host_claim_missing" | "api_host_reserved" | "api_host_taken" | "api_host_unproven" | "as_of_required" | "authentication_required" | "authentication_unavailable" | "authorization_unavailable" | "billing_archive_integrity" | "billing_archive_invalid_artifact" | "billing_archive_merchant_mismatch" | "billing_archive_not_empty" | "billing_archive_unavailable" | "billing_archive_unsupported_state" | "billing_policy_not_found" | "cancel_unsupported_on_rail" | "captcha_invalid" | "captcha_required" | "card_attempts_blocked" | "card_declined" | "card_not_saved" | "card_requires_https" | "catalog_benefit_overlap" | "catalog_revision_conflict" | "catalog_updates_disabled" | "checkout_attempt_closed" | "checkout_attempt_expired" | "checkout_offer_unavailable" | "checkout_payment_in_progress" | "checkout_request_invalid" | "checkout_session_expired" | "checkout_session_not_found" | "checkout_session_unavailable" | "collection_payment_method_invalid" | "collection_payment_method_required" | "creation_refused" | "credential_custody_transition_required" | "credential_expired" | "credential_identity_mismatch" | "credential_operation_conflict" | "credential_revoked" | "credential_source_read_only" | "credential_store_read_only" | "credentials_manage_required" | "credit_grant_held" | "credit_grant_not_found" | "credit_grant_unavailable" | "csrf_origin_denied" | "currency_unsupported" | "custodian_capture_unavailable" | "customer_action_required" | "customer_email_required" | "customer_not_found" | "customer_payment_unsupported" | "customer_proof_required" | "customer_session_required" | "dashboard_invalid" | "database_busy" | "default_rate_card_not_found" | "default_rate_card_required" | "delegated_principal_invalid" | "email_unverified" | "finding_action_failed" | "finding_not_actionable" | "hold_not_found" | "host_event_not_found" | "host_merchant_mismatch" | "host_principal_invalid" | "idempotency_key_in_use" | "idempotency_key_required" | "idempotency_key_reused" | "insufficient_credits" | "insufficient_funds" | "insufficient_scope" | "internal_error" | "invalid_api_host" | "invalid_cursor" | "invalid_customer_id" | "invalid_email" | "invalid_host_event_request" | "invalid_name" | "invalid_param" | "invalid_payment_method" | "invalid_psp_reference" | "invalid_query" | "invalid_request_body" | "invalid_settlement_status_request" | "invalid_user" | "invites_disabled" | "invoice_action_not_allowed" | "invoice_not_retryable" | "invoice_retry_idempotency_conflict" | "invoice_retry_in_progress" | "invoice_retry_outcome_unknown" | "invoker_scoped_principal" | "last_owner" | "members_manage_required" | "merchant_binding_mismatch" | "merchant_configuration_application_conflict" | "merchant_configuration_revision_conflict" | "merchant_context_mismatch" | "merchant_creation_payment_method_required" | "merchant_directory_unavailable" | "merchant_not_found" | "merchant_selector_invalid" | "merchant_unresolved" | "meter_in_use" | "meter_rate_card_conflict" | "method_not_allowed" | "metrics_query_invalid" | "model_unavailable" | "name_reserved" | "name_taken" | "order_has_recurring_line" | "order_line_unavailable" | "order_not_cancelable" | "order_not_payable" | "order_payment_in_progress" | "order_total_changed" | "payment_duplicate_refused" | "payment_exceeds_due" | "payment_failed" | "payment_idempotency_conflict" | "payment_in_progress" | "payment_method_delete_failed" | "payment_method_delete_unsupported" | "payment_method_not_psp_vaulted" | "payment_method_not_usable" | "payment_method_psp_mismatch" | "payment_method_required" | "payment_method_same_vault" | "payment_method_stale" | "payment_method_update_failed" | "payment_method_update_retry_required" | "payment_method_update_unsupported" | "payment_not_found" | "payment_not_refundable" | "payment_not_retryable" | "payment_option_unavailable" | "payment_provider_rejected" | "permission_required" | "price_change_currency_mismatch" | "price_change_target_archived" | "price_increase_notice_too_short" | "price_key_cadence_conflict" | "price_key_not_found" | "price_migration_not_found" | "price_not_found" | "price_not_sellable" | "product_not_found" | "product_tier_group_conflict" | "product_tier_group_in_use" | "provider_billing_observation_conflict" | "provider_cancel_held" | "provider_operation_conflict" | "provider_operation_has_billing_evidence" | "provider_operation_not_found" | "provider_operation_not_open" | "provider_operation_not_refused" | "provider_operation_refused" | "provider_outcome_unknown" | "psp_claim_requires_proof" | "psp_credentials_rejected" | "psp_exists" | "psp_key_taken" | "psp_last_active" | "psp_not_found" | "purchase_review_resolved" | "quantity_not_allowed" | "rate_card_currency_mismatch" | "rate_card_has_overrides" | "rate_card_product_not_found" | "rate_limit_exceeded" | "rebill_terms_committed" | "refund_failed" | "refund_rail_unavailable" | "refund_unsupported" | "rename_too_soon" | "renames_disabled" | "request_body_too_large" | "resource_access_denied" | "resource_conflict" | "resource_not_found" | "role_escalation" | "route_not_found" | "scheduled_change_exists" | "sender_proof_required" | "service_credential_customer_scope_denied" | "service_credential_invalid" | "service_credential_merchant_unresolved" | "service_credential_resource_scope_denied" | "service_unavailable" | "solana_rpc_unavailable" | "solana_transaction_refused" | "spend_delegation_not_found" | "step_up_required" | "step_up_unavailable" | "subscription_not_active" | "subscription_not_found" | "subscription_paid_through" | "subscription_resumable" | "tier_change_already_scheduled" | "tier_change_cadence_unsupported" | "tier_change_credit_exceeds_price" | "tier_change_cycle_unknown" | "tier_change_idempotency_conflict" | "tier_change_idempotency_key_required" | "tier_change_in_flight" | "tier_change_period_unknown" | "tier_change_provider_conflict" | "tier_change_refused" | "tier_change_renewal_due" | "tier_change_requires_linked_plan" | "tier_change_target_inactive" | "tier_change_unsupported_on_rail" | "trial_unsupported_on_rail" | "unknown_field" | "unknown_role" | "unsupported_media_type" | "usage_meter_invalid" | "usage_meter_not_found" | "usage_rate_card_invalid" | "use_dpop_nonce" | "webhook_account_mismatch" | "webhook_invalid" | "widget_generation_invalid";
1
+ export type OpenRailsErrorCode = "access_token_invalid" | "access_token_issuer_unknown" | "access_token_merchant_not_bound" | "admission_captured" | "admission_not_found" | "allowance_meter_not_found" | "allowance_source_in_use" | "allowance_source_invalid" | "already_owned" | "as_of_required" | "authentication_required" | "authentication_unavailable" | "authorization_unavailable" | "billing_archive_integrity" | "billing_archive_invalid_artifact" | "billing_archive_merchant_mismatch" | "billing_archive_not_empty" | "billing_archive_unavailable" | "billing_archive_unsupported_state" | "billing_policy_not_found" | "cancel_unsupported_on_rail" | "captcha_invalid" | "captcha_required" | "card_attempts_blocked" | "card_declined" | "card_not_saved" | "card_requires_https" | "catalog_benefit_overlap" | "catalog_revision_conflict" | "checkout_attempt_closed" | "checkout_attempt_expired" | "checkout_offer_unavailable" | "checkout_payment_in_progress" | "checkout_request_invalid" | "checkout_session_expired" | "checkout_session_not_found" | "checkout_session_unavailable" | "credential_custody_transition_required" | "credential_expired" | "credential_identity_mismatch" | "credential_operation_conflict" | "credential_revoked" | "credential_source_read_only" | "credential_store_read_only" | "credit_grant_held" | "credit_grant_not_found" | "credit_grant_unavailable" | "csrf_origin_denied" | "currency_unsupported" | "custodian_capture_unavailable" | "customer_action_required" | "customer_email_required" | "customer_not_found" | "customer_payment_unsupported" | "customer_proof_required" | "customer_session_required" | "dashboard_invalid" | "database_busy" | "default_payment_method_invalid" | "default_payment_method_required" | "default_rate_card_not_found" | "default_rate_card_required" | "delegated_principal_invalid" | "finding_action_failed" | "finding_not_actionable" | "hold_not_found" | "host_event_not_found" | "host_merchant_mismatch" | "host_principal_invalid" | "idempotency_key_in_use" | "idempotency_key_required" | "idempotency_key_reused" | "insufficient_credits" | "insufficient_funds" | "insufficient_scope" | "internal_error" | "invalid_cursor" | "invalid_customer_id" | "invalid_host_event_request" | "invalid_param" | "invalid_payment_method" | "invalid_psp_reference" | "invalid_query" | "invalid_request_body" | "invalid_settlement_status_request" | "invoice_action_not_allowed" | "invoice_not_retryable" | "invoice_retry_idempotency_conflict" | "invoice_retry_in_progress" | "invoice_retry_outcome_unknown" | "invoker_scoped_principal" | "merchant_binding_mismatch" | "merchant_configuration_application_conflict" | "merchant_configuration_revision_conflict" | "merchant_context_mismatch" | "merchant_directory_unavailable" | "merchant_not_found" | "merchant_selector_invalid" | "merchant_unresolved" | "meter_in_use" | "meter_rate_card_conflict" | "method_not_allowed" | "metrics_query_invalid" | "model_unavailable" | "order_has_recurring_line" | "order_line_unavailable" | "order_not_cancelable" | "order_not_payable" | "order_payment_in_progress" | "order_total_changed" | "payment_duplicate_refused" | "payment_exceeds_due" | "payment_failed" | "payment_idempotency_conflict" | "payment_in_progress" | "payment_method_delete_failed" | "payment_method_delete_unsupported" | "payment_method_not_psp_vaulted" | "payment_method_not_usable" | "payment_method_psp_mismatch" | "payment_method_required" | "payment_method_same_vault" | "payment_method_stale" | "payment_method_update_failed" | "payment_method_update_retry_required" | "payment_method_update_unsupported" | "payment_not_found" | "payment_not_refundable" | "payment_not_retryable" | "payment_option_unavailable" | "payment_provider_rejected" | "permission_required" | "price_change_currency_mismatch" | "price_change_target_archived" | "price_increase_notice_too_short" | "price_key_cadence_conflict" | "price_key_not_found" | "price_migration_not_found" | "price_not_found" | "price_not_sellable" | "product_not_found" | "product_tier_group_conflict" | "product_tier_group_in_use" | "provider_billing_observation_conflict" | "provider_cancel_held" | "provider_operation_conflict" | "provider_operation_has_billing_evidence" | "provider_operation_not_found" | "provider_operation_not_open" | "provider_operation_not_refused" | "provider_operation_refused" | "provider_outcome_unknown" | "psp_claim_requires_proof" | "psp_credentials_rejected" | "psp_exists" | "psp_key_taken" | "psp_last_active" | "psp_not_found" | "purchase_review_resolved" | "quantity_not_allowed" | "rate_card_currency_mismatch" | "rate_card_has_overrides" | "rate_card_product_not_found" | "rate_limit_exceeded" | "rebill_terms_committed" | "refund_failed" | "refund_rail_unavailable" | "refund_unsupported" | "request_body_too_large" | "resource_access_denied" | "resource_conflict" | "resource_not_found" | "revision_mismatch" | "route_not_found" | "scheduled_change_exists" | "sender_proof_required" | "service_credential_customer_scope_denied" | "service_credential_invalid" | "service_credential_merchant_unresolved" | "service_credential_resource_scope_denied" | "service_unavailable" | "solana_rpc_unavailable" | "solana_transaction_refused" | "spend_delegation_not_found" | "step_up_required" | "step_up_unavailable" | "stored_credential_required" | "subscription_change_already_scheduled" | "subscription_change_cadence_unsupported" | "subscription_change_credit_exceeds_price" | "subscription_change_cycle_unknown" | "subscription_change_idempotency_conflict" | "subscription_change_idempotency_key_required" | "subscription_change_in_flight" | "subscription_change_period_unknown" | "subscription_change_provider_conflict" | "subscription_change_refused" | "subscription_change_renewal_due" | "subscription_change_requires_linked_plan" | "subscription_change_target_inactive" | "subscription_change_unsupported_on_rail" | "subscription_not_active" | "subscription_not_found" | "subscription_paid_through" | "subscription_resumable" | "trial_unsupported_on_rail" | "unknown_field" | "unsupported_media_type" | "usage_meter_invalid" | "usage_meter_not_found" | "usage_rate_card_invalid" | "use_dpop_nonce" | "webhook_account_mismatch" | "webhook_invalid" | "widget_generation_invalid";
2
2
  export type OpenRailsErrorType = "api_error" | "authentication_error" | "authorization_error" | "card_error" | "invalid_request_error" | "rate_limit_error";
3
3
  export declare const OPENRAILS_ERROR_CODES: Readonly<Record<OpenRailsErrorCode, {
4
4
  status: number;
@@ -39,20 +39,6 @@ export declare const OPENRAILS_ROUTES: readonly [{
39
39
  };
40
40
  readonly errors: readonly ["service_unavailable"];
41
41
  readonly errorSets: readonly ["tier:public"];
42
- }, {
43
- readonly method: "GET";
44
- readonly path: "/metrics";
45
- readonly group: "meta";
46
- readonly auth: "public";
47
- readonly permission: null;
48
- readonly sensitive: false;
49
- readonly mountedWhen: null;
50
- readonly request: null;
51
- readonly responses: {
52
- readonly 200: "text/plain";
53
- };
54
- readonly errors: readonly [];
55
- readonly errorSets: readonly ["tier:public"];
56
42
  }, {
57
43
  readonly method: "GET";
58
44
  readonly path: "/v1/config";
@@ -360,7 +346,7 @@ export declare const OPENRAILS_ROUTES: readonly [{
360
346
  readonly responses: {
361
347
  readonly 200: "Subscription";
362
348
  };
363
- readonly errors: readonly ["authentication_required", "card_declined", "invalid_param", "payment_method_not_psp_vaulted", "payment_method_psp_mismatch", "payment_method_same_vault", "payment_provider_rejected", "rebill_terms_committed", "resource_conflict", "resource_not_found", "service_unavailable"];
349
+ readonly errors: readonly ["authentication_required", "card_declined", "default_payment_method_required", "invalid_param", "payment_method_not_psp_vaulted", "payment_method_psp_mismatch", "payment_method_same_vault", "payment_method_stale", "payment_provider_rejected", "rebill_terms_committed", "resource_conflict", "resource_not_found", "service_unavailable"];
364
350
  readonly errorSets: readonly ["tier:customer", "request"];
365
351
  }, {
366
352
  readonly method: "GET";
@@ -407,32 +393,32 @@ export declare const OPENRAILS_ROUTES: readonly [{
407
393
  readonly errorSets: readonly ["tier:customer", "request"];
408
394
  }, {
409
395
  readonly method: "POST";
410
- readonly path: "/v1/me/subscriptions/{id}/change-tier";
396
+ readonly path: "/v1/me/subscriptions/{id}/change";
411
397
  readonly group: "customer";
412
398
  readonly auth: "customer";
413
399
  readonly permission: null;
414
400
  readonly sensitive: false;
415
401
  readonly mountedWhen: null;
416
- readonly request: "CustomerChangeTierParams";
402
+ readonly request: "CustomerChangeSubscriptionParams";
417
403
  readonly responses: {
418
- readonly 200: "TierChange";
419
- readonly 202: "TierChange";
404
+ readonly 200: "SubscriptionChange";
405
+ readonly 202: "SubscriptionChange";
420
406
  };
421
- readonly errors: readonly ["authentication_required", "card_declined", "customer_action_required", "customer_email_required", "invalid_param", "payment_duplicate_refused", "payment_method_stale", "payment_provider_rejected", "price_change_currency_mismatch", "price_not_found", "product_not_found", "rebill_terms_committed", "resource_conflict", "resource_not_found", "scheduled_change_exists", "service_unavailable", "solana_rpc_unavailable", "solana_transaction_refused", "subscription_not_active", "subscription_not_found", "tier_change_in_flight", "tier_change_period_unknown", "tier_change_provider_conflict", "tier_change_refused", "tier_change_requires_linked_plan", "tier_change_target_inactive", "tier_change_unsupported_on_rail"];
407
+ readonly errors: readonly ["authentication_required", "card_declined", "customer_action_required", "customer_email_required", "invalid_param", "payment_duplicate_refused", "payment_method_stale", "payment_provider_rejected", "price_change_currency_mismatch", "price_not_found", "product_not_found", "quantity_not_allowed", "rebill_terms_committed", "resource_conflict", "resource_not_found", "scheduled_change_exists", "service_unavailable", "solana_rpc_unavailable", "solana_transaction_refused", "subscription_change_already_scheduled", "subscription_change_credit_exceeds_price", "subscription_change_cycle_unknown", "subscription_change_idempotency_conflict", "subscription_change_idempotency_key_required", "subscription_change_in_flight", "subscription_change_period_unknown", "subscription_change_provider_conflict", "subscription_change_refused", "subscription_change_renewal_due", "subscription_change_requires_linked_plan", "subscription_change_target_inactive", "subscription_change_unsupported_on_rail", "subscription_not_active", "subscription_not_found"];
422
408
  readonly errorSets: readonly ["tier:customer", "request"];
423
409
  }, {
424
410
  readonly method: "POST";
425
- readonly path: "/v1/me/subscriptions/{id}/change-tier/preview";
411
+ readonly path: "/v1/me/subscriptions/{id}/change/preview";
426
412
  readonly group: "customer";
427
413
  readonly auth: "customer";
428
414
  readonly permission: null;
429
415
  readonly sensitive: false;
430
416
  readonly mountedWhen: null;
431
- readonly request: "ChangeTierParams";
417
+ readonly request: "PreviewSubscriptionChangeParams";
432
418
  readonly responses: {
433
- readonly 200: "TierChangePreview";
419
+ readonly 200: "SubscriptionChangePreview";
434
420
  };
435
- readonly errors: readonly ["authentication_required", "card_declined", "customer_email_required", "invalid_param", "payment_method_stale", "payment_provider_rejected", "price_change_currency_mismatch", "price_not_found", "product_not_found", "resource_conflict", "resource_not_found", "service_unavailable", "subscription_not_active", "subscription_not_found", "tier_change_in_flight", "tier_change_period_unknown", "tier_change_provider_conflict", "tier_change_requires_linked_plan", "tier_change_target_inactive", "tier_change_unsupported_on_rail"];
421
+ readonly errors: readonly ["authentication_required", "card_declined", "customer_email_required", "invalid_param", "payment_method_stale", "payment_provider_rejected", "price_change_currency_mismatch", "price_not_found", "product_not_found", "quantity_not_allowed", "resource_conflict", "resource_not_found", "service_unavailable", "subscription_change_already_scheduled", "subscription_change_credit_exceeds_price", "subscription_change_cycle_unknown", "subscription_change_in_flight", "subscription_change_period_unknown", "subscription_change_provider_conflict", "subscription_change_renewal_due", "subscription_change_requires_linked_plan", "subscription_change_target_inactive", "subscription_change_unsupported_on_rail", "subscription_not_active", "subscription_not_found"];
436
422
  readonly errorSets: readonly ["tier:customer", "request"];
437
423
  }, {
438
424
  readonly method: "GET";
@@ -605,17 +591,17 @@ export declare const OPENRAILS_ROUTES: readonly [{
605
591
  readonly errorSets: readonly ["tier:customer", "request"];
606
592
  }, {
607
593
  readonly method: "PUT";
608
- readonly path: "/v1/me/collection-payment-method";
594
+ readonly path: "/v1/me/default-payment-methods/{currency}";
609
595
  readonly group: "customer";
610
596
  readonly auth: "customer";
611
597
  readonly permission: null;
612
598
  readonly sensitive: false;
613
599
  readonly mountedWhen: null;
614
- readonly request: "CollectionPaymentMethod";
600
+ readonly request: "SetDefaultPaymentMethodParams";
615
601
  readonly responses: {
616
- readonly 200: "CollectionPaymentMethod";
602
+ readonly 200: "DefaultPaymentMethod";
617
603
  };
618
- readonly errors: readonly ["collection_payment_method_invalid", "invalid_param"];
604
+ readonly errors: readonly ["authentication_required", "card_declined", "default_payment_method_invalid", "invalid_param", "payment_method_not_psp_vaulted", "payment_method_psp_mismatch", "payment_method_same_vault", "payment_method_stale", "payment_provider_rejected", "rebill_terms_committed", "resource_conflict", "resource_not_found", "service_unavailable"];
619
605
  readonly errorSets: readonly ["tier:customer", "request"];
620
606
  }, {
621
607
  readonly method: "GET";
@@ -660,6 +646,34 @@ export declare const OPENRAILS_ROUTES: readonly [{
660
646
  };
661
647
  readonly errors: readonly ["card_declined", "card_not_saved", "card_requires_https", "credential_custody_transition_required", "invalid_param", "payment_method_update_failed", "payment_method_update_retry_required", "payment_method_update_unsupported", "payment_provider_rejected", "resource_conflict", "resource_not_found", "service_unavailable"];
662
648
  readonly errorSets: readonly ["tier:customer", "request"];
649
+ }, {
650
+ readonly method: "PATCH";
651
+ readonly path: "/v1/me/payment-methods/{id}";
652
+ readonly group: "customer";
653
+ readonly auth: "customer";
654
+ readonly permission: null;
655
+ readonly sensitive: false;
656
+ readonly mountedWhen: null;
657
+ readonly request: "UpdatePaymentMethodParams";
658
+ readonly responses: {
659
+ readonly 200: "PaymentMethod";
660
+ };
661
+ readonly errors: readonly ["card_requires_https", "invalid_param", "payment_method_not_usable", "payment_method_update_unsupported", "payment_provider_rejected", "provider_outcome_unknown", "resource_not_found", "service_unavailable"];
662
+ readonly errorSets: readonly ["tier:customer", "request"];
663
+ }, {
664
+ readonly method: "POST";
665
+ readonly path: "/v1/me/payment-methods/{id}/verify";
666
+ readonly group: "customer";
667
+ readonly auth: "customer";
668
+ readonly permission: null;
669
+ readonly sensitive: false;
670
+ readonly mountedWhen: null;
671
+ readonly request: null;
672
+ readonly responses: {
673
+ readonly 200: "PaymentMethod";
674
+ };
675
+ readonly errors: readonly ["card_attempts_blocked", "card_declined", "insufficient_funds", "invalid_param", "payment_method_not_usable", "payment_method_update_unsupported", "payment_provider_rejected", "provider_outcome_unknown", "resource_not_found", "service_unavailable"];
676
+ readonly errorSets: readonly ["tier:customer"];
663
677
  }, {
664
678
  readonly method: "DELETE";
665
679
  readonly path: "/v1/me/payment-methods/{id}";