@stackbe/sdk 0.12.1 → 0.13.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 CHANGED
@@ -174,6 +174,12 @@ await stackbe.auth.sendMagicLink('user@example.com', {
174
174
  useDev: true,
175
175
  });
176
176
 
177
+ // Log user directly into a specific organization
178
+ // Customer must already be a member of the org
179
+ await stackbe.auth.sendMagicLink('user@example.com', {
180
+ organizationId: 'org_abc123',
181
+ });
182
+
177
183
  // Verify magic link token (in your /verify route)
178
184
  const { token } = req.query;
179
185
  const result = await stackbe.auth.verifyToken(token);
@@ -198,6 +204,15 @@ if (session) {
198
204
 
199
205
  // Check if authenticated
200
206
  const isAuthenticated = await stackbe.auth.isAuthenticated(sessionToken);
207
+
208
+ // Switch to a different organization (for multi-org users)
209
+ const orgs = await stackbe.organizations.listByCustomer(customerId);
210
+ if (orgs.length > 1) {
211
+ // User belongs to multiple orgs - show org picker
212
+ const { sessionToken: newToken, organizationId, orgRole } =
213
+ await stackbe.auth.switchOrganization(sessionToken, targetOrgId);
214
+ // Store newToken - it's scoped to the target org
215
+ }
201
216
  ```
202
217
 
203
218
  ### Plans & Products
package/dist/index.d.mts CHANGED
@@ -255,6 +255,12 @@ interface MagicLinkOptions {
255
255
  redirectUrl?: string;
256
256
  /** Use development callback URL (for localhost testing) */
257
257
  useDev?: boolean;
258
+ /**
259
+ * Organization ID to scope the session to after verification.
260
+ * Customer must already be a member of this organization.
261
+ * Use this to log existing members directly into a specific org.
262
+ */
263
+ organizationId?: string;
258
264
  }
259
265
  interface MagicLinkResponse {
260
266
  success: boolean;
@@ -278,6 +284,14 @@ interface VerifyTokenResponse {
278
284
  /** URL to redirect to after verification */
279
285
  redirectUrl?: string;
280
286
  }
287
+ interface SwitchOrganizationResponse {
288
+ /** New session token scoped to the target organization */
289
+ sessionToken: string;
290
+ /** Organization ID the session is now scoped to */
291
+ organizationId: string;
292
+ /** Customer's role in the organization */
293
+ orgRole: 'owner' | 'admin' | 'member';
294
+ }
281
295
  interface SessionResponse {
282
296
  valid: boolean;
283
297
  /** Customer ID */
@@ -1381,6 +1395,11 @@ declare class AuthClient {
1381
1395
  * await stackbe.auth.sendMagicLink('user@example.com', {
1382
1396
  * useDev: true,
1383
1397
  * });
1398
+ *
1399
+ * // Log user directly into a specific organization
1400
+ * await stackbe.auth.sendMagicLink('user@example.com', {
1401
+ * organizationId: 'org_abc123',
1402
+ * });
1384
1403
  * ```
1385
1404
  */
1386
1405
  sendMagicLink(email: string, options?: MagicLinkOptions): Promise<MagicLinkResponse>;
@@ -1469,6 +1488,31 @@ declare class AuthClient {
1469
1488
  * ```
1470
1489
  */
1471
1490
  isAuthenticated(sessionToken: string): Promise<boolean>;
1491
+ /**
1492
+ * Switch the current session to a different organization.
1493
+ * The customer must be a member of the target organization.
1494
+ *
1495
+ * Returns a new session token scoped to the target organization.
1496
+ * The original session token remains valid but is scoped to the previous org (or no org).
1497
+ *
1498
+ * @example
1499
+ * ```typescript
1500
+ * // Get available organizations for the customer
1501
+ * const orgs = await stackbe.organizations.listByCustomer(customerId);
1502
+ *
1503
+ * // Switch to a different organization
1504
+ * const { sessionToken: newToken, organizationId, orgRole } =
1505
+ * await stackbe.auth.switchOrganization(currentSessionToken, targetOrgId);
1506
+ *
1507
+ * // Store the new token - it's scoped to the target org
1508
+ * localStorage.setItem('sessionToken', newToken);
1509
+ * ```
1510
+ *
1511
+ * @throws {StackBEError} with code 'NOT_MEMBER' if customer is not a member of the organization
1512
+ * @throws {StackBEError} with code 'ORG_NOT_FOUND' if organization doesn't exist
1513
+ * @throws {StackBEError} with code 'SESSION_INVALID' if session token is invalid
1514
+ */
1515
+ switchOrganization(sessionToken: string, organizationId: string): Promise<SwitchOrganizationResponse>;
1472
1516
  }
1473
1517
 
1474
1518
  declare class OrganizationsClient {
@@ -2325,6 +2369,8 @@ interface CreateCouponOptions {
2325
2369
  interface UpdateCouponOptions {
2326
2370
  name?: string;
2327
2371
  maxRedemptions?: number;
2372
+ /** Reset or adjust the redemption count */
2373
+ timesRedeemed?: number;
2328
2374
  expiresAt?: string;
2329
2375
  validPlanIds?: string[];
2330
2376
  active?: boolean;
@@ -2737,4 +2783,4 @@ declare class StackBE {
2737
2783
  }): (req: any, res: any, next: any) => Promise<any>;
2738
2784
  }
2739
2785
 
2740
- export { type AddMemberOptions, type AffiliateCommission, type AffiliateCommissionsResponse, type AffiliateEnrollment, type AffiliateInfo, type AffiliateStats, AffiliatesClient, AnalyticsClient, type AnalyticsFilterOptions, type AnyWebhookEvent, AuthClient, type BillingPortalSession, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type Coupon, type CouponDiscountType, type CouponDuration, CouponsClient, type CreateCheckoutOptions, type CreateCouponOptions, type CreateCustomerOptions, type CreateEarlyAccessSignupOptions, type CreateFeatureRequestOptions, type CreateOrganizationOptions, type Customer, type CustomerCreatedEvent, type CustomerFeatureActivity, type CustomerInvoice, type CustomerInvoicesResponse, type CustomerPaymentMethod, type CustomerSubscriptionHistory, type CustomerSubscriptionHistoryResponse, type CustomerUpdatedEvent, type CustomerUsageResponse, type CustomerWebhookPayload, type CustomerWithSubscription, CustomersClient, type DashboardMetrics, type DunningStatus, EarlyAccessClient, type EarlyAccessSignup, type EarlyAccessSignupListResponse, type EnrollOptions, EntitlementsClient, type EntitlementsResponse, type FeatureRequest, type FeatureRequestComment, type FeatureRequestImage, type FeatureRequestListResponse, FeatureRequestsClient, type FeatureUsagePoint, type GetSubscriptionOptions, type GrowthChartPoint, type GrowthMetrics, type InterestedCustomer, type InterestedCustomersResponse, type InviteMemberOptions, type ListEarlyAccessOptions, type ListFeatureRequestsOptions, type ListPlansOptions, type ListProductsOptions, type MRRHistoryPoint, type MagicLinkOptions, type MagicLinkResponse, type Organization, type OrganizationInvite, type OrganizationMember, OrganizationsClient, type PaymentFailedEvent, type PaymentSucceededEvent, type PaymentWebhookPayload, type PerformanceMetrics, type Plan, type PlanMetrics, PlansClient, type PopularEndpoint, type Product, ProductsClient, type RequestCountPoint, type RevenueByPlan, type SessionResponse, StackBE, type StackBEConfig, StackBEError, type StackBEErrorCode, type StackBEErrorResponse, type Subscription, type SubscriptionCancelledEvent, type SubscriptionCreatedEvent, type SubscriptionPlan, type SubscriptionRenewedEvent, type SubscriptionUpdatedEvent, type SubscriptionWebhookPayload, type SubscriptionWithPlan, SubscriptionsClient, type TimeRangeOptions, type TrackReferralResponse, type TrackUsageOptions, type TrackUsageResponse, type TrialEndedEvent, type TrialMetrics, type TrialStartedEvent, type TrialStatus, type UpcomingInvoice, type UpdateCouponOptions, type UpdateCustomerOptions, type UpdateOrganizationOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type ValidateCouponResult, type VerifyTokenResponse, type WebhookEvent, type WebhookEventType };
2786
+ export { type AddMemberOptions, type AffiliateCommission, type AffiliateCommissionsResponse, type AffiliateEnrollment, type AffiliateInfo, type AffiliateStats, AffiliatesClient, AnalyticsClient, type AnalyticsFilterOptions, type AnyWebhookEvent, AuthClient, type BillingPortalSession, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type Coupon, type CouponDiscountType, type CouponDuration, CouponsClient, type CreateCheckoutOptions, type CreateCouponOptions, type CreateCustomerOptions, type CreateEarlyAccessSignupOptions, type CreateFeatureRequestOptions, type CreateOrganizationOptions, type Customer, type CustomerCreatedEvent, type CustomerFeatureActivity, type CustomerInvoice, type CustomerInvoicesResponse, type CustomerPaymentMethod, type CustomerSubscriptionHistory, type CustomerSubscriptionHistoryResponse, type CustomerUpdatedEvent, type CustomerUsageResponse, type CustomerWebhookPayload, type CustomerWithSubscription, CustomersClient, type DashboardMetrics, type DunningStatus, EarlyAccessClient, type EarlyAccessSignup, type EarlyAccessSignupListResponse, type EnrollOptions, EntitlementsClient, type EntitlementsResponse, type FeatureRequest, type FeatureRequestComment, type FeatureRequestImage, type FeatureRequestListResponse, FeatureRequestsClient, type FeatureUsagePoint, type GetSubscriptionOptions, type GrowthChartPoint, type GrowthMetrics, type InterestedCustomer, type InterestedCustomersResponse, type InviteMemberOptions, type ListEarlyAccessOptions, type ListFeatureRequestsOptions, type ListPlansOptions, type ListProductsOptions, type MRRHistoryPoint, type MagicLinkOptions, type MagicLinkResponse, type Organization, type OrganizationInvite, type OrganizationMember, OrganizationsClient, type PaymentFailedEvent, type PaymentSucceededEvent, type PaymentWebhookPayload, type PerformanceMetrics, type Plan, type PlanMetrics, PlansClient, type PopularEndpoint, type Product, ProductsClient, type RequestCountPoint, type RevenueByPlan, type SessionResponse, StackBE, type StackBEConfig, StackBEError, type StackBEErrorCode, type StackBEErrorResponse, type Subscription, type SubscriptionCancelledEvent, type SubscriptionCreatedEvent, type SubscriptionPlan, type SubscriptionRenewedEvent, type SubscriptionUpdatedEvent, type SubscriptionWebhookPayload, type SubscriptionWithPlan, SubscriptionsClient, type SwitchOrganizationResponse, type TimeRangeOptions, type TrackReferralResponse, type TrackUsageOptions, type TrackUsageResponse, type TrialEndedEvent, type TrialMetrics, type TrialStartedEvent, type TrialStatus, type UpcomingInvoice, type UpdateCouponOptions, type UpdateCustomerOptions, type UpdateOrganizationOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type ValidateCouponResult, type VerifyTokenResponse, type WebhookEvent, type WebhookEventType };
package/dist/index.d.ts CHANGED
@@ -255,6 +255,12 @@ interface MagicLinkOptions {
255
255
  redirectUrl?: string;
256
256
  /** Use development callback URL (for localhost testing) */
257
257
  useDev?: boolean;
258
+ /**
259
+ * Organization ID to scope the session to after verification.
260
+ * Customer must already be a member of this organization.
261
+ * Use this to log existing members directly into a specific org.
262
+ */
263
+ organizationId?: string;
258
264
  }
259
265
  interface MagicLinkResponse {
260
266
  success: boolean;
@@ -278,6 +284,14 @@ interface VerifyTokenResponse {
278
284
  /** URL to redirect to after verification */
279
285
  redirectUrl?: string;
280
286
  }
287
+ interface SwitchOrganizationResponse {
288
+ /** New session token scoped to the target organization */
289
+ sessionToken: string;
290
+ /** Organization ID the session is now scoped to */
291
+ organizationId: string;
292
+ /** Customer's role in the organization */
293
+ orgRole: 'owner' | 'admin' | 'member';
294
+ }
281
295
  interface SessionResponse {
282
296
  valid: boolean;
283
297
  /** Customer ID */
@@ -1381,6 +1395,11 @@ declare class AuthClient {
1381
1395
  * await stackbe.auth.sendMagicLink('user@example.com', {
1382
1396
  * useDev: true,
1383
1397
  * });
1398
+ *
1399
+ * // Log user directly into a specific organization
1400
+ * await stackbe.auth.sendMagicLink('user@example.com', {
1401
+ * organizationId: 'org_abc123',
1402
+ * });
1384
1403
  * ```
1385
1404
  */
1386
1405
  sendMagicLink(email: string, options?: MagicLinkOptions): Promise<MagicLinkResponse>;
@@ -1469,6 +1488,31 @@ declare class AuthClient {
1469
1488
  * ```
1470
1489
  */
1471
1490
  isAuthenticated(sessionToken: string): Promise<boolean>;
1491
+ /**
1492
+ * Switch the current session to a different organization.
1493
+ * The customer must be a member of the target organization.
1494
+ *
1495
+ * Returns a new session token scoped to the target organization.
1496
+ * The original session token remains valid but is scoped to the previous org (or no org).
1497
+ *
1498
+ * @example
1499
+ * ```typescript
1500
+ * // Get available organizations for the customer
1501
+ * const orgs = await stackbe.organizations.listByCustomer(customerId);
1502
+ *
1503
+ * // Switch to a different organization
1504
+ * const { sessionToken: newToken, organizationId, orgRole } =
1505
+ * await stackbe.auth.switchOrganization(currentSessionToken, targetOrgId);
1506
+ *
1507
+ * // Store the new token - it's scoped to the target org
1508
+ * localStorage.setItem('sessionToken', newToken);
1509
+ * ```
1510
+ *
1511
+ * @throws {StackBEError} with code 'NOT_MEMBER' if customer is not a member of the organization
1512
+ * @throws {StackBEError} with code 'ORG_NOT_FOUND' if organization doesn't exist
1513
+ * @throws {StackBEError} with code 'SESSION_INVALID' if session token is invalid
1514
+ */
1515
+ switchOrganization(sessionToken: string, organizationId: string): Promise<SwitchOrganizationResponse>;
1472
1516
  }
1473
1517
 
1474
1518
  declare class OrganizationsClient {
@@ -2325,6 +2369,8 @@ interface CreateCouponOptions {
2325
2369
  interface UpdateCouponOptions {
2326
2370
  name?: string;
2327
2371
  maxRedemptions?: number;
2372
+ /** Reset or adjust the redemption count */
2373
+ timesRedeemed?: number;
2328
2374
  expiresAt?: string;
2329
2375
  validPlanIds?: string[];
2330
2376
  active?: boolean;
@@ -2737,4 +2783,4 @@ declare class StackBE {
2737
2783
  }): (req: any, res: any, next: any) => Promise<any>;
2738
2784
  }
2739
2785
 
2740
- export { type AddMemberOptions, type AffiliateCommission, type AffiliateCommissionsResponse, type AffiliateEnrollment, type AffiliateInfo, type AffiliateStats, AffiliatesClient, AnalyticsClient, type AnalyticsFilterOptions, type AnyWebhookEvent, AuthClient, type BillingPortalSession, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type Coupon, type CouponDiscountType, type CouponDuration, CouponsClient, type CreateCheckoutOptions, type CreateCouponOptions, type CreateCustomerOptions, type CreateEarlyAccessSignupOptions, type CreateFeatureRequestOptions, type CreateOrganizationOptions, type Customer, type CustomerCreatedEvent, type CustomerFeatureActivity, type CustomerInvoice, type CustomerInvoicesResponse, type CustomerPaymentMethod, type CustomerSubscriptionHistory, type CustomerSubscriptionHistoryResponse, type CustomerUpdatedEvent, type CustomerUsageResponse, type CustomerWebhookPayload, type CustomerWithSubscription, CustomersClient, type DashboardMetrics, type DunningStatus, EarlyAccessClient, type EarlyAccessSignup, type EarlyAccessSignupListResponse, type EnrollOptions, EntitlementsClient, type EntitlementsResponse, type FeatureRequest, type FeatureRequestComment, type FeatureRequestImage, type FeatureRequestListResponse, FeatureRequestsClient, type FeatureUsagePoint, type GetSubscriptionOptions, type GrowthChartPoint, type GrowthMetrics, type InterestedCustomer, type InterestedCustomersResponse, type InviteMemberOptions, type ListEarlyAccessOptions, type ListFeatureRequestsOptions, type ListPlansOptions, type ListProductsOptions, type MRRHistoryPoint, type MagicLinkOptions, type MagicLinkResponse, type Organization, type OrganizationInvite, type OrganizationMember, OrganizationsClient, type PaymentFailedEvent, type PaymentSucceededEvent, type PaymentWebhookPayload, type PerformanceMetrics, type Plan, type PlanMetrics, PlansClient, type PopularEndpoint, type Product, ProductsClient, type RequestCountPoint, type RevenueByPlan, type SessionResponse, StackBE, type StackBEConfig, StackBEError, type StackBEErrorCode, type StackBEErrorResponse, type Subscription, type SubscriptionCancelledEvent, type SubscriptionCreatedEvent, type SubscriptionPlan, type SubscriptionRenewedEvent, type SubscriptionUpdatedEvent, type SubscriptionWebhookPayload, type SubscriptionWithPlan, SubscriptionsClient, type TimeRangeOptions, type TrackReferralResponse, type TrackUsageOptions, type TrackUsageResponse, type TrialEndedEvent, type TrialMetrics, type TrialStartedEvent, type TrialStatus, type UpcomingInvoice, type UpdateCouponOptions, type UpdateCustomerOptions, type UpdateOrganizationOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type ValidateCouponResult, type VerifyTokenResponse, type WebhookEvent, type WebhookEventType };
2786
+ export { type AddMemberOptions, type AffiliateCommission, type AffiliateCommissionsResponse, type AffiliateEnrollment, type AffiliateInfo, type AffiliateStats, AffiliatesClient, AnalyticsClient, type AnalyticsFilterOptions, type AnyWebhookEvent, AuthClient, type BillingPortalSession, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type Coupon, type CouponDiscountType, type CouponDuration, CouponsClient, type CreateCheckoutOptions, type CreateCouponOptions, type CreateCustomerOptions, type CreateEarlyAccessSignupOptions, type CreateFeatureRequestOptions, type CreateOrganizationOptions, type Customer, type CustomerCreatedEvent, type CustomerFeatureActivity, type CustomerInvoice, type CustomerInvoicesResponse, type CustomerPaymentMethod, type CustomerSubscriptionHistory, type CustomerSubscriptionHistoryResponse, type CustomerUpdatedEvent, type CustomerUsageResponse, type CustomerWebhookPayload, type CustomerWithSubscription, CustomersClient, type DashboardMetrics, type DunningStatus, EarlyAccessClient, type EarlyAccessSignup, type EarlyAccessSignupListResponse, type EnrollOptions, EntitlementsClient, type EntitlementsResponse, type FeatureRequest, type FeatureRequestComment, type FeatureRequestImage, type FeatureRequestListResponse, FeatureRequestsClient, type FeatureUsagePoint, type GetSubscriptionOptions, type GrowthChartPoint, type GrowthMetrics, type InterestedCustomer, type InterestedCustomersResponse, type InviteMemberOptions, type ListEarlyAccessOptions, type ListFeatureRequestsOptions, type ListPlansOptions, type ListProductsOptions, type MRRHistoryPoint, type MagicLinkOptions, type MagicLinkResponse, type Organization, type OrganizationInvite, type OrganizationMember, OrganizationsClient, type PaymentFailedEvent, type PaymentSucceededEvent, type PaymentWebhookPayload, type PerformanceMetrics, type Plan, type PlanMetrics, PlansClient, type PopularEndpoint, type Product, ProductsClient, type RequestCountPoint, type RevenueByPlan, type SessionResponse, StackBE, type StackBEConfig, StackBEError, type StackBEErrorCode, type StackBEErrorResponse, type Subscription, type SubscriptionCancelledEvent, type SubscriptionCreatedEvent, type SubscriptionPlan, type SubscriptionRenewedEvent, type SubscriptionUpdatedEvent, type SubscriptionWebhookPayload, type SubscriptionWithPlan, SubscriptionsClient, type SwitchOrganizationResponse, type TimeRangeOptions, type TrackReferralResponse, type TrackUsageOptions, type TrackUsageResponse, type TrialEndedEvent, type TrialMetrics, type TrialStartedEvent, type TrialStatus, type UpcomingInvoice, type UpdateCouponOptions, type UpdateCustomerOptions, type UpdateOrganizationOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type ValidateCouponResult, type VerifyTokenResponse, type WebhookEvent, type WebhookEventType };
package/dist/index.js CHANGED
@@ -1230,6 +1230,11 @@ var AuthClient = class {
1230
1230
  * await stackbe.auth.sendMagicLink('user@example.com', {
1231
1231
  * useDev: true,
1232
1232
  * });
1233
+ *
1234
+ * // Log user directly into a specific organization
1235
+ * await stackbe.auth.sendMagicLink('user@example.com', {
1236
+ * organizationId: 'org_abc123',
1237
+ * });
1233
1238
  * ```
1234
1239
  */
1235
1240
  async sendMagicLink(email, options = {}) {
@@ -1245,7 +1250,8 @@ var AuthClient = class {
1245
1250
  {
1246
1251
  email,
1247
1252
  redirectUrl,
1248
- useDev
1253
+ useDev,
1254
+ organizationId: options.organizationId
1249
1255
  }
1250
1256
  );
1251
1257
  }
@@ -1460,6 +1466,59 @@ var AuthClient = class {
1460
1466
  const session = await this.getSession(sessionToken);
1461
1467
  return session !== null;
1462
1468
  }
1469
+ /**
1470
+ * Switch the current session to a different organization.
1471
+ * The customer must be a member of the target organization.
1472
+ *
1473
+ * Returns a new session token scoped to the target organization.
1474
+ * The original session token remains valid but is scoped to the previous org (or no org).
1475
+ *
1476
+ * @example
1477
+ * ```typescript
1478
+ * // Get available organizations for the customer
1479
+ * const orgs = await stackbe.organizations.listByCustomer(customerId);
1480
+ *
1481
+ * // Switch to a different organization
1482
+ * const { sessionToken: newToken, organizationId, orgRole } =
1483
+ * await stackbe.auth.switchOrganization(currentSessionToken, targetOrgId);
1484
+ *
1485
+ * // Store the new token - it's scoped to the target org
1486
+ * localStorage.setItem('sessionToken', newToken);
1487
+ * ```
1488
+ *
1489
+ * @throws {StackBEError} with code 'NOT_MEMBER' if customer is not a member of the organization
1490
+ * @throws {StackBEError} with code 'ORG_NOT_FOUND' if organization doesn't exist
1491
+ * @throws {StackBEError} with code 'SESSION_INVALID' if session token is invalid
1492
+ */
1493
+ async switchOrganization(sessionToken, organizationId) {
1494
+ this.sessionCache.delete(sessionToken);
1495
+ const response = await fetch(
1496
+ `${this.http.baseUrl}/v1/apps/${this.appId}/auth/switch-organization`,
1497
+ {
1498
+ method: "POST",
1499
+ headers: {
1500
+ "Authorization": `Bearer ${sessionToken}`,
1501
+ "Content-Type": "application/json"
1502
+ },
1503
+ body: JSON.stringify({ organizationId })
1504
+ }
1505
+ );
1506
+ if (!response.ok) {
1507
+ const errorData = await response.json().catch(() => ({}));
1508
+ const message = errorData.message || errorData.error || "Failed to switch organization";
1509
+ let code = "SWITCH_ORG_FAILED";
1510
+ if (response.status === 401) {
1511
+ code = "SESSION_INVALID";
1512
+ } else if (message.toLowerCase().includes("not a member")) {
1513
+ code = "NOT_MEMBER";
1514
+ } else if (message.toLowerCase().includes("not found")) {
1515
+ code = "ORG_NOT_FOUND";
1516
+ }
1517
+ throw new StackBEError(message, response.status, code);
1518
+ }
1519
+ const data = await response.json();
1520
+ return data;
1521
+ }
1463
1522
  };
1464
1523
 
1465
1524
  // src/organizations.ts
package/dist/index.mjs CHANGED
@@ -1189,6 +1189,11 @@ var AuthClient = class {
1189
1189
  * await stackbe.auth.sendMagicLink('user@example.com', {
1190
1190
  * useDev: true,
1191
1191
  * });
1192
+ *
1193
+ * // Log user directly into a specific organization
1194
+ * await stackbe.auth.sendMagicLink('user@example.com', {
1195
+ * organizationId: 'org_abc123',
1196
+ * });
1192
1197
  * ```
1193
1198
  */
1194
1199
  async sendMagicLink(email, options = {}) {
@@ -1204,7 +1209,8 @@ var AuthClient = class {
1204
1209
  {
1205
1210
  email,
1206
1211
  redirectUrl,
1207
- useDev
1212
+ useDev,
1213
+ organizationId: options.organizationId
1208
1214
  }
1209
1215
  );
1210
1216
  }
@@ -1419,6 +1425,59 @@ var AuthClient = class {
1419
1425
  const session = await this.getSession(sessionToken);
1420
1426
  return session !== null;
1421
1427
  }
1428
+ /**
1429
+ * Switch the current session to a different organization.
1430
+ * The customer must be a member of the target organization.
1431
+ *
1432
+ * Returns a new session token scoped to the target organization.
1433
+ * The original session token remains valid but is scoped to the previous org (or no org).
1434
+ *
1435
+ * @example
1436
+ * ```typescript
1437
+ * // Get available organizations for the customer
1438
+ * const orgs = await stackbe.organizations.listByCustomer(customerId);
1439
+ *
1440
+ * // Switch to a different organization
1441
+ * const { sessionToken: newToken, organizationId, orgRole } =
1442
+ * await stackbe.auth.switchOrganization(currentSessionToken, targetOrgId);
1443
+ *
1444
+ * // Store the new token - it's scoped to the target org
1445
+ * localStorage.setItem('sessionToken', newToken);
1446
+ * ```
1447
+ *
1448
+ * @throws {StackBEError} with code 'NOT_MEMBER' if customer is not a member of the organization
1449
+ * @throws {StackBEError} with code 'ORG_NOT_FOUND' if organization doesn't exist
1450
+ * @throws {StackBEError} with code 'SESSION_INVALID' if session token is invalid
1451
+ */
1452
+ async switchOrganization(sessionToken, organizationId) {
1453
+ this.sessionCache.delete(sessionToken);
1454
+ const response = await fetch(
1455
+ `${this.http.baseUrl}/v1/apps/${this.appId}/auth/switch-organization`,
1456
+ {
1457
+ method: "POST",
1458
+ headers: {
1459
+ "Authorization": `Bearer ${sessionToken}`,
1460
+ "Content-Type": "application/json"
1461
+ },
1462
+ body: JSON.stringify({ organizationId })
1463
+ }
1464
+ );
1465
+ if (!response.ok) {
1466
+ const errorData = await response.json().catch(() => ({}));
1467
+ const message = errorData.message || errorData.error || "Failed to switch organization";
1468
+ let code = "SWITCH_ORG_FAILED";
1469
+ if (response.status === 401) {
1470
+ code = "SESSION_INVALID";
1471
+ } else if (message.toLowerCase().includes("not a member")) {
1472
+ code = "NOT_MEMBER";
1473
+ } else if (message.toLowerCase().includes("not found")) {
1474
+ code = "ORG_NOT_FOUND";
1475
+ }
1476
+ throw new StackBEError(message, response.status, code);
1477
+ }
1478
+ const data = await response.json();
1479
+ return data;
1480
+ }
1422
1481
  };
1423
1482
 
1424
1483
  // src/organizations.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackbe/sdk",
3
- "version": "0.12.1",
3
+ "version": "0.13.0",
4
4
  "description": "Official JavaScript/TypeScript SDK for StackBE - the billing backend for your side project",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",