/** * Billing API * * API client functions for the billing/subscription system. */ import apiClient from './client'; // ============================================================================ // Types // ============================================================================ /** * Entitlements - a map of feature codes to their values. * Boolean features indicate permission (true/false). * Integer features indicate limits. */ export interface Entitlements { [key: string]: boolean | number | null; } /** * Plan information (nested in PlanVersion) */ export interface Plan { code: string; name: string; description?: string; } /** * Plan version with pricing and features */ export interface PlanVersion { id: number; name: string; is_legacy: boolean; is_public?: boolean; plan: Plan; price_monthly_cents: number; price_yearly_cents: number; features?: PlanFeature[]; } /** * Feature attached to a plan version */ export interface PlanFeature { feature_code: string; feature_name: string; feature_type: 'boolean' | 'integer'; bool_value?: boolean; int_value?: number; } /** * Current subscription */ export interface Subscription { id: number; status: 'active' | 'canceled' | 'past_due' | 'trialing'; plan_version: PlanVersion; current_period_start: string; current_period_end: string; canceled_at?: string; stripe_subscription_id?: string; } /** * Add-on product */ export interface AddOnProduct { id: number; code: string; name: string; description?: string; price_monthly_cents: number; is_active: boolean; } /** * Invoice line item */ export interface InvoiceLine { id: number; line_type: 'plan' | 'addon' | 'adjustment' | 'credit'; description: string; quantity: number; unit_amount: number; total_amount: number; } /** * Invoice */ export interface Invoice { id: number; status: 'draft' | 'pending' | 'paid' | 'void' | 'uncollectible'; period_start: string; period_end: string; subtotal_amount: number; total_amount: number; plan_name_at_billing: string; plan_code_at_billing?: string; created_at: string; paid_at?: string; lines?: InvoiceLine[]; } // ============================================================================ // API Functions // ============================================================================ /** * Get effective entitlements for the current business. * Returns a map of feature codes to their values. */ export const getEntitlements = async (): Promise => { try { const response = await apiClient.get('/me/entitlements/'); return response.data; } catch (error) { console.error('Failed to fetch entitlements:', error); return {}; } }; /** * Get the current subscription for the business. * Returns null if no subscription exists. */ export const getCurrentSubscription = async (): Promise => { try { const response = await apiClient.get('/me/subscription/'); return response.data; } catch (error: any) { if (error?.response?.status === 404) { return null; } console.error('Failed to fetch subscription:', error); throw error; } }; /** * Get available plans (public, non-legacy plans). */ export const getPlans = async (): Promise => { const response = await apiClient.get('/billing/plans/'); return response.data; }; /** * Get available add-on products. */ export const getAddOns = async (): Promise => { const response = await apiClient.get('/billing/addons/'); return response.data; }; /** * Get invoices for the current business. */ export const getInvoices = async (): Promise => { const response = await apiClient.get('/billing/invoices/'); return response.data; }; /** * Get a single invoice by ID. * Returns null if not found. */ export const getInvoice = async (invoiceId: number): Promise => { try { const response = await apiClient.get(`/billing/invoices/${invoiceId}/`); return response.data; } catch (error: any) { if (error?.response?.status === 404) { return null; } console.error('Failed to fetch invoice:', error); throw error; } };