@feelflow/ffid-sdk 9.0.0 → 10.1.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.
@@ -126,6 +126,781 @@ declare const EFFECTIVE_SUBSCRIPTION_STATUSES: readonly ["active", "active_cance
126
126
  */
127
127
  type EffectiveSubscriptionStatus = (typeof EFFECTIVE_SUBSCRIPTION_STATUSES)[number];
128
128
 
129
+ /** Billing interval for subscriptions */
130
+ type FFIDBillingInterval = 'monthly' | 'yearly';
131
+ /**
132
+ * Supported currencies for billing responses.
133
+ * Mirrors the platform's `SupportedCurrency` enum (`jpy` = zero-decimal Japanese Yen, `usd` = US Dollar).
134
+ */
135
+ type FFIDSupportedCurrency = 'jpy' | 'usd';
136
+ /** Service information returned by plans endpoint */
137
+ interface FFIDServiceInfo {
138
+ id: string;
139
+ code: string;
140
+ name: string;
141
+ description: string | null;
142
+ isActive: boolean;
143
+ createdAt: string;
144
+ plans: FFIDPlanInfo[];
145
+ }
146
+ /** Plan information returned by plans endpoint */
147
+ interface FFIDPlanInfo {
148
+ id: string;
149
+ serviceId: string;
150
+ code: string;
151
+ name: string;
152
+ description: string | null;
153
+ minSeats: number;
154
+ maxSeats: number | null;
155
+ seatSelectionEnabled: boolean;
156
+ trialDays: number;
157
+ /** flat: period fee; per_seat: multiply by selected quantity. Older servers omit this. */
158
+ pricingModel?: 'per_seat' | 'flat';
159
+ /**
160
+ * flat: member limit of the plan (`null` = unlimited). Absent on per_seat plans
161
+ * and on FFID servers released before #6392 — do not read absence as unlimited.
162
+ */
163
+ maxMembers?: number | null;
164
+ /** flat: monthly AI credit allowance (0 = none). Absent on older servers. */
165
+ monthlyCredits?: number;
166
+ /** Plan tier in the personal / team / enterprise ladder. Absent on older servers. */
167
+ tier?: 'personal' | 'team' | 'enterprise';
168
+ /**
169
+ * Monthly price in the smallest currency unit.
170
+ *
171
+ * `null` when the plan is not self-serve priced. Once the FFID #4482 rollout
172
+ * is enabled, `customPricing: true` (Enterprise / "contact us") plans return
173
+ * `null` here — branch on `customPricing` to render an inquiry CTA rather than
174
+ * a price. Standard plans always return a number.
175
+ */
176
+ priceMonthly: number | null;
177
+ priceYearly: number | null;
178
+ currency: string;
179
+ isActive: boolean;
180
+ displayOrder: number;
181
+ customPricing: boolean;
182
+ createdAt: string;
183
+ }
184
+ /** Response from list plans endpoint */
185
+ interface FFIDListPlansResponse {
186
+ services: FFIDServiceInfo[];
187
+ count: number;
188
+ }
189
+ /** Subscription details returned by ext API (sanitized, no Stripe IDs) */
190
+ interface FFIDSubscriptionDetail {
191
+ id: string;
192
+ organizationId: string;
193
+ organizationName: string;
194
+ serviceCode: string;
195
+ serviceName: string;
196
+ planCode: string;
197
+ planName: string;
198
+ status: FFIDSubscriptionStatus;
199
+ paymentMethod: string | null;
200
+ billingInterval: FFIDBillingInterval;
201
+ quantity: number;
202
+ currentPeriodStart: string | null;
203
+ currentPeriodEnd: string | null;
204
+ trialStart: string | null;
205
+ trialEnd: string | null;
206
+ canceledAt: string | null;
207
+ /**
208
+ * `true` while a cancellation is reserved until the period end. `status` stays
209
+ * `active` until then; the subscription becomes `canceled` at `currentPeriodEnd`.
210
+ * The reservation can only be withdrawn in the FFID portal (there is no SDK method).
211
+ */
212
+ cancelAtPeriodEnd: boolean;
213
+ /**
214
+ * Change reserved until the period end (null = nothing reserved).
215
+ *
216
+ * Every decrease — a lower plan, paid → free, fewer seats, yearly → monthly — is
217
+ * reserved instead of applied immediately (FFID #6327). The current plan, seats and
218
+ * interval stay in effect until `scheduledAt`. Withdraw it with `cancelPendingDowngrade()`.
219
+ */
220
+ pendingDowngrade: {
221
+ /** Plan in effect after the period end. Equals `planCode` for a seat-only or interval-only reservation. */
222
+ planCode: string;
223
+ planName: string;
224
+ /** Billing interval in effect after the period end */
225
+ billingInterval: FFIDBillingInterval;
226
+ /**
227
+ * Seat count in effect after the period end. `null` = the seat count does not change.
228
+ * Seat reductions are made in the FFID portal; this lets you show them (8.0.0).
229
+ * FFID servers released before #6327 omit it, so compare with `== null` at runtime.
230
+ */
231
+ quantity: number | null;
232
+ scheduledAt: string;
233
+ requestedAt: string;
234
+ } | null;
235
+ createdAt: string;
236
+ }
237
+ /** Parameters for subscribing to a plan */
238
+ interface FFIDSubscribeParams {
239
+ /** Organization ID (UUID) */
240
+ organizationId: string;
241
+ /** Plan code (e.g., 'free', 'basic', 'pro') */
242
+ planCode: string;
243
+ /** Billing interval (default: 'monthly') */
244
+ billingInterval?: FFIDBillingInterval;
245
+ /**
246
+ * Number of seats (default: plan's minSeats). per_seat plans only — a flat plan
247
+ * answers 400 `VALIDATION_ERROR` (`details.field: 'quantity'`), so omit it there.
248
+ */
249
+ quantity?: number;
250
+ /** User ID for seat auto-assignment (only needed for service-key mode) */
251
+ userId?: string;
252
+ }
253
+ /** Sanitized subscription fields returned by subscribe/reactivate endpoints (no Stripe IDs) */
254
+ interface FFIDSubscriptionSummary {
255
+ id: string;
256
+ organizationId: string;
257
+ serviceId: string;
258
+ planId: string;
259
+ status: FFIDSubscriptionStatus;
260
+ paymentMethod: string | null;
261
+ billingInterval: FFIDBillingInterval;
262
+ quantity: number;
263
+ currentPeriodStart: string | null;
264
+ currentPeriodEnd: string | null;
265
+ trialStart: string | null;
266
+ trialEnd: string | null;
267
+ canceledAt: string | null;
268
+ cancelAtPeriodEnd: boolean;
269
+ createdAt: string;
270
+ }
271
+ /** Response from subscribe endpoint */
272
+ interface FFIDSubscribeResponse {
273
+ subscription: FFIDSubscriptionSummary;
274
+ service: {
275
+ id: string;
276
+ code: string;
277
+ name: string;
278
+ };
279
+ plan: {
280
+ id: string;
281
+ code: string;
282
+ name: string;
283
+ priceMonthly: number;
284
+ priceYearly: number | null;
285
+ trialDays: number;
286
+ };
287
+ /** True if a canceled subscription was reactivated */
288
+ reactivated?: boolean;
289
+ /** True if Stripe checkout is needed (canceled paid plan reactivation) */
290
+ needsCheckout?: boolean;
291
+ }
292
+ /** Parameters for changing plan */
293
+ interface FFIDChangePlanParams {
294
+ /** Subscription ID (UUID) */
295
+ subscriptionId: string;
296
+ /** New plan code */
297
+ planCode: string;
298
+ /** New billing interval (default: keeps current) */
299
+ billingInterval?: FFIDBillingInterval;
300
+ }
301
+ /**
302
+ * Response from change plan endpoint.
303
+ *
304
+ * - An increase (higher plan / monthly → yearly) applies immediately and the difference up to
305
+ * the current period end is charged now. `pendingDowngrade` is absent.
306
+ * - A decrease (lower plan / paid → free / yearly → monthly) is reserved until the period end:
307
+ * `pendingDowngrade` is present and `subscription.planCode` is still the current plan.
308
+ * Nothing is charged or refunded. A contract that cannot be reserved still changes
309
+ * immediately, without a refund: one with no period end, or a paid → paid decrease on a
310
+ * contract without a Stripe subscription.
311
+ */
312
+ interface FFIDChangePlanResponse {
313
+ message: string;
314
+ subscription: {
315
+ id: string;
316
+ organizationId: string;
317
+ serviceCode: string;
318
+ planCode: string;
319
+ planName: string;
320
+ billingInterval: FFIDBillingInterval;
321
+ status: FFIDSubscriptionStatus;
322
+ isUpgrade: boolean;
323
+ };
324
+ /** Present when the change is a decrease reserved until the period end */
325
+ pendingDowngrade?: {
326
+ planCode: string;
327
+ planName: string;
328
+ scheduledAt: string;
329
+ };
330
+ }
331
+ /** Parameters for canceling subscription */
332
+ interface FFIDCancelSubscriptionParams {
333
+ /** Subscription ID (UUID) */
334
+ subscriptionId: string;
335
+ /** Cancellation reason code */
336
+ reason?: 'too_expensive' | 'missing_features' | 'switched_service' | 'rarely_used' | 'customer_service' | 'other';
337
+ /** Additional cancellation details */
338
+ reasonDetails?: string;
339
+ }
340
+ /**
341
+ * Response from cancel subscription endpoint.
342
+ *
343
+ * Since 8.0.0 a contract billed through Stripe is **reserved** for cancellation at the period
344
+ * end (FFID #6327): `status` stays `active`, `cancelAtPeriodEnd` is `true` and `cancelAt` is the
345
+ * period end. Access continues until then and nothing is refunded. A contract that cannot be
346
+ * reserved (no Stripe subscription, no period end yet, or Stripe not configured on FFID) is
347
+ * canceled immediately (`status: 'canceled'`, `cancelAtPeriodEnd: false`, `cancelAt: null`).
348
+ * Branch on `cancelAtPeriodEnd`, not on whether the contract uses Stripe.
349
+ *
350
+ * Do not treat this response as "access revoked". The `subscription.canceled` webhook arrives
351
+ * at reservation (`source: 'user_initiated'`) and again at the period end
352
+ * (`source: 'stripe_confirmed'`); see `FFIDSubscriptionCanceledPayload`.
353
+ */
354
+ interface FFIDCancelSubscriptionResponse {
355
+ message: string;
356
+ subscription: {
357
+ id: string;
358
+ organizationId: string;
359
+ /** `active` while the cancellation is reserved; `canceled` only for an immediate cancellation */
360
+ status: FFIDSubscriptionStatus;
361
+ canceledAt: string | null;
362
+ /** `true` when the cancellation is reserved until the period end */
363
+ cancelAtPeriodEnd: boolean;
364
+ /** When the reserved cancellation takes effect (the period end). `null` for an immediate cancellation */
365
+ cancelAt: string | null;
366
+ };
367
+ }
368
+ /**
369
+ * Response from cancel pending downgrade endpoint.
370
+ *
371
+ * Withdraws the reserved change on the Stripe side as well, so the current plan, seats and
372
+ * interval simply continue after the period end. It does not withdraw a reserved
373
+ * cancellation — that is done in the FFID portal.
374
+ */
375
+ interface FFIDCancelPendingDowngradeResponse {
376
+ message: string;
377
+ subscription: {
378
+ id: string;
379
+ organizationId: string;
380
+ serviceCode: string;
381
+ planCode: string;
382
+ billingInterval: FFIDBillingInterval;
383
+ status: FFIDSubscriptionStatus;
384
+ /** Always null after successful cancellation */
385
+ pendingDowngradePlanId: null;
386
+ };
387
+ }
388
+ /** Parameters for previewing plan change */
389
+ interface FFIDPreviewPlanChangeParams {
390
+ /** Subscription ID (UUID) */
391
+ subscriptionId: string;
392
+ /** New plan code */
393
+ planCode: string;
394
+ /** New billing interval (default: keeps current) */
395
+ billingInterval?: FFIDBillingInterval;
396
+ }
397
+ /** Plan change preview line item */
398
+ interface FFIDPlanChangeLineItem {
399
+ description: string;
400
+ amount: number;
401
+ }
402
+ /** Fields shared by every plan-change preview variant (internal; consumers use `FFIDPlanChangePreview`) */
403
+ interface FFIDPlanChangePreviewBase {
404
+ /** Discriminant for preview response variants (reserved for future unions with e.g. seat-change previews) */
405
+ type: 'plan-change';
406
+ /** Current plan display info. `price` is the period total: flat fee, or per-seat price times quantity. */
407
+ currentPlan: {
408
+ name: string;
409
+ price: number;
410
+ };
411
+ /** New plan display info. `price` is the period total: flat fee, or per-seat price times quantity. */
412
+ newPlan: {
413
+ name: string;
414
+ price: number;
415
+ };
416
+ billingInterval: FFIDBillingInterval;
417
+ isUpgrade: boolean;
418
+ /** Full amount of the next billing cycle at the new plan's standard price. Never overwritten by Stripe proration data. */
419
+ nextInvoiceAmount: number;
420
+ nextInvoiceDate: string | null;
421
+ currency: FFIDSupportedCurrency;
422
+ /** true when amounts are estimated from local prices (no Stripe proration data) */
423
+ isEstimate: boolean;
424
+ /** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
425
+ estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
426
+ lineItems: FFIDPlanChangeLineItem[];
427
+ }
428
+ /**
429
+ * Plan change proration preview. It is computed with the same rules as `changePlan()`.
430
+ *
431
+ * `willApplyAtPeriodEnd` is a discriminant that constrains related fields at the type level:
432
+ * - `true`: a decrease reserved until the period end. `proratedAmount` is always 0 (nothing is
433
+ * charged or refunded now); `effectiveDate` mirrors the subscription's `currentPeriodEnd`
434
+ * (may be `null` when the subscription has no active billing cycle yet).
435
+ * - `false`: immediate change. `effectiveDate` is always `null`. For an increase,
436
+ * `proratedAmount` is the difference up to the current period end that is charged now
437
+ * (possibly Stripe-refined). A decrease on a contract that cannot be reserved also lands here:
438
+ * `0` for a contract without a Stripe subscription (no refund), but Stripe's prorated amount —
439
+ * negative, credited on the next invoice — for a Stripe contract with no period end yet
440
+ * (e.g. during a trial).
441
+ */
442
+ type FFIDPlanChangePreview = FFIDPlanChangePreviewBase & ({
443
+ willApplyAtPeriodEnd: true;
444
+ effectiveDate: string | null;
445
+ /** 0 on period-end-deferred changes; charge happens at the next invoice */
446
+ proratedAmount: 0;
447
+ } | {
448
+ willApplyAtPeriodEnd: false;
449
+ effectiveDate: null;
450
+ /** Difference up to the current period end charged now (see the type doc for the decrease cases) */
451
+ proratedAmount: number;
452
+ });
453
+ /** Response from plan change preview endpoint */
454
+ interface FFIDPlanChangePreviewResponse {
455
+ preview: FFIDPlanChangePreview;
456
+ }
457
+ /** Parameters for previewing a seat count change */
458
+ interface FFIDPreviewSeatChangeParams {
459
+ /** Subscription ID (UUID) */
460
+ subscriptionId: string;
461
+ /** New seat quantity. Must be an integer within the plan's allowed range. */
462
+ quantity: number;
463
+ }
464
+ /** Seat change preview line item */
465
+ interface FFIDSeatChangeLineItem {
466
+ description: string;
467
+ amount: number;
468
+ }
469
+ /**
470
+ * Seat change proration preview.
471
+ *
472
+ * Sister type to `FFIDPlanChangePreview`. The shared `type` discriminant lets
473
+ * consumers narrow a preview payload without inspecting unrelated fields.
474
+ *
475
+ * - `willApplyAtPeriodEnd=true`: a seat reduction reserved until the period end.
476
+ * `proratedAmount` is 0 and `effectiveDate` is when the new seat count applies.
477
+ * - Otherwise the change applies immediately. For an increase, `proratedAmount` is the amount
478
+ * charged now up to the current period end. A reduction that cannot be reserved is normally
479
+ * `0`, but can be negative (a credit on the next invoice) for a Stripe contract with no period
480
+ * end yet or when only the contract unit price is known.
481
+ * - `isEstimate=true` (default when Stripe is not configured or data is unavailable):
482
+ * `proratedAmount` is computed locally. `isEstimate=false`: it reflects Stripe's live
483
+ * proration calculation.
484
+ *
485
+ * `nextInvoiceAmount` is a local estimate: flat period fee, or `unitPrice * newQuantity`.
486
+ * Flat capacity changes have zero prorated cost.
487
+ *
488
+ * `pricingUnavailable=true` means custom pricing or an unverified contracted Stripe
489
+ * Price. Hide amounts; zero is not a quote. `custom_pricing` permits the existing
490
+ * unbilled seat-change flow. Require another preview before confirmation only when
491
+ * pricing is unavailable and the reason is not `custom_pricing`. `stripe_error` also
492
+ * covers invoice/address failures after the contract price is known; use
493
+ * `pricingUnavailable`, not the reason alone, to decide whether to hide amounts.
494
+ * `no_stripe_data` means invoice proration is unavailable even if the contract unit
495
+ * price is known. Portal seat PUT independently enforces subscription limits;
496
+ * external consumers should guide users to the FFID portal for seat changes.
497
+ */
498
+ interface FFIDSeatChangePreview {
499
+ /** flat: unitPrice is the whole period fee; per_seat: multiply by capacity. */
500
+ pricingModel?: 'per_seat' | 'flat';
501
+ /** Discriminant for preview response variants (pairs with `FFIDPlanChangePreview.type`) */
502
+ type: 'seat-change';
503
+ currentQuantity: number;
504
+ newQuantity: number;
505
+ /** Per-seat price for the current billing interval */
506
+ unitPrice: number;
507
+ billingInterval: FFIDBillingInterval;
508
+ /**
509
+ * Amount charged now for the rest of the current billing period. A reserved seat reduction
510
+ * (`willApplyAtPeriodEnd: true`) is always `0`; see the type doc for reductions that cannot
511
+ * be reserved. Also `0` when `pricingUnavailable === true`; hide it instead of quoting zero.
512
+ */
513
+ proratedAmount: number;
514
+ /** Next invoice full amount — flat period fee or per-seat price times newQuantity */
515
+ nextInvoiceAmount: number;
516
+ nextInvoiceDate: string | null;
517
+ currency: FFIDSupportedCurrency;
518
+ /** true when proratedAmount is a local estimate rather than Stripe invoice/proration data */
519
+ isEstimate: boolean;
520
+ /** Hide amounts: custom pricing or contracted Stripe Price could not be verified. */
521
+ pricingUnavailable?: boolean;
522
+ /** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
523
+ estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
524
+ /**
525
+ * `true` when the seat reduction would be reserved until the period end (8.0.0).
526
+ * Absent or `false` = the change applies immediately.
527
+ */
528
+ willApplyAtPeriodEnd?: boolean;
529
+ /** When the reserved seat count applies (present when `willApplyAtPeriodEnd` is `true`) */
530
+ effectiveDate?: string | null;
531
+ lineItems: FFIDSeatChangeLineItem[];
532
+ }
533
+ /** Response from seat change preview endpoint */
534
+ interface FFIDSeatChangePreviewResponse {
535
+ preview: FFIDSeatChangePreview;
536
+ }
537
+
538
+ /** Deployment environments a catalog publication can apply to (single source) */
539
+ declare const FFID_CATALOG_ENVIRONMENTS: readonly ["staging", "production"];
540
+ /** Deployment environment a catalog publication applies to */
541
+ type FFIDCatalogEnvironment = (typeof FFID_CATALOG_ENVIRONMENTS)[number];
542
+ /**
543
+ * Tax behavior of a published price.
544
+ * `inclusive`: displayed price contains Stripe-calculated tax.
545
+ * `exclusive`: tax is added on top of the base price.
546
+ */
547
+ type FFIDTaxBehavior = 'inclusive' | 'exclusive';
548
+ /**
549
+ * Publication lifecycle statuses (single source — the type, the SDK runtime
550
+ * validator, and consumer sets all derive from this tuple so a new literal
551
+ * cannot be added to one side only).
552
+ */
553
+ declare const FFID_CATALOG_PUBLICATION_STATUSES: readonly ["approved", "superseded", "revoking", "revoked"];
554
+ /**
555
+ * Publication lifecycle status.
556
+ * - `approved`: sellable — the only status that permits new paid checkout
557
+ * - `superseded`: replaced by a newer revision (old sessions may sell through
558
+ * until `sellThroughUntil`)
559
+ * - `revoking`: emergency stop in progress — never sellable
560
+ * - `revoked`: emergency stop completed — never sellable
561
+ */
562
+ type FFIDCatalogPublicationStatus = (typeof FFID_CATALOG_PUBLICATION_STATUSES)[number];
563
+ /**
564
+ * Human-approved publication record binding a catalog revision to the
565
+ * content/config hashes reviewed at approval time.
566
+ *
567
+ * All `*Hash` fields are lowercase SHA-256 hex computed with the shared
568
+ * canonicalization helpers in `shared/catalog-hash` — consumers re-hash the
569
+ * content they actually render and must refuse new sales on any mismatch.
570
+ */
571
+ interface FFIDCatalogPublication {
572
+ serviceCode: string;
573
+ environment: FFIDCatalogEnvironment;
574
+ catalogVersion: string;
575
+ praxisCopyHash: string;
576
+ ffidCheckoutCopyHash: string;
577
+ legalDisclosureHash: string;
578
+ taxConfigurationHash: string;
579
+ paymentConfigurationHash: string;
580
+ scopeHash: string;
581
+ /** Monotonically increasing per (service, environment) publication counter */
582
+ salesEpoch: number;
583
+ /** FFID-generated immutable human-review approval ID */
584
+ approvalId: string;
585
+ /** ISO 8601 timestamp of the recorded human review */
586
+ reviewedAt: string;
587
+ /** ISO 8601 timestamp the publication became effective */
588
+ effectiveAt: string;
589
+ /** ISO 8601 timestamp the publication was superseded (null while current) */
590
+ supersededAt: string | null;
591
+ /** ISO 8601 upper bound for old-session sell-through (null unless superseded) */
592
+ sellThroughUntil: string | null;
593
+ /** ISO 8601 timestamp an emergency revoke took effect (null unless revoking/revoked) */
594
+ revocationEffectiveAt: string | null;
595
+ status: FFIDCatalogPublicationStatus;
596
+ }
597
+ /**
598
+ * A plan inside a published catalog revision (public-safe snapshot).
599
+ * Never contains Stripe Product/Price identifiers or other secrets.
600
+ */
601
+ interface FFIDPublishedPlan {
602
+ /**
603
+ * Plan code — always a lowercase slug (`^[a-z0-9][a-z0-9_-]*$`).
604
+ * Per-service open set; see the FFID repo's
605
+ * `docs/04-api/PLAN_CODE_CONTRACT.md` for the full guarantees.
606
+ */
607
+ code: string;
608
+ name: string;
609
+ description: string | null;
610
+ /** Monthly price in the catalog currency; null when monthly is not offered */
611
+ priceMonthly: number | null;
612
+ /** Yearly price in the catalog currency; null when yearly is not offered */
613
+ priceYearly: number | null;
614
+ currency: string;
615
+ /** Billing intervals actually purchasable for this plan */
616
+ billingIntervals: FFIDBillingInterval[];
617
+ taxBehavior: FFIDTaxBehavior;
618
+ minSeats: number;
619
+ maxSeats: number | null;
620
+ displayOrder: number;
621
+ /** Billing model (10.0.0). Absent on snapshots published before ADR-008 (e.g. praxis) */
622
+ pricingModel?: 'per_seat' | 'flat';
623
+ /** flat: member limit (`null` = unlimited). Absent on older snapshots */
624
+ maxMembers?: number | null;
625
+ /** flat: monthly AI credit allowance (0 = none). Absent on older snapshots */
626
+ monthlyCredits?: number;
627
+ /** Plan tier. Absent on older snapshots */
628
+ tier?: 'personal' | 'team' | 'enterprise';
629
+ }
630
+ /**
631
+ * Response of GET /api/v1/subscriptions/ext/catalog/{serviceCode}.
632
+ *
633
+ * `catalogVersion` always equals `publication.catalogVersion`; it is hoisted
634
+ * to the top level so consumers can pin the version (e.g. as
635
+ * `expectedCatalogVersion` for checkout) without digging into the publication.
636
+ */
637
+ interface FFIDPublishedCatalog {
638
+ service: {
639
+ code: string;
640
+ name: string;
641
+ };
642
+ catalogVersion: string;
643
+ publication: FFIDCatalogPublication;
644
+ plans: FFIDPublishedPlan[];
645
+ }
646
+
647
+ /**
648
+ * Credits API types (SDK 10.0.0 / FFID #6395, CREDITS_API.md v1.3.1).
649
+ *
650
+ * `pricing_model='flat'` plans (fixed fee + member limit + monthly AI credits)
651
+ * keep a credit ledger in FFID. These types mirror the FFID server's response
652
+ * shapes exactly; the FFID repository type-checks them against the server types
653
+ * (`src/lib/credits/__tests__/sdk-credits-types.sync.test.ts`), so a field changed
654
+ * on one side only fails FFID's gate.
655
+ *
656
+ * Kept out of `types/index.ts` (file-size limit). Exported directly from the
657
+ * package entry.
658
+ */
659
+
660
+ /** Low-balance threshold, in percent of `monthlyCredits` (`credits.low`, `isLow`) */
661
+ declare const FFID_CREDITS_LOW_THRESHOLD_PERCENT = 20;
662
+ /** Smallest `amount` a single `consume` accepts (credits) */
663
+ declare const FFID_CREDITS_CONSUME_MIN_AMOUNT = 1;
664
+ /** Largest `amount` a single `consume` accepts (credits) */
665
+ declare const FFID_CREDITS_CONSUME_MAX_AMOUNT = 1000000;
666
+ /** Max size of `consume` `metadata`, in UTF-8 bytes after `JSON.stringify` */
667
+ declare const FFID_CREDITS_METADATA_MAX_BYTES = 4096;
668
+ /** Smallest `limit` for credit history (items per page) */
669
+ declare const FFID_CREDITS_HISTORY_MIN_LIMIT = 1;
670
+ /** Largest `limit` for credit history (items per page) */
671
+ declare const FFID_CREDITS_HISTORY_MAX_LIMIT = 100;
672
+ /** Server default `limit` for credit history when omitted (items per page) */
673
+ declare const FFID_CREDITS_HISTORY_DEFAULT_LIMIT = 20;
674
+ /** Smallest number of packs per purchase */
675
+ declare const FFID_CREDIT_PACK_MIN_QUANTITY = 1;
676
+ /** Largest number of packs per purchase */
677
+ declare const FFID_CREDIT_PACK_MAX_QUANTITY = 10;
678
+ /**
679
+ * Format of the `consume` idempotency key (CREDITS_API §7).
680
+ * Recommended form: `feature:requestId` (e.g. `chat.reply:req_01HZX`).
681
+ */
682
+ declare const FFID_CREDITS_IDEMPOTENCY_KEY_PATTERN: RegExp;
683
+ /** Format of the `consume` `feature` identifier (CREDITS_API §3) */
684
+ declare const FFID_CREDITS_FEATURE_PATTERN: RegExp;
685
+ /** Values of the history `type` filter / item `type` */
686
+ declare const FFID_CREDIT_HISTORY_TYPES: readonly ["grant", "consumption", "revocation"];
687
+ /** Kinds of credit grant */
688
+ declare const FFID_CREDIT_GRANT_KINDS: readonly ["monthly", "manual", "pack"];
689
+ /**
690
+ * Billing model of a plan. `flat` = fixed fee + member limit + monthly credits;
691
+ * `per_seat` = seat billing (praxis). Do not infer it from `planCode`.
692
+ */
693
+ type FFIDPricingModel = 'per_seat' | 'flat';
694
+ /** History item / filter type */
695
+ type FFIDCreditHistoryType = (typeof FFID_CREDIT_HISTORY_TYPES)[number];
696
+ /** Grant kind: monthly allowance, operator grant, or purchased pack */
697
+ type FFIDCreditGrantKind = (typeof FFID_CREDIT_GRANT_KINDS)[number];
698
+ /** Remaining credits per grant kind */
699
+ interface FFIDCreditBreakdown {
700
+ monthly: number;
701
+ manual: number;
702
+ pack: number;
703
+ }
704
+ /** `GET /ext/{id}/credits/balance` (CREDITS_API §4.2) */
705
+ interface FFIDCreditBalance {
706
+ subscriptionId: string;
707
+ organizationId: string;
708
+ serviceCode: string;
709
+ pricingModel: 'flat';
710
+ /** Credits usable now (sum of active grants' remaining) */
711
+ available: number;
712
+ /** This period's monthly allowance */
713
+ monthlyCredits: number;
714
+ /** Current monthly window; null when there is no monthly grant this period */
715
+ period: {
716
+ start: string;
717
+ end: string;
718
+ } | null;
719
+ breakdown: FFIDCreditBreakdown;
720
+ /** Next manual / pack expiry; null when none is active */
721
+ nextExpiry: {
722
+ at: string;
723
+ amount: number;
724
+ } | null;
725
+ lowThresholdPercent: number;
726
+ /** `available < monthlyCredits * lowThresholdPercent / 100` (always false when monthlyCredits = 0) */
727
+ isLow: boolean;
728
+ /** `available === 0` */
729
+ isExhausted: boolean;
730
+ /** ISO 8601 time the balance was read */
731
+ asOf: string;
732
+ }
733
+ /** `POST /ext/{id}/credits/consume` 200 response (CREDITS_API §4.1) */
734
+ interface FFIDCreditConsumeResult {
735
+ /**
736
+ * `duplicate` = same idempotency key and amount was already consumed. No side
737
+ * effect; `consumptionId` / `amount` are the first call's, `balance` is current,
738
+ * and `crossedLow` / `crossedExhausted` are always false.
739
+ */
740
+ status: 'consumed' | 'duplicate';
741
+ consumptionId: string;
742
+ amount: number;
743
+ balance: {
744
+ available: number;
745
+ monthlyCredits: number;
746
+ breakdown: FFIDCreditBreakdown;
747
+ };
748
+ /** This consumption crossed the low-balance threshold (once per period) */
749
+ crossedLow: boolean;
750
+ /** This consumption brought the balance to 0 (once per period) */
751
+ crossedExhausted: boolean;
752
+ }
753
+ /** `details` of a `CREDITS_INSUFFICIENT` (409) error from `consume` */
754
+ interface FFIDCreditsInsufficientDetails {
755
+ requested: number;
756
+ available: number;
757
+ monthlyCredits: number;
758
+ /** End of the current period (ISO 8601); null only when FFID could not read it */
759
+ periodEnd: string | null;
760
+ }
761
+ /** One row of the credit history (CREDITS_API §4.3) */
762
+ interface FFIDCreditHistoryItem {
763
+ /** Grant / consumption id. For `revocation` this is the revoked grant's id */
764
+ id: string;
765
+ type: FFIDCreditHistoryType;
766
+ /** Always positive; the direction is given by `type` */
767
+ amount: number;
768
+ occurredAt: string;
769
+ /** Set for `grant` / `revocation` */
770
+ kind: FFIDCreditGrantKind | null;
771
+ expiresAt: string | null;
772
+ /** Set for `consumption` */
773
+ feature: string | null;
774
+ /** Set for `consumption` */
775
+ idempotencyKey: string | null;
776
+ actorUserId: string | null;
777
+ reason: string | null;
778
+ metadata: Record<string, unknown> | null;
779
+ }
780
+ /** `GET /ext/{id}/credits/history` (newest first) */
781
+ interface FFIDCreditHistoryPage {
782
+ items: FFIDCreditHistoryItem[];
783
+ /** Opaque cursor for the next page; null on the last page */
784
+ nextCursor: string | null;
785
+ }
786
+ /** One purchasable credit pack (CREDITS_API §4.4) */
787
+ interface FFIDCreditPack {
788
+ code: string;
789
+ name: string;
790
+ credits: number;
791
+ /** Tax-inclusive price in the smallest currency unit */
792
+ price: number;
793
+ currency: string;
794
+ taxBehavior: FFIDTaxBehavior;
795
+ validityMonths: number;
796
+ displayOrder: number;
797
+ }
798
+ /** `GET /ext/credits/packs` */
799
+ interface FFIDCreditPackList {
800
+ serviceCode: string;
801
+ packs: FFIDCreditPack[];
802
+ }
803
+ /**
804
+ * `POST /ext/credits/packs/checkout` (CREDITS_API §4.5). Credits are **not**
805
+ * granted yet when this returns — confirm with `credits.pack_purchased` /
806
+ * `credits.granted` or the balance.
807
+ */
808
+ interface FFIDCreditPackCheckout {
809
+ checkoutUrl: string;
810
+ sessionId: string;
811
+ operationId: string;
812
+ /** ISO 8601 */
813
+ expiresAt: string;
814
+ }
815
+ /**
816
+ * `credits` field added to `/ext/check` (CREDITS_API §5.1). Null for per_seat,
817
+ * for no subscription, **and** when FFID could not read the ledger — so null
818
+ * does not mean "not flat"; use `pricingModel`.
819
+ */
820
+ interface FFIDSubscriptionCheckCredits {
821
+ available: number;
822
+ monthlyCredits: number;
823
+ isLow: boolean;
824
+ isExhausted: boolean;
825
+ periodEnd: string | null;
826
+ }
827
+ /**
828
+ * `GET /ext/{id}/seats` (CREDITS_API §5.2).
829
+ *
830
+ * flat contracts report the member limit: `maxMembers` (null = unlimited),
831
+ * `assignedMembers`, `availableMembers` (null = unlimited); `quantity` /
832
+ * `minSeats` / `maxSeats` are always 1 and `availableSeats === availableMembers`.
833
+ * per_seat contracts keep the seat shape and only add `pricingModel`.
834
+ * FFID servers released before #6392 omit `pricingModel` and the member fields.
835
+ */
836
+ interface FFIDSeatsSummary {
837
+ subscriptionId: string;
838
+ organizationId: string;
839
+ pricingModel?: FFIDPricingModel;
840
+ quantity: number;
841
+ assignedSeats: number;
842
+ availableSeats: number | null;
843
+ minSeats: number;
844
+ maxSeats: number | null;
845
+ maxMembers?: number | null;
846
+ assignedMembers?: number;
847
+ availableMembers?: number | null;
848
+ }
849
+ /** Input of `client.credits.consume()` (service-key mode only) */
850
+ interface FFIDCreditConsumeParams {
851
+ /** Contract id: UUID, `ffid:<uuid>` or Stripe `sub_...` */
852
+ subscriptionId: string;
853
+ /** Integer, `FFID_CREDITS_CONSUME_MIN_AMOUNT`..`FFID_CREDITS_CONSUME_MAX_AMOUNT` */
854
+ amount: number;
855
+ /**
856
+ * One key per AI execution, reused on retry (`FFID_CREDITS_IDEMPOTENCY_KEY_PATTERN`).
857
+ * Recommended: `${feature}:${requestId}`.
858
+ */
859
+ idempotencyKey: string;
860
+ /** Service-side feature identifier (`FFID_CREDITS_FEATURE_PATTERN`) */
861
+ feature: string;
862
+ /**
863
+ * Aggregation values only (model name, token counts). **No personal data** —
864
+ * consumption rows are accounting records and survive user deletion.
865
+ * JSON object, at most `FFID_CREDITS_METADATA_MAX_BYTES` bytes.
866
+ */
867
+ metadata?: Record<string, unknown>;
868
+ /** End user who ran the AI (UUID). Recorded for audit only */
869
+ userId?: string;
870
+ }
871
+ /** Options of `client.credits.listHistory()` */
872
+ interface FFIDListCreditHistoryOptions {
873
+ /** `nextCursor` of the previous page */
874
+ cursor?: string;
875
+ /** `FFID_CREDITS_HISTORY_MIN_LIMIT`..`FFID_CREDITS_HISTORY_MAX_LIMIT` (server default 20) */
876
+ limit?: number;
877
+ /** Filter by type; omitted = all */
878
+ type?: FFIDCreditHistoryType;
879
+ }
880
+ /** Input of `client.credits.createPackCheckout()` (token mode only) */
881
+ interface FFIDCreatePackCheckoutParams {
882
+ /** Contract id: UUID, `ffid:<uuid>` or Stripe `sub_...` */
883
+ subscriptionId: string;
884
+ /** `code` from `listPacks()` */
885
+ packCode: string;
886
+ /** https URL to return to after payment */
887
+ successUrl: string;
888
+ /** https URL to return to on cancel */
889
+ cancelUrl: string;
890
+ /** `FFID_CREDIT_PACK_MIN_QUANTITY`..`FFID_CREDIT_PACK_MAX_QUANTITY` (server default 1) */
891
+ quantity?: number;
892
+ }
893
+ /** Input of `client.credits.getBuyCreditsUrl()` / `redirectToBuyCredits()` */
894
+ interface FFIDBuyCreditsUrlParams {
895
+ /**
896
+ * Contract id as a UUID or `ffid:<uuid>`. The FFID portal page takes the UUID
897
+ * form only, so a Stripe `sub_...` id is rejected with `VALIDATION_ERROR`.
898
+ */
899
+ subscriptionId: string;
900
+ /** Organization ID — passed as `?org=` so FFID selects that organization */
901
+ orgId?: string;
902
+ }
903
+
129
904
  /**
130
905
  * Canonical service-access types for subscription lifecycle decisions.
131
906
  */
@@ -163,9 +938,37 @@ interface FFIDSubscriptionCheckResponse {
163
938
  gracePeriodEndsAt?: string | null;
164
939
  /** Whether a canceled subscription can be resumed via a re-subscription flow. */
165
940
  reactivatable?: boolean;
941
+ /**
942
+ * Billing model of the subscription's plan (10.0.0; CREDITS_API §5.1). `null` when
943
+ * there is no subscription. FFID servers released before #6390 omit it.
944
+ */
945
+ pricingModel?: FFIDPricingModel | null;
946
+ /**
947
+ * Credit balance summary — flat plans only (10.0.0). `null` for per_seat, for no
948
+ * subscription, **and** when FFID could not read the ledger, so `null` does not
949
+ * mean "not flat" (use `pricingModel`). Never affects `hasAccess`.
950
+ */
951
+ credits?: FFIDSubscriptionCheckCredits | null;
952
+ /**
953
+ * The plan's member limit is full (10.0.0). Informational: `hasAccess` is not
954
+ * affected. A user who cannot get a seat because of it is refused at login with
955
+ * OAuth `denial_reason: 'member_limit_reached'`.
956
+ */
957
+ memberLimitReached?: boolean;
166
958
  }
167
959
  type FFIDServiceAccessFailPolicy = 'failClosed';
168
- type FFIDServiceAccessDenialReason = 'no_subscription' | 'grace_disallowed' | 'blocked' | 'canceled' | 'expired' | 'trial_expired' | 'ffid_unreachable';
960
+ /**
961
+ * Why access was denied.
962
+ *
963
+ * `member_limit_reached` (10.0.0) is FFID's denial reason when a flat plan's member
964
+ * limit is full and the user has no seat. It reaches you through OAuth
965
+ * (`denial_reason` on the authorize redirect / userinfo 403; see
966
+ * `FFIDOAuthDenialReason` for that vocabulary); `checkServiceAccess()`
967
+ * derives its decision from `effectiveStatus` and never returns it, because a full
968
+ * member limit does not change `hasAccess` (CREDITS_API §1-5). It is in this union so
969
+ * one exhaustive `switch` over denial reasons covers both paths.
970
+ */
971
+ type FFIDServiceAccessDenialReason = 'no_subscription' | 'grace_disallowed' | 'blocked' | 'canceled' | 'expired' | 'trial_expired' | 'ffid_unreachable' | 'member_limit_reached';
169
972
  interface FFIDCheckServiceAccessParams {
170
973
  userId?: string;
171
974
  organizationId: string;
@@ -204,6 +1007,15 @@ interface FFIDServiceAccessDecision {
204
1007
  currentPeriodEnd: string | null;
205
1008
  gracePeriodEndsAt: string | null;
206
1009
  reactivatable: boolean;
1010
+ /** Passed through from `/ext/check` when the server sends it (10.0.0). Informational. */
1011
+ pricingModel?: FFIDPricingModel | null;
1012
+ /**
1013
+ * Passed through from `/ext/check` (10.0.0). Gate AI features on this or on
1014
+ * `credits.consume`'s result — not on `hasAccess`.
1015
+ */
1016
+ credits?: FFIDSubscriptionCheckCredits | null;
1017
+ /** Passed through from `/ext/check` (10.0.0). Does not affect `hasAccess`. */
1018
+ memberLimitReached?: boolean;
207
1019
  /**
208
1020
  * Present when the decision was produced by the SDK fail-closed policy
209
1021
  * rather than by a successful FFID response.
@@ -1597,4 +2409,4 @@ interface FFIDInquiryFormPlaceholderContext {
1597
2409
  }
1598
2410
  declare function FFIDInquiryForm({ mode, prefill, organizations, preselectedOrganizationId, categories, termsVersion, privacyVersion, termsHref, privacyHref, turnstileToken, acquisitionSource, turnstileSlot, onSubmit, onChange, legalLayout, messagePlaceholder, requireCategorySelection, unstyled, classNames, locale, className, }: FFIDInquiryFormProps): react_jsx_runtime.JSX.Element;
1599
2411
 
1600
- export { type FFIDInquiryFormProps as $, type AnnouncementListResponse as A, type Announcement as B, type AnnouncementStatus as C, type AnnouncementType as D, type EffectiveSubscriptionStatus as E, type FFIDSubscriptionStatus as F, EFFECTIVE_SUBSCRIPTION_STATUSES as G, FFIDAnnouncementBadge as H, FFIDAnnouncementList as I, type FFIDAnnouncementsError as J, type FFIDAnnouncementsErrorCode as K, type ListAnnouncementsOptions as L, type FFIDAnnouncementsServerResponse as M, type FFIDApiResponseMeta as N, type FFIDCacheConfig as O, type FFIDContextValue as P, type FFIDInquiryAcquisitionSource as Q, type FFIDInquiryCategory as R, type FFIDInquiryCategorySite2026 as S, type TokenStore as T, FFIDInquiryForm as U, type FFIDInquiryFormCategoryItem as V, type FFIDInquiryFormClassNames as W, type FFIDInquiryFormLegalLayout as X, type FFIDInquiryFormOrganization as Y, type FFIDInquiryFormPlaceholderContext as Z, type FFIDInquiryFormPrefill as _, type FFIDOAuthUserInfoSubscription as a, type FFIDInquiryFormSubmitData as a0, type FFIDInquiryFormSubmitResult as a1, type FFIDJwtClaims as a2, FFIDLoginButton as a3, type FFIDOAuthUserInfoMemberRole as a4, FFIDOrganizationSwitcher as a5, type FFIDSeatAssignmentClaim as a6, type FFIDSeatAssignmentStatus as a7, type FFIDSeatModel as a8, type FFIDServiceAccessDenialReason as a9, type FFIDServiceAccessFailPolicy as aa, FFIDSubscriptionBadge as ab, FFIDUserMenu as ac, FFID_INQUIRY_ACQUISITION_SOURCES as ad, FFID_INQUIRY_CATEGORIES as ae, FFID_INQUIRY_CATEGORIES_SITE_2026 as af, type TokenData as ag, type UseFFIDAnnouncementsOptions as ah, type UseFFIDAnnouncementsReturn as ai, createTokenStore as aj, isFFIDInquiryAcquisitionSource as ak, isFFIDInquiryCategorySite2026 as al, useFFIDAnnouncements as am, type FFIDAnnouncementBadgeClassNames as an, type FFIDAnnouncementBadgeProps as ao, type FFIDAnnouncementListClassNames as ap, type FFIDAnnouncementListProps as aq, type FFIDLoginButtonProps as ar, type FFIDOrganizationSwitcherClassNames as as, type FFIDOrganizationSwitcherProps as at, type FFIDSubscriptionBadgeClassNames as au, type FFIDSubscriptionBadgeProps as av, type FFIDUserMenuClassNames as aw, type FFIDUserMenuProps as ax, type FFIDAccountType as b, type FFIDPrompt as c, type FFIDConfig as d, type FFIDApiResponse as e, type FFIDSessionResponse as f, type FFIDSignOutResult as g, type FFIDError as h, type FFIDSubscriptionCheckResponse as i, type FFIDCheckServiceAccessParams as j, type FFIDServiceAccessDecision as k, type FFIDAnalyticsConfig as l, type FFIDVerifyAccessTokenOptions as m, type FFIDOAuthUserInfo as n, type FFIDInquiryCreateParams as o, type FFIDInquiryCreateResponse as p, type FFIDAuthMode as q, type FFIDLogger as r, type FFIDCacheAdapter as s, type FFIDUser as t, type FFIDOrganization as u, type FFIDSubscription as v, type FFIDSubscriptionContextValue as w, type FFIDAnnouncementsClientConfig as x, type FFIDAnnouncementsApiResponse as y, type FFIDAnnouncementsLogger as z };
2412
+ export { type FFIDAnnouncementsClientConfig as $, type FFIDVerifyAccessTokenOptions as A, type FFIDOAuthUserInfo as B, type FFIDInquiryCreateParams as C, type FFIDInquiryCreateResponse as D, type FFIDCreditBalance as E, type FFIDOAuthUserInfoSubscription as F, type FFIDListCreditHistoryOptions as G, type FFIDCreditHistoryPage as H, type FFIDCreditPackList as I, type FFIDCreatePackCheckoutParams as J, type FFIDCreditPackCheckout as K, type FFIDCreditConsumeParams as L, type FFIDCreditConsumeResult as M, type FFIDBuyCreditsUrlParams as N, type FFIDAuthMode as O, type FFIDLogger as P, type FFIDCacheAdapter as Q, type FFIDUser as R, type FFIDOrganization as S, type TokenStore as T, type FFIDSubscription as U, type FFIDSubscriptionContextValue as V, type EffectiveSubscriptionStatus as W, type FFIDSubscriptionStatus as X, type FFIDCatalogEnvironment as Y, type FFIDBillingInterval as Z, type FFIDTaxBehavior as _, type FFIDAccountType as a, FFID_CREDITS_FEATURE_PATTERN as a$, type ListAnnouncementsOptions as a0, type FFIDAnnouncementsApiResponse as a1, type AnnouncementListResponse as a2, type FFIDAnnouncementsLogger as a3, type Announcement as a4, type AnnouncementStatus as a5, type AnnouncementType as a6, EFFECTIVE_SUBSCRIPTION_STATUSES as a7, FFIDAnnouncementBadge as a8, FFIDAnnouncementList as a9, type FFIDInquiryFormSubmitResult as aA, type FFIDJwtClaims as aB, FFIDLoginButton as aC, type FFIDOAuthUserInfoMemberRole as aD, FFIDOrganizationSwitcher as aE, type FFIDPlanChangeLineItem as aF, type FFIDPlanChangePreview as aG, type FFIDPlanInfo as aH, type FFIDPricingModel as aI, type FFIDPublishedPlan as aJ, type FFIDSeatAssignmentClaim as aK, type FFIDSeatAssignmentStatus as aL, type FFIDSeatChangeLineItem as aM, type FFIDSeatChangePreview as aN, type FFIDSeatModel as aO, type FFIDServiceAccessDenialReason as aP, type FFIDServiceAccessFailPolicy as aQ, type FFIDServiceInfo as aR, FFIDSubscriptionBadge as aS, type FFIDSubscriptionCheckCredits as aT, type FFIDSubscriptionSummary as aU, type FFIDSupportedCurrency as aV, FFIDUserMenu as aW, FFID_CATALOG_ENVIRONMENTS as aX, FFID_CATALOG_PUBLICATION_STATUSES as aY, FFID_CREDITS_CONSUME_MAX_AMOUNT as aZ, FFID_CREDITS_CONSUME_MIN_AMOUNT as a_, type FFIDAnnouncementsError as aa, type FFIDAnnouncementsErrorCode as ab, type FFIDAnnouncementsServerResponse as ac, type FFIDApiResponseMeta as ad, type FFIDCacheConfig as ae, type FFIDCatalogPublication as af, type FFIDCatalogPublicationStatus as ag, type FFIDContextValue as ah, type FFIDCreditBreakdown as ai, type FFIDCreditGrantKind as aj, type FFIDCreditHistoryItem as ak, type FFIDCreditHistoryType as al, type FFIDCreditPack as am, type FFIDCreditsInsufficientDetails as an, type FFIDInquiryAcquisitionSource as ao, type FFIDInquiryCategory as ap, type FFIDInquiryCategorySite2026 as aq, FFIDInquiryForm as ar, type FFIDInquiryFormCategoryItem as as, type FFIDInquiryFormClassNames as at, type FFIDInquiryFormLegalLayout as au, type FFIDInquiryFormOrganization as av, type FFIDInquiryFormPlaceholderContext as aw, type FFIDInquiryFormPrefill as ax, type FFIDInquiryFormProps as ay, type FFIDInquiryFormSubmitData as az, type FFIDPrompt as b, FFID_CREDITS_HISTORY_DEFAULT_LIMIT as b0, FFID_CREDITS_HISTORY_MAX_LIMIT as b1, FFID_CREDITS_HISTORY_MIN_LIMIT as b2, FFID_CREDITS_IDEMPOTENCY_KEY_PATTERN as b3, FFID_CREDITS_LOW_THRESHOLD_PERCENT as b4, FFID_CREDITS_METADATA_MAX_BYTES as b5, FFID_CREDIT_GRANT_KINDS as b6, FFID_CREDIT_HISTORY_TYPES as b7, FFID_CREDIT_PACK_MAX_QUANTITY as b8, FFID_CREDIT_PACK_MIN_QUANTITY as b9, FFID_INQUIRY_ACQUISITION_SOURCES as ba, FFID_INQUIRY_CATEGORIES as bb, FFID_INQUIRY_CATEGORIES_SITE_2026 as bc, type TokenData as bd, type UseFFIDAnnouncementsOptions as be, type UseFFIDAnnouncementsReturn as bf, createTokenStore as bg, isFFIDInquiryAcquisitionSource as bh, isFFIDInquiryCategorySite2026 as bi, useFFIDAnnouncements as bj, type FFIDAnnouncementBadgeClassNames as bk, type FFIDAnnouncementBadgeProps as bl, type FFIDAnnouncementListClassNames as bm, type FFIDAnnouncementListProps as bn, type FFIDLoginButtonProps as bo, type FFIDOrganizationSwitcherClassNames as bp, type FFIDOrganizationSwitcherProps as bq, type FFIDSubscriptionBadgeClassNames as br, type FFIDSubscriptionBadgeProps as bs, type FFIDUserMenuClassNames as bt, type FFIDUserMenuProps as bu, type FFIDConfig as c, type FFIDApiResponse as d, type FFIDSessionResponse as e, type FFIDSignOutResult as f, type FFIDError as g, type FFIDSubscriptionCheckResponse as h, type FFIDCheckServiceAccessParams as i, type FFIDServiceAccessDecision as j, type FFIDAnalyticsConfig as k, type FFIDSeatsSummary as l, type FFIDListPlansResponse as m, type FFIDPublishedCatalog as n, type FFIDSubscriptionDetail as o, type FFIDSubscribeParams as p, type FFIDSubscribeResponse as q, type FFIDChangePlanParams as r, type FFIDChangePlanResponse as s, type FFIDCancelSubscriptionParams as t, type FFIDCancelSubscriptionResponse as u, type FFIDCancelPendingDowngradeResponse as v, type FFIDPreviewPlanChangeParams as w, type FFIDPlanChangePreviewResponse as x, type FFIDPreviewSeatChangeParams as y, type FFIDSeatChangePreviewResponse as z };