@stackbe/sdk 0.13.0 → 0.15.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.js CHANGED
@@ -30,6 +30,7 @@ __export(index_exports, {
30
30
  EntitlementsClient: () => EntitlementsClient,
31
31
  FeatureRequestsClient: () => FeatureRequestsClient,
32
32
  OrganizationsClient: () => OrganizationsClient,
33
+ PaymentMethodsClient: () => PaymentMethodsClient,
33
34
  PlansClient: () => PlansClient,
34
35
  ProductsClient: () => ProductsClient,
35
36
  StackBE: () => StackBE,
@@ -1168,6 +1169,201 @@ var SubscriptionsClient = class {
1168
1169
  `/v1/subscriptions/${subscriptionId}/has-access`
1169
1170
  );
1170
1171
  }
1172
+ // ============================================
1173
+ // StackBE-Managed Billing Methods
1174
+ // ============================================
1175
+ /**
1176
+ * Manually charge a StackBE-managed subscription.
1177
+ *
1178
+ * This is useful for:
1179
+ * - Testing billing in development
1180
+ * - Recovering from failed automatic charges
1181
+ * - Charging ahead of schedule
1182
+ *
1183
+ * The subscription must be in `stackbe_managed` billing mode.
1184
+ *
1185
+ * @example
1186
+ * ```typescript
1187
+ * const result = await stackbe.subscriptions.charge('sub_123');
1188
+ *
1189
+ * if (result.success) {
1190
+ * console.log('Charge successful:', result.chargeId);
1191
+ * } else if (result.requiresAction) {
1192
+ * // Redirect customer to 3DS authentication
1193
+ * window.location.href = result.actionUrl;
1194
+ * } else {
1195
+ * console.log('Charge failed:', result.errorMessage);
1196
+ * }
1197
+ * ```
1198
+ */
1199
+ async charge(subscriptionId) {
1200
+ return this.http.post(
1201
+ `/v1/subscriptions/${subscriptionId}/charge`
1202
+ );
1203
+ }
1204
+ /**
1205
+ * Migrate a subscription from gateway-managed to StackBE-managed billing.
1206
+ *
1207
+ * This will:
1208
+ * 1. Extract the payment method from the gateway subscription
1209
+ * 2. Store it in StackBE's PaymentMethod table
1210
+ * 3. Set the subscription to `stackbe_managed` billing mode
1211
+ * 4. Cancel the gateway subscription at period end
1212
+ * 5. StackBE will handle renewals going forward
1213
+ *
1214
+ * Use cases:
1215
+ * - Migrate existing Stripe subscriptions to unified StackBE billing
1216
+ * - Prepare for multi-gateway support
1217
+ * - Gain more control over billing timing and retry logic
1218
+ *
1219
+ * @example
1220
+ * ```typescript
1221
+ * const result = await stackbe.subscriptions.migrateToStackbeManaged('sub_123');
1222
+ *
1223
+ * console.log('Migration complete');
1224
+ * console.log('Payment method:', result.paymentMethodId);
1225
+ * console.log('Next billing date:', result.nextBillingDate);
1226
+ * ```
1227
+ */
1228
+ async migrateToStackbeManaged(subscriptionId) {
1229
+ return this.http.post(
1230
+ `/v1/subscriptions/${subscriptionId}/migrate-to-stackbe-managed`
1231
+ );
1232
+ }
1233
+ };
1234
+
1235
+ // src/payment-methods.ts
1236
+ var PaymentMethodsClient = class {
1237
+ constructor(http) {
1238
+ this.http = http;
1239
+ }
1240
+ /**
1241
+ * Create a setup session for collecting a payment method.
1242
+ *
1243
+ * Returns a URL to redirect the customer to for secure payment method collection.
1244
+ * This is similar to Stripe Checkout but in setup mode - no charge is made.
1245
+ *
1246
+ * @example
1247
+ * ```typescript
1248
+ * const session = await stackbe.paymentMethods.createSetupSession('cust_123', {
1249
+ * successUrl: 'https://yourapp.com/payment-methods/success',
1250
+ * cancelUrl: 'https://yourapp.com/payment-methods/cancel',
1251
+ * });
1252
+ *
1253
+ * // Redirect customer to payment method collection
1254
+ * window.location.href = session.url;
1255
+ * ```
1256
+ */
1257
+ async createSetupSession(customerId, options) {
1258
+ return this.http.post(
1259
+ `/v1/apps/{appId}/customers/${customerId}/payment-methods/setup`,
1260
+ options
1261
+ );
1262
+ }
1263
+ /**
1264
+ * Attach a payment method to a customer.
1265
+ *
1266
+ * After the customer completes the setup session, call this to store
1267
+ * the payment method in StackBE for future charges.
1268
+ *
1269
+ * @example
1270
+ * ```typescript
1271
+ * // After redirect from setup session
1272
+ * const paymentMethod = await stackbe.paymentMethods.attach('cust_123', {
1273
+ * gatewayPaymentMethodId: 'pm_1234...', // From setup session completion
1274
+ * setAsDefault: true,
1275
+ * });
1276
+ *
1277
+ * console.log(`Added ${paymentMethod.brand} ending in ${paymentMethod.last4}`);
1278
+ * ```
1279
+ */
1280
+ async attach(customerId, options) {
1281
+ return this.http.post(
1282
+ `/v1/apps/{appId}/customers/${customerId}/payment-methods`,
1283
+ options
1284
+ );
1285
+ }
1286
+ /**
1287
+ * List all payment methods for a customer.
1288
+ *
1289
+ * @example
1290
+ * ```typescript
1291
+ * const paymentMethods = await stackbe.paymentMethods.list('cust_123');
1292
+ *
1293
+ * for (const pm of paymentMethods) {
1294
+ * console.log(`${pm.brand} **** ${pm.last4} ${pm.isDefault ? '(default)' : ''}`);
1295
+ * }
1296
+ * ```
1297
+ */
1298
+ async list(customerId, options) {
1299
+ const params = {};
1300
+ if (options?.status) params.status = options.status;
1301
+ return this.http.get(
1302
+ `/v1/apps/{appId}/customers/${customerId}/payment-methods`,
1303
+ params
1304
+ );
1305
+ }
1306
+ /**
1307
+ * Get a specific payment method.
1308
+ *
1309
+ * @example
1310
+ * ```typescript
1311
+ * const pm = await stackbe.paymentMethods.get('cust_123', 'pm_123');
1312
+ * console.log(`Expires: ${pm.expiryMonth}/${pm.expiryYear}`);
1313
+ * ```
1314
+ */
1315
+ async get(customerId, paymentMethodId) {
1316
+ return this.http.get(
1317
+ `/v1/apps/{appId}/customers/${customerId}/payment-methods/${paymentMethodId}`
1318
+ );
1319
+ }
1320
+ /**
1321
+ * Set a payment method as the default for a customer.
1322
+ *
1323
+ * The default payment method is used for subscription renewals.
1324
+ *
1325
+ * @example
1326
+ * ```typescript
1327
+ * await stackbe.paymentMethods.setDefault('cust_123', 'pm_456');
1328
+ * console.log('Default payment method updated');
1329
+ * ```
1330
+ */
1331
+ async setDefault(customerId, paymentMethodId) {
1332
+ return this.http.post(
1333
+ `/v1/apps/{appId}/customers/${customerId}/payment-methods/${paymentMethodId}/default`
1334
+ );
1335
+ }
1336
+ /**
1337
+ * Remove a payment method.
1338
+ *
1339
+ * Cannot remove a payment method that is being used by an active subscription.
1340
+ *
1341
+ * @example
1342
+ * ```typescript
1343
+ * await stackbe.paymentMethods.remove('cust_123', 'pm_old');
1344
+ * console.log('Payment method removed');
1345
+ * ```
1346
+ */
1347
+ async remove(customerId, paymentMethodId) {
1348
+ return this.http.delete(
1349
+ `/v1/apps/{appId}/customers/${customerId}/payment-methods/${paymentMethodId}`
1350
+ );
1351
+ }
1352
+ /**
1353
+ * Get the default payment method for a customer.
1354
+ *
1355
+ * @example
1356
+ * ```typescript
1357
+ * const defaultPM = await stackbe.paymentMethods.getDefault('cust_123');
1358
+ * if (defaultPM) {
1359
+ * console.log(`Default: ${defaultPM.brand} **** ${defaultPM.last4}`);
1360
+ * }
1361
+ * ```
1362
+ */
1363
+ async getDefault(customerId) {
1364
+ const paymentMethods = await this.list(customerId, { status: "active" });
1365
+ return paymentMethods.find((pm) => pm.isDefault) || null;
1366
+ }
1171
1367
  };
