@billingos/sdk 0.1.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 +582 -0
- package/dist/index.d.ts +3346 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +6283 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +89 -0
package/README.md
ADDED
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
# BillingOS SDK
|
|
2
|
+
|
|
3
|
+
Official React SDK for BillingOS - A comprehensive billing, subscriptions, and payments platform.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ **React Hooks** - Powerful hooks for subscriptions, entitlements, usage tracking, and more
|
|
8
|
+
- ✅ **TypeScript Support** - Full type safety with auto-generated types
|
|
9
|
+
- ✅ **React Query Integration** - Automatic caching, refetching, and state management
|
|
10
|
+
- ✅ **API Client** - Comprehensive API client with error handling
|
|
11
|
+
- ✅ **Money Utilities** - Currency formatting and conversion helpers
|
|
12
|
+
- ✅ **Date Utilities** - Date formatting and manipulation
|
|
13
|
+
- ✅ **Next.js Compatible** - Works seamlessly with Next.js App Router and Pages Router
|
|
14
|
+
- ✅ **Framework Agnostic Core** - Can be extended to other frameworks in the future
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# npm
|
|
20
|
+
npm install @billingos/sdk
|
|
21
|
+
|
|
22
|
+
# pnpm
|
|
23
|
+
pnpm add @billingos/sdk
|
|
24
|
+
|
|
25
|
+
# yarn
|
|
26
|
+
yarn add @billingos/sdk
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
### 1. Wrap your app with BillingOSProvider
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
// app/layout.tsx (Next.js App Router)
|
|
35
|
+
import { BillingOSProvider } from '@billingos/sdk'
|
|
36
|
+
import '@billingos/sdk/styles.css'
|
|
37
|
+
|
|
38
|
+
export default function RootLayout({ children }) {
|
|
39
|
+
return (
|
|
40
|
+
<html lang="en">
|
|
41
|
+
<body>
|
|
42
|
+
<BillingOSProvider
|
|
43
|
+
apiKey={process.env.NEXT_PUBLIC_BILLINGOS_API_KEY}
|
|
44
|
+
customerId="cus_123" // Optional: current user's customer ID
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
</BillingOSProvider>
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 2. Use hooks in your components
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
'use client' // Next.js App Router
|
|
58
|
+
|
|
59
|
+
import { useSubscriptions, useHasFeature } from '@billingos/sdk'
|
|
60
|
+
|
|
61
|
+
export default function SubscriptionsPage() {
|
|
62
|
+
const { data: subscriptions, isLoading } = useSubscriptions({
|
|
63
|
+
customer_id: 'cus_123'
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
const hasAdvancedAnalytics = useHasFeature('cus_123', 'advanced_analytics')
|
|
67
|
+
|
|
68
|
+
if (isLoading) return <div>Loading...</div>
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div>
|
|
72
|
+
<h1>Your Subscriptions</h1>
|
|
73
|
+
{subscriptions?.data.map(subscription => (
|
|
74
|
+
<SubscriptionCard key={subscription.id} subscription={subscription} />
|
|
75
|
+
))}
|
|
76
|
+
|
|
77
|
+
{hasAdvancedAnalytics && (
|
|
78
|
+
<AdvancedAnalyticsDashboard />
|
|
79
|
+
)}
|
|
80
|
+
</div>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API Reference
|
|
86
|
+
|
|
87
|
+
### BillingOSProvider
|
|
88
|
+
|
|
89
|
+
The root provider component that wraps your app.
|
|
90
|
+
|
|
91
|
+
**Props:**
|
|
92
|
+
- `apiKey` (string, required) - Your BillingOS API key
|
|
93
|
+
- `customerId` (string, optional) - Current user's customer ID
|
|
94
|
+
- `organizationId` (string, optional) - Current organization ID
|
|
95
|
+
- `options` (object, optional) - Client configuration options
|
|
96
|
+
- `baseUrl` (string) - Custom API base URL
|
|
97
|
+
- `environment` ('production' | 'sandbox') - Environment
|
|
98
|
+
- `version` (string) - API version
|
|
99
|
+
- `headers` (object) - Additional headers
|
|
100
|
+
- `timeout` (number) - Request timeout in milliseconds
|
|
101
|
+
|
|
102
|
+
### Subscription Hooks
|
|
103
|
+
|
|
104
|
+
#### `useSubscription(id, options?)`
|
|
105
|
+
|
|
106
|
+
Fetch a single subscription by ID.
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
const { data: subscription, isLoading, error } = useSubscription('sub_123')
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### `useSubscriptions(params?, options?)`
|
|
113
|
+
|
|
114
|
+
List all subscriptions with pagination.
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
const { data, isLoading } = useSubscriptions({
|
|
118
|
+
customer_id: 'cus_123',
|
|
119
|
+
page: 1,
|
|
120
|
+
page_size: 10
|
|
121
|
+
})
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### `useCreateSubscription(options?)`
|
|
125
|
+
|
|
126
|
+
Create a new subscription.
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
const createSubscription = useCreateSubscription()
|
|
130
|
+
|
|
131
|
+
const handleSubscribe = () => {
|
|
132
|
+
createSubscription.mutate({
|
|
133
|
+
customer_id: 'cus_123',
|
|
134
|
+
price_id: 'price_pro_plan',
|
|
135
|
+
trial_days: 14
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### `useUpdateSubscription(subscriptionId, options?)`
|
|
141
|
+
|
|
142
|
+
Update an existing subscription (upgrade/downgrade).
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
const updateSubscription = useUpdateSubscription('sub_123')
|
|
146
|
+
|
|
147
|
+
const handleUpgrade = () => {
|
|
148
|
+
updateSubscription.mutate({
|
|
149
|
+
price_id: 'price_enterprise_plan'
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### `useCancelSubscription(subscriptionId, options?)`
|
|
155
|
+
|
|
156
|
+
Cancel a subscription.
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
const cancelSubscription = useCancelSubscription('sub_123')
|
|
160
|
+
|
|
161
|
+
const handleCancel = () => {
|
|
162
|
+
cancelSubscription.mutate({ immediately: false }) // Cancel at period end
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
#### `useReactivateSubscription(subscriptionId, options?)`
|
|
167
|
+
|
|
168
|
+
Reactivate a canceled subscription.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
const reactivateSubscription = useReactivateSubscription('sub_123')
|
|
172
|
+
|
|
173
|
+
const handleReactivate = () => {
|
|
174
|
+
reactivateSubscription.mutate()
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### `useSubscriptionPreview(subscriptionId, input, options?)`
|
|
179
|
+
|
|
180
|
+
Preview subscription changes before applying.
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
const { data: preview } = useSubscriptionPreview('sub_123', {
|
|
184
|
+
price_id: 'price_pro_plan'
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
console.log(`Proration: $${preview?.proration_amount / 100}`)
|
|
188
|
+
console.log(`Next invoice: $${preview?.next_invoice_amount / 100}`)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Entitlement Hooks
|
|
192
|
+
|
|
193
|
+
#### `useCheckEntitlement(customerId, featureKey, options?)`
|
|
194
|
+
|
|
195
|
+
Check if a customer has access to a feature.
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
const { data: entitlement } = useCheckEntitlement('cus_123', 'advanced_analytics')
|
|
199
|
+
|
|
200
|
+
if (entitlement?.has_access) {
|
|
201
|
+
// Show premium feature
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
#### `useHasFeature(customerId, featureKey, options?)`
|
|
206
|
+
|
|
207
|
+
Simplified hook that returns a boolean.
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
const hasAccess = useHasFeature('cus_123', 'advanced_analytics')
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### `useEntitlements(customerId, options?)`
|
|
214
|
+
|
|
215
|
+
Get all entitlements for a customer.
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
const { data: entitlements } = useEntitlements('cus_123')
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### `useTrackUsage(options?)`
|
|
222
|
+
|
|
223
|
+
Track usage events.
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
const trackUsage = useTrackUsage()
|
|
227
|
+
|
|
228
|
+
const handleAPICall = async () => {
|
|
229
|
+
await makeAPICall()
|
|
230
|
+
|
|
231
|
+
trackUsage.mutate({
|
|
232
|
+
customer_id: 'cus_123',
|
|
233
|
+
feature_key: 'api_calls',
|
|
234
|
+
quantity: 1
|
|
235
|
+
})
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### `useUsageMetrics(customerId, featureKey, options?)`
|
|
240
|
+
|
|
241
|
+
Get usage metrics for a feature.
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
const { data: metrics } = useUsageMetrics('cus_123', 'api_calls')
|
|
245
|
+
|
|
246
|
+
console.log(`Usage: ${metrics?.current_usage} / ${metrics?.limit}`)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### `useIsApproachingLimit(customerId, featureKey, threshold?, options?)`
|
|
250
|
+
|
|
251
|
+
Check if usage is approaching the limit.
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
const isApproachingLimit = useIsApproachingLimit('cus_123', 'api_calls', 80)
|
|
255
|
+
|
|
256
|
+
if (isApproachingLimit) {
|
|
257
|
+
// Show warning message
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### API Client
|
|
262
|
+
|
|
263
|
+
You can also use the API client directly for custom requests.
|
|
264
|
+
|
|
265
|
+
```tsx
|
|
266
|
+
import { useBillingOS } from '@billingos/sdk'
|
|
267
|
+
|
|
268
|
+
function MyComponent() {
|
|
269
|
+
const { client } = useBillingOS()
|
|
270
|
+
|
|
271
|
+
const handleCustomRequest = async () => {
|
|
272
|
+
const subscription = await client.getSubscription('sub_123')
|
|
273
|
+
const customer = await client.getCustomer('cus_123')
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**Available Methods:**
|
|
279
|
+
- `createCustomer(input)` - Create customer
|
|
280
|
+
- `getCustomer(id)` - Get customer
|
|
281
|
+
- `listCustomers(params)` - List customers
|
|
282
|
+
- `updateCustomer(id, input)` - Update customer
|
|
283
|
+
- `deleteCustomer(id)` - Delete customer
|
|
284
|
+
- `createSubscription(input)` - Create subscription
|
|
285
|
+
- `getSubscription(id)` - Get subscription
|
|
286
|
+
- `listSubscriptions(params)` - List subscriptions
|
|
287
|
+
- `updateSubscription(id, input)` - Update subscription
|
|
288
|
+
- `cancelSubscription(id, immediately)` - Cancel subscription
|
|
289
|
+
- `reactivateSubscription(id)` - Reactivate subscription
|
|
290
|
+
- `previewSubscription(id, input)` - Preview changes
|
|
291
|
+
- `checkEntitlement(input)` - Check feature access
|
|
292
|
+
- `listEntitlements(customerId)` - List entitlements
|
|
293
|
+
- `trackUsage(event)` - Track usage
|
|
294
|
+
- `getUsageMetrics(customerId, featureKey)` - Get metrics
|
|
295
|
+
- `getInvoice(id)` - Get invoice
|
|
296
|
+
- `listInvoices(params)` - List invoices
|
|
297
|
+
- `listPaymentMethods(customerId)` - List payment methods
|
|
298
|
+
- `removePaymentMethod(id)` - Remove payment method
|
|
299
|
+
- `setDefaultPaymentMethod(id)` - Set default payment method
|
|
300
|
+
|
|
301
|
+
### Utilities
|
|
302
|
+
|
|
303
|
+
#### Money Utilities
|
|
304
|
+
|
|
305
|
+
```tsx
|
|
306
|
+
import { Money, formatCurrencyAndAmount, getCentsInDollarString } from '@billingos/sdk'
|
|
307
|
+
|
|
308
|
+
// Format currency with symbol
|
|
309
|
+
Money.format(1050, 'USD') // "$10.50"
|
|
310
|
+
Money.formatCompact(1200000, 'USD') // "$12K"
|
|
311
|
+
Money.formatWhole(1050, 'USD') // "$10"
|
|
312
|
+
|
|
313
|
+
// Convert between cents and dollars
|
|
314
|
+
Money.fromCents(1050) // 10.5
|
|
315
|
+
Money.toCents(10.5) // 1050
|
|
316
|
+
|
|
317
|
+
// Get currency symbol
|
|
318
|
+
Money.getSymbol('USD') // "$"
|
|
319
|
+
Money.getSymbol('EUR') // "€"
|
|
320
|
+
|
|
321
|
+
// Calculations
|
|
322
|
+
Money.calculatePercentage(10000, 20) // 2000 (20% of $100)
|
|
323
|
+
Money.add(1000, 2000, 3000) // 6000 ($60)
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
#### Date Utilities
|
|
327
|
+
|
|
328
|
+
```tsx
|
|
329
|
+
import { DateUtils, formatDate, formatRelativeTime } from '@billingos/sdk'
|
|
330
|
+
|
|
331
|
+
// Format dates
|
|
332
|
+
DateUtils.format('2024-01-15T10:30:00Z', 'PPP') // "January 15th, 2024"
|
|
333
|
+
DateUtils.format(new Date(), 'yyyy-MM-dd') // "2024-01-15"
|
|
334
|
+
|
|
335
|
+
// Relative time
|
|
336
|
+
DateUtils.formatRelative('2024-01-15T08:30:00Z') // "2 hours ago"
|
|
337
|
+
|
|
338
|
+
// Check dates
|
|
339
|
+
DateUtils.isPast('2024-01-01') // true
|
|
340
|
+
DateUtils.isFuture('2025-01-01') // true
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Examples
|
|
344
|
+
|
|
345
|
+
### Complete Subscription Management Page
|
|
346
|
+
|
|
347
|
+
```tsx
|
|
348
|
+
'use client'
|
|
349
|
+
|
|
350
|
+
import {
|
|
351
|
+
useSubscriptions,
|
|
352
|
+
useUpdateSubscription,
|
|
353
|
+
useCancelSubscription,
|
|
354
|
+
useSubscriptionPreview
|
|
355
|
+
} from '@billingos/sdk'
|
|
356
|
+
|
|
357
|
+
export default function SubscriptionsPage() {
|
|
358
|
+
const { data, isLoading } = useSubscriptions({ customer_id: 'cus_123' })
|
|
359
|
+
|
|
360
|
+
if (isLoading) return <div>Loading...</div>
|
|
361
|
+
|
|
362
|
+
return (
|
|
363
|
+
<div>
|
|
364
|
+
<h1>Your Subscriptions</h1>
|
|
365
|
+
{data?.data.map(subscription => (
|
|
366
|
+
<SubscriptionCard key={subscription.id} subscription={subscription} />
|
|
367
|
+
))}
|
|
368
|
+
</div>
|
|
369
|
+
)
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function SubscriptionCard({ subscription }) {
|
|
373
|
+
const updateSubscription = useUpdateSubscription(subscription.id)
|
|
374
|
+
const cancelSubscription = useCancelSubscription(subscription.id)
|
|
375
|
+
const { data: preview } = useSubscriptionPreview(subscription.id, {
|
|
376
|
+
price_id: 'price_pro_plan'
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
const handleUpgrade = () => {
|
|
380
|
+
if (confirm(`Upgrade for $${preview?.proration_amount / 100}?`)) {
|
|
381
|
+
updateSubscription.mutate({ price_id: 'price_pro_plan' })
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const handleCancel = () => {
|
|
386
|
+
if (confirm('Cancel subscription?')) {
|
|
387
|
+
cancelSubscription.mutate({ immediately: false })
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return (
|
|
392
|
+
<div className="border p-4 rounded-lg">
|
|
393
|
+
<h2>Status: {subscription.status}</h2>
|
|
394
|
+
<p>Period: {subscription.current_period_start} - {subscription.current_period_end}</p>
|
|
395
|
+
|
|
396
|
+
<div className="mt-4 flex gap-2">
|
|
397
|
+
<button onClick={handleUpgrade}>Upgrade</button>
|
|
398
|
+
<button onClick={handleCancel}>Cancel</button>
|
|
399
|
+
</div>
|
|
400
|
+
</div>
|
|
401
|
+
)
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Feature Gating
|
|
406
|
+
|
|
407
|
+
```tsx
|
|
408
|
+
'use client'
|
|
409
|
+
|
|
410
|
+
import { useHasFeature } from '@billingos/sdk'
|
|
411
|
+
|
|
412
|
+
export default function DashboardPage() {
|
|
413
|
+
const hasAnalytics = useHasFeature('cus_123', 'advanced_analytics')
|
|
414
|
+
const hasExport = useHasFeature('cus_123', 'data_export')
|
|
415
|
+
|
|
416
|
+
return (
|
|
417
|
+
<div>
|
|
418
|
+
<h1>Dashboard</h1>
|
|
419
|
+
|
|
420
|
+
{hasAnalytics ? (
|
|
421
|
+
<AdvancedAnalytics />
|
|
422
|
+
) : (
|
|
423
|
+
<UpgradePrompt feature="Advanced Analytics" />
|
|
424
|
+
)}
|
|
425
|
+
|
|
426
|
+
{hasExport && <ExportButton />}
|
|
427
|
+
</div>
|
|
428
|
+
)
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Usage Tracking
|
|
433
|
+
|
|
434
|
+
```tsx
|
|
435
|
+
'use client'
|
|
436
|
+
|
|
437
|
+
import { useTrackUsage, useUsageMetrics } from '@billingos/sdk'
|
|
438
|
+
|
|
439
|
+
export default function APICallButton() {
|
|
440
|
+
const trackUsage = useTrackUsage()
|
|
441
|
+
const { data: metrics } = useUsageMetrics('cus_123', 'api_calls')
|
|
442
|
+
|
|
443
|
+
const handleAPICall = async () => {
|
|
444
|
+
try {
|
|
445
|
+
// Make API call
|
|
446
|
+
await fetch('/api/data')
|
|
447
|
+
|
|
448
|
+
// Track usage
|
|
449
|
+
trackUsage.mutate({
|
|
450
|
+
customer_id: 'cus_123',
|
|
451
|
+
feature_key: 'api_calls',
|
|
452
|
+
quantity: 1
|
|
453
|
+
})
|
|
454
|
+
} catch (error) {
|
|
455
|
+
console.error('API call failed:', error)
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return (
|
|
460
|
+
<div>
|
|
461
|
+
<p>Usage: {metrics?.current_usage} / {metrics?.limit} calls</p>
|
|
462
|
+
<button onClick={handleAPICall}>Make API Call</button>
|
|
463
|
+
</div>
|
|
464
|
+
)
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Error Handling
|
|
469
|
+
|
|
470
|
+
The SDK includes typed error classes for better error handling:
|
|
471
|
+
|
|
472
|
+
```tsx
|
|
473
|
+
import {
|
|
474
|
+
isValidationError,
|
|
475
|
+
isUnauthorizedError,
|
|
476
|
+
isNotFoundError
|
|
477
|
+
} from '@billingos/sdk'
|
|
478
|
+
|
|
479
|
+
try {
|
|
480
|
+
await client.getSubscription('sub_123')
|
|
481
|
+
} catch (error) {
|
|
482
|
+
if (isUnauthorizedError(error)) {
|
|
483
|
+
console.error('Invalid API key')
|
|
484
|
+
} else if (isNotFoundError(error)) {
|
|
485
|
+
console.error('Subscription not found')
|
|
486
|
+
} else if (isValidationError(error)) {
|
|
487
|
+
console.error('Validation failed:', error.data)
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
## TypeScript
|
|
493
|
+
|
|
494
|
+
The SDK is built with TypeScript and includes full type definitions.
|
|
495
|
+
|
|
496
|
+
```tsx
|
|
497
|
+
import type {
|
|
498
|
+
Subscription,
|
|
499
|
+
Customer,
|
|
500
|
+
Entitlement,
|
|
501
|
+
CreateSubscriptionInput,
|
|
502
|
+
UpdateSubscriptionInput
|
|
503
|
+
} from '@billingos/sdk'
|
|
504
|
+
|
|
505
|
+
const subscription: Subscription = {
|
|
506
|
+
id: 'sub_123',
|
|
507
|
+
customer_id: 'cus_123',
|
|
508
|
+
price_id: 'price_pro',
|
|
509
|
+
status: 'active',
|
|
510
|
+
// ... other fields
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## Next.js Integration
|
|
515
|
+
|
|
516
|
+
### App Router
|
|
517
|
+
|
|
518
|
+
```tsx
|
|
519
|
+
// app/layout.tsx
|
|
520
|
+
import { BillingOSProvider } from '@billingos/sdk'
|
|
521
|
+
import '@billingos/sdk/styles.css'
|
|
522
|
+
|
|
523
|
+
export default function RootLayout({ children }) {
|
|
524
|
+
return (
|
|
525
|
+
<html>
|
|
526
|
+
<body>
|
|
527
|
+
<BillingOSProvider apiKey={process.env.NEXT_PUBLIC_BILLINGOS_API_KEY}>
|
|
528
|
+
{children}
|
|
529
|
+
</BillingOSProvider>
|
|
530
|
+
</body>
|
|
531
|
+
</html>
|
|
532
|
+
)
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// app/subscriptions/page.tsx
|
|
536
|
+
'use client'
|
|
537
|
+
|
|
538
|
+
import { useSubscriptions } from '@billingos/sdk'
|
|
539
|
+
|
|
540
|
+
export default function SubscriptionsPage() {
|
|
541
|
+
const { data } = useSubscriptions()
|
|
542
|
+
return <div>{/* ... */}</div>
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### Pages Router
|
|
547
|
+
|
|
548
|
+
```tsx
|
|
549
|
+
// pages/_app.tsx
|
|
550
|
+
import { BillingOSProvider } from '@billingos/sdk'
|
|
551
|
+
import '@billingos/sdk/styles.css'
|
|
552
|
+
|
|
553
|
+
export default function App({ Component, pageProps }) {
|
|
554
|
+
return (
|
|
555
|
+
<BillingOSProvider apiKey={process.env.NEXT_PUBLIC_BILLINGOS_API_KEY}>
|
|
556
|
+
<Component {...pageProps} />
|
|
557
|
+
</BillingOSProvider>
|
|
558
|
+
)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// pages/subscriptions.tsx
|
|
562
|
+
import { useSubscriptions } from '@billingos/sdk'
|
|
563
|
+
|
|
564
|
+
export default function SubscriptionsPage() {
|
|
565
|
+
const { data } = useSubscriptions()
|
|
566
|
+
return <div>{/* ... */}</div>
|
|
567
|
+
}
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
## Contributing
|
|
571
|
+
|
|
572
|
+
We welcome contributions! Please see our contributing guidelines for more information.
|
|
573
|
+
|
|
574
|
+
## License
|
|
575
|
+
|
|
576
|
+
MIT
|
|
577
|
+
|
|
578
|
+
## Support
|
|
579
|
+
|
|
580
|
+
- Documentation: https://docs.billingos.com
|
|
581
|
+
- Issues: https://github.com/billingos/sdk/issues
|
|
582
|
+
- Email: support@billingos.com
|