@stackbe/sdk 0.8.5 → 0.9.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
@@ -353,6 +353,8 @@ interface CreateCheckoutOptions {
353
353
  cancelUrl?: string;
354
354
  /** Organization ID for org-level subscriptions. Customer must be owner/admin of the org. */
355
355
  organizationId?: string;
356
+ /** Coupon/promo code to apply (e.g., "SAVE20") */
357
+ couponCode?: string;
356
358
  /** Allow promotion codes */
357
359
  allowPromotionCodes?: boolean;
358
360
  /** Trial period in days */
@@ -756,6 +758,27 @@ interface CustomerInvoicesResponse {
756
758
  invoices: CustomerInvoice[];
757
759
  hasMore: boolean;
758
760
  }
761
+ interface CustomerPaymentMethod {
762
+ hasPaymentMethod: boolean;
763
+ card: {
764
+ brand: string;
765
+ last4: string;
766
+ expMonth: number;
767
+ expYear: number;
768
+ } | null;
769
+ }
770
+ interface BillingPortalSession {
771
+ url: string;
772
+ }
773
+ interface UpcomingInvoice {
774
+ amountDue: number;
775
+ currency: string;
776
+ dueDate: string | null;
777
+ lines: Array<{
778
+ description: string;
779
+ amount: number;
780
+ }>;
781
+ }
759
782
  declare class CustomersClient {
760
783
  private http;
761
784
  private appId;
@@ -879,6 +902,55 @@ declare class CustomersClient {
879
902
  getInvoices(customerId: string, options?: {
880
903
  limit?: number;
881
904
  }): Promise<CustomerInvoicesResponse>;
905
+ /**
906
+ * Get the customer's saved payment method (card) from Stripe.
907
+ *
908
+ * @example
909
+ * ```typescript
910
+ * const paymentMethod = await stackbe.customers.getPaymentMethod('cust_123');
911
+ *
912
+ * if (paymentMethod.hasPaymentMethod && paymentMethod.card) {
913
+ * console.log(`${paymentMethod.card.brand} ending in ${paymentMethod.card.last4}`);
914
+ * console.log(`Expires: ${paymentMethod.card.expMonth}/${paymentMethod.card.expYear}`);
915
+ * }
916
+ * ```
917
+ */
918
+ getPaymentMethod(customerId: string): Promise<CustomerPaymentMethod>;
919
+ /**
920
+ * Create a Stripe billing portal session for the customer.
921
+ * Redirect the customer to the returned URL to let them manage their billing.
922
+ *
923
+ * @example
924
+ * ```typescript
925
+ * const { url } = await stackbe.customers.createBillingPortalSession('cust_123', {
926
+ * returnUrl: 'https://myapp.com/account'
927
+ * });
928
+ *
929
+ * // Redirect customer to Stripe billing portal
930
+ * window.location.href = url;
931
+ * ```
932
+ */
933
+ createBillingPortalSession(customerId: string, options?: {
934
+ returnUrl?: string;
935
+ }): Promise<BillingPortalSession>;
936
+ /**
937
+ * Get the customer's upcoming invoice preview (next charge).
938
+ * Returns null if the customer has no active subscription.
939
+ *
940
+ * @example
941
+ * ```typescript
942
+ * const upcoming = await stackbe.customers.getUpcomingInvoice('cust_123');
943
+ *
944
+ * if (upcoming) {
945
+ * console.log(`Next charge: $${upcoming.amountDue} ${upcoming.currency}`);
946
+ * console.log(`Due: ${upcoming.dueDate}`);
947
+ * upcoming.lines.forEach(line => {
948
+ * console.log(` ${line.description}: $${line.amount}`);
949
+ * });
950
+ * }
951
+ * ```
952
+ */
953
+ getUpcomingInvoice(customerId: string): Promise<UpcomingInvoice | null>;
882
954
  }
883
955
 
884
956
  declare class CheckoutClient {
@@ -2019,6 +2091,137 @@ declare class EarlyAccessClient {
2019
2091
  updateStatus(signupId: string, status: 'new' | 'invited' | 'converted' | 'archived'): Promise<EarlyAccessSignup>;
2020
2092
  }
2021
2093
 
2094
+ type CouponDiscountType = 'percentage' | 'fixed_amount';
2095
+ interface Coupon {
2096
+ id: string;
2097
+ code: string;
2098
+ name?: string;
2099
+ discountType: CouponDiscountType;
2100
+ discountValue: number;
2101
+ currency?: string;
2102
+ maxRedemptions?: number;
2103
+ timesRedeemed: number;
2104
+ expiresAt?: string;
2105
+ validPlanIds: string[];
2106
+ active: boolean;
2107
+ createdAt: string;
2108
+ updatedAt: string;
2109
+ }
2110
+ interface CreateCouponOptions {
2111
+ /** Coupon code (alphanumeric, will be uppercased) */
2112
+ code: string;
2113
+ /** Internal name for dashboard */
2114
+ name?: string;
2115
+ /** Type of discount */
2116
+ discountType: CouponDiscountType;
2117
+ /** Discount value (percentage 1-100, or cents for fixed_amount) */
2118
+ discountValue: number;
2119
+ /** Currency code (required for fixed_amount) */
2120
+ currency?: string;
2121
+ /** Maximum number of times this coupon can be used */
2122
+ maxRedemptions?: number;
2123
+ /** When the coupon expires (ISO date string) */
2124
+ expiresAt?: string;
2125
+ /** Restrict to specific plan IDs (empty = valid for all plans) */
2126
+ validPlanIds?: string[];
2127
+ /** Whether the coupon is active */
2128
+ active?: boolean;
2129
+ }
2130
+ interface UpdateCouponOptions {
2131
+ name?: string;
2132
+ maxRedemptions?: number;
2133
+ expiresAt?: string;
2134
+ validPlanIds?: string[];
2135
+ active?: boolean;
2136
+ }
2137
+ interface ValidateCouponResult {
2138
+ valid: boolean;
2139
+ coupon?: {
2140
+ id: string;
2141
+ code: string;
2142
+ discountType: CouponDiscountType;
2143
+ discountValue: number;
2144
+ currency?: string;
2145
+ };
2146
+ error?: string;
2147
+ }
2148
+ declare class CouponsClient {
2149
+ private http;
2150
+ private appId;
2151
+ constructor(http: HttpClient, appId: string);
2152
+ /**
2153
+ * Create a new coupon/promo code.
2154
+ *
2155
+ * @example
2156
+ * ```typescript
2157
+ * const coupon = await stackbe.coupons.create({
2158
+ * code: 'SAVE20',
2159
+ * discountType: 'percentage',
2160
+ * discountValue: 20,
2161
+ * maxRedemptions: 100,
2162
+ * expiresAt: '2026-12-31T23:59:59Z',
2163
+ * });
2164
+ * ```
2165
+ */
2166
+ create(options: CreateCouponOptions): Promise<Coupon>;
2167
+ /**
2168
+ * List all coupons for your app.
2169
+ *
2170
+ * @example
2171
+ * ```typescript
2172
+ * const coupons = await stackbe.coupons.list();
2173
+ * const activeCoupons = await stackbe.coupons.list({ active: true });
2174
+ * ```
2175
+ */
2176
+ list(options?: {
2177
+ active?: boolean;
2178
+ }): Promise<Coupon[]>;
2179
+ /**
2180
+ * Get a specific coupon by ID.
2181
+ *
2182
+ * @example
2183
+ * ```typescript
2184
+ * const coupon = await stackbe.coupons.get('coupon_abc123');
2185
+ * ```
2186
+ */
2187
+ get(couponId: string): Promise<Coupon>;
2188
+ /**
2189
+ * Validate a coupon code before checkout.
2190
+ *
2191
+ * @example
2192
+ * ```typescript
2193
+ * const result = await stackbe.coupons.validate('SAVE20', 'plan_pro');
2194
+ *
2195
+ * if (result.valid) {
2196
+ * console.log(`${result.coupon.discountValue}% off!`);
2197
+ * } else {
2198
+ * console.log(result.error); // "Coupon has expired"
2199
+ * }
2200
+ * ```
2201
+ */
2202
+ validate(code: string, planId?: string): Promise<ValidateCouponResult>;
2203
+ /**
2204
+ * Update a coupon.
2205
+ *
2206
+ * @example
2207
+ * ```typescript
2208
+ * const coupon = await stackbe.coupons.update('coupon_abc123', {
2209
+ * active: false,
2210
+ * });
2211
+ * ```
2212
+ */
2213
+ update(couponId: string, options: UpdateCouponOptions): Promise<Coupon>;
2214
+ /**
2215
+ * Delete a coupon.
2216
+ *
2217
+ * @example
2218
+ * ```typescript
2219
+ * await stackbe.coupons.delete('coupon_abc123');
2220
+ * ```
2221
+ */
2222
+ delete(couponId: string): Promise<void>;
2223
+ }
2224
+
2022
2225
  declare class StackBE {
2023
2226
  private http;
2024
2227
  private appId;
@@ -2046,6 +2249,8 @@ declare class StackBE {
2046
2249
  readonly affiliates: AffiliatesClient;
2047
2250
  /** Early access / waitlist signups */
2048
2251
  readonly earlyAccess: EarlyAccessClient;
2252
+ /** Coupon/promo code management */
2253
+ readonly coupons: CouponsClient;
2049
2254
  /**
2050
2255
  * Create a new StackBE client.
2051
2256
  *
@@ -2146,4 +2351,4 @@ declare class StackBE {
2146
2351
  }): (req: any, res: any, next: any) => Promise<any>;
2147
2352
  }
2148
2353
 
2149
- export { type AddMemberOptions, type AffiliateCommission, type AffiliateCommissionsResponse, type AffiliateEnrollment, type AffiliateInfo, type AffiliateStats, AffiliatesClient, type AnyWebhookEvent, AuthClient, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type CreateCheckoutOptions, type CreateCustomerOptions, type CreateEarlyAccessSignupOptions, type CreateFeatureRequestOptions, type CreateOrganizationOptions, type Customer, type CustomerCreatedEvent, type CustomerFeatureActivity, type CustomerInvoice, type CustomerInvoicesResponse, type CustomerSubscriptionHistory, type CustomerSubscriptionHistoryResponse, type CustomerUpdatedEvent, type CustomerUsageResponse, type CustomerWebhookPayload, type CustomerWithSubscription, CustomersClient, EarlyAccessClient, type EarlyAccessSignup, type EarlyAccessSignupListResponse, type EnrollOptions, EntitlementsClient, type EntitlementsResponse, type FeatureRequest, type FeatureRequestComment, type FeatureRequestImage, type FeatureRequestListResponse, FeatureRequestsClient, type GetSubscriptionOptions, type InterestedCustomer, type InterestedCustomersResponse, type InviteMemberOptions, type ListEarlyAccessOptions, type ListFeatureRequestsOptions, 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 SubscriptionPlan, type SubscriptionRenewedEvent, type SubscriptionUpdatedEvent, type SubscriptionWebhookPayload, type SubscriptionWithPlan, SubscriptionsClient, type TrackReferralResponse, type TrackUsageOptions, type TrackUsageResponse, type TrialEndedEvent, type TrialStartedEvent, type UpdateCustomerOptions, type UpdateOrganizationOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type VerifyTokenResponse, type WebhookEvent, type WebhookEventType };
2354
+ export { type AddMemberOptions, type AffiliateCommission, type AffiliateCommissionsResponse, type AffiliateEnrollment, type AffiliateInfo, type AffiliateStats, AffiliatesClient, type AnyWebhookEvent, AuthClient, type BillingPortalSession, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type Coupon, type CouponDiscountType, 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, EarlyAccessClient, type EarlyAccessSignup, type EarlyAccessSignupListResponse, type EnrollOptions, EntitlementsClient, type EntitlementsResponse, type FeatureRequest, type FeatureRequestComment, type FeatureRequestImage, type FeatureRequestListResponse, FeatureRequestsClient, type GetSubscriptionOptions, type InterestedCustomer, type InterestedCustomersResponse, type InviteMemberOptions, type ListEarlyAccessOptions, type ListFeatureRequestsOptions, 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 SubscriptionPlan, type SubscriptionRenewedEvent, type SubscriptionUpdatedEvent, type SubscriptionWebhookPayload, type SubscriptionWithPlan, SubscriptionsClient, type TrackReferralResponse, type TrackUsageOptions, type TrackUsageResponse, type TrialEndedEvent, type TrialStartedEvent, 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
@@ -353,6 +353,8 @@ interface CreateCheckoutOptions {
353
353
  cancelUrl?: string;
354
354
  /** Organization ID for org-level subscriptions. Customer must be owner/admin of the org. */
355
355
  organizationId?: string;
356
+ /** Coupon/promo code to apply (e.g., "SAVE20") */
357
+ couponCode?: string;
356
358
  /** Allow promotion codes */
357
359
  allowPromotionCodes?: boolean;
358
360
  /** Trial period in days */
@@ -756,6 +758,27 @@ interface CustomerInvoicesResponse {
756
758
  invoices: CustomerInvoice[];
757
759
  hasMore: boolean;
758
760
  }
761
+ interface CustomerPaymentMethod {
762
+ hasPaymentMethod: boolean;
763
+ card: {
764
+ brand: string;
765
+ last4: string;
766
+ expMonth: number;
767
+ expYear: number;
768
+ } | null;
769
+ }
770
+ interface BillingPortalSession {
771
+ url: string;
772
+ }
773
+ interface UpcomingInvoice {
774
+ amountDue: number;
775
+ currency: string;
776
+ dueDate: string | null;
777
+ lines: Array<{
778
+ description: string;
779
+ amount: number;
780
+ }>;
781
+ }
759
782
  declare class CustomersClient {
760
783
  private http;
761
784
  private appId;
@@ -879,6 +902,55 @@ declare class CustomersClient {
879
902
  getInvoices(customerId: string, options?: {
880
903
  limit?: number;
881
904
  }): Promise<CustomerInvoicesResponse>;
905
+ /**
906
+ * Get the customer's saved payment method (card) from Stripe.
907
+ *
908
+ * @example
909
+ * ```typescript
910
+ * const paymentMethod = await stackbe.customers.getPaymentMethod('cust_123');
911
+ *
912
+ * if (paymentMethod.hasPaymentMethod && paymentMethod.card) {
913
+ * console.log(`${paymentMethod.card.brand} ending in ${paymentMethod.card.last4}`);
914
+ * console.log(`Expires: ${paymentMethod.card.expMonth}/${paymentMethod.card.expYear}`);
915
+ * }
916
+ * ```
917
+ */
918
+ getPaymentMethod(customerId: string): Promise<CustomerPaymentMethod>;
919
+ /**
920
+ * Create a Stripe billing portal session for the customer.
921
+ * Redirect the customer to the returned URL to let them manage their billing.
922
+ *
923
+ * @example
924
+ * ```typescript
925
+ * const { url } = await stackbe.customers.createBillingPortalSession('cust_123', {
926
+ * returnUrl: 'https://myapp.com/account'
927
+ * });
928
+ *
929
+ * // Redirect customer to Stripe billing portal
930
+ * window.location.href = url;
931
+ * ```
932
+ */
933
+ createBillingPortalSession(customerId: string, options?: {
934
+ returnUrl?: string;
935
+ }): Promise<BillingPortalSession>;
936
+ /**
937
+ * Get the customer's upcoming invoice preview (next charge).
938
+ * Returns null if the customer has no active subscription.
939
+ *
940
+ * @example
941
+ * ```typescript
942
+ * const upcoming = await stackbe.customers.getUpcomingInvoice('cust_123');
943
+ *
944
+ * if (upcoming) {
945
+ * console.log(`Next charge: $${upcoming.amountDue} ${upcoming.currency}`);
946
+ * console.log(`Due: ${upcoming.dueDate}`);
947
+ * upcoming.lines.forEach(line => {
948
+ * console.log(` ${line.description}: $${line.amount}`);
949
+ * });
950
+ * }
951
+ * ```
952
+ */
953
+ getUpcomingInvoice(customerId: string): Promise<UpcomingInvoice | null>;
882
954
  }
883
955
 
884
956
  declare class CheckoutClient {
@@ -2019,6 +2091,137 @@ declare class EarlyAccessClient {
2019
2091
  updateStatus(signupId: string, status: 'new' | 'invited' | 'converted' | 'archived'): Promise<EarlyAccessSignup>;
2020
2092
  }
2021
2093
 
2094
+ type CouponDiscountType = 'percentage' | 'fixed_amount';
2095
+ interface Coupon {
2096
+ id: string;
2097
+ code: string;
2098
+ name?: string;
2099
+ discountType: CouponDiscountType;
2100
+ discountValue: number;
2101
+ currency?: string;
2102
+ maxRedemptions?: number;
2103
+ timesRedeemed: number;
2104
+ expiresAt?: string;
2105
+ validPlanIds: string[];
2106
+ active: boolean;
2107
+ createdAt: string;
2108
+ updatedAt: string;
2109
+ }
2110
+ interface CreateCouponOptions {
2111
+ /** Coupon code (alphanumeric, will be uppercased) */
2112
+ code: string;
2113
+ /** Internal name for dashboard */
2114
+ name?: string;
2115
+ /** Type of discount */
2116
+ discountType: CouponDiscountType;
2117
+ /** Discount value (percentage 1-100, or cents for fixed_amount) */
2118
+ discountValue: number;
2119
+ /** Currency code (required for fixed_amount) */
2120
+ currency?: string;
2121
+ /** Maximum number of times this coupon can be used */
2122
+ maxRedemptions?: number;
2123
+ /** When the coupon expires (ISO date string) */
2124
+ expiresAt?: string;
2125
+ /** Restrict to specific plan IDs (empty = valid for all plans) */
2126
+ validPlanIds?: string[];
2127
+ /** Whether the coupon is active */
2128
+ active?: boolean;
2129
+ }
2130
+ interface UpdateCouponOptions {
2131
+ name?: string;
2132
+ maxRedemptions?: number;
2133
+ expiresAt?: string;
2134
+ validPlanIds?: string[];
2135
+ active?: boolean;
2136
+ }
2137
+ interface ValidateCouponResult {
2138
+ valid: boolean;
2139
+ coupon?: {
2140
+ id: string;
2141
+ code: string;
2142
+ discountType: CouponDiscountType;
2143
+ discountValue: number;
2144
+ currency?: string;
2145
+ };
2146
+ error?: string;
2147
+ }
2148
+ declare class CouponsClient {
2149
+ private http;
2150
+ private appId;
2151
+ constructor(http: HttpClient, appId: string);
2152
+ /**
2153
+ * Create a new coupon/promo code.
2154
+ *
2155
+ * @example
2156
+ * ```typescript
2157
+ * const coupon = await stackbe.coupons.create({
2158
+ * code: 'SAVE20',
2159
+ * discountType: 'percentage',
2160
+ * discountValue: 20,
2161
+ * maxRedemptions: 100,
2162
+ * expiresAt: '2026-12-31T23:59:59Z',
2163
+ * });
2164
+ * ```
2165
+ */
2166
+ create(options: CreateCouponOptions): Promise<Coupon>;
2167
+ /**
2168
+ * List all coupons for your app.
2169
+ *
2170
+ * @example
2171
+ * ```typescript
2172
+ * const coupons = await stackbe.coupons.list();
2173
+ * const activeCoupons = await stackbe.coupons.list({ active: true });
2174
+ * ```
2175
+ */
2176
+ list(options?: {
2177
+ active?: boolean;
2178
+ }): Promise<Coupon[]>;
2179
+ /**
2180
+ * Get a specific coupon by ID.
2181
+ *
2182
+ * @example
2183
+ * ```typescript
2184
+ * const coupon = await stackbe.coupons.get('coupon_abc123');
2185
+ * ```
2186
+ */
2187
+ get(couponId: string): Promise<Coupon>;
2188
+ /**
2189
+ * Validate a coupon code before checkout.
2190
+ *
2191
+ * @example
2192
+ * ```typescript
2193
+ * const result = await stackbe.coupons.validate('SAVE20', 'plan_pro');
2194
+ *
2195
+ * if (result.valid) {
2196
+ * console.log(`${result.coupon.discountValue}% off!`);
2197
+ * } else {
2198
+ * console.log(result.error); // "Coupon has expired"
2199
+ * }
2200
+ * ```
2201
+ */
2202
+ validate(code: string, planId?: string): Promise<ValidateCouponResult>;
2203
+ /**
2204
+ * Update a coupon.
2205
+ *
2206
+ * @example
2207
+ * ```typescript
2208
+ * const coupon = await stackbe.coupons.update('coupon_abc123', {
2209
+ * active: false,
2210
+ * });
2211
+ * ```
2212
+ */
2213
+ update(couponId: string, options: UpdateCouponOptions): Promise<Coupon>;
2214
+ /**
2215
+ * Delete a coupon.
2216
+ *
2217
+ * @example
2218
+ * ```typescript
2219
+ * await stackbe.coupons.delete('coupon_abc123');
2220
+ * ```
2221
+ */
2222
+ delete(couponId: string): Promise<void>;
2223
+ }
2224
+
2022
2225
  declare class StackBE {
2023
2226
  private http;
2024
2227
  private appId;
@@ -2046,6 +2249,8 @@ declare class StackBE {
2046
2249
  readonly affiliates: AffiliatesClient;
2047
2250
  /** Early access / waitlist signups */
2048
2251
  readonly earlyAccess: EarlyAccessClient;
2252
+ /** Coupon/promo code management */
2253
+ readonly coupons: CouponsClient;
2049
2254
  /**
2050
2255
  * Create a new StackBE client.
2051
2256
  *
@@ -2146,4 +2351,4 @@ declare class StackBE {
2146
2351
  }): (req: any, res: any, next: any) => Promise<any>;
2147
2352
  }
2148
2353
 
2149
- export { type AddMemberOptions, type AffiliateCommission, type AffiliateCommissionsResponse, type AffiliateEnrollment, type AffiliateInfo, type AffiliateStats, AffiliatesClient, type AnyWebhookEvent, AuthClient, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type CreateCheckoutOptions, type CreateCustomerOptions, type CreateEarlyAccessSignupOptions, type CreateFeatureRequestOptions, type CreateOrganizationOptions, type Customer, type CustomerCreatedEvent, type CustomerFeatureActivity, type CustomerInvoice, type CustomerInvoicesResponse, type CustomerSubscriptionHistory, type CustomerSubscriptionHistoryResponse, type CustomerUpdatedEvent, type CustomerUsageResponse, type CustomerWebhookPayload, type CustomerWithSubscription, CustomersClient, EarlyAccessClient, type EarlyAccessSignup, type EarlyAccessSignupListResponse, type EnrollOptions, EntitlementsClient, type EntitlementsResponse, type FeatureRequest, type FeatureRequestComment, type FeatureRequestImage, type FeatureRequestListResponse, FeatureRequestsClient, type GetSubscriptionOptions, type InterestedCustomer, type InterestedCustomersResponse, type InviteMemberOptions, type ListEarlyAccessOptions, type ListFeatureRequestsOptions, 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 SubscriptionPlan, type SubscriptionRenewedEvent, type SubscriptionUpdatedEvent, type SubscriptionWebhookPayload, type SubscriptionWithPlan, SubscriptionsClient, type TrackReferralResponse, type TrackUsageOptions, type TrackUsageResponse, type TrialEndedEvent, type TrialStartedEvent, type UpdateCustomerOptions, type UpdateOrganizationOptions, type UpdateSubscriptionOptions, UsageClient, type UsageMetric, type VerifyTokenResponse, type WebhookEvent, type WebhookEventType };
2354
+ export { type AddMemberOptions, type AffiliateCommission, type AffiliateCommissionsResponse, type AffiliateEnrollment, type AffiliateInfo, type AffiliateStats, AffiliatesClient, type AnyWebhookEvent, AuthClient, type BillingPortalSession, type CancelSubscriptionOptions, type CancelSubscriptionResponse, type CheckEntitlementResponse, type CheckUsageResponse, CheckoutClient, type CheckoutSessionResponse, type Coupon, type CouponDiscountType, 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, EarlyAccessClient, type EarlyAccessSignup, type EarlyAccessSignupListResponse, type EnrollOptions, EntitlementsClient, type EntitlementsResponse, type FeatureRequest, type FeatureRequestComment, type FeatureRequestImage, type FeatureRequestListResponse, FeatureRequestsClient, type GetSubscriptionOptions, type InterestedCustomer, type InterestedCustomersResponse, type InviteMemberOptions, type ListEarlyAccessOptions, type ListFeatureRequestsOptions, 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 SubscriptionPlan, type SubscriptionRenewedEvent, type SubscriptionUpdatedEvent, type SubscriptionWebhookPayload, type SubscriptionWithPlan, SubscriptionsClient, type TrackReferralResponse, type TrackUsageOptions, type TrackUsageResponse, type TrialEndedEvent, type TrialStartedEvent, 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
@@ -23,6 +23,7 @@ __export(index_exports, {
23
23
  AffiliatesClient: () => AffiliatesClient,
24
24
  AuthClient: () => AuthClient,
25
25
  CheckoutClient: () => CheckoutClient,
26
+ CouponsClient: () => CouponsClient,
26
27
  CustomersClient: () => CustomersClient,
27
28
  EarlyAccessClient: () => EarlyAccessClient,
28
29
  EntitlementsClient: () => EntitlementsClient,
@@ -651,6 +652,67 @@ var CustomersClient = class {
651
652
  params
652
653
  );
653
654
  }
655
+ // ==================== Billing Self-Service ====================
656
+ /**
657
+ * Get the customer's saved payment method (card) from Stripe.
658
+ *
659
+ * @example
660
+ * ```typescript
661
+ * const paymentMethod = await stackbe.customers.getPaymentMethod('cust_123');
662
+ *
663
+ * if (paymentMethod.hasPaymentMethod && paymentMethod.card) {
664
+ * console.log(`${paymentMethod.card.brand} ending in ${paymentMethod.card.last4}`);
665
+ * console.log(`Expires: ${paymentMethod.card.expMonth}/${paymentMethod.card.expYear}`);
666
+ * }
667
+ * ```
668
+ */
669
+ async getPaymentMethod(customerId) {
670
+ return this.http.get(
671
+ `/v1/apps/${this.appId}/customers/${customerId}/payment-method`
672
+ );
673
+ }
674
+ /**
675
+ * Create a Stripe billing portal session for the customer.
676
+ * Redirect the customer to the returned URL to let them manage their billing.
677
+ *
678
+ * @example
679
+ * ```typescript
680
+ * const { url } = await stackbe.customers.createBillingPortalSession('cust_123', {
681
+ * returnUrl: 'https://myapp.com/account'
682
+ * });
683
+ *
684
+ * // Redirect customer to Stripe billing portal
685
+ * window.location.href = url;
686
+ * ```
687
+ */
688
+ async createBillingPortalSession(customerId, options) {
689
+ return this.http.post(
690
+ `/v1/apps/${this.appId}/customers/${customerId}/billing-portal`,
691
+ { returnUrl: options?.returnUrl }
692
+ );
693
+ }
694
+ /**
695
+ * Get the customer's upcoming invoice preview (next charge).
696
+ * Returns null if the customer has no active subscription.
697
+ *
698
+ * @example
699
+ * ```typescript
700
+ * const upcoming = await stackbe.customers.getUpcomingInvoice('cust_123');
701
+ *
702
+ * if (upcoming) {
703
+ * console.log(`Next charge: $${upcoming.amountDue} ${upcoming.currency}`);
704
+ * console.log(`Due: ${upcoming.dueDate}`);
705
+ * upcoming.lines.forEach(line => {
706
+ * console.log(` ${line.description}: $${line.amount}`);
707
+ * });
708
+ * }
709
+ * ```
710
+ */
711
+ async getUpcomingInvoice(customerId) {
712
+ return this.http.get(
713
+ `/v1/apps/${this.appId}/customers/${customerId}/upcoming-invoice`
714
+ );
715
+ }
654
716
  };
655
717
 
656
718
  // src/checkout.ts
@@ -707,6 +769,7 @@ var CheckoutClient = class {
707
769
  successUrl: options.successUrl,
708
770
  cancelUrl: options.cancelUrl,
709
771
  organizationId: options.organizationId,
772
+ couponCode: options.couponCode,
710
773
  allowPromotionCodes: options.allowPromotionCodes,
711
774
  trialDays: options.trialDays,
712
775
  metadata: options.metadata
@@ -1978,6 +2041,102 @@ var EarlyAccessClient = class {
1978
2041
  }
1979
2042
  };
1980
2043
 
2044
+ // src/coupons.ts
2045
+ var CouponsClient = class {
2046
+ constructor(http, appId) {
2047
+ this.http = http;
2048
+ this.appId = appId;
2049
+ }
2050
+ /**
2051
+ * Create a new coupon/promo code.
2052
+ *
2053
+ * @example
2054
+ * ```typescript
2055
+ * const coupon = await stackbe.coupons.create({
2056
+ * code: 'SAVE20',
2057
+ * discountType: 'percentage',
2058
+ * discountValue: 20,
2059
+ * maxRedemptions: 100,
2060
+ * expiresAt: '2026-12-31T23:59:59Z',
2061
+ * });
2062
+ * ```
2063
+ */
2064
+ async create(options) {
2065
+ return this.http.post(`/v1/apps/${this.appId}/coupons`, options);
2066
+ }
2067
+ /**
2068
+ * List all coupons for your app.
2069
+ *
2070
+ * @example
2071
+ * ```typescript
2072
+ * const coupons = await stackbe.coupons.list();
2073
+ * const activeCoupons = await stackbe.coupons.list({ active: true });
2074
+ * ```
2075
+ */
2076
+ async list(options) {
2077
+ const params = {};
2078
+ if (options?.active !== void 0) {
2079
+ params.active = String(options.active);
2080
+ }
2081
+ return this.http.get(`/v1/apps/${this.appId}/coupons`, params);
2082
+ }
2083
+ /**
2084
+ * Get a specific coupon by ID.
2085
+ *
2086
+ * @example
2087
+ * ```typescript
2088
+ * const coupon = await stackbe.coupons.get('coupon_abc123');
2089
+ * ```
2090
+ */
2091
+ async get(couponId) {
2092
+ return this.http.get(`/v1/apps/${this.appId}/coupons/${couponId}`);
2093
+ }
2094
+ /**
2095
+ * Validate a coupon code before checkout.
2096
+ *
2097
+ * @example
2098
+ * ```typescript
2099
+ * const result = await stackbe.coupons.validate('SAVE20', 'plan_pro');
2100
+ *
2101
+ * if (result.valid) {
2102
+ * console.log(`${result.coupon.discountValue}% off!`);
2103
+ * } else {
2104
+ * console.log(result.error); // "Coupon has expired"
2105
+ * }
2106
+ * ```
2107
+ */
2108
+ async validate(code, planId) {
2109
+ return this.http.post(`/v1/apps/${this.appId}/coupons/validate`, {
2110
+ code,
2111
+ planId
2112
+ });
2113
+ }
2114
+ /**
2115
+ * Update a coupon.
2116
+ *
2117
+ * @example
2118
+ * ```typescript
2119
+ * const coupon = await stackbe.coupons.update('coupon_abc123', {
2120
+ * active: false,
2121
+ * });
2122
+ * ```
2123
+ */
2124
+ async update(couponId, options) {
2125
+ return this.http.patch(`/v1/apps/${this.appId}/coupons/${couponId}`, options);
2126
+ }
2127
+ /**
2128
+ * Delete a coupon.
2129
+ *
2130
+ * @example
2131
+ * ```typescript
2132
+ * await stackbe.coupons.delete('coupon_abc123');
2133
+ * ```
2134
+ */
2135
+ async delete(couponId) {
2136
+ await this.http.delete(`/v1/apps/${this.appId}/coupons/${couponId}`);
2137
+ }
2138
+ };
2139
+
1981
2140
  // src/client.ts
1982
2141
  var DEFAULT_BASE_URL = "https://api.stackbe.io";
1983
2142
  var DEFAULT_TIMEOUT = 3e4;
@@ -2043,6 +2202,7 @@ var StackBE = class {
2043
2202
  this.featureRequests = new FeatureRequestsClient(this.http, config.appId);
2044
2203
  this.affiliates = new AffiliatesClient(this.http);
2045
2204
  this.earlyAccess = new EarlyAccessClient(this.http, config.appId);
2205
+ this.coupons = new CouponsClient(this.http, config.appId);
2046
2206
  }
2047
2207
  /**
2048
2208
  * Create a middleware for Express that tracks usage automatically.
@@ -2179,6 +2339,7 @@ var StackBE = class {
2179
2339
  AffiliatesClient,
2180
2340
  AuthClient,
2181
2341
  CheckoutClient,
2342
+ CouponsClient,
2182
2343
  CustomersClient,
2183
2344
  EarlyAccessClient,
2184
2345
  EntitlementsClient,
package/dist/index.mjs CHANGED
@@ -612,6 +612,67 @@ var CustomersClient = class {
612
612
  params
613
613
  );
614
614
  }
615
+ // ==================== Billing Self-Service ====================
616
+ /**
617
+ * Get the customer's saved payment method (card) from Stripe.
618
+ *
619
+ * @example
620
+ * ```typescript
621
+ * const paymentMethod = await stackbe.customers.getPaymentMethod('cust_123');
622
+ *
623
+ * if (paymentMethod.hasPaymentMethod && paymentMethod.card) {
624
+ * console.log(`${paymentMethod.card.brand} ending in ${paymentMethod.card.last4}`);
625
+ * console.log(`Expires: ${paymentMethod.card.expMonth}/${paymentMethod.card.expYear}`);
626
+ * }
627
+ * ```
628
+ */
629
+ async getPaymentMethod(customerId) {
630
+ return this.http.get(
631
+ `/v1/apps/${this.appId}/customers/${customerId}/payment-method`
632
+ );
633
+ }
634
+ /**
635
+ * Create a Stripe billing portal session for the customer.
636
+ * Redirect the customer to the returned URL to let them manage their billing.
637
+ *
638
+ * @example
639
+ * ```typescript
640
+ * const { url } = await stackbe.customers.createBillingPortalSession('cust_123', {
641
+ * returnUrl: 'https://myapp.com/account'
642
+ * });
643
+ *
644
+ * // Redirect customer to Stripe billing portal
645
+ * window.location.href = url;
646
+ * ```
647
+ */
648
+ async createBillingPortalSession(customerId, options) {
649
+ return this.http.post(
650
+ `/v1/apps/${this.appId}/customers/${customerId}/billing-portal`,
651
+ { returnUrl: options?.returnUrl }
652
+ );
653
+ }
654
+ /**
655
+ * Get the customer's upcoming invoice preview (next charge).
656
+ * Returns null if the customer has no active subscription.
657
+ *
658
+ * @example
659
+ * ```typescript
660
+ * const upcoming = await stackbe.customers.getUpcomingInvoice('cust_123');
661
+ *
662
+ * if (upcoming) {
663
+ * console.log(`Next charge: $${upcoming.amountDue} ${upcoming.currency}`);
664
+ * console.log(`Due: ${upcoming.dueDate}`);
665
+ * upcoming.lines.forEach(line => {
666
+ * console.log(` ${line.description}: $${line.amount}`);
667
+ * });
668
+ * }
669
+ * ```
670
+ */
671
+ async getUpcomingInvoice(customerId) {
672
+ return this.http.get(
673
+ `/v1/apps/${this.appId}/customers/${customerId}/upcoming-invoice`
674
+ );
675
+ }
615
676
  };
616
677
 
617
678
  // src/checkout.ts
@@ -668,6 +729,7 @@ var CheckoutClient = class {
668
729
  successUrl: options.successUrl,
669
730
  cancelUrl: options.cancelUrl,
670
731
  organizationId: options.organizationId,
732
+ couponCode: options.couponCode,
671
733
  allowPromotionCodes: options.allowPromotionCodes,
672
734
  trialDays: options.trialDays,
673
735
  metadata: options.metadata
@@ -1939,6 +2001,102 @@ var EarlyAccessClient = class {
1939
2001
  }
1940
2002
  };
1941
2003
 
2004
+ // src/coupons.ts
2005
+ var CouponsClient = class {
2006
+ constructor(http, appId) {
2007
+ this.http = http;
2008
+ this.appId = appId;
2009
+ }
2010
+ /**
2011
+ * Create a new coupon/promo code.
2012
+ *
2013
+ * @example
2014
+ * ```typescript
2015
+ * const coupon = await stackbe.coupons.create({
2016
+ * code: 'SAVE20',
2017
+ * discountType: 'percentage',
2018
+ * discountValue: 20,
2019
+ * maxRedemptions: 100,
2020
+ * expiresAt: '2026-12-31T23:59:59Z',
2021
+ * });
2022
+ * ```
2023
+ */
2024
+ async create(options) {
2025
+ return this.http.post(`/v1/apps/${this.appId}/coupons`, options);
2026
+ }
2027
+ /**
2028
+ * List all coupons for your app.
2029
+ *
2030
+ * @example
2031
+ * ```typescript
2032
+ * const coupons = await stackbe.coupons.list();
2033
+ * const activeCoupons = await stackbe.coupons.list({ active: true });
2034
+ * ```
2035
+ */
2036
+ async list(options) {
2037
+ const params = {};
2038
+ if (options?.active !== void 0) {
2039
+ params.active = String(options.active);
2040
+ }
2041
+ return this.http.get(`/v1/apps/${this.appId}/coupons`, params);
2042
+ }
2043
+ /**
2044
+ * Get a specific coupon by ID.
2045
+ *
2046
+ * @example
2047
+ * ```typescript
2048
+ * const coupon = await stackbe.coupons.get('coupon_abc123');
2049
+ * ```
2050
+ */
2051
+ async get(couponId) {
2052
+ return this.http.get(`/v1/apps/${this.appId}/coupons/${couponId}`);
2053
+ }
2054
+ /**
2055
+ * Validate a coupon code before checkout.
2056
+ *
2057
+ * @example
2058
+ * ```typescript
2059
+ * const result = await stackbe.coupons.validate('SAVE20', 'plan_pro');
2060
+ *
2061
+ * if (result.valid) {
2062
+ * console.log(`${result.coupon.discountValue}% off!`);
2063
+ * } else {
2064
+ * console.log(result.error); // "Coupon has expired"
2065
+ * }
2066
+ * ```
2067
+ */
2068
+ async validate(code, planId) {
2069
+ return this.http.post(`/v1/apps/${this.appId}/coupons/validate`, {
2070
+ code,
2071
+ planId
2072
+ });
2073
+ }
2074
+ /**
2075
+ * Update a coupon.
2076
+ *
2077
+ * @example
2078
+ * ```typescript
2079
+ * const coupon = await stackbe.coupons.update('coupon_abc123', {
2080
+ * active: false,
2081
+ * });
2082
+ * ```
2083
+ */
2084
+ async update(couponId, options) {
2085
+ return this.http.patch(`/v1/apps/${this.appId}/coupons/${couponId}`, options);
2086
+ }
2087
+ /**
2088
+ * Delete a coupon.
2089
+ *
2090
+ * @example
2091
+ * ```typescript
2092
+ * await stackbe.coupons.delete('coupon_abc123');
2093
+ * ```
2094
+ */
2095
+ async delete(couponId) {
2096
+ await this.http.delete(`/v1/apps/${this.appId}/coupons/${couponId}`);
2097
+ }
2098
+ };
2099
+
1942
2100
  // src/client.ts
1943
2101
  var DEFAULT_BASE_URL = "https://api.stackbe.io";
1944
2102
  var DEFAULT_TIMEOUT = 3e4;
@@ -2004,6 +2162,7 @@ var StackBE = class {
2004
2162
  this.featureRequests = new FeatureRequestsClient(this.http, config.appId);
2005
2163
  this.affiliates = new AffiliatesClient(this.http);
2006
2164
  this.earlyAccess = new EarlyAccessClient(this.http, config.appId);
2165
+ this.coupons = new CouponsClient(this.http, config.appId);
2007
2166
  }
2008
2167
  /**
2009
2168
  * Create a middleware for Express that tracks usage automatically.
@@ -2139,6 +2298,7 @@ export {
2139
2298
  AffiliatesClient,
2140
2299
  AuthClient,
2141
2300
  CheckoutClient,
2301
+ CouponsClient,
2142
2302
  CustomersClient,
2143
2303
  EarlyAccessClient,
2144
2304
  EntitlementsClient,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackbe/sdk",
3
- "version": "0.8.5",
3
+ "version": "0.9.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",