@stackbe/sdk 0.6.3 → 0.6.5

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
@@ -200,6 +200,64 @@ if (session) {
200
200
  const isAuthenticated = await stackbe.auth.isAuthenticated(sessionToken);
201
201
  ```
202
202
 
203
+ ### Plans & Products
204
+
205
+ List available pricing plans for your pricing page:
206
+
207
+ ```typescript
208
+ // List all plans
209
+ const plans = await stackbe.plans.list();
210
+
211
+ // List active plans sorted by price
212
+ const plans = await stackbe.plans.listByPrice();
213
+ // [Free ($0), Starter ($9), Pro ($29), Enterprise ($99)]
214
+
215
+ // Filter by product
216
+ const plans = await stackbe.plans.list({ productId: 'prod_123' });
217
+
218
+ // Get a specific plan
219
+ const plan = await stackbe.plans.get('plan_123');
220
+ console.log(plan.name, plan.priceCents, plan.entitlements);
221
+
222
+ // List products
223
+ const products = await stackbe.products.list();
224
+
225
+ // Get product details
226
+ const product = await stackbe.products.get('prod_123');
227
+ ```
228
+
229
+ #### Dynamic Pricing Page Example
230
+
231
+ ```typescript
232
+ // Next.js pricing page
233
+ export default async function PricingPage() {
234
+ const plans = await stackbe.plans.listByPrice();
235
+
236
+ return (
237
+ <div className="grid grid-cols-3 gap-4">
238
+ {plans.map((plan) => (
239
+ <div key={plan.id} className="border p-4 rounded">
240
+ <h3>{plan.name}</h3>
241
+ <p className="text-2xl">
242
+ ${plan.priceCents / 100}/{plan.interval}
243
+ </p>
244
+ <ul>
245
+ {Object.entries(plan.entitlements).map(([key, value]) => (
246
+ <li key={key}>
247
+ {key}: {value === true ? '✓' : value}
248
+ </li>
249
+ ))}
250
+ </ul>
251
+ <a href={`/checkout?plan=${plan.id}`}>
252
+ {plan.priceCents === 0 ? 'Start Free' : 'Subscribe'}
253
+ </a>
254
+ </div>
255
+ ))}
256
+ </div>
257
+ );
258
+ }
259
+ ```
260
+
203
261
  ### Customer Management
204
262
 
205
263
  ```typescript
@@ -226,6 +284,76 @@ const customer = await stackbe.customers.getOrCreate({
226
284
  await stackbe.customers.update('cust_123', { name: 'Jane Doe' });
227
285
  ```
228
286
 
287
+ ### Organizations (B2B Multi-User)
288
+
289
+ Manage customer organizations for B2B apps:
290
+
291
+ ```typescript
292
+ // Create organization with customer as owner
293
+ const org = await stackbe.organizations.create({
294
+ name: 'Acme Corp',
295
+ ownerId: customer.id,
296
+ });
297
+
298
+ // List all organizations
299
+ const orgs = await stackbe.organizations.list();
300
+
301
+ // Get organization by ID
302
+ const org = await stackbe.organizations.get('org_123');
303
+
304
+ // Update organization
305
+ await stackbe.organizations.update('org_123', { name: 'New Name' });
306
+
307
+ // Delete organization (must have no active subscriptions)
308
+ await stackbe.organizations.delete('org_123');
309
+
310
+ // Add member to organization
311
+ await stackbe.organizations.addMember('org_123', {
312
+ customerId: 'cust_456',
313
+ role: 'member', // 'admin' | 'member'
314
+ });
315
+
316
+ // Remove member
317
+ await stackbe.organizations.removeMember('org_123', 'member_456');
318
+
319
+ // Update member role
320
+ await stackbe.organizations.updateMember('org_123', 'member_456', {
321
+ role: 'admin',
322
+ });
323
+
324
+ // Invite by email
325
+ await stackbe.organizations.invite('org_123', {
326
+ email: 'newuser@company.com',
327
+ role: 'member',
328
+ });
329
+
330
+ // List pending invites
331
+ const invites = await stackbe.organizations.listInvites('org_123');
332
+
333
+ // Cancel invite
334
+ await stackbe.organizations.cancelInvite('org_123', 'invite_456');
335
+ ```
336
+
337
+ #### B2B Signup Flow
338
+
339
+ ```typescript
340
+ async function signup(email: string, orgName: string) {
341
+ // 1. Get or create customer
342
+ const customer = await stackbe.customers.getOrCreate({ email });
343
+
344
+ // 2. Create organization with customer as owner
345
+ const org = await stackbe.organizations.create({
346
+ name: orgName,
347
+ ownerId: customer.id,
348
+ });
349
+
350
+ // 3. Send magic link
351
+ await stackbe.auth.sendMagicLink(email);
352
+
353
+ return { customer, org };
354
+ }
355
+ ```
356
+
229
357
  ## Express Middleware
230
358
 
231
359
  ### Track Usage Automatically
package/dist/index.d.mts CHANGED
@@ -251,6 +251,94 @@ interface SessionResponse {
251
251
  /** Feature entitlements */
252
252
  entitlements?: Record<string, boolean | number | string>;
253
253
  }
254
+ interface OrganizationMember {
255
+ id: string;
256
+ customerId: string;
257
+ email: string;
258
+ role: 'owner' | 'admin' | 'member';
259
+ invitedAt: string;
260
+ acceptedAt?: string;
261
+ }
262
+ interface Organization {
263
+ id: string;
264
+ appId: string;
265
+ name: string;
266
+ slug: string;
267
+ logoUrl?: string;
268
+ members: OrganizationMember[];
269
+ memberCount: number;
270
+ createdAt: string;
271
+ updatedAt: string;
272
+ }
273
+ interface CreateOrganizationOptions {
274
+ /** Organization name */
275
+ name: string;
276
+ /** Customer ID to set as owner */
277
+ ownerId: string;
278
+ /** Optional logo URL */
279
+ logoUrl?: string;
280
+ }
281
+ interface UpdateOrganizationOptions {
282
+ /** New organization name */
283
+ name?: string;
284
+ /** New logo URL */
285
+ logoUrl?: string;
286
+ }
287
+ interface AddMemberOptions {
288
+ /** Customer ID to add */
289
+ customerId: string;
290
+ /** Role for the member */
291
+ role?: 'admin' | 'member';
292
+ }
293
+ interface InviteMemberOptions {
294
+ /** Email to invite */
295
+ email: string;
296
+ /** Role for the invited member */
297
+ role?: 'admin' | 'member';
298
+ }
299
+ interface OrganizationInvite {
300
+ id: string;
301
+ organizationId: string;
302
+ email: string;
303
+ role: 'admin' | 'member';
304
+ status: 'pending' | 'accepted' | 'cancelled';
305
+ sentAt: string;
306
+ }
307
+ interface Plan {
308
+ id: string;
309
+ name: string;
310
+ slug: string;
311
+ description?: string;
312
+ priceCents: number;
313
+ currency: string;
314
+ interval: 'month' | 'year';
315
+ trialDays?: number;
316
+ entitlements: Record<string, boolean | number | string>;
317
+ status: 'active' | 'archived';
318
+ requirePaymentMethod: boolean;
319
+ productId: string;
320
+ product?: Product;
321
+ createdAt: string;
322
+ updatedAt: string;
323
+ }
324
+ interface Product {
325
+ id: string;
326
+ name: string;
327
+ slug: string;
328
+ description?: string;
329
+ appId: string;
330
+ plans?: Plan[];
331
+ createdAt: string;
332
+ updatedAt: string;
333
+ }
334
+ interface ListPlansOptions {
335
+ /** Filter by product ID */
336
+ productId?: string;
337
+ }
338
+ interface ListProductsOptions {
339
+ /** Filter by app ID (defaults to SDK appId) */
340
+ appId?: string;
341
+ }
254
342
  interface CreateCheckoutOptions {
255
343
  /** Customer ID or email */
256
344
  customer: string | {
@@ -1050,6 +1138,243 @@ declare class AuthClient {
1050
1138
  isAuthenticated(sessionToken: string): Promise<boolean>;
1051
1139
  }
1052
1140
 
1141
+ declare class OrganizationsClient {
1142
+ private http;
1143
+ private appId;
1144
+ constructor(http: HttpClient, appId: string);
1145
+ /**
1146
+ * Create a new organization with a customer as owner.
1147
+ * Use this for B2B signup flows where you provision everything server-side.
1148
+ *
1149
+ * @example
1150
+ * ```typescript
1151
+ * const customer = await stackbe.customers.getOrCreate({ email: 'user@company.com' });
1152
+ * const org = await stackbe.organizations.create({
1153
+ * name: 'Acme Corp',
1154
+ * ownerId: customer.id
1155
+ * });
1156
+ * ```
1157
+ */
1158
+ create(options: CreateOrganizationOptions): Promise<Organization>;
1159
+ /**
1160
+ * List all organizations for this app.
1161
+ *
1162
+ * @example
1163
+ * ```typescript
1164
+ * const orgs = await stackbe.organizations.list();
1165
+ * ```
1166
+ */
1167
+ list(options?: {
1168
+ limit?: number;
1169
+ offset?: number;
1170
+ search?: string;
1171
+ }): Promise<Organization[]>;
1172
+ /**
1173
+ * Get an organization by ID.
1174
+ *
1175
+ * @example
1176
+ * ```typescript
1177
+ * const org = await stackbe.organizations.get('org_123');
1178
+ * ```
1179
+ */
1180
+ get(orgId: string): Promise<Organization>;
1181
+ /**
1182
+ * Update an organization.
1183
+ *
1184
+ * @example
1185
+ * ```typescript
1186
+ * const org = await stackbe.organizations.update('org_123', {
1187
+ * name: 'New Name'
1188
+ * });
1189
+ * ```
1190
+ */
1191
+ update(orgId: string, options: UpdateOrganizationOptions): Promise<Organization>;
1192
+ /**
1193
+ * Delete an organization.
1194
+ * Note: Organizations with active subscriptions cannot be deleted.
1195
+ *
1196
+ * @example
1197
+ * ```typescript
1198
+ * await stackbe.organizations.delete('org_123');
1199
+ * ```
1200
+ */
1201
+ delete(orgId: string): Promise<void>;
1202
+ /**
1203
+ * Add a customer as a member of an organization.
1204
+ *
1205
+ * @example
1206
+ * ```typescript
1207
+ * await stackbe.organizations.addMember('org_123', {
1208
+ * customerId: 'cust_456',
1209
+ * role: 'member'
1210
+ * });
1211
+ * ```
1212
+ */
1213
+ addMember(orgId: string, options: AddMemberOptions): Promise<OrganizationMember>;
1214
+ /**
1215
+ * Remove a member from an organization.
1216
+ *
1217
+ * @example
1218
+ * ```typescript
1219
+ * await stackbe.organizations.removeMember('org_123', 'member_456');
1220
+ * ```
1221
+ */
1222
+ removeMember(orgId: string, memberId: string): Promise<void>;
1223
+ /**
1224
+ * Update a member's role.
1225
+ *
1226
+ * @example
1227
+ * ```typescript
1228
+ * await stackbe.organizations.updateMember('org_123', 'member_456', {
1229
+ * role: 'admin'
1230
+ * });
1231
+ * ```
1232
+ */
1233
+ updateMember(orgId: string, memberId: string, options: {
1234
+ role: 'admin' | 'member';
1235
+ }): Promise<OrganizationMember>;
1236
+ /**
1237
+ * Send an invite to join an organization.
1238
+ *
1239
+ * @example
1240
+ * ```typescript
1241
+ * await stackbe.organizations.invite('org_123', {
1242
+ * email: 'newuser@company.com',
1243
+ * role: 'member'
1244
+ * });
1245
+ * ```
1246
+ */
1247
+ invite(orgId: string, options: InviteMemberOptions): Promise<OrganizationInvite>;
1248
+ /**
1249
+ * List pending invites for an organization.
1250
+ *
1251
+ * @example
1252
+ * ```typescript
1253
+ * const invites = await stackbe.organizations.listInvites('org_123');
1254
+ * ```
1255
+ */
1256
+ listInvites(orgId: string): Promise<OrganizationInvite[]>;
1257
+ /**
1258
+ * Cancel a pending invite.
1259
+ *
1260
+ * @example
1261
+ * ```typescript
1262
+ * await stackbe.organizations.cancelInvite('org_123', 'invite_456');
1263
+ * ```
1264
+ */
1265
+ cancelInvite(orgId: string, inviteId: string): Promise<void>;
1266
+ }
1267
+
1268
+ /**
1269
+ * Client for managing plans and products.
1270
+ * Use this to list available pricing plans for display in your pricing page.
1271
+ *
1272
+ * @example
1273
+ * ```typescript
1274
+ * // List all plans
1275
+ * const plans = await stackbe.plans.list();
1276
+ *
1277
+ * // List plans for a specific product
1278
+ * const plans = await stackbe.plans.list({ productId: 'prod_123' });
1279
+ *
1280
+ * // Get a specific plan
1281
+ * const plan = await stackbe.plans.get('plan_123');
1282
+ *
1283
+ * // List products
1284
+ * const products = await stackbe.products.list();
1285
+ * ```
1286
+ */
1287
+ declare class PlansClient {
1288
+ private readonly http;
1289
+ constructor(http: HttpClient);
1290
+ /**
1291
+ * List all plans for the app.
1292
+ *
1293
+ * @example
1294
+ * ```typescript
1295
+ * // List all plans
1296
+ * const plans = await stackbe.plans.list();
1297
+ *
1298
+ * // Filter by product
1299
+ * const plans = await stackbe.plans.list({ productId: 'prod_123' });
1300
+ *
1301
+ * // Display in pricing page
1302
+ * plans.forEach(plan => {
1303
+ * console.log(`${plan.name}: $${plan.priceCents / 100}/${plan.interval}`);
1304
+ * });
1305
+ * ```
1306
+ */
1307
+ list(options?: ListPlansOptions): Promise<Plan[]>;
1308
+ /**
1309
+ * Get a plan by ID.
1310
+ *
1311
+ * @example
1312
+ * ```typescript
1313
+ * const plan = await stackbe.plans.get('plan_123');
1314
+ * console.log(plan.name, plan.priceCents, plan.entitlements);
1315
+ * ```
1316
+ */
1317
+ get(planId: string): Promise<Plan>;
1318
+ /**
1319
+ * Get active plans only (excludes archived plans).
1320
+ *
1321
+ * @example
1322
+ * ```typescript
1323
+ * const activePlans = await stackbe.plans.getActive();
1324
+ * ```
1325
+ */
1326
+ getActive(options?: ListPlansOptions): Promise<Plan[]>;
1327
+ /**
1328
+ * Get plans sorted by price (ascending).
1329
+ *
1330
+ * @example
1331
+ * ```typescript
1332
+ * const plans = await stackbe.plans.listByPrice();
1333
+ * // [Free, Starter, Pro, Enterprise]
1334
+ * ```
1335
+ */
1336
+ listByPrice(options?: ListPlansOptions): Promise<Plan[]>;
1337
+ }
1338
+ /**
1339
+ * Client for managing products.
1340
+ *
1341
+ * @example
1342
+ * ```typescript
1343
+ * // List all products
1344
+ * const products = await stackbe.products.list();
1345
+ *
1346
+ * // Get a specific product
1347
+ * const product = await stackbe.products.get('prod_123');
1348
+ * ```
1349
+ */
1350
+ declare class ProductsClient {
1351
+ private readonly http;
1352
+ private readonly appId;
1353
+ constructor(http: HttpClient, appId: string);
1354
+ /**
1355
+ * List all products for the app.
1356
+ *
1357
+ * @example
1358
+ * ```typescript
1359
+ * const products = await stackbe.products.list();
1360
+ * products.forEach(product => {
1361
+ * console.log(product.name, product.plans?.length, 'plans');
1362
+ * });
1363
+ * ```
1364
+ */
1365
+ list(options?: ListProductsOptions): Promise<Product[]>;
1366
+ /**
1367
+ * Get a product by ID.
1368
+ *
1369
+ * @example
1370
+ * ```typescript
1371
+ * const product = await stackbe.products.get('prod_123');
1372
+ * console.log(product.name, product.description);
1373
+ * ```
1374
+ */
1375
+ get(productId: string): Promise<Product>;
1376
+ }
1377
+
1053
1378
  declare class StackBE {
1054
1379
  private http;
1055
1380
  private appId;
@@ -1065,6 +1390,12 @@ declare class StackBE {
1065
1390
  readonly subscriptions: SubscriptionsClient;
1066
1391
  /** Customer authentication (magic links) */
1067
1392
  readonly auth: AuthClient;
1393
+ /** Organization management (B2B multi-user) */
1394
+ readonly organizations: OrganizationsClient;
1395
+ /** Pricing plans */
1396
+ readonly plans: PlansClient;
1397
+ /** Products */
1398
+ readonly products: ProductsClient;
1068
1399
  /**
1069
1400
  * Create a new StackBE client.
1070
1401
  *
@@ -1165,4 +1496,4 @@ declare class StackBE {
1165
1496
  }): (req: any, res: any, next: any) => Promise<any>;
1166
1497
  }
1167
1498
 
1168
- 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 };
1499
+ export { type AddMemberOptions, type AnyWebhookEvent, AuthClient, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type CreateCheckoutOptions, type CreateCustomerOptions, type CreateOrganizationOptions, type Customer, type CustomerCreatedEvent, type CustomerUpdatedEvent, type CustomerUsageResponse, type CustomerWebhookPayload, type CustomerWithSubscription, CustomersClient, EntitlementsClient, type EntitlementsResponse, type InviteMemberOptions, type ListPlansOptions, type ListProductsOptions, type MagicLinkOptions, type MagicLinkResponse, type Organization, type OrganizationInvite, type OrganizationMember, OrganizationsClient, type PaymentFailedEvent, type PaymentSucceededEvent, type PaymentWebhookPayload, type Plan, PlansClient, type Product, ProductsClient, 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 UpdateOrganizationOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type VerifyTokenResponse, type WebhookEvent, type WebhookEventType };