1172
1368
 
1173
1369
  // src/auth.ts
@@ -2063,37 +2259,18 @@ var AffiliatesClient = class {
2063
2259
  /**
2064
2260
  * Get the current customer's affiliate info.
2065
2261
  * Requires customer session token.
2066
- *
2067
- * @example
2068
- * ```typescript
2069
- * const affiliate = await stackbe.affiliates.get();
2070
- *
2071
- * if (affiliate.enrolled) {
2072
- * console.log(`Your referral code: ${affiliate.code}`);
2073
- * console.log(`Earnings: $${(affiliate.totalEarned! / 100).toFixed(2)}`);
2074
- * } else {
2075
- * console.log('Not enrolled in affiliate program');
2076
- * }
2077
- * ```
2078
2262
  */
2079
2263
  async get() {
2080
2264
  return this.http.get("/v1/affiliate");
2081
2265
  }
2082
2266
  /**
2083
- * Enroll the current customer as an affiliate.
2267
+ * Enroll the current customer as an affiliate/partner.
2084
2268
  * Requires customer session token.
2085
2269
  *
2086
2270
  * @example
2087
2271
  * ```typescript
2088
- * // Enroll with auto-generated code
2089
- * const affiliate = await stackbe.affiliates.enroll();
2272
+ * const affiliate = await stackbe.affiliates.enroll({ type: 'referral' });
2090
2273
  * console.log(`Your referral code: ${affiliate.code}`);
2091
- *
2092
- * // Enroll with custom code
2093
- * const affiliate = await stackbe.affiliates.enroll({
2094
- * code: 'MYCODE',
2095
- * payoutEmail: 'payouts@example.com',
2096
- * });
2097
2274
  * ```
2098
2275
  */
2099
2276
  async enroll(options = {}) {
@@ -2102,18 +2279,6 @@ var AffiliatesClient = class {
2102
2279
  /**
2103
2280
  * Get affiliate statistics.
2104
2281
  * Requires customer session token.
2105
- *
2106
- * @example
2107
- * ```typescript
2108
- * const stats = await stackbe.affiliates.getStats();
2109
- *
2110
- * if (stats.enrolled) {
2111
- * console.log(`Total earned: $${(stats.totalEarned / 100).toFixed(2)}`);
2112
- * console.log(`Pending: $${(stats.pendingBalance / 100).toFixed(2)}`);
2113
- * console.log(`Referrals: ${stats.totalReferrals}`);
2114
- * console.log(`Conversions: ${stats.totalConversions}`);
2115
- * }
2116
- * ```
2117
2282
  */
2118
2283
  async getStats() {
2119
2284
  return this.http.get("/v1/affiliate/stats");
@@ -2121,34 +2286,13 @@ var AffiliatesClient = class {
2121
2286
  /**
2122
2287
  * Get affiliate commission history.
2123
2288
  * Requires customer session token.
2124
- *
2125
- * @example
2126
- * ```typescript
2127
- * const { commissions, total } = await stackbe.affiliates.getCommissions();
2128
- *
2129
- * commissions.forEach((c) => {
2130
- * console.log(`$${(c.amount / 100).toFixed(2)} - ${c.status}`);
2131
- * });
2132
- * ```
2133
2289
  */
2134
2290
  async getCommissions() {
2135
2291
  return this.http.get("/v1/affiliate/commissions");
2136
2292
  }
2137
2293
  /**
2138
2294
  * Track a referral click (store token for attribution).
2139
- * Call this when a user lands on your site with a referral code.
2140
2295
  * Requires API key.
2141
- *
2142
- * @example
2143
- * ```typescript
2144
- * // In your landing page handler
2145
- * const refCode = req.query.ref;
2146
- * if (refCode) {
2147
- * const { token, expiresInDays } = await stackbe.affiliates.trackReferral(refCode);
2148
- * // Store token in cookie for attribution on signup
2149
- * res.cookie('ref_token', token, { maxAge: expiresInDays * 24 * 60 * 60 * 1000 });
2150
- * }
2151
- * ```
2152
2296
  */
2153
2297
  async trackReferral(code, referralUrl) {
2154
2298
  return this.http.post("/v1/affiliate/track", {
@@ -2156,6 +2300,44 @@ var AffiliatesClient = class {
2156
2300
  referralUrl
2157
2301
  });
2158
2302
  }
2303
+ /**
2304
+ * Get the full partner dashboard with stats, earnings by source, deals, and coupons.
2305
+ * Requires customer session token.
2306
+ *
2307
+ * @example
2308
+ * ```typescript
2309
+ * const dashboard = await stackbe.affiliates.getDashboard();
2310
+ * console.log(`Link earnings: $${dashboard.earningsBySource.link}`);
2311
+ * console.log(`Coupon earnings: $${dashboard.earningsBySource.coupon}`);
2312
+ * console.log(`Deal earnings: $${dashboard.earningsBySource.deal}`);
2313
+ * ```
2314
+ */
2315
+ async getDashboard() {
2316
+ return this.http.get("/v1/affiliate/dashboard");
2317
+ }
2318
+ /**
2319
+ * Register a deal (lead attribution).
2320
+ * Requires customer session token and active partner enrollment.
2321
+ *
2322
+ * @example
2323
+ * ```typescript
2324
+ * const deal = await stackbe.affiliates.registerDeal({
2325
+ * leadEmail: 'prospect@company.com',
2326
+ * leadName: 'John Smith',
2327
+ * notes: 'Met at conference, interested in Pro plan',
2328
+ * });
2329
+ * ```
2330
+ */
2331
+ async registerDeal(options) {
2332
+ return this.http.post("/v1/affiliate/deals", options);
2333
+ }
2334
+ /**
2335
+ * List the current partner's deal registrations.
2336
+ * Requires customer session token.
2337
+ */
2338
+ async listDeals() {
2339
+ return this.http.get("/v1/affiliate/deals");
2340
+ }
2159
2341
  };
2160
2342
 
2161
2343
  // src/early-access.ts
@@ -2566,6 +2748,7 @@ var StackBE = class {
2566
2748
  this.customers = new CustomersClient(this.http, config.appId);
2567
2749
  this.checkout = new CheckoutClient(this.http, config.appId);
2568
2750
  this.subscriptions = new SubscriptionsClient(this.http);
2751
+ this.paymentMethods = new PaymentMethodsClient(this.http);
2569
2752
  this.auth = new AuthClient(this.http, config.appId, {
2570
2753
  sessionCacheTTL: config.sessionCacheTTL,
2571
2754
  devCallbackUrl: config.devCallbackUrl
@@ -2721,6 +2904,7 @@ var StackBE = class {
2721
2904
  EntitlementsClient,
2722
2905
  FeatureRequestsClient,
2723
2906
  OrganizationsClient,
2907
+ PaymentMethodsClient,
2724
2908
  PlansClient,
2725
2909
  ProductsClient,
2726
2910
  StackBE,