@feelflow/ffid-sdk 9.0.0 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1010 -960
- package/dist/{chunk-Q2ZQJS36.cjs → chunk-2LU2F3F2.cjs} +279 -5
- package/dist/{chunk-TUXIJEEZ.js → chunk-OXW6QSTO.js} +266 -6
- package/dist/components/index.cjs +8 -8
- package/dist/components/index.d.cts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/{ffid-client-B0cORHac.d.ts → ffid-client-5uxXRgIO.d.ts} +686 -376
- package/dist/{ffid-client-6aLs9Fqc.d.cts → ffid-client-CumygXXz.d.cts} +686 -376
- package/dist/{index-BG7g99pK.d.cts → index-KjewcNn1.d.cts} +813 -2
- package/dist/{index-BG7g99pK.d.ts → index-KjewcNn1.d.ts} +813 -2
- package/dist/index.cjs +130 -74
- package/dist/index.d.cts +115 -504
- package/dist/index.d.ts +115 -504
- package/dist/index.js +2 -2
- package/dist/server/index.cjs +249 -5
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +249 -5
- package/dist/server/test/index.d.cts +1 -1
- package/dist/server/test/index.d.ts +1 -1
- package/dist/webhooks/index.d.cts +74 -2
- package/dist/webhooks/index.d.ts +74 -2
- package/package.json +131 -131
|
@@ -211,178 +211,6 @@ interface FFIDCacheConfig {
|
|
|
211
211
|
ttl: number;
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
/**
|
|
215
|
-
* Canonical service-access types for subscription lifecycle decisions.
|
|
216
|
-
*/
|
|
217
|
-
|
|
218
|
-
/** Subscription status values matching the FFID platform's SubscriptionStatus type */
|
|
219
|
-
type FFIDSubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'pending_invoice' | 'paused' | 'incomplete' | 'incomplete_expired' | 'unpaid';
|
|
220
|
-
interface FFIDSubscriptionCheckResponse {
|
|
221
|
-
hasActiveSubscription: boolean;
|
|
222
|
-
/**
|
|
223
|
-
* Canonical access decision returned by FFID's `/subscriptions/ext/check`.
|
|
224
|
-
*
|
|
225
|
-
* This is the server-side source of truth for service gates. Consumers
|
|
226
|
-
* should not recompute access from `currentPeriodEnd`, `past_due_since`, or
|
|
227
|
-
* local payment timestamps.
|
|
228
|
-
*/
|
|
229
|
-
hasAccess?: boolean;
|
|
230
|
-
/** True when `effectiveStatus === 'past_due_grace'`. */
|
|
231
|
-
isGrace?: boolean;
|
|
232
|
-
/** True when FFID's canonical effective status denies service access. */
|
|
233
|
-
isBlocked?: boolean;
|
|
234
|
-
organizationId: string | null;
|
|
235
|
-
subscriptionId: string | null;
|
|
236
|
-
status: FFIDSubscriptionStatus | null;
|
|
237
|
-
planCode: string | null;
|
|
238
|
-
currentPeriodEnd: string | null;
|
|
239
|
-
/**
|
|
240
|
-
* Semantic FFID access-control status. `null` means the organization has no
|
|
241
|
-
* subscription row for this service.
|
|
242
|
-
*/
|
|
243
|
-
effectiveStatus?: EffectiveSubscriptionStatus | null;
|
|
244
|
-
/**
|
|
245
|
-
* ISO timestamp at which `past_due_grace` flips to `blocked`; null outside
|
|
246
|
-
* the grace window.
|
|
247
|
-
*/
|
|
248
|
-
gracePeriodEndsAt?: string | null;
|
|
249
|
-
/** Whether a canceled subscription can be resumed via a re-subscription flow. */
|
|
250
|
-
reactivatable?: boolean;
|
|
251
|
-
}
|
|
252
|
-
type FFIDServiceAccessFailPolicy = 'failClosed';
|
|
253
|
-
type FFIDServiceAccessDenialReason = 'no_subscription' | 'grace_disallowed' | 'blocked' | 'canceled' | 'expired' | 'trial_expired' | 'ffid_unreachable';
|
|
254
|
-
interface FFIDCheckServiceAccessParams {
|
|
255
|
-
userId?: string;
|
|
256
|
-
organizationId: string;
|
|
257
|
-
/**
|
|
258
|
-
* Whether `past_due_grace` should keep access open.
|
|
259
|
-
*
|
|
260
|
-
* @default true
|
|
261
|
-
*/
|
|
262
|
-
allowGrace?: boolean;
|
|
263
|
-
/**
|
|
264
|
-
* Error policy when FFID cannot return a canonical decision.
|
|
265
|
-
*
|
|
266
|
-
* Currently only `failClosed` is supported: network/server/parse failures
|
|
267
|
-
* become `hasAccess=false` decisions with `denialReason='ffid_unreachable'`
|
|
268
|
-
* and the root cause in `decision.error`. Treat `hasAccess` as the gate.
|
|
269
|
-
*/
|
|
270
|
-
failPolicy?: FFIDServiceAccessFailPolicy;
|
|
271
|
-
}
|
|
272
|
-
interface FFIDServiceAccessError {
|
|
273
|
-
code: string;
|
|
274
|
-
message: string;
|
|
275
|
-
details?: unknown;
|
|
276
|
-
}
|
|
277
|
-
interface FFIDServiceAccessDecision {
|
|
278
|
-
hasAccess: boolean;
|
|
279
|
-
effectiveStatus: EffectiveSubscriptionStatus | null;
|
|
280
|
-
isGrace: boolean;
|
|
281
|
-
isBlocked: boolean;
|
|
282
|
-
allowGrace: boolean;
|
|
283
|
-
failPolicy: FFIDServiceAccessFailPolicy;
|
|
284
|
-
denialReason: FFIDServiceAccessDenialReason | null;
|
|
285
|
-
organizationId: string | null;
|
|
286
|
-
subscriptionId: string | null;
|
|
287
|
-
status: FFIDSubscriptionStatus | null;
|
|
288
|
-
planCode: string | null;
|
|
289
|
-
currentPeriodEnd: string | null;
|
|
290
|
-
gracePeriodEndsAt: string | null;
|
|
291
|
-
reactivatable: boolean;
|
|
292
|
-
/**
|
|
293
|
-
* Present when the decision was produced by the SDK fail-closed policy
|
|
294
|
-
* rather than by a successful FFID response.
|
|
295
|
-
*/
|
|
296
|
-
error?: FFIDServiceAccessError;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Token Store
|
|
301
|
-
*
|
|
302
|
-
* Manages OAuth 2.0 tokens (access + refresh) with dual-storage support.
|
|
303
|
-
* Falls back to in-memory storage when localStorage is unavailable
|
|
304
|
-
* (e.g., Safari private browsing mode).
|
|
305
|
-
*/
|
|
306
|
-
/**
|
|
307
|
-
* Token data stored by the token store
|
|
308
|
-
*/
|
|
309
|
-
interface TokenData {
|
|
310
|
-
/** OAuth 2.0 access token */
|
|
311
|
-
accessToken: string;
|
|
312
|
-
/** OAuth 2.0 refresh token */
|
|
313
|
-
refreshToken: string;
|
|
314
|
-
/** Expiration timestamp in milliseconds (Unix epoch) */
|
|
315
|
-
expiresAt: number;
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Token store interface for managing OAuth tokens
|
|
319
|
-
*/
|
|
320
|
-
interface TokenStore {
|
|
321
|
-
/** Get stored tokens (null if not stored) */
|
|
322
|
-
getTokens(): TokenData | null;
|
|
323
|
-
/** Store new tokens */
|
|
324
|
-
setTokens(tokens: TokenData): void;
|
|
325
|
-
/** Clear all stored tokens */
|
|
326
|
-
clearTokens(): void;
|
|
327
|
-
/** Check if access token is expired (with 30s buffer) */
|
|
328
|
-
isAccessTokenExpired(): boolean;
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Create a token store with the specified storage type.
|
|
332
|
-
*
|
|
333
|
-
* When storageType is 'localStorage' (default in browser), falls back
|
|
334
|
-
* to memory if localStorage is not available (e.g., Safari private mode).
|
|
335
|
-
*
|
|
336
|
-
* @param storageType - 'localStorage' (default) or 'memory'
|
|
337
|
-
*/
|
|
338
|
-
declare function createTokenStore(storageType?: 'localStorage' | 'memory'): TokenStore;
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* Billing checkout / portal session types.
|
|
342
|
-
*
|
|
343
|
-
* types/index.ts のサイズ上限対応で切り出し(中身は逐語移設、#3787 Phase A)。
|
|
344
|
-
*/
|
|
345
|
-
/**
|
|
346
|
-
* Checkout session response from billing checkout endpoint
|
|
347
|
-
*/
|
|
348
|
-
interface FFIDCheckoutSessionResponse {
|
|
349
|
-
/** Stripe Checkout session ID */
|
|
350
|
-
sessionId: string;
|
|
351
|
-
/** Stripe Checkout session URL (null if session creation had issues) */
|
|
352
|
-
url: string | null;
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Portal session response from billing portal endpoint
|
|
356
|
-
*/
|
|
357
|
-
interface FFIDPortalSessionResponse {
|
|
358
|
-
/** Stripe Billing Portal URL */
|
|
359
|
-
url: string;
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Parameters for creating a checkout session
|
|
363
|
-
*/
|
|
364
|
-
interface FFIDCreateCheckoutParams {
|
|
365
|
-
/** Organization ID (UUID) */
|
|
366
|
-
organizationId: string;
|
|
367
|
-
/** Subscription ID (UUID) */
|
|
368
|
-
subscriptionId: string;
|
|
369
|
-
/** URL to redirect after successful checkout */
|
|
370
|
-
successUrl: string;
|
|
371
|
-
/** URL to redirect after cancelled checkout */
|
|
372
|
-
cancelUrl: string;
|
|
373
|
-
/** Optional plan ID for upgrade or resubscription */
|
|
374
|
-
planId?: string;
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Parameters for creating a billing portal session
|
|
378
|
-
*/
|
|
379
|
-
interface FFIDCreatePortalParams {
|
|
380
|
-
/** Organization ID (UUID) */
|
|
381
|
-
organizationId: string;
|
|
382
|
-
/** URL to redirect when user exits the portal */
|
|
383
|
-
returnUrl: string;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
214
|
/** Billing interval for subscriptions */
|
|
387
215
|
type FFIDBillingInterval = 'monthly' | 'yearly';
|
|
388
216
|
/**
|
|
@@ -413,6 +241,15 @@ interface FFIDPlanInfo {
|
|
|
413
241
|
trialDays: number;
|
|
414
242
|
/** flat: period fee; per_seat: multiply by selected quantity. Older servers omit this. */
|
|
415
243
|
pricingModel?: 'per_seat' | 'flat';
|
|
244
|
+
/**
|
|
245
|
+
* flat: member limit of the plan (`null` = unlimited). Absent on per_seat plans
|
|
246
|
+
* and on FFID servers released before #6392 — do not read absence as unlimited.
|
|
247
|
+
*/
|
|
248
|
+
maxMembers?: number | null;
|
|
249
|
+
/** flat: monthly AI credit allowance (0 = none). Absent on older servers. */
|
|
250
|
+
monthlyCredits?: number;
|
|
251
|
+
/** Plan tier in the personal / team / enterprise ladder. Absent on older servers. */
|
|
252
|
+
tier?: 'personal' | 'team' | 'enterprise';
|
|
416
253
|
/**
|
|
417
254
|
* Monthly price in the smallest currency unit.
|
|
418
255
|
*
|
|
@@ -490,7 +327,10 @@ interface FFIDSubscribeParams {
|
|
|
490
327
|
planCode: string;
|
|
491
328
|
/** Billing interval (default: 'monthly') */
|
|
492
329
|
billingInterval?: FFIDBillingInterval;
|
|
493
|
-
/**
|
|
330
|
+
/**
|
|
331
|
+
* Number of seats (default: plan's minSeats). per_seat plans only — a flat plan
|
|
332
|
+
* answers 400 `VALIDATION_ERROR` (`details.field: 'quantity'`), so omit it there.
|
|
333
|
+
*/
|
|
494
334
|
quantity?: number;
|
|
495
335
|
/** User ID for seat auto-assignment (only needed for service-key mode) */
|
|
496
336
|
userId?: string;
|
|
@@ -671,113 +511,654 @@ interface FFIDPlanChangePreviewBase {
|
|
|
671
511
|
lineItems: FFIDPlanChangeLineItem[];
|
|
672
512
|
}
|
|
673
513
|
/**
|
|
674
|
-
* Plan change proration preview. It is computed with the same rules as `changePlan()`.
|
|
514
|
+
* Plan change proration preview. It is computed with the same rules as `changePlan()`.
|
|
515
|
+
*
|
|
516
|
+
* `willApplyAtPeriodEnd` is a discriminant that constrains related fields at the type level:
|
|
517
|
+
* - `true`: a decrease reserved until the period end. `proratedAmount` is always 0 (nothing is
|
|
518
|
+
* charged or refunded now); `effectiveDate` mirrors the subscription's `currentPeriodEnd`
|
|
519
|
+
* (may be `null` when the subscription has no active billing cycle yet).
|
|
520
|
+
* - `false`: immediate change. `effectiveDate` is always `null`. For an increase,
|
|
521
|
+
* `proratedAmount` is the difference up to the current period end that is charged now
|
|
522
|
+
* (possibly Stripe-refined). A decrease on a contract that cannot be reserved also lands here:
|
|
523
|
+
* `0` for a contract without a Stripe subscription (no refund), but Stripe's prorated amount —
|
|
524
|
+
* negative, credited on the next invoice — for a Stripe contract with no period end yet
|
|
525
|
+
* (e.g. during a trial).
|
|
526
|
+
*/
|
|
527
|
+
type FFIDPlanChangePreview = FFIDPlanChangePreviewBase & ({
|
|
528
|
+
willApplyAtPeriodEnd: true;
|
|
529
|
+
effectiveDate: string | null;
|
|
530
|
+
/** 0 on period-end-deferred changes; charge happens at the next invoice */
|
|
531
|
+
proratedAmount: 0;
|
|
532
|
+
} | {
|
|
533
|
+
willApplyAtPeriodEnd: false;
|
|
534
|
+
effectiveDate: null;
|
|
535
|
+
/** Difference up to the current period end charged now (see the type doc for the decrease cases) */
|
|
536
|
+
proratedAmount: number;
|
|
537
|
+
});
|
|
538
|
+
/** Response from plan change preview endpoint */
|
|
539
|
+
interface FFIDPlanChangePreviewResponse {
|
|
540
|
+
preview: FFIDPlanChangePreview;
|
|
541
|
+
}
|
|
542
|
+
/** Parameters for previewing a seat count change */
|
|
543
|
+
interface FFIDPreviewSeatChangeParams {
|
|
544
|
+
/** Subscription ID (UUID) */
|
|
545
|
+
subscriptionId: string;
|
|
546
|
+
/** New seat quantity. Must be an integer within the plan's allowed range. */
|
|
547
|
+
quantity: number;
|
|
548
|
+
}
|
|
549
|
+
/** Seat change preview line item */
|
|
550
|
+
interface FFIDSeatChangeLineItem {
|
|
551
|
+
description: string;
|
|
552
|
+
amount: number;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Seat change proration preview.
|
|
556
|
+
*
|
|
557
|
+
* Sister type to `FFIDPlanChangePreview`. The shared `type` discriminant lets
|
|
558
|
+
* consumers narrow a preview payload without inspecting unrelated fields.
|
|
559
|
+
*
|
|
560
|
+
* - `willApplyAtPeriodEnd=true`: a seat reduction reserved until the period end.
|
|
561
|
+
* `proratedAmount` is 0 and `effectiveDate` is when the new seat count applies.
|
|
562
|
+
* - Otherwise the change applies immediately. For an increase, `proratedAmount` is the amount
|
|
563
|
+
* charged now up to the current period end. A reduction that cannot be reserved is normally
|
|
564
|
+
* `0`, but can be negative (a credit on the next invoice) for a Stripe contract with no period
|
|
565
|
+
* end yet or when only the contract unit price is known.
|
|
566
|
+
* - `isEstimate=true` (default when Stripe is not configured or data is unavailable):
|
|
567
|
+
* `proratedAmount` is computed locally. `isEstimate=false`: it reflects Stripe's live
|
|
568
|
+
* proration calculation.
|
|
569
|
+
*
|
|
570
|
+
* `nextInvoiceAmount` is a local estimate: flat period fee, or `unitPrice * newQuantity`.
|
|
571
|
+
* Flat capacity changes have zero prorated cost.
|
|
572
|
+
*
|
|
573
|
+
* `pricingUnavailable=true` means custom pricing or an unverified contracted Stripe
|
|
574
|
+
* Price. Hide amounts; zero is not a quote. `custom_pricing` permits the existing
|
|
575
|
+
* unbilled seat-change flow. Require another preview before confirmation only when
|
|
576
|
+
* pricing is unavailable and the reason is not `custom_pricing`. `stripe_error` also
|
|
577
|
+
* covers invoice/address failures after the contract price is known; use
|
|
578
|
+
* `pricingUnavailable`, not the reason alone, to decide whether to hide amounts.
|
|
579
|
+
* `no_stripe_data` means invoice proration is unavailable even if the contract unit
|
|
580
|
+
* price is known. Portal seat PUT independently enforces subscription limits;
|
|
581
|
+
* external consumers should guide users to the FFID portal for seat changes.
|
|
582
|
+
*/
|
|
583
|
+
interface FFIDSeatChangePreview {
|
|
584
|
+
/** flat: unitPrice is the whole period fee; per_seat: multiply by capacity. */
|
|
585
|
+
pricingModel?: 'per_seat' | 'flat';
|
|
586
|
+
/** Discriminant for preview response variants (pairs with `FFIDPlanChangePreview.type`) */
|
|
587
|
+
type: 'seat-change';
|
|
588
|
+
currentQuantity: number;
|
|
589
|
+
newQuantity: number;
|
|
590
|
+
/** Per-seat price for the current billing interval */
|
|
591
|
+
unitPrice: number;
|
|
592
|
+
billingInterval: FFIDBillingInterval;
|
|
593
|
+
/**
|
|
594
|
+
* Amount charged now for the rest of the current billing period. A reserved seat reduction
|
|
595
|
+
* (`willApplyAtPeriodEnd: true`) is always `0`; see the type doc for reductions that cannot
|
|
596
|
+
* be reserved. Also `0` when `pricingUnavailable === true`; hide it instead of quoting zero.
|
|
597
|
+
*/
|
|
598
|
+
proratedAmount: number;
|
|
599
|
+
/** Next invoice full amount — flat period fee or per-seat price times newQuantity */
|
|
600
|
+
nextInvoiceAmount: number;
|
|
601
|
+
nextInvoiceDate: string | null;
|
|
602
|
+
currency: FFIDSupportedCurrency;
|
|
603
|
+
/** true when proratedAmount is a local estimate rather than Stripe invoice/proration data */
|
|
604
|
+
isEstimate: boolean;
|
|
605
|
+
/** Hide amounts: custom pricing or contracted Stripe Price could not be verified. */
|
|
606
|
+
pricingUnavailable?: boolean;
|
|
607
|
+
/** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
|
|
608
|
+
estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
|
|
609
|
+
/**
|
|
610
|
+
* `true` when the seat reduction would be reserved until the period end (8.0.0).
|
|
611
|
+
* Absent or `false` = the change applies immediately.
|
|
612
|
+
*/
|
|
613
|
+
willApplyAtPeriodEnd?: boolean;
|
|
614
|
+
/** When the reserved seat count applies (present when `willApplyAtPeriodEnd` is `true`) */
|
|
615
|
+
effectiveDate?: string | null;
|
|
616
|
+
lineItems: FFIDSeatChangeLineItem[];
|
|
617
|
+
}
|
|
618
|
+
/** Response from seat change preview endpoint */
|
|
619
|
+
interface FFIDSeatChangePreviewResponse {
|
|
620
|
+
preview: FFIDSeatChangePreview;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/** Deployment environments a catalog publication can apply to (single source) */
|
|
624
|
+
declare const FFID_CATALOG_ENVIRONMENTS: readonly ["staging", "production"];
|
|
625
|
+
/** Deployment environment a catalog publication applies to */
|
|
626
|
+
type FFIDCatalogEnvironment = (typeof FFID_CATALOG_ENVIRONMENTS)[number];
|
|
627
|
+
/**
|
|
628
|
+
* Tax behavior of a published price.
|
|
629
|
+
* `inclusive`: displayed price contains Stripe-calculated tax.
|
|
630
|
+
* `exclusive`: tax is added on top of the base price.
|
|
631
|
+
*/
|
|
632
|
+
type FFIDTaxBehavior = 'inclusive' | 'exclusive';
|
|
633
|
+
/**
|
|
634
|
+
* Publication lifecycle statuses (single source — the type, the SDK runtime
|
|
635
|
+
* validator, and consumer sets all derive from this tuple so a new literal
|
|
636
|
+
* cannot be added to one side only).
|
|
637
|
+
*/
|
|
638
|
+
declare const FFID_CATALOG_PUBLICATION_STATUSES: readonly ["approved", "superseded", "revoking", "revoked"];
|
|
639
|
+
/**
|
|
640
|
+
* Publication lifecycle status.
|
|
641
|
+
* - `approved`: sellable — the only status that permits new paid checkout
|
|
642
|
+
* - `superseded`: replaced by a newer revision (old sessions may sell through
|
|
643
|
+
* until `sellThroughUntil`)
|
|
644
|
+
* - `revoking`: emergency stop in progress — never sellable
|
|
645
|
+
* - `revoked`: emergency stop completed — never sellable
|
|
646
|
+
*/
|
|
647
|
+
type FFIDCatalogPublicationStatus = (typeof FFID_CATALOG_PUBLICATION_STATUSES)[number];
|
|
648
|
+
/**
|
|
649
|
+
* Human-approved publication record binding a catalog revision to the
|
|
650
|
+
* content/config hashes reviewed at approval time.
|
|
651
|
+
*
|
|
652
|
+
* All `*Hash` fields are lowercase SHA-256 hex computed with the shared
|
|
653
|
+
* canonicalization helpers in `shared/catalog-hash` — consumers re-hash the
|
|
654
|
+
* content they actually render and must refuse new sales on any mismatch.
|
|
655
|
+
*/
|
|
656
|
+
interface FFIDCatalogPublication {
|
|
657
|
+
serviceCode: string;
|
|
658
|
+
environment: FFIDCatalogEnvironment;
|
|
659
|
+
catalogVersion: string;
|
|
660
|
+
praxisCopyHash: string;
|
|
661
|
+
ffidCheckoutCopyHash: string;
|
|
662
|
+
legalDisclosureHash: string;
|
|
663
|
+
taxConfigurationHash: string;
|
|
664
|
+
paymentConfigurationHash: string;
|
|
665
|
+
scopeHash: string;
|
|
666
|
+
/** Monotonically increasing per (service, environment) publication counter */
|
|
667
|
+
salesEpoch: number;
|
|
668
|
+
/** FFID-generated immutable human-review approval ID */
|
|
669
|
+
approvalId: string;
|
|
670
|
+
/** ISO 8601 timestamp of the recorded human review */
|
|
671
|
+
reviewedAt: string;
|
|
672
|
+
/** ISO 8601 timestamp the publication became effective */
|
|
673
|
+
effectiveAt: string;
|
|
674
|
+
/** ISO 8601 timestamp the publication was superseded (null while current) */
|
|
675
|
+
supersededAt: string | null;
|
|
676
|
+
/** ISO 8601 upper bound for old-session sell-through (null unless superseded) */
|
|
677
|
+
sellThroughUntil: string | null;
|
|
678
|
+
/** ISO 8601 timestamp an emergency revoke took effect (null unless revoking/revoked) */
|
|
679
|
+
revocationEffectiveAt: string | null;
|
|
680
|
+
status: FFIDCatalogPublicationStatus;
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* A plan inside a published catalog revision (public-safe snapshot).
|
|
684
|
+
* Never contains Stripe Product/Price identifiers or other secrets.
|
|
685
|
+
*/
|
|
686
|
+
interface FFIDPublishedPlan {
|
|
687
|
+
/**
|
|
688
|
+
* Plan code — always a lowercase slug (`^[a-z0-9][a-z0-9_-]*$`).
|
|
689
|
+
* Per-service open set; see the FFID repo's
|
|
690
|
+
* `docs/04-api/PLAN_CODE_CONTRACT.md` for the full guarantees.
|
|
691
|
+
*/
|
|
692
|
+
code: string;
|
|
693
|
+
name: string;
|
|
694
|
+
description: string | null;
|
|
695
|
+
/** Monthly price in the catalog currency; null when monthly is not offered */
|
|
696
|
+
priceMonthly: number | null;
|
|
697
|
+
/** Yearly price in the catalog currency; null when yearly is not offered */
|
|
698
|
+
priceYearly: number | null;
|
|
699
|
+
currency: string;
|
|
700
|
+
/** Billing intervals actually purchasable for this plan */
|
|
701
|
+
billingIntervals: FFIDBillingInterval[];
|
|
702
|
+
taxBehavior: FFIDTaxBehavior;
|
|
703
|
+
minSeats: number;
|
|
704
|
+
maxSeats: number | null;
|
|
705
|
+
displayOrder: number;
|
|
706
|
+
/** Billing model (10.0.0). Absent on snapshots published before ADR-008 (e.g. praxis) */
|
|
707
|
+
pricingModel?: 'per_seat' | 'flat';
|
|
708
|
+
/** flat: member limit (`null` = unlimited). Absent on older snapshots */
|
|
709
|
+
maxMembers?: number | null;
|
|
710
|
+
/** flat: monthly AI credit allowance (0 = none). Absent on older snapshots */
|
|
711
|
+
monthlyCredits?: number;
|
|
712
|
+
/** Plan tier. Absent on older snapshots */
|
|
713
|
+
tier?: 'personal' | 'team' | 'enterprise';
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Response of GET /api/v1/subscriptions/ext/catalog/{serviceCode}.
|
|
717
|
+
*
|
|
718
|
+
* `catalogVersion` always equals `publication.catalogVersion`; it is hoisted
|
|
719
|
+
* to the top level so consumers can pin the version (e.g. as
|
|
720
|
+
* `expectedCatalogVersion` for checkout) without digging into the publication.
|
|
721
|
+
*/
|
|
722
|
+
interface FFIDPublishedCatalog {
|
|
723
|
+
service: {
|
|
724
|
+
code: string;
|
|
725
|
+
name: string;
|
|
726
|
+
};
|
|
727
|
+
catalogVersion: string;
|
|
728
|
+
publication: FFIDCatalogPublication;
|
|
729
|
+
plans: FFIDPublishedPlan[];
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Credits API types (SDK 10.0.0 / FFID #6395, CREDITS_API.md v1.3.1).
|
|
734
|
+
*
|
|
735
|
+
* `pricing_model='flat'` plans (fixed fee + member limit + monthly AI credits)
|
|
736
|
+
* keep a credit ledger in FFID. These types mirror the FFID server's response
|
|
737
|
+
* shapes exactly; the FFID repository type-checks them against the server types
|
|
738
|
+
* (`src/lib/credits/__tests__/sdk-credits-types.sync.test.ts`), so a field changed
|
|
739
|
+
* on one side only fails FFID's gate.
|
|
740
|
+
*
|
|
741
|
+
* Kept out of `types/index.ts` (file-size limit). Exported directly from the
|
|
742
|
+
* package entry.
|
|
743
|
+
*/
|
|
744
|
+
|
|
745
|
+
/** Values of the history `type` filter / item `type` */
|
|
746
|
+
declare const FFID_CREDIT_HISTORY_TYPES: readonly ["grant", "consumption", "revocation"];
|
|
747
|
+
/** Kinds of credit grant */
|
|
748
|
+
declare const FFID_CREDIT_GRANT_KINDS: readonly ["monthly", "manual", "pack"];
|
|
749
|
+
/**
|
|
750
|
+
* Billing model of a plan. `flat` = fixed fee + member limit + monthly credits;
|
|
751
|
+
* `per_seat` = seat billing (praxis). Do not infer it from `planCode`.
|
|
752
|
+
*/
|
|
753
|
+
type FFIDPricingModel = 'per_seat' | 'flat';
|
|
754
|
+
/** History item / filter type */
|
|
755
|
+
type FFIDCreditHistoryType = (typeof FFID_CREDIT_HISTORY_TYPES)[number];
|
|
756
|
+
/** Grant kind: monthly allowance, operator grant, or purchased pack */
|
|
757
|
+
type FFIDCreditGrantKind = (typeof FFID_CREDIT_GRANT_KINDS)[number];
|
|
758
|
+
/** Remaining credits per grant kind */
|
|
759
|
+
interface FFIDCreditBreakdown {
|
|
760
|
+
monthly: number;
|
|
761
|
+
manual: number;
|
|
762
|
+
pack: number;
|
|
763
|
+
}
|
|
764
|
+
/** `GET /ext/{id}/credits/balance` (CREDITS_API §4.2) */
|
|
765
|
+
interface FFIDCreditBalance {
|
|
766
|
+
subscriptionId: string;
|
|
767
|
+
organizationId: string;
|
|
768
|
+
serviceCode: string;
|
|
769
|
+
pricingModel: 'flat';
|
|
770
|
+
/** Credits usable now (sum of active grants' remaining) */
|
|
771
|
+
available: number;
|
|
772
|
+
/** This period's monthly allowance */
|
|
773
|
+
monthlyCredits: number;
|
|
774
|
+
/** Current monthly window; null when there is no monthly grant this period */
|
|
775
|
+
period: {
|
|
776
|
+
start: string;
|
|
777
|
+
end: string;
|
|
778
|
+
} | null;
|
|
779
|
+
breakdown: FFIDCreditBreakdown;
|
|
780
|
+
/** Next manual / pack expiry; null when none is active */
|
|
781
|
+
nextExpiry: {
|
|
782
|
+
at: string;
|
|
783
|
+
amount: number;
|
|
784
|
+
} | null;
|
|
785
|
+
lowThresholdPercent: number;
|
|
786
|
+
/** `available < monthlyCredits * lowThresholdPercent / 100` (always false when monthlyCredits = 0) */
|
|
787
|
+
isLow: boolean;
|
|
788
|
+
/** `available === 0` */
|
|
789
|
+
isExhausted: boolean;
|
|
790
|
+
/** ISO 8601 time the balance was read */
|
|
791
|
+
asOf: string;
|
|
792
|
+
}
|
|
793
|
+
/** `POST /ext/{id}/credits/consume` 200 response (CREDITS_API §4.1) */
|
|
794
|
+
interface FFIDCreditConsumeResult {
|
|
795
|
+
/**
|
|
796
|
+
* `duplicate` = same idempotency key and amount was already consumed. No side
|
|
797
|
+
* effect; `consumptionId` / `amount` are the first call's, `balance` is current,
|
|
798
|
+
* and `crossedLow` / `crossedExhausted` are always false.
|
|
799
|
+
*/
|
|
800
|
+
status: 'consumed' | 'duplicate';
|
|
801
|
+
consumptionId: string;
|
|
802
|
+
amount: number;
|
|
803
|
+
balance: {
|
|
804
|
+
available: number;
|
|
805
|
+
monthlyCredits: number;
|
|
806
|
+
breakdown: FFIDCreditBreakdown;
|
|
807
|
+
};
|
|
808
|
+
/** This consumption crossed the low-balance threshold (once per period) */
|
|
809
|
+
crossedLow: boolean;
|
|
810
|
+
/** This consumption brought the balance to 0 (once per period) */
|
|
811
|
+
crossedExhausted: boolean;
|
|
812
|
+
}
|
|
813
|
+
/** One row of the credit history (CREDITS_API §4.3) */
|
|
814
|
+
interface FFIDCreditHistoryItem {
|
|
815
|
+
/** Grant / consumption id. For `revocation` this is the revoked grant's id */
|
|
816
|
+
id: string;
|
|
817
|
+
type: FFIDCreditHistoryType;
|
|
818
|
+
/** Always positive; the direction is given by `type` */
|
|
819
|
+
amount: number;
|
|
820
|
+
occurredAt: string;
|
|
821
|
+
/** Set for `grant` / `revocation` */
|
|
822
|
+
kind: FFIDCreditGrantKind | null;
|
|
823
|
+
expiresAt: string | null;
|
|
824
|
+
/** Set for `consumption` */
|
|
825
|
+
feature: string | null;
|
|
826
|
+
/** Set for `consumption` */
|
|
827
|
+
idempotencyKey: string | null;
|
|
828
|
+
actorUserId: string | null;
|
|
829
|
+
reason: string | null;
|
|
830
|
+
metadata: Record<string, unknown> | null;
|
|
831
|
+
}
|
|
832
|
+
/** `GET /ext/{id}/credits/history` (newest first) */
|
|
833
|
+
interface FFIDCreditHistoryPage {
|
|
834
|
+
items: FFIDCreditHistoryItem[];
|
|
835
|
+
/** Opaque cursor for the next page; null on the last page */
|
|
836
|
+
nextCursor: string | null;
|
|
837
|
+
}
|
|
838
|
+
/** One purchasable credit pack (CREDITS_API §4.4) */
|
|
839
|
+
interface FFIDCreditPack {
|
|
840
|
+
code: string;
|
|
841
|
+
name: string;
|
|
842
|
+
credits: number;
|
|
843
|
+
/** Tax-inclusive price in the smallest currency unit */
|
|
844
|
+
price: number;
|
|
845
|
+
currency: string;
|
|
846
|
+
taxBehavior: FFIDTaxBehavior;
|
|
847
|
+
validityMonths: number;
|
|
848
|
+
displayOrder: number;
|
|
849
|
+
}
|
|
850
|
+
/** `GET /ext/credits/packs` */
|
|
851
|
+
interface FFIDCreditPackList {
|
|
852
|
+
serviceCode: string;
|
|
853
|
+
packs: FFIDCreditPack[];
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* `POST /ext/credits/packs/checkout` (CREDITS_API §4.5). Credits are **not**
|
|
857
|
+
* granted yet when this returns — confirm with `credits.pack_purchased` /
|
|
858
|
+
* `credits.granted` or the balance.
|
|
859
|
+
*/
|
|
860
|
+
interface FFIDCreditPackCheckout {
|
|
861
|
+
checkoutUrl: string;
|
|
862
|
+
sessionId: string;
|
|
863
|
+
operationId: string;
|
|
864
|
+
/** ISO 8601 */
|
|
865
|
+
expiresAt: string;
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* `credits` field added to `/ext/check` (CREDITS_API §5.1). Null for per_seat,
|
|
869
|
+
* for no subscription, **and** when FFID could not read the ledger — so null
|
|
870
|
+
* does not mean "not flat"; use `pricingModel`.
|
|
871
|
+
*/
|
|
872
|
+
interface FFIDSubscriptionCheckCredits {
|
|
873
|
+
available: number;
|
|
874
|
+
monthlyCredits: number;
|
|
875
|
+
isLow: boolean;
|
|
876
|
+
isExhausted: boolean;
|
|
877
|
+
periodEnd: string | null;
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* `GET /ext/{id}/seats` (CREDITS_API §5.2).
|
|
881
|
+
*
|
|
882
|
+
* flat contracts report the member limit: `maxMembers` (null = unlimited),
|
|
883
|
+
* `assignedMembers`, `availableMembers` (null = unlimited); `quantity` /
|
|
884
|
+
* `minSeats` / `maxSeats` are always 1 and `availableSeats === availableMembers`.
|
|
885
|
+
* per_seat contracts keep the seat shape and only add `pricingModel`.
|
|
886
|
+
* FFID servers released before #6392 omit `pricingModel` and the member fields.
|
|
887
|
+
*/
|
|
888
|
+
interface FFIDSeatsSummary {
|
|
889
|
+
subscriptionId: string;
|
|
890
|
+
organizationId: string;
|
|
891
|
+
pricingModel?: FFIDPricingModel;
|
|
892
|
+
quantity: number;
|
|
893
|
+
assignedSeats: number;
|
|
894
|
+
availableSeats: number | null;
|
|
895
|
+
minSeats: number;
|
|
896
|
+
maxSeats: number | null;
|
|
897
|
+
maxMembers?: number | null;
|
|
898
|
+
assignedMembers?: number;
|
|
899
|
+
availableMembers?: number | null;
|
|
900
|
+
}
|
|
901
|
+
/** Input of `client.credits.consume()` (service-key mode only) */
|
|
902
|
+
interface FFIDCreditConsumeParams {
|
|
903
|
+
/** Contract id: UUID, `ffid:<uuid>` or Stripe `sub_...` */
|
|
904
|
+
subscriptionId: string;
|
|
905
|
+
/** Integer, `FFID_CREDITS_CONSUME_MIN_AMOUNT`..`FFID_CREDITS_CONSUME_MAX_AMOUNT` */
|
|
906
|
+
amount: number;
|
|
907
|
+
/**
|
|
908
|
+
* One key per AI execution, reused on retry (`FFID_CREDITS_IDEMPOTENCY_KEY_PATTERN`).
|
|
909
|
+
* Recommended: `${feature}:${requestId}`.
|
|
910
|
+
*/
|
|
911
|
+
idempotencyKey: string;
|
|
912
|
+
/** Service-side feature identifier (`FFID_CREDITS_FEATURE_PATTERN`) */
|
|
913
|
+
feature: string;
|
|
914
|
+
/**
|
|
915
|
+
* Aggregation values only (model name, token counts). **No personal data** —
|
|
916
|
+
* consumption rows are accounting records and survive user deletion.
|
|
917
|
+
* JSON object, at most `FFID_CREDITS_METADATA_MAX_BYTES` bytes.
|
|
918
|
+
*/
|
|
919
|
+
metadata?: Record<string, unknown>;
|
|
920
|
+
/** End user who ran the AI (UUID). Recorded for audit only */
|
|
921
|
+
userId?: string;
|
|
922
|
+
}
|
|
923
|
+
/** Options of `client.credits.listHistory()` */
|
|
924
|
+
interface FFIDListCreditHistoryOptions {
|
|
925
|
+
/** `nextCursor` of the previous page */
|
|
926
|
+
cursor?: string;
|
|
927
|
+
/** `FFID_CREDITS_HISTORY_MIN_LIMIT`..`FFID_CREDITS_HISTORY_MAX_LIMIT` (server default 20) */
|
|
928
|
+
limit?: number;
|
|
929
|
+
/** Filter by type; omitted = all */
|
|
930
|
+
type?: FFIDCreditHistoryType;
|
|
931
|
+
}
|
|
932
|
+
/** Input of `client.credits.createPackCheckout()` (token mode only) */
|
|
933
|
+
interface FFIDCreatePackCheckoutParams {
|
|
934
|
+
/** Contract id: UUID, `ffid:<uuid>` or Stripe `sub_...` */
|
|
935
|
+
subscriptionId: string;
|
|
936
|
+
/** `code` from `listPacks()` */
|
|
937
|
+
packCode: string;
|
|
938
|
+
/** https URL to return to after payment */
|
|
939
|
+
successUrl: string;
|
|
940
|
+
/** https URL to return to on cancel */
|
|
941
|
+
cancelUrl: string;
|
|
942
|
+
/** `FFID_CREDIT_PACK_MIN_QUANTITY`..`FFID_CREDIT_PACK_MAX_QUANTITY` (server default 1) */
|
|
943
|
+
quantity?: number;
|
|
944
|
+
}
|
|
945
|
+
/** Input of `client.credits.getBuyCreditsUrl()` / `redirectToBuyCredits()` */
|
|
946
|
+
interface FFIDBuyCreditsUrlParams {
|
|
947
|
+
/**
|
|
948
|
+
* Contract id as a UUID or `ffid:<uuid>`. The FFID portal page takes the UUID
|
|
949
|
+
* form only, so a Stripe `sub_...` id is rejected with `VALIDATION_ERROR`.
|
|
950
|
+
*/
|
|
951
|
+
subscriptionId: string;
|
|
952
|
+
/** Organization ID — passed as `?org=` so FFID selects that organization */
|
|
953
|
+
orgId?: string;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
/**
|
|
957
|
+
* Canonical service-access types for subscription lifecycle decisions.
|
|
958
|
+
*/
|
|
959
|
+
|
|
960
|
+
/** Subscription status values matching the FFID platform's SubscriptionStatus type */
|
|
961
|
+
type FFIDSubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'pending_invoice' | 'paused' | 'incomplete' | 'incomplete_expired' | 'unpaid';
|
|
962
|
+
interface FFIDSubscriptionCheckResponse {
|
|
963
|
+
hasActiveSubscription: boolean;
|
|
964
|
+
/**
|
|
965
|
+
* Canonical access decision returned by FFID's `/subscriptions/ext/check`.
|
|
966
|
+
*
|
|
967
|
+
* This is the server-side source of truth for service gates. Consumers
|
|
968
|
+
* should not recompute access from `currentPeriodEnd`, `past_due_since`, or
|
|
969
|
+
* local payment timestamps.
|
|
970
|
+
*/
|
|
971
|
+
hasAccess?: boolean;
|
|
972
|
+
/** True when `effectiveStatus === 'past_due_grace'`. */
|
|
973
|
+
isGrace?: boolean;
|
|
974
|
+
/** True when FFID's canonical effective status denies service access. */
|
|
975
|
+
isBlocked?: boolean;
|
|
976
|
+
organizationId: string | null;
|
|
977
|
+
subscriptionId: string | null;
|
|
978
|
+
status: FFIDSubscriptionStatus | null;
|
|
979
|
+
planCode: string | null;
|
|
980
|
+
currentPeriodEnd: string | null;
|
|
981
|
+
/**
|
|
982
|
+
* Semantic FFID access-control status. `null` means the organization has no
|
|
983
|
+
* subscription row for this service.
|
|
984
|
+
*/
|
|
985
|
+
effectiveStatus?: EffectiveSubscriptionStatus | null;
|
|
986
|
+
/**
|
|
987
|
+
* ISO timestamp at which `past_due_grace` flips to `blocked`; null outside
|
|
988
|
+
* the grace window.
|
|
989
|
+
*/
|
|
990
|
+
gracePeriodEndsAt?: string | null;
|
|
991
|
+
/** Whether a canceled subscription can be resumed via a re-subscription flow. */
|
|
992
|
+
reactivatable?: boolean;
|
|
993
|
+
/**
|
|
994
|
+
* Billing model of the subscription's plan (10.0.0; CREDITS_API §5.1). `null` when
|
|
995
|
+
* there is no subscription. FFID servers released before #6390 omit it.
|
|
996
|
+
*/
|
|
997
|
+
pricingModel?: FFIDPricingModel | null;
|
|
998
|
+
/**
|
|
999
|
+
* Credit balance summary — flat plans only (10.0.0). `null` for per_seat, for no
|
|
1000
|
+
* subscription, **and** when FFID could not read the ledger, so `null` does not
|
|
1001
|
+
* mean "not flat" (use `pricingModel`). Never affects `hasAccess`.
|
|
1002
|
+
*/
|
|
1003
|
+
credits?: FFIDSubscriptionCheckCredits | null;
|
|
1004
|
+
/**
|
|
1005
|
+
* The plan's member limit is full (10.0.0). Informational: `hasAccess` is not
|
|
1006
|
+
* affected. A user who cannot get a seat because of it is refused at login with
|
|
1007
|
+
* OAuth `denial_reason: 'member_limit_reached'`.
|
|
1008
|
+
*/
|
|
1009
|
+
memberLimitReached?: boolean;
|
|
1010
|
+
}
|
|
1011
|
+
type FFIDServiceAccessFailPolicy = 'failClosed';
|
|
1012
|
+
/**
|
|
1013
|
+
* Why access was denied.
|
|
1014
|
+
*
|
|
1015
|
+
* `member_limit_reached` (10.0.0) is FFID's denial reason when a flat plan's member
|
|
1016
|
+
* limit is full and the user has no seat. It reaches you through OAuth
|
|
1017
|
+
* (`denial_reason` on authorize / userinfo / introspect); `checkServiceAccess()`
|
|
1018
|
+
* derives its decision from `effectiveStatus` and never returns it, because a full
|
|
1019
|
+
* member limit does not change `hasAccess` (CREDITS_API §1-5). It is in this union so
|
|
1020
|
+
* one exhaustive `switch` over denial reasons covers both paths.
|
|
1021
|
+
*/
|
|
1022
|
+
type FFIDServiceAccessDenialReason = 'no_subscription' | 'grace_disallowed' | 'blocked' | 'canceled' | 'expired' | 'trial_expired' | 'ffid_unreachable' | 'member_limit_reached';
|
|
1023
|
+
interface FFIDCheckServiceAccessParams {
|
|
1024
|
+
userId?: string;
|
|
1025
|
+
organizationId: string;
|
|
1026
|
+
/**
|
|
1027
|
+
* Whether `past_due_grace` should keep access open.
|
|
1028
|
+
*
|
|
1029
|
+
* @default true
|
|
1030
|
+
*/
|
|
1031
|
+
allowGrace?: boolean;
|
|
1032
|
+
/**
|
|
1033
|
+
* Error policy when FFID cannot return a canonical decision.
|
|
1034
|
+
*
|
|
1035
|
+
* Currently only `failClosed` is supported: network/server/parse failures
|
|
1036
|
+
* become `hasAccess=false` decisions with `denialReason='ffid_unreachable'`
|
|
1037
|
+
* and the root cause in `decision.error`. Treat `hasAccess` as the gate.
|
|
1038
|
+
*/
|
|
1039
|
+
failPolicy?: FFIDServiceAccessFailPolicy;
|
|
1040
|
+
}
|
|
1041
|
+
interface FFIDServiceAccessError {
|
|
1042
|
+
code: string;
|
|
1043
|
+
message: string;
|
|
1044
|
+
details?: unknown;
|
|
1045
|
+
}
|
|
1046
|
+
interface FFIDServiceAccessDecision {
|
|
1047
|
+
hasAccess: boolean;
|
|
1048
|
+
effectiveStatus: EffectiveSubscriptionStatus | null;
|
|
1049
|
+
isGrace: boolean;
|
|
1050
|
+
isBlocked: boolean;
|
|
1051
|
+
allowGrace: boolean;
|
|
1052
|
+
failPolicy: FFIDServiceAccessFailPolicy;
|
|
1053
|
+
denialReason: FFIDServiceAccessDenialReason | null;
|
|
1054
|
+
organizationId: string | null;
|
|
1055
|
+
subscriptionId: string | null;
|
|
1056
|
+
status: FFIDSubscriptionStatus | null;
|
|
1057
|
+
planCode: string | null;
|
|
1058
|
+
currentPeriodEnd: string | null;
|
|
1059
|
+
gracePeriodEndsAt: string | null;
|
|
1060
|
+
reactivatable: boolean;
|
|
1061
|
+
/** Passed through from `/ext/check` when the server sends it (10.0.0). Informational. */
|
|
1062
|
+
pricingModel?: FFIDPricingModel | null;
|
|
1063
|
+
/**
|
|
1064
|
+
* Passed through from `/ext/check` (10.0.0). Gate AI features on this or on
|
|
1065
|
+
* `credits.consume`'s result — not on `hasAccess`.
|
|
1066
|
+
*/
|
|
1067
|
+
credits?: FFIDSubscriptionCheckCredits | null;
|
|
1068
|
+
/** Passed through from `/ext/check` (10.0.0). Does not affect `hasAccess`. */
|
|
1069
|
+
memberLimitReached?: boolean;
|
|
1070
|
+
/**
|
|
1071
|
+
* Present when the decision was produced by the SDK fail-closed policy
|
|
1072
|
+
* rather than by a successful FFID response.
|
|
1073
|
+
*/
|
|
1074
|
+
error?: FFIDServiceAccessError;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
/**
|
|
1078
|
+
* Token Store
|
|
1079
|
+
*
|
|
1080
|
+
* Manages OAuth 2.0 tokens (access + refresh) with dual-storage support.
|
|
1081
|
+
* Falls back to in-memory storage when localStorage is unavailable
|
|
1082
|
+
* (e.g., Safari private browsing mode).
|
|
1083
|
+
*/
|
|
1084
|
+
/**
|
|
1085
|
+
* Token data stored by the token store
|
|
1086
|
+
*/
|
|
1087
|
+
interface TokenData {
|
|
1088
|
+
/** OAuth 2.0 access token */
|
|
1089
|
+
accessToken: string;
|
|
1090
|
+
/** OAuth 2.0 refresh token */
|
|
1091
|
+
refreshToken: string;
|
|
1092
|
+
/** Expiration timestamp in milliseconds (Unix epoch) */
|
|
1093
|
+
expiresAt: number;
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Token store interface for managing OAuth tokens
|
|
1097
|
+
*/
|
|
1098
|
+
interface TokenStore {
|
|
1099
|
+
/** Get stored tokens (null if not stored) */
|
|
1100
|
+
getTokens(): TokenData | null;
|
|
1101
|
+
/** Store new tokens */
|
|
1102
|
+
setTokens(tokens: TokenData): void;
|
|
1103
|
+
/** Clear all stored tokens */
|
|
1104
|
+
clearTokens(): void;
|
|
1105
|
+
/** Check if access token is expired (with 30s buffer) */
|
|
1106
|
+
isAccessTokenExpired(): boolean;
|
|
1107
|
+
}
|
|
1108
|
+
/**
|
|
1109
|
+
* Create a token store with the specified storage type.
|
|
675
1110
|
*
|
|
676
|
-
*
|
|
677
|
-
*
|
|
678
|
-
*
|
|
679
|
-
*
|
|
680
|
-
* - `false`: immediate change. `effectiveDate` is always `null`. For an increase,
|
|
681
|
-
* `proratedAmount` is the difference up to the current period end that is charged now
|
|
682
|
-
* (possibly Stripe-refined). A decrease on a contract that cannot be reserved also lands here:
|
|
683
|
-
* `0` for a contract without a Stripe subscription (no refund), but Stripe's prorated amount —
|
|
684
|
-
* negative, credited on the next invoice — for a Stripe contract with no period end yet
|
|
685
|
-
* (e.g. during a trial).
|
|
1111
|
+
* When storageType is 'localStorage' (default in browser), falls back
|
|
1112
|
+
* to memory if localStorage is not available (e.g., Safari private mode).
|
|
1113
|
+
*
|
|
1114
|
+
* @param storageType - 'localStorage' (default) or 'memory'
|
|
686
1115
|
*/
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
/**
|
|
699
|
-
|
|
700
|
-
|
|
1116
|
+
declare function createTokenStore(storageType?: 'localStorage' | 'memory'): TokenStore;
|
|
1117
|
+
|
|
1118
|
+
/**
|
|
1119
|
+
* Billing checkout / portal session types.
|
|
1120
|
+
*
|
|
1121
|
+
* types/index.ts のサイズ上限対応で切り出し(中身は逐語移設、#3787 Phase A)。
|
|
1122
|
+
*/
|
|
1123
|
+
/**
|
|
1124
|
+
* Checkout session response from billing checkout endpoint
|
|
1125
|
+
*/
|
|
1126
|
+
interface FFIDCheckoutSessionResponse {
|
|
1127
|
+
/** Stripe Checkout session ID */
|
|
1128
|
+
sessionId: string;
|
|
1129
|
+
/** Stripe Checkout session URL (null if session creation had issues) */
|
|
1130
|
+
url: string | null;
|
|
701
1131
|
}
|
|
702
|
-
/**
|
|
703
|
-
|
|
1132
|
+
/**
|
|
1133
|
+
* Portal session response from billing portal endpoint
|
|
1134
|
+
*/
|
|
1135
|
+
interface FFIDPortalSessionResponse {
|
|
1136
|
+
/** Stripe Billing Portal URL */
|
|
1137
|
+
url: string;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Parameters for creating a checkout session
|
|
1141
|
+
*/
|
|
1142
|
+
interface FFIDCreateCheckoutParams {
|
|
1143
|
+
/** Organization ID (UUID) */
|
|
1144
|
+
organizationId: string;
|
|
704
1145
|
/** Subscription ID (UUID) */
|
|
705
1146
|
subscriptionId: string;
|
|
706
|
-
/**
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
amount: number;
|
|
1147
|
+
/** URL to redirect after successful checkout */
|
|
1148
|
+
successUrl: string;
|
|
1149
|
+
/** URL to redirect after cancelled checkout */
|
|
1150
|
+
cancelUrl: string;
|
|
1151
|
+
/** Optional plan ID for upgrade or resubscription */
|
|
1152
|
+
planId?: string;
|
|
713
1153
|
}
|
|
714
1154
|
/**
|
|
715
|
-
*
|
|
716
|
-
*
|
|
717
|
-
* Sister type to `FFIDPlanChangePreview`. The shared `type` discriminant lets
|
|
718
|
-
* consumers narrow a preview payload without inspecting unrelated fields.
|
|
719
|
-
*
|
|
720
|
-
* - `willApplyAtPeriodEnd=true`: a seat reduction reserved until the period end.
|
|
721
|
-
* `proratedAmount` is 0 and `effectiveDate` is when the new seat count applies.
|
|
722
|
-
* - Otherwise the change applies immediately. For an increase, `proratedAmount` is the amount
|
|
723
|
-
* charged now up to the current period end. A reduction that cannot be reserved is normally
|
|
724
|
-
* `0`, but can be negative (a credit on the next invoice) for a Stripe contract with no period
|
|
725
|
-
* end yet or when only the contract unit price is known.
|
|
726
|
-
* - `isEstimate=true` (default when Stripe is not configured or data is unavailable):
|
|
727
|
-
* `proratedAmount` is computed locally. `isEstimate=false`: it reflects Stripe's live
|
|
728
|
-
* proration calculation.
|
|
729
|
-
*
|
|
730
|
-
* `nextInvoiceAmount` is a local estimate: flat period fee, or `unitPrice * newQuantity`.
|
|
731
|
-
* Flat capacity changes have zero prorated cost.
|
|
732
|
-
*
|
|
733
|
-
* `pricingUnavailable=true` means custom pricing or an unverified contracted Stripe
|
|
734
|
-
* Price. Hide amounts; zero is not a quote. `custom_pricing` permits the existing
|
|
735
|
-
* unbilled seat-change flow. Require another preview before confirmation only when
|
|
736
|
-
* pricing is unavailable and the reason is not `custom_pricing`. `stripe_error` also
|
|
737
|
-
* covers invoice/address failures after the contract price is known; use
|
|
738
|
-
* `pricingUnavailable`, not the reason alone, to decide whether to hide amounts.
|
|
739
|
-
* `no_stripe_data` means invoice proration is unavailable even if the contract unit
|
|
740
|
-
* price is known. Portal seat PUT independently enforces subscription limits;
|
|
741
|
-
* external consumers should guide users to the FFID portal for seat changes.
|
|
1155
|
+
* Parameters for creating a billing portal session
|
|
742
1156
|
*/
|
|
743
|
-
interface
|
|
744
|
-
/**
|
|
745
|
-
|
|
746
|
-
/**
|
|
747
|
-
|
|
748
|
-
currentQuantity: number;
|
|
749
|
-
newQuantity: number;
|
|
750
|
-
/** Per-seat price for the current billing interval */
|
|
751
|
-
unitPrice: number;
|
|
752
|
-
billingInterval: FFIDBillingInterval;
|
|
753
|
-
/**
|
|
754
|
-
* Amount charged now for the rest of the current billing period. A reserved seat reduction
|
|
755
|
-
* (`willApplyAtPeriodEnd: true`) is always `0`; see the type doc for reductions that cannot
|
|
756
|
-
* be reserved. Also `0` when `pricingUnavailable === true`; hide it instead of quoting zero.
|
|
757
|
-
*/
|
|
758
|
-
proratedAmount: number;
|
|
759
|
-
/** Next invoice full amount — flat period fee or per-seat price times newQuantity */
|
|
760
|
-
nextInvoiceAmount: number;
|
|
761
|
-
nextInvoiceDate: string | null;
|
|
762
|
-
currency: FFIDSupportedCurrency;
|
|
763
|
-
/** true when proratedAmount is a local estimate rather than Stripe invoice/proration data */
|
|
764
|
-
isEstimate: boolean;
|
|
765
|
-
/** Hide amounts: custom pricing or contracted Stripe Price could not be verified. */
|
|
766
|
-
pricingUnavailable?: boolean;
|
|
767
|
-
/** Reason why `isEstimate` is true. Only meaningful when `isEstimate === true`. */
|
|
768
|
-
estimateReason?: 'no_stripe_data' | 'custom_pricing' | 'stripe_error';
|
|
769
|
-
/**
|
|
770
|
-
* `true` when the seat reduction would be reserved until the period end (8.0.0).
|
|
771
|
-
* Absent or `false` = the change applies immediately.
|
|
772
|
-
*/
|
|
773
|
-
willApplyAtPeriodEnd?: boolean;
|
|
774
|
-
/** When the reserved seat count applies (present when `willApplyAtPeriodEnd` is `true`) */
|
|
775
|
-
effectiveDate?: string | null;
|
|
776
|
-
lineItems: FFIDSeatChangeLineItem[];
|
|
777
|
-
}
|
|
778
|
-
/** Response from seat change preview endpoint */
|
|
779
|
-
interface FFIDSeatChangePreviewResponse {
|
|
780
|
-
preview: FFIDSeatChangePreview;
|
|
1157
|
+
interface FFIDCreatePortalParams {
|
|
1158
|
+
/** Organization ID (UUID) */
|
|
1159
|
+
organizationId: string;
|
|
1160
|
+
/** URL to redirect when user exits the portal */
|
|
1161
|
+
returnUrl: string;
|
|
781
1162
|
}
|
|
782
1163
|
|
|
783
1164
|
/** Member role in an organization */
|
|
@@ -1124,12 +1505,28 @@ interface FFIDSeatAssignmentRecord {
|
|
|
1124
1505
|
createdAt: string;
|
|
1125
1506
|
updatedAt: string;
|
|
1126
1507
|
}
|
|
1127
|
-
/**
|
|
1508
|
+
/**
|
|
1509
|
+
* GET /api/v1/subscriptions/ext/{id}/seats/assignments のレスポンス
|
|
1510
|
+
*
|
|
1511
|
+
* 10.0.0(破壊的変更): flat 契約では `totalSeats` = 人数枠(`maxMembers`)で、
|
|
1512
|
+
* 無制限のプランでは `totalSeats` / `availableSeats` が `null` になる。
|
|
1513
|
+
* `pricingModel` で分岐すること(#6395(10.0.0)で assignments にも追加。それより前の FFID は返さない)。
|
|
1514
|
+
*/
|
|
1128
1515
|
interface FFIDListSeatAssignmentsResponse {
|
|
1129
1516
|
assignments: FFIDSeatAssignmentWithUser[];
|
|
1130
|
-
|
|
1517
|
+
/** 課金モデル。#6395(10.0.0)で assignments にも追加(それより前の FFID サーバーは返さない) */
|
|
1518
|
+
pricingModel?: 'per_seat' | 'flat';
|
|
1519
|
+
/** per_seat: 契約の席数。flat: 人数枠(`null` = 無制限) */
|
|
1520
|
+
totalSeats: number | null;
|
|
1131
1521
|
assignedSeats: number;
|
|
1132
|
-
|
|
1522
|
+
/** 残り。flat で無制限のときは `null` */
|
|
1523
|
+
availableSeats: number | null;
|
|
1524
|
+
/** flat のみ: 人数枠(`null` = 無制限) */
|
|
1525
|
+
maxMembers?: number | null;
|
|
1526
|
+
/** flat のみ: 割り当て済みの人数 */
|
|
1527
|
+
assignedMembers?: number;
|
|
1528
|
+
/** flat のみ: 残りの人数枠(`null` = 無制限) */
|
|
1529
|
+
availableMembers?: number | null;
|
|
1133
1530
|
}
|
|
1134
1531
|
/** listSeatAssignments のパラメータ */
|
|
1135
1532
|
interface FFIDListSeatAssignmentsParams {
|
|
@@ -1705,107 +2102,6 @@ type FFIDRedirectResult = {
|
|
|
1705
2102
|
code?: FFIDRedirectErrorCode;
|
|
1706
2103
|
};
|
|
1707
2104
|
|
|
1708
|
-
/** Deployment environments a catalog publication can apply to (single source) */
|
|
1709
|
-
declare const FFID_CATALOG_ENVIRONMENTS: readonly ["staging", "production"];
|
|
1710
|
-
/** Deployment environment a catalog publication applies to */
|
|
1711
|
-
type FFIDCatalogEnvironment = (typeof FFID_CATALOG_ENVIRONMENTS)[number];
|
|
1712
|
-
/**
|
|
1713
|
-
* Tax behavior of a published price.
|
|
1714
|
-
* `inclusive`: displayed price contains Stripe-calculated tax.
|
|
1715
|
-
* `exclusive`: tax is added on top of the base price.
|
|
1716
|
-
*/
|
|
1717
|
-
type FFIDTaxBehavior = 'inclusive' | 'exclusive';
|
|
1718
|
-
/**
|
|
1719
|
-
* Publication lifecycle statuses (single source — the type, the SDK runtime
|
|
1720
|
-
* validator, and consumer sets all derive from this tuple so a new literal
|
|
1721
|
-
* cannot be added to one side only).
|
|
1722
|
-
*/
|
|
1723
|
-
declare const FFID_CATALOG_PUBLICATION_STATUSES: readonly ["approved", "superseded", "revoking", "revoked"];
|
|
1724
|
-
/**
|
|
1725
|
-
* Publication lifecycle status.
|
|
1726
|
-
* - `approved`: sellable — the only status that permits new paid checkout
|
|
1727
|
-
* - `superseded`: replaced by a newer revision (old sessions may sell through
|
|
1728
|
-
* until `sellThroughUntil`)
|
|
1729
|
-
* - `revoking`: emergency stop in progress — never sellable
|
|
1730
|
-
* - `revoked`: emergency stop completed — never sellable
|
|
1731
|
-
*/
|
|
1732
|
-
type FFIDCatalogPublicationStatus = (typeof FFID_CATALOG_PUBLICATION_STATUSES)[number];
|
|
1733
|
-
/**
|
|
1734
|
-
* Human-approved publication record binding a catalog revision to the
|
|
1735
|
-
* content/config hashes reviewed at approval time.
|
|
1736
|
-
*
|
|
1737
|
-
* All `*Hash` fields are lowercase SHA-256 hex computed with the shared
|
|
1738
|
-
* canonicalization helpers in `shared/catalog-hash` — consumers re-hash the
|
|
1739
|
-
* content they actually render and must refuse new sales on any mismatch.
|
|
1740
|
-
*/
|
|
1741
|
-
interface FFIDCatalogPublication {
|
|
1742
|
-
serviceCode: string;
|
|
1743
|
-
environment: FFIDCatalogEnvironment;
|
|
1744
|
-
catalogVersion: string;
|
|
1745
|
-
praxisCopyHash: string;
|
|
1746
|
-
ffidCheckoutCopyHash: string;
|
|
1747
|
-
legalDisclosureHash: string;
|
|
1748
|
-
taxConfigurationHash: string;
|
|
1749
|
-
paymentConfigurationHash: string;
|
|
1750
|
-
scopeHash: string;
|
|
1751
|
-
/** Monotonically increasing per (service, environment) publication counter */
|
|
1752
|
-
salesEpoch: number;
|
|
1753
|
-
/** FFID-generated immutable human-review approval ID */
|
|
1754
|
-
approvalId: string;
|
|
1755
|
-
/** ISO 8601 timestamp of the recorded human review */
|
|
1756
|
-
reviewedAt: string;
|
|
1757
|
-
/** ISO 8601 timestamp the publication became effective */
|
|
1758
|
-
effectiveAt: string;
|
|
1759
|
-
/** ISO 8601 timestamp the publication was superseded (null while current) */
|
|
1760
|
-
supersededAt: string | null;
|
|
1761
|
-
/** ISO 8601 upper bound for old-session sell-through (null unless superseded) */
|
|
1762
|
-
sellThroughUntil: string | null;
|
|
1763
|
-
/** ISO 8601 timestamp an emergency revoke took effect (null unless revoking/revoked) */
|
|
1764
|
-
revocationEffectiveAt: string | null;
|
|
1765
|
-
status: FFIDCatalogPublicationStatus;
|
|
1766
|
-
}
|
|
1767
|
-
/**
|
|
1768
|
-
* A plan inside a published catalog revision (public-safe snapshot).
|
|
1769
|
-
* Never contains Stripe Product/Price identifiers or other secrets.
|
|
1770
|
-
*/
|
|
1771
|
-
interface FFIDPublishedPlan {
|
|
1772
|
-
/**
|
|
1773
|
-
* Plan code — always a lowercase slug (`^[a-z0-9][a-z0-9_-]*$`).
|
|
1774
|
-
* Per-service open set; see the FFID repo's
|
|
1775
|
-
* `docs/04-api/PLAN_CODE_CONTRACT.md` for the full guarantees.
|
|
1776
|
-
*/
|
|
1777
|
-
code: string;
|
|
1778
|
-
name: string;
|
|
1779
|
-
description: string | null;
|
|
1780
|
-
/** Monthly price in the catalog currency; null when monthly is not offered */
|
|
1781
|
-
priceMonthly: number | null;
|
|
1782
|
-
/** Yearly price in the catalog currency; null when yearly is not offered */
|
|
1783
|
-
priceYearly: number | null;
|
|
1784
|
-
currency: string;
|
|
1785
|
-
/** Billing intervals actually purchasable for this plan */
|
|
1786
|
-
billingIntervals: FFIDBillingInterval[];
|
|
1787
|
-
taxBehavior: FFIDTaxBehavior;
|
|
1788
|
-
minSeats: number;
|
|
1789
|
-
maxSeats: number | null;
|
|
1790
|
-
displayOrder: number;
|
|
1791
|
-
}
|
|
1792
|
-
/**
|
|
1793
|
-
* Response of GET /api/v1/subscriptions/ext/catalog/{serviceCode}.
|
|
1794
|
-
*
|
|
1795
|
-
* `catalogVersion` always equals `publication.catalogVersion`; it is hoisted
|
|
1796
|
-
* to the top level so consumers can pin the version (e.g. as
|
|
1797
|
-
* `expectedCatalogVersion` for checkout) without digging into the publication.
|
|
1798
|
-
*/
|
|
1799
|
-
interface FFIDPublishedCatalog {
|
|
1800
|
-
service: {
|
|
1801
|
-
code: string;
|
|
1802
|
-
name: string;
|
|
1803
|
-
};
|
|
1804
|
-
catalogVersion: string;
|
|
1805
|
-
publication: FFIDCatalogPublication;
|
|
1806
|
-
plans: FFIDPublishedPlan[];
|
|
1807
|
-
}
|
|
1808
|
-
|
|
1809
2105
|
/**
|
|
1810
2106
|
* FFID SDK Type Definitions
|
|
1811
2107
|
*
|
|
@@ -2513,6 +2809,7 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
2513
2809
|
getInvoice: (params: FFIDGetInvoiceParams) => Promise<FFIDApiResponse<FFIDGetInvoiceResponse>>;
|
|
2514
2810
|
retryPayment: (params: FFIDRetryPaymentParams) => Promise<FFIDApiResponse<FFIDRetryPaymentSummary>>;
|
|
2515
2811
|
listSeatAssignments: (params: FFIDListSeatAssignmentsParams) => Promise<FFIDApiResponse<FFIDListSeatAssignmentsResponse>>;
|
|
2812
|
+
getSeats: (subscriptionId: string) => Promise<FFIDApiResponse<FFIDSeatsSummary>>;
|
|
2516
2813
|
assignSeats: (params: FFIDAssignSeatsParams) => Promise<FFIDApiResponse<FFIDAssignSeatsResponse>>;
|
|
2517
2814
|
unassignSeat: (params: FFIDUnassignSeatParams) => Promise<FFIDApiResponse<FFIDUnassignSeatResponse>>;
|
|
2518
2815
|
listPlans: () => Promise<FFIDApiResponse<FFIDListPlansResponse>>;
|
|
@@ -2523,13 +2820,16 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
2523
2820
|
cancelSubscription: (params: FFIDCancelSubscriptionParams) => Promise<FFIDApiResponse<FFIDCancelSubscriptionResponse>>;
|
|
2524
2821
|
cancelPendingDowngrade: (subscriptionId: string) => Promise<FFIDApiResponse<FFIDCancelPendingDowngradeResponse>>;
|
|
2525
2822
|
previewPlanChange: (params: FFIDPreviewPlanChangeParams) => Promise<FFIDApiResponse<FFIDPlanChangePreviewResponse>>;
|
|
2823
|
+
/** @deprecated 10.0.0: per_seat (praxis) only; removed in 11.0.0 */
|
|
2526
2824
|
previewSeatChange: (params: FFIDPreviewSeatChangeParams) => Promise<FFIDApiResponse<FFIDSeatChangePreviewResponse>>;
|
|
2527
2825
|
verifyAccessToken: (accessToken: string, options?: FFIDVerifyAccessTokenOptions) => Promise<FFIDApiResponse<FFIDOAuthUserInfo>>;
|
|
2528
2826
|
getSubscribeUrl: (options?: ContractWizardSubscribeOptions) => string;
|
|
2529
2827
|
redirectToSubscribe: (options?: ContractWizardSubscribeOptions) => FFIDRedirectResult;
|
|
2530
2828
|
getChangePlanUrl: (subscriptionId: string, options?: ContractWizardSubscriptionOptions) => string;
|
|
2531
2829
|
redirectToChangePlan: (subscriptionId: string, options?: ContractWizardSubscriptionOptions) => FFIDRedirectResult;
|
|
2830
|
+
/** @deprecated 10.0.0: per_seat (praxis) only; removed in 11.0.0 */
|
|
2532
2831
|
getChangeSeatsUrl: (subscriptionId: string, options?: ContractWizardSubscriptionOptions) => string;
|
|
2832
|
+
/** @deprecated 10.0.0: per_seat (praxis) only; removed in 11.0.0 */
|
|
2533
2833
|
redirectToChangeSeats: (subscriptionId: string, options?: ContractWizardSubscriptionOptions) => FFIDRedirectResult;
|
|
2534
2834
|
getRecoverPaymentUrl: (subscriptionId: string, options?: ContractWizardSubscriptionOptions) => string;
|
|
2535
2835
|
redirectToRecoverPayment: (subscriptionId: string, options?: ContractWizardSubscriptionOptions) => FFIDRedirectResult;
|
|
@@ -2557,6 +2857,16 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
2557
2857
|
inquiry: {
|
|
2558
2858
|
create: (params: FFIDInquiryCreateParams) => Promise<FFIDApiResponse<FFIDInquiryCreateResponse>>;
|
|
2559
2859
|
};
|
|
2860
|
+
/** Credits methods for flat plans (consume / balance / history / packs) */
|
|
2861
|
+
credits: {
|
|
2862
|
+
getBalance: (subscriptionId: string) => Promise<FFIDApiResponse<FFIDCreditBalance>>;
|
|
2863
|
+
listHistory: (subscriptionId: string, options?: FFIDListCreditHistoryOptions) => Promise<FFIDApiResponse<FFIDCreditHistoryPage>>;
|
|
2864
|
+
listPacks: (packServiceCode?: string) => Promise<FFIDApiResponse<FFIDCreditPackList>>;
|
|
2865
|
+
createPackCheckout: (params: FFIDCreatePackCheckoutParams) => Promise<FFIDApiResponse<FFIDCreditPackCheckout>>;
|
|
2866
|
+
consume: (params: FFIDCreditConsumeParams) => Promise<FFIDApiResponse<FFIDCreditConsumeResult>>;
|
|
2867
|
+
getBuyCreditsUrl: (params: FFIDBuyCreditsUrlParams) => FFIDApiResponse<string>;
|
|
2868
|
+
redirectToBuyCredits: (params: FFIDBuyCreditsUrlParams) => FFIDRedirectResult;
|
|
2869
|
+
};
|
|
2560
2870
|
/** Token store (token mode only) */
|
|
2561
2871
|
tokenStore: TokenStore;
|
|
2562
2872
|
/**
|