@isnap/sdk 1.3.0-next.97 → 1.3.0-next.98

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.
@@ -387,7 +387,7 @@ export interface paths {
387
387
  };
388
388
  /**
389
389
  * List available lines (public marketplace)
390
- * @description Browse the marketplace inventory of unassigned lines. Filter by billing tier, area code, country code, status. Returns only `status: available` and never the iSnap-internal `shared_pool` tier. Unauthenticated — partners use this in prospecting / quote flows.
390
+ * @description Browse the marketplace inventory of unassigned lines. Filter by billing tier, area code, country code, state, country. Returns only `status: available` and never the iSnap-internal `shared_pool` tier — `?status=` therefore accepts `available` alone and refuses any other status with a 400, rather than answering with a list you did not ask for (WHA-2777). Unauthenticated — partners use this in prospecting / quote flows.
391
391
  */
392
392
  get: {
393
393
  parameters: {
@@ -399,6 +399,7 @@ export interface paths {
399
399
  state?: string;
400
400
  /** @description Country filter — ISO alpha-2 code or country name. */
401
401
  country?: string;
402
+ /** @description Comma-separated set of statuses to filter on. Every member must be one of: available — anything else is a 400, never an empty list. Omitted or blank means no status filter. */
402
403
  status?: string;
403
404
  page?: number;
404
405
  limit?: number;
@@ -1059,7 +1060,7 @@ export interface paths {
1059
1060
  put?: never;
1060
1061
  /**
1061
1062
  * Activate a reserved line
1062
- * @description Commit a `reserved` line to `active`. Wholesale partners (no Stripe checkout surface) use this as the second phase of reserve→activate — they reserve, bill their own end-user, then activate within the 15-minute window with no per-line Stripe sub (EOM-metered), and may pick the inbound-only rental variant via `inbound_only`. Direct callers get the test/dev mock-sub shortcut (production direct activation happens via the Stripe webhook on `checkout.session.completed`); `inbound_only` is ignored for them (theirs comes from the checkout price).
1063
+ * @description Commit a `reserved` line to `active`. **Wholesale partners only** (no Stripe checkout surface): this is the second phase of reserve→activate — they reserve, bill their own end-user, then activate within the 15-minute window with no per-line Stripe sub (EOM-metered), and may pick the INBOUND product via `inbound_only` (a line that cannot initiate — the contact must message first, after which the exchange is unrestricted; not receive-only). Direct customers get `402 checkout_required`: their line is activated by the `checkout.session.completed` webhook once `POST /v1/billing/checkout` is paid, which is what mints the Stripe subscription that bills them (§2.5 Flow A). `inbound_only` is meaningless for them theirs comes from the checkout price.
1063
1064
  */
1064
1065
  post: {
1065
1066
  parameters: {
@@ -1109,6 +1110,15 @@ export interface paths {
1109
1110
  "application/json": components["schemas"]["ErrorEnvelope"];
1110
1111
  };
1111
1112
  };
1113
+ /** @description Payment required — no billing relationship entitles this call */
1114
+ 402: {
1115
+ headers: {
1116
+ [name: string]: unknown;
1117
+ };
1118
+ content: {
1119
+ "application/json": components["schemas"]["ErrorEnvelope"];
1120
+ };
1121
+ };
1112
1122
  /** @description Forbidden — caller authenticated but not allowed */
1113
1123
  403: {
1114
1124
  headers: {
@@ -1287,7 +1297,7 @@ export interface paths {
1287
1297
  put?: never;
1288
1298
  /**
1289
1299
  * Convert an owned rental line into a test line
1290
- * @description Flip a rental line you own into an owned test line that backs trials in your own pool (ownership → pool; the monthly price stays the rental-equivalent, not the $0 global-pool rate). Rejected on byod lines, lines you do not own, and lines carrying an active subscription.
1300
+ * @description Flip a rental line you own into an owned test line that backs trials in your own pool (ownership → pool; test lines are free, so the deprecated monthly_price reads 0). Rejected on byod lines, lines you do not own, and lines carrying an active subscription.
1291
1301
  */
1292
1302
  post: {
1293
1303
  parameters: {
@@ -1397,7 +1407,7 @@ export interface paths {
1397
1407
  put?: never;
1398
1408
  /**
1399
1409
  * Revert an owned test line back to a rental line
1400
- * @description Symmetric to convert-to-test: flip an owned test line back to a rental line (ownership → rental, rental price re-stamped). Rejected while the test line still hosts live trials, since reverting would strand them.
1410
+ * @description Symmetric to convert-to-test: flip an owned test line back to a rental line (ownership → rental; monthly_price reads the rental tier price again, derived — nothing is stored). Rejected while the test line still hosts live trials, since reverting would strand them.
1401
1411
  */
1402
1412
  post: {
1403
1413
  parameters: {
@@ -2073,12 +2083,12 @@ export interface paths {
2073
2083
  };
2074
2084
  /**
2075
2085
  * List pre-orders
2076
- * @description Cursor-paginated list of the caller's pre-orders. Filter by status (`pending`, `provisioning`, `ready`, `fulfilled`, `cancelled`, `refunded`) to surface only the ones the dashboard needs.
2086
+ * @description Cursor-paginated list of the caller's pre-orders. Filter by status (`draft`, `provisioning`, `fulfilled`, `cancelled`) to surface only the ones the dashboard needs.
2077
2087
  */
2078
2088
  get: {
2079
2089
  parameters: {
2080
2090
  query?: {
2081
- status?: "draft" | "pending" | "provisioning" | "ready" | "fulfilled" | "cancelled" | "refunded";
2091
+ status?: "draft" | "provisioning" | "fulfilled" | "cancelled";
2082
2092
  cursor?: string;
2083
2093
  limit?: number;
2084
2094
  };
@@ -2138,7 +2148,7 @@ export interface paths {
2138
2148
  put?: never;
2139
2149
  /**
2140
2150
  * Create a pre-order (draft)
2141
- * @description Place a pre-order as a `draft` (WHA-1155). A draft has NO side effects — no provisioning line, no procurement, no Stripe charge — so the partner can hold intent / bill its own end-user first. Call `POST /v1/pre-orders/{id}/confirm` to engage the month and start procurement. `inbound_only` is remembered for confirm.
2151
+ * @description Place a pre-order as a `draft` (WHA-1155). A draft has NO side effects — no provisioning line, no procurement, no Stripe charge — so the partner can hold intent / bill its own end-user first. Call `POST /v1/pre-orders/{id}/confirm` to engage the month and start procurement. A pre-order carries exactly two inputs: the area codes you would accept, in order of preference, and the plan (`inbound_only`), which is remembered for confirm and read back on every response. The body is STRICT (WHA-2644) — any other property is a `400`, including `billing_tier`, `quantity` and `metadata`, which earlier revisions of this contract documented and the server silently discarded.
2142
2152
  */
2143
2153
  post: {
2144
2154
  parameters: {
@@ -2150,8 +2160,6 @@ export interface paths {
2150
2160
  requestBody?: {
2151
2161
  content: {
2152
2162
  "application/json": {
2153
- /** @enum {string} */
2154
- billing_tier: "rental_iphone" | "rental_android";
2155
2163
  /** @default [] */
2156
2164
  preferred_area_codes?: string[];
2157
2165
  /** @default false */
@@ -2527,9 +2535,15 @@ export interface paths {
2527
2535
  requestBody?: {
2528
2536
  content: {
2529
2537
  "application/json": {
2530
- /** Format: uuid */
2538
+ /**
2539
+ * @description Line to check out. Send the `line_<base62>` public ID returned by `POST /v1/lines/{id}/reserve`; the internal UUID is also accepted for backward compatibility. Must be status `reserved`.
2540
+ * @example line_2k9Qp7RtY4mNb8VcXs3Wd6Lf1
2541
+ */
2531
2542
  line_id: string;
2532
- /** @default false */
2543
+ /**
2544
+ * @description Buy the INBOUND rental product instead of the outbound one. An inbound line cannot INITIATE a conversation — the contact must message first, after which the exchange is unrestricted; it is NOT receive-only. Rental tiers only. The chosen Stripe price is the source of truth: `lines.inbound_only` is re-derived from its lookup_key on `customer.subscription.created/updated`.
2545
+ * @default false
2546
+ */
2533
2547
  inbound_only?: boolean;
2534
2548
  };
2535
2549
  };
@@ -2676,33 +2690,39 @@ export interface paths {
2676
2690
  patch?: never;
2677
2691
  trace?: never;
2678
2692
  };
2679
- "/v1/billing/subscriptions": {
2693
+ "/v1/billing/mac-checkout": {
2680
2694
  parameters: {
2681
2695
  query?: never;
2682
2696
  header?: never;
2683
2697
  path?: never;
2684
2698
  cookie?: never;
2685
2699
  };
2700
+ get?: never;
2701
+ put?: never;
2686
2702
  /**
2687
- * List Stripe subscriptions
2688
- * @description Return every active Stripe subscription on the authenticated user's customer record both per-line rental subs and BYOD slot subs. Period boundaries, line link, price ID, and cancellation flag are surfaced verbatim from Stripe.
2703
+ * Start a Stripe Checkout for hosted macOS sessions
2704
+ * @description Create a Stripe Checkout Session for `quantity` rented macOS sessions, priced on a graduated ladder ($35/$30/$25/$20 per session across the 1–10 / 11–30 / 31–50 / 51+ bands). Two rules are enforced here and nowhere else: the quantity must be a whole number of packs at or above the one-pack minimum (`422 mac_quantity_not_a_pack`, the divisor echoed as `issues[0].min`), and a rented session hosts the bridge for one BYOP iPhone so sessions may not exceed the account’s BYOP lines (`422 mac_sessions_exceed_byop_lines`). Stripe’s hosted UI cannot change the quantity afterwards — use `PATCH /v1/billing/subscriptions/{id}`, which applies the same two rules.
2689
2705
  */
2690
- get: {
2706
+ post: {
2691
2707
  parameters: {
2692
2708
  query?: never;
2693
2709
  header?: never;
2694
2710
  path?: never;
2695
2711
  cookie?: never;
2696
2712
  };
2697
- requestBody?: never;
2713
+ requestBody?: {
2714
+ content: {
2715
+ "application/json": components["schemas"]["MacCheckoutBody"];
2716
+ };
2717
+ };
2698
2718
  responses: {
2699
- /** @description Subscription list */
2719
+ /** @description macOS session checkout */
2700
2720
  200: {
2701
2721
  headers: {
2702
2722
  [name: string]: unknown;
2703
2723
  };
2704
2724
  content: {
2705
- "application/json": components["schemas"]["SubscriptionListEnvelope"];
2725
+ "application/json": components["schemas"]["MacCheckoutEnvelope"];
2706
2726
  };
2707
2727
  };
2708
2728
  /** @description Bad request — validation failed */
@@ -2723,6 +2743,24 @@ export interface paths {
2723
2743
  "application/json": components["schemas"]["ErrorEnvelope"];
2724
2744
  };
2725
2745
  };
2746
+ /** @description Not found */
2747
+ 404: {
2748
+ headers: {
2749
+ [name: string]: unknown;
2750
+ };
2751
+ content: {
2752
+ "application/json": components["schemas"]["ErrorEnvelope"];
2753
+ };
2754
+ };
2755
+ /** @description Unprocessable — domain rule violation */
2756
+ 422: {
2757
+ headers: {
2758
+ [name: string]: unknown;
2759
+ };
2760
+ content: {
2761
+ "application/json": components["schemas"]["ErrorEnvelope"];
2762
+ };
2763
+ };
2726
2764
  /** @description Too many requests — rate limit exceeded */
2727
2765
  429: {
2728
2766
  headers: {
@@ -2743,41 +2781,44 @@ export interface paths {
2743
2781
  };
2744
2782
  };
2745
2783
  };
2746
- put?: never;
2747
- post?: never;
2748
2784
  delete?: never;
2749
2785
  options?: never;
2750
2786
  head?: never;
2751
2787
  patch?: never;
2752
2788
  trace?: never;
2753
2789
  };
2754
- "/v1/billing/invoices": {
2790
+ "/v1/billing/subscriptions/{id}": {
2755
2791
  parameters: {
2756
2792
  query?: never;
2757
2793
  header?: never;
2758
2794
  path?: never;
2759
2795
  cookie?: never;
2760
2796
  };
2797
+ get?: never;
2798
+ put?: never;
2799
+ post?: never;
2761
2800
  /**
2762
- * List Stripe invoices
2763
- * @description List the authenticated user's Stripe invoices in reverse-chronological order. Each invoice exposes the period boundaries (unix seconds), the integer-cent amounts, the hosted invoice URL, and the PDF link.
2801
+ * Cancel a subscription
2802
+ * @description Schedule the subscription to cancel at the end of the current billing period. The line remains active until the period rolls over; the partner sees the `cancel_at_period_end: true` flag in `GET /v1/billing/subscriptions` until then.
2764
2803
  */
2765
- get: {
2804
+ delete: {
2766
2805
  parameters: {
2767
2806
  query?: never;
2768
2807
  header?: never;
2769
- path?: never;
2808
+ path: {
2809
+ id: string;
2810
+ };
2770
2811
  cookie?: never;
2771
2812
  };
2772
2813
  requestBody?: never;
2773
2814
  responses: {
2774
- /** @description Invoice list */
2815
+ /** @description Subscription cancelled */
2775
2816
  200: {
2776
2817
  headers: {
2777
2818
  [name: string]: unknown;
2778
2819
  };
2779
2820
  content: {
2780
- "application/json": components["schemas"]["InvoiceListEnvelope"];
2821
+ "application/json": components["schemas"]["BillingMessage"];
2781
2822
  };
2782
2823
  };
2783
2824
  /** @description Bad request — validation failed */
@@ -2798,6 +2839,24 @@ export interface paths {
2798
2839
  "application/json": components["schemas"]["ErrorEnvelope"];
2799
2840
  };
2800
2841
  };
2842
+ /** @description Not found */
2843
+ 404: {
2844
+ headers: {
2845
+ [name: string]: unknown;
2846
+ };
2847
+ content: {
2848
+ "application/json": components["schemas"]["ErrorEnvelope"];
2849
+ };
2850
+ };
2851
+ /** @description Conflict — concurrent or terminal state */
2852
+ 409: {
2853
+ headers: {
2854
+ [name: string]: unknown;
2855
+ };
2856
+ content: {
2857
+ "application/json": components["schemas"]["ErrorEnvelope"];
2858
+ };
2859
+ };
2801
2860
  /** @description Too many requests — rate limit exceeded */
2802
2861
  429: {
2803
2862
  headers: {
@@ -2818,46 +2877,139 @@ export interface paths {
2818
2877
  };
2819
2878
  };
2820
2879
  };
2821
- put?: never;
2822
- post?: never;
2823
- delete?: never;
2824
2880
  options?: never;
2825
2881
  head?: never;
2826
- patch?: never;
2882
+ /**
2883
+ * Change a subscription’s quantity
2884
+ * @description Set the quantity on the subscription’s single quantity-adjustable item — hosted macOS sessions, or BYOP slots. Both directions of the 1:1 rule are enforced: raising sessions above the account’s BYOP lines is `422 mac_sessions_exceed_byop_lines`, and lowering BYOP below the macOS sessions already rented is `422 byop_reduction_strands_mac_sessions`. A macOS quantity must additionally be a whole pack (`422 mac_quantity_not_a_pack`). A subscription that does not carry exactly one adjustable item — a per-line rental, or a wholesale master subscription whose quantities are pushed by metering — is refused `409 subscription_not_quantity_adjustable`.
2885
+ */
2886
+ patch: {
2887
+ parameters: {
2888
+ query?: never;
2889
+ header?: never;
2890
+ path: {
2891
+ id: string;
2892
+ };
2893
+ cookie?: never;
2894
+ };
2895
+ requestBody?: {
2896
+ content: {
2897
+ "application/json": components["schemas"]["SubscriptionQuantityBody"];
2898
+ };
2899
+ };
2900
+ responses: {
2901
+ /** @description Quantity updated */
2902
+ 200: {
2903
+ headers: {
2904
+ [name: string]: unknown;
2905
+ };
2906
+ content: {
2907
+ "application/json": components["schemas"]["SubscriptionQuantityEnvelope"];
2908
+ };
2909
+ };
2910
+ /** @description Bad request — validation failed */
2911
+ 400: {
2912
+ headers: {
2913
+ [name: string]: unknown;
2914
+ };
2915
+ content: {
2916
+ "application/json": components["schemas"]["ErrorEnvelope"];
2917
+ };
2918
+ };
2919
+ /** @description Unauthenticated — missing or invalid bearer token */
2920
+ 401: {
2921
+ headers: {
2922
+ [name: string]: unknown;
2923
+ };
2924
+ content: {
2925
+ "application/json": components["schemas"]["ErrorEnvelope"];
2926
+ };
2927
+ };
2928
+ /** @description Forbidden — caller authenticated but not allowed */
2929
+ 403: {
2930
+ headers: {
2931
+ [name: string]: unknown;
2932
+ };
2933
+ content: {
2934
+ "application/json": components["schemas"]["ErrorEnvelope"];
2935
+ };
2936
+ };
2937
+ /** @description Not found */
2938
+ 404: {
2939
+ headers: {
2940
+ [name: string]: unknown;
2941
+ };
2942
+ content: {
2943
+ "application/json": components["schemas"]["ErrorEnvelope"];
2944
+ };
2945
+ };
2946
+ /** @description Conflict — concurrent or terminal state */
2947
+ 409: {
2948
+ headers: {
2949
+ [name: string]: unknown;
2950
+ };
2951
+ content: {
2952
+ "application/json": components["schemas"]["ErrorEnvelope"];
2953
+ };
2954
+ };
2955
+ /** @description Unprocessable — domain rule violation */
2956
+ 422: {
2957
+ headers: {
2958
+ [name: string]: unknown;
2959
+ };
2960
+ content: {
2961
+ "application/json": components["schemas"]["ErrorEnvelope"];
2962
+ };
2963
+ };
2964
+ /** @description Too many requests — rate limit exceeded */
2965
+ 429: {
2966
+ headers: {
2967
+ [name: string]: unknown;
2968
+ };
2969
+ content: {
2970
+ "application/json": components["schemas"]["ErrorEnvelope"];
2971
+ };
2972
+ };
2973
+ /** @description Internal server error */
2974
+ 500: {
2975
+ headers: {
2976
+ [name: string]: unknown;
2977
+ };
2978
+ content: {
2979
+ "application/json": components["schemas"]["ErrorEnvelope"];
2980
+ };
2981
+ };
2982
+ };
2983
+ };
2827
2984
  trace?: never;
2828
2985
  };
2829
- "/v1/billing/subscriptions/{id}": {
2986
+ "/v1/billing/subscriptions": {
2830
2987
  parameters: {
2831
2988
  query?: never;
2832
2989
  header?: never;
2833
2990
  path?: never;
2834
2991
  cookie?: never;
2835
2992
  };
2836
- get?: never;
2837
- put?: never;
2838
- post?: never;
2839
2993
  /**
2840
- * Cancel a subscription
2841
- * @description Schedule the subscription to cancel at the end of the current billing period. The line remains active until the period rolls over; the partner sees the `cancel_at_period_end: true` flag in `GET /v1/billing/subscriptions` until then.
2994
+ * List Stripe subscriptions
2995
+ * @description Return every active Stripe subscription on the authenticated user's customer record both per-line rental subs and BYOD slot subs. Period boundaries, line link, price ID, and cancellation flag are surfaced verbatim from Stripe.
2842
2996
  */
2843
- delete: {
2997
+ get: {
2844
2998
  parameters: {
2845
2999
  query?: never;
2846
3000
  header?: never;
2847
- path: {
2848
- id: string;
2849
- };
3001
+ path?: never;
2850
3002
  cookie?: never;
2851
3003
  };
2852
3004
  requestBody?: never;
2853
3005
  responses: {
2854
- /** @description Subscription cancelled */
3006
+ /** @description Subscription list */
2855
3007
  200: {
2856
3008
  headers: {
2857
3009
  [name: string]: unknown;
2858
3010
  };
2859
3011
  content: {
2860
- "application/json": components["schemas"]["BillingMessage"];
3012
+ "application/json": components["schemas"]["SubscriptionListEnvelope"];
2861
3013
  };
2862
3014
  };
2863
3015
  /** @description Bad request — validation failed */
@@ -2878,8 +3030,8 @@ export interface paths {
2878
3030
  "application/json": components["schemas"]["ErrorEnvelope"];
2879
3031
  };
2880
3032
  };
2881
- /** @description Not found */
2882
- 404: {
3033
+ /** @description Too many requests — rate limit exceeded */
3034
+ 429: {
2883
3035
  headers: {
2884
3036
  [name: string]: unknown;
2885
3037
  };
@@ -2887,8 +3039,65 @@ export interface paths {
2887
3039
  "application/json": components["schemas"]["ErrorEnvelope"];
2888
3040
  };
2889
3041
  };
2890
- /** @description Conflict concurrent or terminal state */
2891
- 409: {
3042
+ /** @description Internal server error */
3043
+ 500: {
3044
+ headers: {
3045
+ [name: string]: unknown;
3046
+ };
3047
+ content: {
3048
+ "application/json": components["schemas"]["ErrorEnvelope"];
3049
+ };
3050
+ };
3051
+ };
3052
+ };
3053
+ put?: never;
3054
+ post?: never;
3055
+ delete?: never;
3056
+ options?: never;
3057
+ head?: never;
3058
+ patch?: never;
3059
+ trace?: never;
3060
+ };
3061
+ "/v1/billing/invoices": {
3062
+ parameters: {
3063
+ query?: never;
3064
+ header?: never;
3065
+ path?: never;
3066
+ cookie?: never;
3067
+ };
3068
+ /**
3069
+ * List Stripe invoices
3070
+ * @description List the authenticated user's Stripe invoices in reverse-chronological order. Each invoice exposes the period boundaries (unix seconds), the integer-cent amounts, the hosted invoice URL, and the PDF link.
3071
+ */
3072
+ get: {
3073
+ parameters: {
3074
+ query?: never;
3075
+ header?: never;
3076
+ path?: never;
3077
+ cookie?: never;
3078
+ };
3079
+ requestBody?: never;
3080
+ responses: {
3081
+ /** @description Invoice list */
3082
+ 200: {
3083
+ headers: {
3084
+ [name: string]: unknown;
3085
+ };
3086
+ content: {
3087
+ "application/json": components["schemas"]["InvoiceListEnvelope"];
3088
+ };
3089
+ };
3090
+ /** @description Bad request — validation failed */
3091
+ 400: {
3092
+ headers: {
3093
+ [name: string]: unknown;
3094
+ };
3095
+ content: {
3096
+ "application/json": components["schemas"]["ErrorEnvelope"];
3097
+ };
3098
+ };
3099
+ /** @description Unauthenticated — missing or invalid bearer token */
3100
+ 401: {
2892
3101
  headers: {
2893
3102
  [name: string]: unknown;
2894
3103
  };
@@ -2916,6 +3125,9 @@ export interface paths {
2916
3125
  };
2917
3126
  };
2918
3127
  };
3128
+ put?: never;
3129
+ post?: never;
3130
+ delete?: never;
2919
3131
  options?: never;
2920
3132
  head?: never;
2921
3133
  patch?: never;
@@ -3317,6 +3529,7 @@ export interface paths {
3317
3529
  content: {
3318
3530
  "application/json": {
3319
3531
  line_id: string;
3532
+ /** @description Recipient phone number. E.164 preferred; loose national forms are normalized (US default region). Phone-only in v1 — an email / Apple-ID handle is rejected with 400 even when POST /v1/lookup reports it iMessage-capable. */
3320
3533
  to: string;
3321
3534
  body?: string;
3322
3535
  /**
@@ -5872,6 +6085,72 @@ export interface paths {
5872
6085
  patch?: never;
5873
6086
  trace?: never;
5874
6087
  };
6088
+ "/v1/apps": {
6089
+ parameters: {
6090
+ query?: never;
6091
+ header?: never;
6092
+ path?: never;
6093
+ cookie?: never;
6094
+ };
6095
+ /**
6096
+ * Get the app/bridge download manifest (public)
6097
+ * @description Per-platform installer URL, published version, and availability. Requires no pairing and no auth — use it for setup guides, "add a device" flows, reinstalls, and update prompts. The URLs are the same stable 302-redirect endpoints `POST /v1/byod/pair` returns in `download_urls`, built by one shared builder so they cannot drift. `version` is read from the release feed beside the artifact the redirect resolves to, and is `null` when that feed publishes nothing — never a configured placeholder.
6098
+ */
6099
+ get: {
6100
+ parameters: {
6101
+ query?: never;
6102
+ header?: never;
6103
+ path?: never;
6104
+ cookie?: never;
6105
+ };
6106
+ requestBody?: never;
6107
+ responses: {
6108
+ /** @description Per-platform download URL, version and availability */
6109
+ 200: {
6110
+ headers: {
6111
+ [name: string]: unknown;
6112
+ };
6113
+ content: {
6114
+ "application/json": components["schemas"]["AppManifestEnvelope"];
6115
+ };
6116
+ };
6117
+ /** @description Bad request — validation failed */
6118
+ 400: {
6119
+ headers: {
6120
+ [name: string]: unknown;
6121
+ };
6122
+ content: {
6123
+ "application/json": components["schemas"]["ErrorEnvelope"];
6124
+ };
6125
+ };
6126
+ /** @description Too many requests — rate limit exceeded */
6127
+ 429: {
6128
+ headers: {
6129
+ [name: string]: unknown;
6130
+ };
6131
+ content: {
6132
+ "application/json": components["schemas"]["ErrorEnvelope"];
6133
+ };
6134
+ };
6135
+ /** @description Internal server error */
6136
+ 500: {
6137
+ headers: {
6138
+ [name: string]: unknown;
6139
+ };
6140
+ content: {
6141
+ "application/json": components["schemas"]["ErrorEnvelope"];
6142
+ };
6143
+ };
6144
+ };
6145
+ };
6146
+ put?: never;
6147
+ post?: never;
6148
+ delete?: never;
6149
+ options?: never;
6150
+ head?: never;
6151
+ patch?: never;
6152
+ trace?: never;
6153
+ };
5875
6154
  }
5876
6155
  export type webhooks = Record<string, never>;
5877
6156
  export interface components {
@@ -5925,10 +6204,14 @@ export interface components {
5925
6204
  billing_tier: "rental_iphone" | "rental_android" | "byod_imessage" | "byod_android" | "shared_pool" | "shared_imessage";
5926
6205
  /** @description True when the customer owns the underlying hardware (BYOD billing tiers). BYOD lines expose the full line-health surface (offline/degraded events, GET /v1/lines/{id}/health). Rental lines (false) only emit durable, actionable events to keep customers out of transient infrastructure noise they cannot act on. */
5927
6206
  byod: boolean;
5928
- /** @description True when the line is inbound-only: it may only message a handle that has messaged it first (a recipient who has never contacted the line is rejected with 403 outbound_first_forbidden). Inbound-only is a cheaper rental-tier variant (Bloo parity); always false on BYOD/pool lines. */
6207
+ /** @description True when the line cannot INITIATE a conversation: the contact must send the first message, after which the exchange is unrestricted in both directions. It is NOT receive-only the line replies, reacts and sends attachments normally once contacted. Messaging a handle that has never contacted the line is rejected with 403 outbound_first_forbidden, per recipient and with no time limit once unlocked. Cheaper than the outbound tier; always false on BYOD/pool lines. */
5929
6208
  inbound_only: boolean;
5930
6209
  capabilities?: unknown;
5931
6210
  status: string;
6211
+ /**
6212
+ * @deprecated
6213
+ * @description Deprecated — derived from the line tier (0 for pool and owned test lines). The price a customer actually pays lives on the Stripe subscription (GET /v1/billing/subscriptions) or the pre-order amount. Removed at the next MAJOR.
6214
+ */
5932
6215
  monthly_price: number;
5933
6216
  stripe_subscription_id: string | null;
5934
6217
  activated_at: string | null;
@@ -5937,15 +6220,12 @@ export interface components {
5937
6220
  metadata: {
5938
6221
  [key: string]: unknown;
5939
6222
  } | null;
5940
- /** @description True when the line is an owner-provisioned test line (ownership=pool with a set owner) that backs the owner's own trial pool. Its monthly_price is the rental-equivalent, not the $0 global pool rate. */
6223
+ /** @description True when the line is an owner-provisioned test line (ownership=pool with a set owner) that backs the owner's own trial pool. Test lines are free: monthly_price is 0, like every pool line. */
5941
6224
  test_line: boolean;
5942
6225
  /** @description True when the line is a virtual shared-plan line (billing_tier shared_imessage): customer-owned, no dedicated hardware, phone_number empty — sends are proxied onto the shared physical iMessage fleet. Line-scoped API keys, webhooks and per-line quota apply to it like any other line. */
5943
6226
  shared: boolean;
5944
6227
  fulfillment_status?: string | null;
5945
6228
  };
5946
- ApiKeyCreate: components["schemas"]["ApiKey"] & {
5947
- key: string;
5948
- };
5949
6229
  ApiKey: {
5950
6230
  /** Format: uuid */
5951
6231
  id: string;
@@ -5957,6 +6237,9 @@ export interface components {
5957
6237
  created_at: string;
5958
6238
  last_used_at: string | null;
5959
6239
  };
6240
+ ApiKeyCreate: components["schemas"]["ApiKey"] & {
6241
+ key: string;
6242
+ };
5960
6243
  ApiKeyList: {
5961
6244
  api_keys: components["schemas"]["ApiKey"][];
5962
6245
  };
@@ -6164,20 +6447,17 @@ export interface components {
6164
6447
  PreOrder: {
6165
6448
  /** Format: uuid */
6166
6449
  id: string;
6167
- /** @enum {string} */
6168
- billing_tier: "rental_iphone" | "rental_android";
6169
6450
  preferred_area_codes: string[];
6451
+ inbound_only: boolean;
6170
6452
  status: components["schemas"]["PreOrderStatus"];
6171
- stripe_payment_intent_id: string | null;
6172
6453
  stripe_client_secret: string | null;
6173
- amount: number;
6174
6454
  estimated_fulfillment: string | null;
6175
6455
  device_status?: components["schemas"]["DeviceFulfillmentStatus"];
6176
6456
  created_at: string;
6177
6457
  updated_at: string;
6178
6458
  };
6179
6459
  /** @enum {string} */
6180
- PreOrderStatus: "draft" | "pending" | "provisioning" | "ready" | "fulfilled" | "cancelled" | "refunded";
6460
+ PreOrderStatus: "draft" | "provisioning" | "fulfilled" | "cancelled";
6181
6461
  /** @enum {string|null} */
6182
6462
  DeviceFulfillmentStatus: "awaiting_hardware" | "received" | "setup_in_progress" | "ready" | "deployed" | null;
6183
6463
  PreOrderList: {
@@ -6227,6 +6507,66 @@ export interface components {
6227
6507
  */
6228
6508
  billing_cycle: "monthly" | "annual";
6229
6509
  };
6510
+ MacCheckoutEnvelope: {
6511
+ /** @enum {boolean} */
6512
+ success: true;
6513
+ data: components["schemas"]["MacCheckoutResponse"];
6514
+ trace_id: string;
6515
+ request_id: string;
6516
+ };
6517
+ MacCheckoutResponse: {
6518
+ /**
6519
+ * Format: uri
6520
+ * @description Hosted Stripe Checkout URL — redirect the customer here.
6521
+ */
6522
+ checkout_url: string;
6523
+ /**
6524
+ * Format: date-time
6525
+ * @description Session expiry (ISO-8601). Stripe default is 24h.
6526
+ */
6527
+ expires_at: string;
6528
+ /** @description Sessions ordered — echoed back as accepted. */
6529
+ quantity: number;
6530
+ /** @description The pack divisor in force, read from the Stripe Price’s `pack_size` metadata. Quantities must be whole multiples of it, at or above it. */
6531
+ pack_size: number;
6532
+ /** @description Recurring total per period in integer cents, from the Price’s graduated tier ladder. Excludes tax, proration and coupons. */
6533
+ estimated_total_cents: number;
6534
+ };
6535
+ MacCheckoutBody: {
6536
+ /**
6537
+ * @description Number of hosted macOS sessions to rent. Must be a whole number of packs at or above the one-pack minimum — the pack size is read from the Stripe Price and echoed as `pack_size` in the response and in the `422` error `issues[0].min`. A quantity that is not a whole pack is refused `422 mac_quantity_not_a_pack`.
6538
+ * @example 5
6539
+ */
6540
+ quantity: number;
6541
+ /**
6542
+ * @description Stripe price cadence for the session subscription.
6543
+ * @example monthly
6544
+ * @enum {string}
6545
+ */
6546
+ billing_cycle: "monthly" | "quarterly" | "annual";
6547
+ };
6548
+ SubscriptionQuantityEnvelope: {
6549
+ /** @enum {boolean} */
6550
+ success: true;
6551
+ data: components["schemas"]["SubscriptionQuantityResponse"];
6552
+ trace_id: string;
6553
+ request_id: string;
6554
+ };
6555
+ SubscriptionQuantityResponse: {
6556
+ /** @description The Stripe subscription ID (`sub_*`). */
6557
+ subscription_id: string;
6558
+ /** @description The quantity now set on the adjustable item. */
6559
+ quantity: number;
6560
+ /** @description Recurring total per period in integer cents. `null` when the item’s Price carries no computable per-period total. Excludes tax, proration and coupons. */
6561
+ estimated_total_cents: number | null;
6562
+ };
6563
+ SubscriptionQuantityBody: {
6564
+ /**
6565
+ * @description New quantity for the subscription’s single adjustable item — macOS sessions, or BYOP slots. Both products are subject to the 1:1 rule (see the `422` codes), and the macOS product additionally to the pack rule.
6566
+ * @example 10
6567
+ */
6568
+ quantity: number;
6569
+ };
6230
6570
  SubscriptionListEnvelope: {
6231
6571
  /** @enum {boolean} */
6232
6572
  success: true;
@@ -6438,7 +6778,7 @@ export interface components {
6438
6778
  * @description A concrete event type (e.g. `message.received`), a family wildcard (`line.*`), or the catch-all `*`.
6439
6779
  * @enum {string}
6440
6780
  */
6441
- WebhookEventName: "message.queued" | "message.sent" | "message.delivered" | "message.read" | "message.failed" | "message.received" | "message.scheduled" | "message.cancelled" | "message.fallback_triggered" | "reaction.added" | "reaction.received" | "reaction.removed" | "line.connected" | "line.disconnected" | "line.offline" | "line.degraded" | "line.apple_id_flagged" | "line.quota_warning" | "line.quota_exceeded" | "line.capability_changed" | "typing_indicator.started" | "typing_indicator.stopped" | "trial.linked" | "trial.dormant" | "trial.reactivated" | "trial.bind_conflict" | "trial.revoked" | "binding.released" | "pre_order.fulfilled" | "pre_order.cancelled" | "pre_order.refunded" | "webhook.test" | "*" | "message.*" | "reaction.*" | "line.*" | "typing_indicator.*" | "trial.*" | "binding.*" | "pre_order.*" | "webhook.*";
6781
+ WebhookEventName: "message.queued" | "message.sent" | "message.delivered" | "message.read" | "message.failed" | "message.received" | "message.scheduled" | "message.cancelled" | "message.fallback_triggered" | "reaction.added" | "reaction.received" | "reaction.removed" | "line.connected" | "line.disconnected" | "line.offline" | "line.degraded" | "line.apple_id_flagged" | "line.quota_warning" | "line.quota_exceeded" | "line.capability_changed" | "typing_indicator.started" | "typing_indicator.stopped" | "trial.linked" | "trial.dormant" | "trial.reactivated" | "trial.bind_conflict" | "trial.revoked" | "binding.released" | "pre_order.fulfilled" | "pre_order.cancelled" | "webhook.test" | "*" | "message.*" | "reaction.*" | "line.*" | "typing_indicator.*" | "trial.*" | "binding.*" | "pre_order.*" | "webhook.*";
6442
6782
  WebhookList: {
6443
6783
  webhooks: components["schemas"]["Webhook"][];
6444
6784
  };
@@ -6604,6 +6944,27 @@ export interface components {
6604
6944
  region: string;
6605
6945
  /** @example US */
6606
6946
  country_code: string;
6947
+ /**
6948
+ * @description A ZIP code whose geography this area code serves — the postal address to use at purchase, and the address most likely to have the carrier assign this area code. `null` when no ZIP is on record for this code: choosing the address is then a judgement call for the operator, and this catalogue may not know of an overlay covering the code either, so no regional address can be assumed to yield it.
6949
+ * @example 10019
6950
+ */
6951
+ purchase_zip: string | null;
6952
+ /**
6953
+ * @description Fallback ZIPs in the same geography, to retry with if the carrier rejects the primary. Empty when no ZIP is on record.
6954
+ * @example [
6955
+ * "10021",
6956
+ * "10023"
6957
+ * ]
6958
+ */
6959
+ alt_zips: string[];
6960
+ /**
6961
+ * @description Other area codes IN THIS CATALOGUE that overlay the same geography. Non-empty means NO address can guarantee this specific code — the carrier may assign any code in the complex. An empty list is NOT the converse guarantee: it says only that no code this endpoint can offer is known to overlay this one, and an overlay outside the catalogue may still take the number.
6962
+ * @example [
6963
+ * "646",
6964
+ * "917"
6965
+ * ]
6966
+ */
6967
+ shared_with: string[];
6607
6968
  };
6608
6969
  Country: {
6609
6970
  /** @example US */
@@ -6830,6 +7191,41 @@ export interface components {
6830
7191
  [key: string]: unknown;
6831
7192
  };
6832
7193
  };
7194
+ AppManifestEnvelope: {
7195
+ /** @enum {boolean} */
7196
+ success: true;
7197
+ data: components["schemas"]["AppManifestResponse"];
7198
+ trace_id: string;
7199
+ request_id: string;
7200
+ };
7201
+ AppManifestResponse: {
7202
+ macos: components["schemas"]["AppDownloadEntry"];
7203
+ android: components["schemas"]["AppDownloadEntry"];
7204
+ };
7205
+ AppDownloadEntry: {
7206
+ /**
7207
+ * Format: uri
7208
+ * @description Absolute URL of the installer redirect for this platform. Follow it (302) to the actual artifact.
7209
+ * @example https://api.isnap.ai/device/apps/download/macos
7210
+ */
7211
+ url: string;
7212
+ /**
7213
+ * @description Version currently published for this platform, read from the release feed that sits beside the artifact `url` resolves to — so the number announced and the file served cannot name different releases. `null` when that feed publishes nothing or could not be read; `version_status` says which. Never a configured placeholder: a fabricated version makes a failed install and an uninformed console indistinguishable to whoever is checking. Compare it against an installed version to offer an update.
7214
+ * @example 0.0.211
7215
+ */
7216
+ version: string | null;
7217
+ /**
7218
+ * @description Why `version` holds what it holds. `version` is non-null if and only if this is `published`, so a null is never ambiguous (WHA-2765). `none_published` — the feed answered and publishes no version (a 404, or a feed with no readable item): a real fact about the channel, render "version not published". `unreachable` — the feed could not be read (timeout, DNS failure, a body past the size cap): OUR fault or the update host's, and nobody knows what this channel publishes, so do not tell an operator the version is missing. `misconfigured` — an artifact URL is configured for the platform and no feed URL can be derived from it; someone must fix the deployment. `not_configured` — this deployment ships no artifact for the platform, which is the same fact `available: false` carries. Before this field the last three and the first were one indistinguishable `null`, so a broken appcast URL and a healthy pre-release channel rendered identically.
7219
+ * @example published
7220
+ * @enum {string}
7221
+ */
7222
+ version_status: "published" | "none_published" | "unreachable" | "misconfigured" | "not_configured";
7223
+ /**
7224
+ * @description False when this deployment has no artifact configured for the platform. The entry is still returned, so a consumer can hide the affordance instead of surfacing a link that 404s on click.
7225
+ * @example true
7226
+ */
7227
+ available: boolean;
7228
+ };
6833
7229
  };
6834
7230
  responses: never;
6835
7231
  parameters: never;