@stackbe/sdk 0.2.0 → 0.4.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/dist/index.d.mts CHANGED
@@ -24,6 +24,30 @@ interface StackBEConfig {
24
24
  baseUrl?: string;
25
25
  /** Request timeout in milliseconds (default: 30000) */
26
26
  timeout?: number;
27
+ /**
28
+ * Session cache TTL in seconds (default: 0 = disabled).
29
+ * When set, getSession() results are cached to reduce API calls.
30
+ * @example
31
+ * ```typescript
32
+ * new StackBE({ apiKey, appId, sessionCacheTTL: 120 }) // Cache for 2 minutes
33
+ * ```
34
+ */
35
+ sessionCacheTTL?: number;
36
+ /**
37
+ * Development callback URL for magic link redirects.
38
+ * When set, this URL is used automatically when:
39
+ * - NODE_ENV !== 'production', or
40
+ * - useDev: true is passed to sendMagicLink()
41
+ * @example
42
+ * ```typescript
43
+ * new StackBE({
44
+ * apiKey,
45
+ * appId,
46
+ * devCallbackUrl: 'http://localhost:3000/auth/callback'
47
+ * })
48
+ * ```
49
+ */
50
+ devCallbackUrl?: string;
27
51
  }
28
52
  interface TrackUsageOptions {
29
53
  /** Quantity to track (default: 1) */
@@ -121,15 +145,43 @@ interface MagicLinkResponse {
121
145
  message: string;
122
146
  }
123
147
  interface VerifyTokenResponse {
148
+ success: boolean;
124
149
  valid: boolean;
125
- customer?: Customer;
126
- token?: string;
127
- expiresAt?: string;
150
+ /** Customer ID */
151
+ customerId: string;
152
+ /** Customer email */
153
+ email: string;
154
+ /** Session JWT token - use this for subsequent authenticated requests */
155
+ sessionToken: string;
156
+ /** Tenant ID (your StackBE tenant) */
157
+ tenantId?: string;
158
+ /** Organization ID if in org context */
159
+ organizationId?: string;
160
+ /** Role in the organization */
161
+ orgRole?: 'owner' | 'admin' | 'member';
162
+ /** URL to redirect to after verification */
163
+ redirectUrl?: string;
128
164
  }
129
165
  interface SessionResponse {
130
- customer: Customer;
166
+ valid: boolean;
167
+ /** Customer ID */
168
+ customerId: string;
169
+ /** Customer email */
170
+ email: string;
171
+ /** Session expiration time */
172
+ expiresAt?: string;
173
+ /** Tenant ID (your StackBE tenant) */
174
+ tenantId?: string;
175
+ /** Organization ID if in org context */
176
+ organizationId?: string;
177
+ /** Role in the organization */
178
+ orgRole?: 'owner' | 'admin' | 'member';
179
+ /** Customer details (if included) */
180
+ customer?: Customer;
181
+ /** Current subscription (if any) */
131
182
  subscription?: Subscription;
132
- entitlements: Record<string, boolean | number | string>;
183
+ /** Feature entitlements */
184
+ entitlements?: Record<string, boolean | number | string>;
133
185
  }
134
186
  interface CreateCheckoutOptions {
135
187
  /** Customer ID or email */
@@ -189,16 +241,109 @@ interface UpdateSubscriptionOptions {
189
241
  /** Proration behavior */
190
242
  prorate?: boolean;
191
243
  }
244
+ /**
245
+ * Error codes returned by StackBE API.
246
+ * Use these to handle specific error cases in your application.
247
+ *
248
+ * @example
249
+ * ```typescript
250
+ * try {
251
+ * await stackbe.auth.verifyToken(token);
252
+ * } catch (error) {
253
+ * if (error instanceof StackBEError) {
254
+ * switch (error.code) {
255
+ * case 'TOKEN_EXPIRED':
256
+ * return res.redirect('/login?error=expired');
257
+ * case 'TOKEN_ALREADY_USED':
258
+ * return res.redirect('/login?error=used');
259
+ * case 'SESSION_EXPIRED':
260
+ * return res.redirect('/login');
261
+ * default:
262
+ * return res.status(500).json({ error: 'Authentication failed' });
263
+ * }
264
+ * }
265
+ * }
266
+ * ```
267
+ */
268
+ type StackBEErrorCode = 'TOKEN_EXPIRED' | 'TOKEN_ALREADY_USED' | 'TOKEN_INVALID' | 'SESSION_EXPIRED' | 'SESSION_INVALID' | 'UNAUTHORIZED' | 'NOT_FOUND' | 'CUSTOMER_NOT_FOUND' | 'SUBSCRIPTION_NOT_FOUND' | 'PLAN_NOT_FOUND' | 'APP_NOT_FOUND' | 'VALIDATION_ERROR' | 'MISSING_REQUIRED_FIELD' | 'INVALID_EMAIL' | 'USAGE_LIMIT_EXCEEDED' | 'METRIC_NOT_FOUND' | 'FEATURE_NOT_AVAILABLE' | 'NO_ACTIVE_SUBSCRIPTION' | 'TIMEOUT' | 'NETWORK_ERROR' | 'UNKNOWN_ERROR';
192
269
  interface StackBEErrorResponse {
193
270
  statusCode: number;
194
271
  message: string;
195
272
  error: string;
273
+ code?: StackBEErrorCode;
196
274
  }
197
275
  declare class StackBEError extends Error {
198
276
  readonly statusCode: number;
199
- readonly code: string;
200
- constructor(message: string, statusCode: number, code: string);
277
+ readonly code: StackBEErrorCode;
278
+ constructor(message: string, statusCode: number, code: StackBEErrorCode | string);
279
+ /** Check if this is a specific error type */
280
+ is(code: StackBEErrorCode): boolean;
281
+ /** Check if this is an auth-related error */
282
+ isAuthError(): boolean;
283
+ /** Check if this is a "not found" error */
284
+ isNotFoundError(): boolean;
285
+ }
286
+ /**
287
+ * Webhook event types emitted by StackBE.
288
+ * Subscribe to these events to react to changes in your customers' subscriptions.
289
+ */
290
+ type WebhookEventType = 'subscription_created' | 'subscription_updated' | 'subscription_cancelled' | 'subscription_renewed' | 'trial_started' | 'trial_ended' | 'payment_succeeded' | 'payment_failed' | 'customer_created' | 'customer_updated';
291
+ /** Base webhook event structure */
292
+ interface WebhookEvent<T extends WebhookEventType = WebhookEventType, P = unknown> {
293
+ /** Event ID */
294
+ id: string;
295
+ /** Event type */
296
+ type: T;
297
+ /** Tenant ID */
298
+ tenantId: string;
299
+ /** App ID */
300
+ appId: string;
301
+ /** Event payload */
302
+ data: P;
303
+ /** When the event was created */
304
+ createdAt: string;
201
305
  }
306
+ /** Subscription webhook payload */
307
+ interface SubscriptionWebhookPayload {
308
+ id: string;
309
+ customerId: string;
310
+ planId: string;
311
+ planName: string;
312
+ status: 'active' | 'canceled' | 'past_due' | 'trialing' | 'paused';
313
+ currentPeriodStart: string;
314
+ currentPeriodEnd: string;
315
+ cancelAtPeriodEnd: boolean;
316
+ trialEnd?: string;
317
+ }
318
+ /** Customer webhook payload */
319
+ interface CustomerWebhookPayload {
320
+ id: string;
321
+ email: string;
322
+ name?: string;
323
+ metadata?: Record<string, unknown>;
324
+ }
325
+ /** Payment webhook payload */
326
+ interface PaymentWebhookPayload {
327
+ id: string;
328
+ subscriptionId: string;
329
+ customerId: string;
330
+ amount: number;
331
+ currency: string;
332
+ status: 'succeeded' | 'failed';
333
+ failureReason?: string;
334
+ }
335
+ type SubscriptionCreatedEvent = WebhookEvent<'subscription_created', SubscriptionWebhookPayload>;
336
+ type SubscriptionUpdatedEvent = WebhookEvent<'subscription_updated', SubscriptionWebhookPayload>;
337
+ type SubscriptionCancelledEvent = WebhookEvent<'subscription_cancelled', SubscriptionWebhookPayload>;
338
+ type SubscriptionRenewedEvent = WebhookEvent<'subscription_renewed', SubscriptionWebhookPayload>;
339
+ type TrialStartedEvent = WebhookEvent<'trial_started', SubscriptionWebhookPayload>;
340
+ type TrialEndedEvent = WebhookEvent<'trial_ended', SubscriptionWebhookPayload>;
341
+ type PaymentSucceededEvent = WebhookEvent<'payment_succeeded', PaymentWebhookPayload>;
342
+ type PaymentFailedEvent = WebhookEvent<'payment_failed', PaymentWebhookPayload>;
343
+ type CustomerCreatedEvent = WebhookEvent<'customer_created', CustomerWebhookPayload>;
344
+ type CustomerUpdatedEvent = WebhookEvent<'customer_updated', CustomerWebhookPayload>;
345
+ /** Union of all webhook event types */
346
+ type AnyWebhookEvent = SubscriptionCreatedEvent | SubscriptionUpdatedEvent | SubscriptionCancelledEvent | SubscriptionRenewedEvent | TrialStartedEvent | TrialEndedEvent | PaymentSucceededEvent | PaymentFailedEvent | CustomerCreatedEvent | CustomerUpdatedEvent;
202
347
 
203
348
  declare class UsageClient {
204
349
  private http;
@@ -570,13 +715,37 @@ declare class SubscriptionsClient {
570
715
  isActive(customerId: string): Promise<boolean>;
571
716
  }
572
717
 
718
+ interface AuthClientOptions {
719
+ /** Session cache TTL in seconds (0 = disabled) */
720
+ sessionCacheTTL?: number;
721
+ /** Development callback URL for magic links */
722
+ devCallbackUrl?: string;
723
+ }
573
724
  declare class AuthClient {
574
725
  private http;
575
726
  private appId;
576
- constructor(http: HttpClient, appId: string);
727
+ private sessionCache;
728
+ private sessionCacheTTL;
729
+ private devCallbackUrl?;
730
+ constructor(http: HttpClient, appId: string, options?: AuthClientOptions);
731
+ /**
732
+ * Check if we're in a development environment.
733
+ */
734
+ private isDev;
735
+ /**
736
+ * Clear the session cache (useful for testing or logout).
737
+ */
738
+ clearCache(): void;
739
+ /**
740
+ * Remove a specific session from the cache.
741
+ */
742
+ invalidateSession(sessionToken: string): void;
577
743
  /**
578
744
  * Send a magic link email to a customer for passwordless authentication.
579
745
  *
746
+ * If `devCallbackUrl` is configured and we're in a dev environment (NODE_ENV !== 'production'),
747
+ * the dev callback URL will be used automatically.
748
+ *
580
749
  * @example
581
750
  * ```typescript
582
751
  * // Send magic link
@@ -587,7 +756,7 @@ declare class AuthClient {
587
756
  * redirectUrl: 'https://myapp.com/dashboard',
588
757
  * });
589
758
  *
590
- * // For localhost development
759
+ * // For localhost development (auto-detected if devCallbackUrl is configured)
591
760
  * await stackbe.auth.sendMagicLink('user@example.com', {
592
761
  * useDev: true,
593
762
  * });
@@ -598,19 +767,27 @@ declare class AuthClient {
598
767
  * Verify a magic link token and get a session token.
599
768
  * Call this when the user clicks the magic link.
600
769
  *
770
+ * Returns the session token along with tenant and organization context.
771
+ *
601
772
  * @example
602
773
  * ```typescript
603
774
  * // In your /verify route handler
604
775
  * const { token } = req.query;
605
776
  *
606
- * const result = await stackbe.auth.verifyToken(token);
777
+ * try {
778
+ * const result = await stackbe.auth.verifyToken(token);
607
779
  *
608
- * if (result.valid) {
609
- * // Set session cookie
610
- * res.cookie('session', result.token, { httpOnly: true });
780
+ * // result includes: customerId, email, sessionToken, tenantId, organizationId
781
+ * res.cookie('session', result.sessionToken, { httpOnly: true });
611
782
  * res.redirect('/dashboard');
612
- * } else {
613
- * res.redirect('/login?error=invalid_token');
783
+ * } catch (error) {
784
+ * if (error instanceof StackBEError) {
785
+ * if (error.code === 'TOKEN_EXPIRED') {
786
+ * res.redirect('/login?error=expired');
787
+ * } else if (error.code === 'TOKEN_ALREADY_USED') {
788
+ * res.redirect('/login?error=used');
789
+ * }
790
+ * }
614
791
  * }
615
792
  * ```
616
793
  */
@@ -619,6 +796,11 @@ declare class AuthClient {
619
796
  * Get the current session for an authenticated customer.
620
797
  * Use this to validate session tokens and get customer data.
621
798
  *
799
+ * If `sessionCacheTTL` is configured, results are cached to reduce API calls.
800
+ * Use `invalidateSession()` or `clearCache()` to manually clear cached sessions.
801
+ *
802
+ * Returns session info including tenant and organization context extracted from the JWT.
803
+ *
622
804
  * @example
623
805
  * ```typescript
624
806
  * // Validate session on each request
@@ -627,9 +809,11 @@ declare class AuthClient {
627
809
  * const session = await stackbe.auth.getSession(sessionToken);
628
810
  *
629
811
  * if (session) {
630
- * req.customer = session.customer;
631
- * req.subscription = session.subscription;
632
- * req.entitlements = session.entitlements;
812
+ * console.log(session.customerId);
813
+ * console.log(session.tenantId); // Tenant context
814
+ * console.log(session.organizationId); // Org context (if applicable)
815
+ * console.log(session.subscription);
816
+ * console.log(session.entitlements);
633
817
  * }
634
818
  * ```
635
819
  */
@@ -781,4 +965,4 @@ declare class StackBE {
781
965
  }): (req: any, res: any, next: any) => Promise<any>;
782
966
  }
783
967
 
784
- export { AuthClient, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type CreateCheckoutOptions, type CreateCustomerOptions, type Customer, type CustomerUsageResponse, type CustomerWithSubscription, CustomersClient, EntitlementsClient, type EntitlementsResponse, type MagicLinkOptions, type MagicLinkResponse, type SessionResponse, StackBE, type StackBEConfig, StackBEError, type StackBEErrorResponse, type Subscription, type SubscriptionWithPlan, SubscriptionsClient, type TrackUsageOptions, type TrackUsageResponse, type UpdateCustomerOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type VerifyTokenResponse };
968
+ export { type AnyWebhookEvent, AuthClient, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type CreateCheckoutOptions, type CreateCustomerOptions, type Customer, type CustomerCreatedEvent, type CustomerUpdatedEvent, type CustomerUsageResponse, type CustomerWebhookPayload, type CustomerWithSubscription, CustomersClient, EntitlementsClient, type EntitlementsResponse, type MagicLinkOptions, type MagicLinkResponse, type PaymentFailedEvent, type PaymentSucceededEvent, type PaymentWebhookPayload, type SessionResponse, StackBE, type StackBEConfig, StackBEError, type StackBEErrorCode, type StackBEErrorResponse, type Subscription, type SubscriptionCancelledEvent, type SubscriptionCreatedEvent, type SubscriptionRenewedEvent, type SubscriptionUpdatedEvent, type SubscriptionWebhookPayload, type SubscriptionWithPlan, SubscriptionsClient, type TrackUsageOptions, type TrackUsageResponse, type TrialEndedEvent, type TrialStartedEvent, type UpdateCustomerOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type VerifyTokenResponse, type WebhookEvent, type WebhookEventType };
package/dist/index.d.ts CHANGED
@@ -24,6 +24,30 @@ interface StackBEConfig {
24
24
  baseUrl?: string;
25
25
  /** Request timeout in milliseconds (default: 30000) */
26
26
  timeout?: number;
27
+ /**
28
+ * Session cache TTL in seconds (default: 0 = disabled).
29
+ * When set, getSession() results are cached to reduce API calls.
30
+ * @example
31
+ * ```typescript
32
+ * new StackBE({ apiKey, appId, sessionCacheTTL: 120 }) // Cache for 2 minutes
33
+ * ```
34
+ */
35
+ sessionCacheTTL?: number;
36
+ /**
37
+ * Development callback URL for magic link redirects.
38
+ * When set, this URL is used automatically when:
39
+ * - NODE_ENV !== 'production', or
40
+ * - useDev: true is passed to sendMagicLink()
41
+ * @example
42
+ * ```typescript
43
+ * new StackBE({
44
+ * apiKey,
45
+ * appId,
46
+ * devCallbackUrl: 'http://localhost:3000/auth/callback'
47
+ * })
48
+ * ```
49
+ */
50
+ devCallbackUrl?: string;
27
51
  }
28
52
  interface TrackUsageOptions {
29
53
  /** Quantity to track (default: 1) */
@@ -121,15 +145,43 @@ interface MagicLinkResponse {
121
145
  message: string;
122
146
  }
123
147
  interface VerifyTokenResponse {
148
+ success: boolean;
124
149
  valid: boolean;
125
- customer?: Customer;
126
- token?: string;
127
- expiresAt?: string;
150
+ /** Customer ID */
151
+ customerId: string;
152
+ /** Customer email */
153
+ email: string;
154
+ /** Session JWT token - use this for subsequent authenticated requests */
155
+ sessionToken: string;
156
+ /** Tenant ID (your StackBE tenant) */
157
+ tenantId?: string;
158
+ /** Organization ID if in org context */
159
+ organizationId?: string;
160
+ /** Role in the organization */
161
+ orgRole?: 'owner' | 'admin' | 'member';
162
+ /** URL to redirect to after verification */
163
+ redirectUrl?: string;
128
164
  }
129
165
  interface SessionResponse {
130
- customer: Customer;
166
+ valid: boolean;
167
+ /** Customer ID */
168
+ customerId: string;
169
+ /** Customer email */
170
+ email: string;
171
+ /** Session expiration time */
172
+ expiresAt?: string;
173
+ /** Tenant ID (your StackBE tenant) */
174
+ tenantId?: string;
175
+ /** Organization ID if in org context */
176
+ organizationId?: string;
177
+ /** Role in the organization */
178
+ orgRole?: 'owner' | 'admin' | 'member';
179
+ /** Customer details (if included) */
180
+ customer?: Customer;
181
+ /** Current subscription (if any) */
131
182
  subscription?: Subscription;
132
- entitlements: Record<string, boolean | number | string>;
183
+ /** Feature entitlements */
184
+ entitlements?: Record<string, boolean | number | string>;
133
185
  }
134
186
  interface CreateCheckoutOptions {
135
187
  /** Customer ID or email */
@@ -189,16 +241,109 @@ interface UpdateSubscriptionOptions {
189
241
  /** Proration behavior */
190
242
  prorate?: boolean;
191
243
  }
244
+ /**
245
+ * Error codes returned by StackBE API.
246
+ * Use these to handle specific error cases in your application.
247
+ *
248
+ * @example
249
+ * ```typescript
250
+ * try {
251
+ * await stackbe.auth.verifyToken(token);
252
+ * } catch (error) {
253
+ * if (error instanceof StackBEError) {
254
+ * switch (error.code) {
255
+ * case 'TOKEN_EXPIRED':
256
+ * return res.redirect('/login?error=expired');
257
+ * case 'TOKEN_ALREADY_USED':
258
+ * return res.redirect('/login?error=used');
259
+ * case 'SESSION_EXPIRED':
260
+ * return res.redirect('/login');
261
+ * default:
262
+ * return res.status(500).json({ error: 'Authentication failed' });
263
+ * }
264
+ * }
265
+ * }
266
+ * ```
267
+ */
268
+ type StackBEErrorCode = 'TOKEN_EXPIRED' | 'TOKEN_ALREADY_USED' | 'TOKEN_INVALID' | 'SESSION_EXPIRED' | 'SESSION_INVALID' | 'UNAUTHORIZED' | 'NOT_FOUND' | 'CUSTOMER_NOT_FOUND' | 'SUBSCRIPTION_NOT_FOUND' | 'PLAN_NOT_FOUND' | 'APP_NOT_FOUND' | 'VALIDATION_ERROR' | 'MISSING_REQUIRED_FIELD' | 'INVALID_EMAIL' | 'USAGE_LIMIT_EXCEEDED' | 'METRIC_NOT_FOUND' | 'FEATURE_NOT_AVAILABLE' | 'NO_ACTIVE_SUBSCRIPTION' | 'TIMEOUT' | 'NETWORK_ERROR' | 'UNKNOWN_ERROR';
192
269
  interface StackBEErrorResponse {
193
270
  statusCode: number;
194
271
  message: string;
195
272
  error: string;
273
+ code?: StackBEErrorCode;
196
274
  }
197
275
  declare class StackBEError extends Error {
198
276
  readonly statusCode: number;
199
- readonly code: string;
200
- constructor(message: string, statusCode: number, code: string);
277
+ readonly code: StackBEErrorCode;
278
+ constructor(message: string, statusCode: number, code: StackBEErrorCode | string);
279
+ /** Check if this is a specific error type */
280
+ is(code: StackBEErrorCode): boolean;
281
+ /** Check if this is an auth-related error */
282
+ isAuthError(): boolean;
283
+ /** Check if this is a "not found" error */
284
+ isNotFoundError(): boolean;
285
+ }
286
+ /**
287
+ * Webhook event types emitted by StackBE.
288
+ * Subscribe to these events to react to changes in your customers' subscriptions.
289
+ */
290
+ type WebhookEventType = 'subscription_created' | 'subscription_updated' | 'subscription_cancelled' | 'subscription_renewed' | 'trial_started' | 'trial_ended' | 'payment_succeeded' | 'payment_failed' | 'customer_created' | 'customer_updated';
291
+ /** Base webhook event structure */
292
+ interface WebhookEvent<T extends WebhookEventType = WebhookEventType, P = unknown> {
293
+ /** Event ID */
294
+ id: string;
295
+ /** Event type */
296
+ type: T;
297
+ /** Tenant ID */
298
+ tenantId: string;
299
+ /** App ID */
300
+ appId: string;
301
+ /** Event payload */
302
+ data: P;
303
+ /** When the event was created */
304
+ createdAt: string;
201
305
  }
306
+ /** Subscription webhook payload */
307
+ interface SubscriptionWebhookPayload {
308
+ id: string;
309
+ customerId: string;
310
+ planId: string;
311
+ planName: string;
312
+ status: 'active' | 'canceled' | 'past_due' | 'trialing' | 'paused';
313
+ currentPeriodStart: string;
314
+ currentPeriodEnd: string;
315
+ cancelAtPeriodEnd: boolean;
316
+ trialEnd?: string;
317
+ }
318
+ /** Customer webhook payload */
319
+ interface CustomerWebhookPayload {
320
+ id: string;
321
+ email: string;
322
+ name?: string;
323
+ metadata?: Record<string, unknown>;
324
+ }
325
+ /** Payment webhook payload */
326
+ interface PaymentWebhookPayload {
327
+ id: string;
328
+ subscriptionId: string;
329
+ customerId: string;
330
+ amount: number;
331
+ currency: string;
332
+ status: 'succeeded' | 'failed';
333
+ failureReason?: string;
334
+ }
335
+ type SubscriptionCreatedEvent = WebhookEvent<'subscription_created', SubscriptionWebhookPayload>;
336
+ type SubscriptionUpdatedEvent = WebhookEvent<'subscription_updated', SubscriptionWebhookPayload>;
337
+ type SubscriptionCancelledEvent = WebhookEvent<'subscription_cancelled', SubscriptionWebhookPayload>;
338
+ type SubscriptionRenewedEvent = WebhookEvent<'subscription_renewed', SubscriptionWebhookPayload>;
339
+ type TrialStartedEvent = WebhookEvent<'trial_started', SubscriptionWebhookPayload>;
340
+ type TrialEndedEvent = WebhookEvent<'trial_ended', SubscriptionWebhookPayload>;
341
+ type PaymentSucceededEvent = WebhookEvent<'payment_succeeded', PaymentWebhookPayload>;
342
+ type PaymentFailedEvent = WebhookEvent<'payment_failed', PaymentWebhookPayload>;
343
+ type CustomerCreatedEvent = WebhookEvent<'customer_created', CustomerWebhookPayload>;
344
+ type CustomerUpdatedEvent = WebhookEvent<'customer_updated', CustomerWebhookPayload>;
345
+ /** Union of all webhook event types */
346
+ type AnyWebhookEvent = SubscriptionCreatedEvent | SubscriptionUpdatedEvent | SubscriptionCancelledEvent | SubscriptionRenewedEvent | TrialStartedEvent | TrialEndedEvent | PaymentSucceededEvent | PaymentFailedEvent | CustomerCreatedEvent | CustomerUpdatedEvent;
202
347
 
203
348
  declare class UsageClient {
204
349
  private http;
@@ -570,13 +715,37 @@ declare class SubscriptionsClient {
570
715
  isActive(customerId: string): Promise<boolean>;
571
716
  }
572
717
 
718
+ interface AuthClientOptions {
719
+ /** Session cache TTL in seconds (0 = disabled) */
720
+ sessionCacheTTL?: number;
721
+ /** Development callback URL for magic links */
722
+ devCallbackUrl?: string;
723
+ }
573
724
  declare class AuthClient {
574
725
  private http;
575
726
  private appId;
576
- constructor(http: HttpClient, appId: string);
727
+ private sessionCache;
728
+ private sessionCacheTTL;
729
+ private devCallbackUrl?;
730
+ constructor(http: HttpClient, appId: string, options?: AuthClientOptions);
731
+ /**
732
+ * Check if we're in a development environment.
733
+ */
734
+ private isDev;
735
+ /**
736
+ * Clear the session cache (useful for testing or logout).
737
+ */
738
+ clearCache(): void;
739
+ /**
740
+ * Remove a specific session from the cache.
741
+ */
742
+ invalidateSession(sessionToken: string): void;
577
743
  /**
578
744
  * Send a magic link email to a customer for passwordless authentication.
579
745
  *
746
+ * If `devCallbackUrl` is configured and we're in a dev environment (NODE_ENV !== 'production'),
747
+ * the dev callback URL will be used automatically.
748
+ *
580
749
  * @example
581
750
  * ```typescript
582
751
  * // Send magic link
@@ -587,7 +756,7 @@ declare class AuthClient {
587
756
  * redirectUrl: 'https://myapp.com/dashboard',
588
757
  * });
589
758
  *
590
- * // For localhost development
759
+ * // For localhost development (auto-detected if devCallbackUrl is configured)
591
760
  * await stackbe.auth.sendMagicLink('user@example.com', {
592
761
  * useDev: true,
593
762
  * });
@@ -598,19 +767,27 @@ declare class AuthClient {
598
767
  * Verify a magic link token and get a session token.
599
768
  * Call this when the user clicks the magic link.
600
769
  *
770
+ * Returns the session token along with tenant and organization context.
771
+ *
601
772
  * @example
602
773
  * ```typescript
603
774
  * // In your /verify route handler
604
775
  * const { token } = req.query;
605
776
  *
606
- * const result = await stackbe.auth.verifyToken(token);
777
+ * try {
778
+ * const result = await stackbe.auth.verifyToken(token);
607
779
  *
608
- * if (result.valid) {
609
- * // Set session cookie
610
- * res.cookie('session', result.token, { httpOnly: true });
780
+ * // result includes: customerId, email, sessionToken, tenantId, organizationId
781
+ * res.cookie('session', result.sessionToken, { httpOnly: true });
611
782
  * res.redirect('/dashboard');
612
- * } else {
613
- * res.redirect('/login?error=invalid_token');
783
+ * } catch (error) {
784
+ * if (error instanceof StackBEError) {
785
+ * if (error.code === 'TOKEN_EXPIRED') {
786
+ * res.redirect('/login?error=expired');
787
+ * } else if (error.code === 'TOKEN_ALREADY_USED') {
788
+ * res.redirect('/login?error=used');
789
+ * }
790
+ * }
614
791
  * }
615
792
  * ```
616
793
  */
@@ -619,6 +796,11 @@ declare class AuthClient {
619
796
  * Get the current session for an authenticated customer.
620
797
  * Use this to validate session tokens and get customer data.
621
798
  *
799
+ * If `sessionCacheTTL` is configured, results are cached to reduce API calls.
800
+ * Use `invalidateSession()` or `clearCache()` to manually clear cached sessions.
801
+ *
802
+ * Returns session info including tenant and organization context extracted from the JWT.
803
+ *
622
804
  * @example
623
805
  * ```typescript
624
806
  * // Validate session on each request
@@ -627,9 +809,11 @@ declare class AuthClient {
627
809
  * const session = await stackbe.auth.getSession(sessionToken);
628
810
  *
629
811
  * if (session) {
630
- * req.customer = session.customer;
631
- * req.subscription = session.subscription;
632
- * req.entitlements = session.entitlements;
812
+ * console.log(session.customerId);
813
+ * console.log(session.tenantId); // Tenant context
814
+ * console.log(session.organizationId); // Org context (if applicable)
815
+ * console.log(session.subscription);
816
+ * console.log(session.entitlements);
633
817
  * }
634
818
  * ```
635
819
  */
@@ -781,4 +965,4 @@ declare class StackBE {
781
965
  }): (req: any, res: any, next: any) => Promise<any>;
782
966
  }
783
967
 
784
- export { AuthClient, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type CreateCheckoutOptions, type CreateCustomerOptions, type Customer, type CustomerUsageResponse, type CustomerWithSubscription, CustomersClient, EntitlementsClient, type EntitlementsResponse, type MagicLinkOptions, type MagicLinkResponse, type SessionResponse, StackBE, type StackBEConfig, StackBEError, type StackBEErrorResponse, type Subscription, type SubscriptionWithPlan, SubscriptionsClient, type TrackUsageOptions, type TrackUsageResponse, type UpdateCustomerOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type VerifyTokenResponse };
968
+ export { type AnyWebhookEvent, AuthClient, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type CreateCheckoutOptions, type CreateCustomerOptions, type Customer, type CustomerCreatedEvent, type CustomerUpdatedEvent, type CustomerUsageResponse, type CustomerWebhookPayload, type CustomerWithSubscription, CustomersClient, EntitlementsClient, type EntitlementsResponse, type MagicLinkOptions, type MagicLinkResponse, type PaymentFailedEvent, type PaymentSucceededEvent, type PaymentWebhookPayload, type SessionResponse, StackBE, type StackBEConfig, StackBEError, type StackBEErrorCode, type StackBEErrorResponse, type Subscription, type SubscriptionCancelledEvent, type SubscriptionCreatedEvent, type SubscriptionRenewedEvent, type SubscriptionUpdatedEvent, type SubscriptionWebhookPayload, type SubscriptionWithPlan, SubscriptionsClient, type TrackUsageOptions, type TrackUsageResponse, type TrialEndedEvent, type TrialStartedEvent, type UpdateCustomerOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type VerifyTokenResponse, type WebhookEvent, type WebhookEventType };