@chatarmin/os 0.1.1 → 0.1.115
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.ts +904 -123
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +731 -58
- package/package.json +1 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,47 +1,322 @@
|
|
|
1
1
|
import type { AppRouter } from "@chatarmin/api";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for the ChatarminOS SDK client.
|
|
4
|
+
*/
|
|
2
5
|
export interface ChatarminOSConfig {
|
|
3
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* API key generated in the OS admin for your product.
|
|
8
|
+
* Found in Settings → Developers → API Keys.
|
|
9
|
+
* @example "os_sk_xxxxxxxxxxxxxxxxxxxx"
|
|
10
|
+
*/
|
|
4
11
|
apiKey: string;
|
|
5
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Base URL of the OS API.
|
|
14
|
+
* @default "https://os.chatarmin.com/api/v1"
|
|
15
|
+
*/
|
|
6
16
|
baseUrl?: string;
|
|
7
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Input for creating a new company with product link.
|
|
20
|
+
*/
|
|
21
|
+
export interface CreateCompanyInput {
|
|
22
|
+
/** Company name (e.g., "Acme Inc") */
|
|
23
|
+
name: string;
|
|
24
|
+
/** Company domain for matching (e.g., "acme.com") */
|
|
25
|
+
domain?: string;
|
|
26
|
+
/** Your product's unique organization ID for this company */
|
|
27
|
+
externalOrgId: string;
|
|
28
|
+
/** Optional user ID who created this in your product */
|
|
29
|
+
externalUserId?: string;
|
|
30
|
+
/** Primary contact email */
|
|
31
|
+
contactEmail?: string;
|
|
32
|
+
/** Primary contact name */
|
|
33
|
+
contactName?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Input for smart linking a company.
|
|
37
|
+
*/
|
|
38
|
+
export interface SmartLinkInput {
|
|
39
|
+
/** Your product's unique organization ID for this company */
|
|
40
|
+
externalOrgId: string;
|
|
41
|
+
/** Hints to help match existing companies */
|
|
42
|
+
hints: {
|
|
43
|
+
/** Company name to match against */
|
|
44
|
+
companyName?: string;
|
|
45
|
+
/** Domain to match (highest confidence) */
|
|
46
|
+
domain?: string;
|
|
47
|
+
/** Email addresses to match by domain */
|
|
48
|
+
emails?: string[];
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Minimum confidence score (0-1) required for auto-linking.
|
|
52
|
+
* @default 0.6
|
|
53
|
+
*/
|
|
54
|
+
minConfidence?: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Result from smart link operation.
|
|
58
|
+
*/
|
|
59
|
+
export interface SmartLinkResult {
|
|
60
|
+
/** Status of the link operation */
|
|
61
|
+
status: "already_linked" | "linked" | "no_match" | "suggestions";
|
|
62
|
+
/** Company ID if linked */
|
|
63
|
+
customerId?: string;
|
|
64
|
+
/** Company name if linked */
|
|
65
|
+
customerName?: string;
|
|
66
|
+
/** Confidence score of the match */
|
|
67
|
+
confidence?: number;
|
|
68
|
+
/** Reason for the match (e.g., "domain_match", "name_match") */
|
|
69
|
+
reason?: string;
|
|
70
|
+
/** Suggestions if no auto-link (when status is "suggestions") */
|
|
71
|
+
suggestions?: Array<{
|
|
72
|
+
customerId: string;
|
|
73
|
+
customerName: string;
|
|
74
|
+
confidence: number;
|
|
75
|
+
reason: string;
|
|
76
|
+
}>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Input for checking feature access.
|
|
80
|
+
*/
|
|
81
|
+
export interface FeatureCheckInput {
|
|
82
|
+
/** Company ID to check */
|
|
83
|
+
companyId: string;
|
|
84
|
+
/** Feature code (e.g., "ai_credit", "whatsapp_messages") */
|
|
85
|
+
featureCode: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Input for tracking feature usage.
|
|
89
|
+
*/
|
|
90
|
+
export interface TrackUsageInput {
|
|
91
|
+
/** Company ID */
|
|
92
|
+
companyId: string;
|
|
93
|
+
/** Feature code to track */
|
|
94
|
+
featureCode: string;
|
|
95
|
+
/**
|
|
96
|
+
* Quantity to track.
|
|
97
|
+
* @default 1
|
|
98
|
+
*/
|
|
99
|
+
quantity?: number;
|
|
100
|
+
/**
|
|
101
|
+
* Idempotency key to prevent duplicate tracking.
|
|
102
|
+
* Use a unique ID per operation (e.g., message ID).
|
|
103
|
+
*/
|
|
104
|
+
idempotencyKey?: string;
|
|
105
|
+
/** Additional metadata for the usage event */
|
|
106
|
+
metadata?: Record<string, unknown>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Input for claiming a Stripe checkout subscription.
|
|
110
|
+
*/
|
|
111
|
+
export interface ClaimCheckoutInput {
|
|
112
|
+
/** Company ID to link the subscription to */
|
|
113
|
+
companyId: string;
|
|
114
|
+
/** Stripe checkout session ID (cs_xxx) */
|
|
115
|
+
checkoutSessionId: string;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Input for linking an existing Stripe subscription.
|
|
119
|
+
*/
|
|
120
|
+
export interface LinkSubscriptionInput {
|
|
121
|
+
/** Company ID to link the subscription to */
|
|
122
|
+
companyId: string;
|
|
123
|
+
/** Stripe subscription ID (sub_xxx) */
|
|
124
|
+
stripeSubscriptionId: string;
|
|
125
|
+
/** Stripe customer ID (cus_xxx) - fetched from subscription if not provided */
|
|
126
|
+
stripeCustomerId?: string;
|
|
127
|
+
/** Tier code to apply features from (e.g., "free", "pro") */
|
|
128
|
+
tierCode?: string;
|
|
129
|
+
/** Display name for the subscription */
|
|
130
|
+
displayName?: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Input for applying a tier to a company.
|
|
134
|
+
*/
|
|
135
|
+
export interface ApplyTierInput {
|
|
136
|
+
/** Company ID to apply the tier to */
|
|
137
|
+
companyId: string;
|
|
138
|
+
/** Feature overrides (key: feature code, value: config overrides) */
|
|
139
|
+
features?: Record<string, Record<string, unknown>>;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Input for the unified onboarding flow.
|
|
143
|
+
*/
|
|
144
|
+
export interface OnboardInput {
|
|
145
|
+
/** Your product's unique organization ID for this customer */
|
|
146
|
+
externalOrgId: string;
|
|
147
|
+
/**
|
|
148
|
+
* Hints for smart company matching.
|
|
149
|
+
* Provide as much info as possible for best matching.
|
|
150
|
+
*/
|
|
151
|
+
hints?: {
|
|
152
|
+
/** Company name to match against */
|
|
153
|
+
companyName?: string;
|
|
154
|
+
/** Domain to match (highest confidence) */
|
|
155
|
+
domain?: string;
|
|
156
|
+
/** Email addresses to match by domain */
|
|
157
|
+
emails?: string[];
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Stripe checkout session ID to claim.
|
|
161
|
+
* Use when user completed Stripe checkout in your product.
|
|
162
|
+
* @example "cs_test_xxxxxxxxxxxxx"
|
|
163
|
+
*/
|
|
164
|
+
checkoutSessionId?: string;
|
|
165
|
+
/**
|
|
166
|
+
* Existing Stripe subscription ID to link.
|
|
167
|
+
* Use when you create subscriptions on your product's Stripe account.
|
|
168
|
+
* @example "sub_xxxxxxxxxxxxx"
|
|
169
|
+
*/
|
|
170
|
+
stripeSubscriptionId?: string;
|
|
171
|
+
/**
|
|
172
|
+
* Stripe customer ID.
|
|
173
|
+
* Will be fetched from subscription if not provided.
|
|
174
|
+
* @example "cus_xxxxxxxxxxxxx"
|
|
175
|
+
*/
|
|
176
|
+
stripeCustomerId?: string;
|
|
177
|
+
/**
|
|
178
|
+
* Tier code to apply features from.
|
|
179
|
+
* Use for free tier signups or to tag linked subscriptions.
|
|
180
|
+
* @example "free" | "pro" | "enterprise"
|
|
181
|
+
*/
|
|
182
|
+
tierCode?: string;
|
|
183
|
+
/** Primary contact email for new companies */
|
|
184
|
+
contactEmail?: string;
|
|
185
|
+
/** Primary contact name for new companies */
|
|
186
|
+
contactName?: string;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Result from the onboarding flow.
|
|
190
|
+
*/
|
|
191
|
+
export interface OnboardResult {
|
|
192
|
+
/** The company ID (either existing or newly created) */
|
|
193
|
+
companyId: string;
|
|
194
|
+
/** The company name */
|
|
195
|
+
companyName: string;
|
|
196
|
+
/**
|
|
197
|
+
* How the company was linked:
|
|
198
|
+
* - `already_linked`: Company was already linked to your product
|
|
199
|
+
* - `linked`: Existing company was found and linked
|
|
200
|
+
* - `created`: New company was created
|
|
201
|
+
*/
|
|
202
|
+
linkStatus: "already_linked" | "linked" | "created";
|
|
203
|
+
/** Billing status (only present if billing was configured) */
|
|
204
|
+
billingStatus?: {
|
|
205
|
+
/** Subscription ID if created/claimed */
|
|
206
|
+
subscriptionId?: string;
|
|
207
|
+
/** True if subscription was claimed from checkout */
|
|
208
|
+
claimed?: boolean;
|
|
209
|
+
/** True if subscription was linked */
|
|
210
|
+
linked?: boolean;
|
|
211
|
+
/** True if tier features were applied */
|
|
212
|
+
tierApplied?: boolean;
|
|
213
|
+
};
|
|
214
|
+
}
|
|
8
215
|
/**
|
|
9
216
|
* ChatarminOS SDK Client
|
|
10
217
|
*
|
|
11
|
-
* Type-safe client for interacting with ChatarminOS from your product.
|
|
218
|
+
* Type-safe client for interacting with ChatarminOS from your B2B SaaS product.
|
|
219
|
+
* Use this SDK to manage companies, track feature usage, and handle billing.
|
|
12
220
|
*
|
|
13
|
-
* @example
|
|
221
|
+
* @example Basic Setup
|
|
14
222
|
* ```typescript
|
|
15
223
|
* import { ChatarminOS } from '@chatarmin/os-sdk'
|
|
16
224
|
*
|
|
17
|
-
* const os = new ChatarminOS({
|
|
225
|
+
* const os = new ChatarminOS({
|
|
226
|
+
* apiKey: process.env.OS_API_KEY!
|
|
227
|
+
* })
|
|
228
|
+
* ```
|
|
229
|
+
*
|
|
230
|
+
* @example Complete Onboarding Flow
|
|
231
|
+
* ```typescript
|
|
232
|
+
* // When a new user signs up in your product:
|
|
233
|
+
* const result = await os.onboard({
|
|
234
|
+
* externalOrgId: 'org_abc123',
|
|
235
|
+
* hints: {
|
|
236
|
+
* companyName: 'Acme Inc',
|
|
237
|
+
* domain: 'acme.com'
|
|
238
|
+
* },
|
|
239
|
+
* tierCode: 'free' // Apply free tier features
|
|
240
|
+
* })
|
|
18
241
|
*
|
|
19
|
-
* //
|
|
20
|
-
*
|
|
242
|
+
* console.log(result.companyId) // Use this for all future API calls
|
|
243
|
+
* ```
|
|
21
244
|
*
|
|
22
|
-
*
|
|
245
|
+
* @example Track Usage
|
|
246
|
+
* ```typescript
|
|
23
247
|
* await os.billing.trackUsage({
|
|
24
248
|
* companyId: company.id,
|
|
25
249
|
* featureCode: 'ai_credit',
|
|
26
250
|
* quantity: 1
|
|
27
251
|
* })
|
|
28
|
-
*
|
|
29
|
-
* // Check feature access
|
|
30
|
-
* const access = await os.features.check({
|
|
31
|
-
* companyId: company.id,
|
|
32
|
-
* featureCode: 'whatsapp_messages'
|
|
33
|
-
* })
|
|
34
252
|
* ```
|
|
253
|
+
*
|
|
254
|
+
* @see https://os.chatarmin.com/docs for full documentation
|
|
35
255
|
*/
|
|
36
256
|
export declare class ChatarminOS {
|
|
37
257
|
private client;
|
|
258
|
+
/**
|
|
259
|
+
* Create a new ChatarminOS SDK client.
|
|
260
|
+
*
|
|
261
|
+
* @param config - Configuration options
|
|
262
|
+
* @param config.apiKey - Your product's API key from OS admin
|
|
263
|
+
* @param config.baseUrl - Custom API base URL (optional)
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* ```typescript
|
|
267
|
+
* const os = new ChatarminOS({
|
|
268
|
+
* apiKey: process.env.OS_API_KEY!,
|
|
269
|
+
* // Optional: custom base URL for development
|
|
270
|
+
* baseUrl: 'http://localhost:3001/api/v1'
|
|
271
|
+
* })
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
38
274
|
constructor(config: ChatarminOSConfig);
|
|
39
275
|
/**
|
|
40
|
-
* Company operations
|
|
276
|
+
* Company management operations.
|
|
277
|
+
*
|
|
278
|
+
* Companies represent your customers in ChatarminOS. Each company can be
|
|
279
|
+
* linked to your product via an external organization ID.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```typescript
|
|
283
|
+
* // Look up a company by your org ID
|
|
284
|
+
* const company = await os.companies.getByProductLink({
|
|
285
|
+
* externalOrgId: 'org_abc123'
|
|
286
|
+
* })
|
|
287
|
+
*
|
|
288
|
+
* // Create a new company
|
|
289
|
+
* const newCompany = await os.companies.create({
|
|
290
|
+
* name: 'Acme Inc',
|
|
291
|
+
* domain: 'acme.com',
|
|
292
|
+
* externalOrgId: 'org_abc123',
|
|
293
|
+
* contactEmail: 'admin@acme.com'
|
|
294
|
+
* })
|
|
295
|
+
* ```
|
|
41
296
|
*/
|
|
42
297
|
get companies(): {
|
|
43
298
|
/**
|
|
44
|
-
*
|
|
299
|
+
* Look up a company by their external organization ID in your product.
|
|
300
|
+
*
|
|
301
|
+
* Use this to resolve your product's org ID to a ChatarminOS company.
|
|
302
|
+
* Returns `null` if no company is linked with this external ID.
|
|
303
|
+
*
|
|
304
|
+
* @param input - The lookup parameters
|
|
305
|
+
* @param input.externalOrgId - Your product's organization ID
|
|
306
|
+
* @returns The company if found, or `null`
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```typescript
|
|
310
|
+
* const company = await os.companies.getByProductLink({
|
|
311
|
+
* externalOrgId: 'org_abc123'
|
|
312
|
+
* })
|
|
313
|
+
*
|
|
314
|
+
* if (company) {
|
|
315
|
+
* console.log(`Found: ${company.name}`)
|
|
316
|
+
* } else {
|
|
317
|
+
* console.log('Company not linked yet')
|
|
318
|
+
* }
|
|
319
|
+
* ```
|
|
45
320
|
*/
|
|
46
321
|
getByProductLink: (input: {
|
|
47
322
|
externalOrgId: string;
|
|
@@ -53,81 +328,125 @@ export declare class ChatarminOS {
|
|
|
53
328
|
external_user_id: string | null;
|
|
54
329
|
} | null>;
|
|
55
330
|
/**
|
|
56
|
-
* Create a new company and link to your product
|
|
331
|
+
* Create a new company and link it to your product.
|
|
332
|
+
*
|
|
333
|
+
* This creates a company in ChatarminOS and automatically links it
|
|
334
|
+
* to your product using the provided external organization ID.
|
|
335
|
+
*
|
|
336
|
+
* @param input - Company creation parameters
|
|
337
|
+
* @returns The created company with ID and short ID
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* ```typescript
|
|
341
|
+
* const company = await os.companies.create({
|
|
342
|
+
* name: 'Acme Inc',
|
|
343
|
+
* domain: 'acme.com',
|
|
344
|
+
* externalOrgId: 'org_abc123',
|
|
345
|
+
* contactEmail: 'admin@acme.com',
|
|
346
|
+
* contactName: 'John Doe'
|
|
347
|
+
* })
|
|
348
|
+
*
|
|
349
|
+
* console.log(company.id) // UUID
|
|
350
|
+
* console.log(company.shortId) // e.g., "acme-inc"
|
|
351
|
+
* ```
|
|
57
352
|
*/
|
|
58
|
-
create: (input: {
|
|
59
|
-
name: string;
|
|
60
|
-
domain?: string;
|
|
61
|
-
externalOrgId: string;
|
|
62
|
-
externalUserId?: string;
|
|
63
|
-
contactEmail?: string;
|
|
64
|
-
contactName?: string;
|
|
65
|
-
}) => Promise<{
|
|
353
|
+
create: (input: CreateCompanyInput) => Promise<{
|
|
66
354
|
id: string;
|
|
67
355
|
shortId: string | null;
|
|
68
356
|
name: string;
|
|
69
357
|
externalOrgId: string;
|
|
70
358
|
}>;
|
|
71
359
|
/**
|
|
72
|
-
* Smart link - find and link company using hints
|
|
360
|
+
* Smart link - intelligently find and link a company using hints.
|
|
73
361
|
*
|
|
74
|
-
*
|
|
362
|
+
* This method attempts to find an existing company in ChatarminOS
|
|
363
|
+
* that matches the provided hints (domain, name, emails). If found
|
|
364
|
+
* with sufficient confidence, it automatically creates a link.
|
|
365
|
+
*
|
|
366
|
+
* **Matching priority:**
|
|
367
|
+
* 1. Domain match (95% confidence)
|
|
368
|
+
* 2. Name match (up to 80% confidence)
|
|
369
|
+
* 3. Email domain match (70% confidence)
|
|
370
|
+
*
|
|
371
|
+
* @param input - Smart link parameters
|
|
372
|
+
* @returns Result with status and company info if linked
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* ```typescript
|
|
376
|
+
* const result = await os.companies.smartLink({
|
|
377
|
+
* externalOrgId: 'org_abc123',
|
|
378
|
+
* hints: {
|
|
379
|
+
* companyName: 'Acme Inc',
|
|
380
|
+
* domain: 'acme.com',
|
|
381
|
+
* emails: ['john@acme.com']
|
|
382
|
+
* },
|
|
383
|
+
* minConfidence: 0.7
|
|
384
|
+
* })
|
|
385
|
+
*
|
|
386
|
+
* if (result.status === 'linked') {
|
|
387
|
+
* console.log(`Linked to ${result.customerName}`)
|
|
388
|
+
* } else if (result.status === 'suggestions') {
|
|
389
|
+
* console.log('Possible matches:', result.suggestions)
|
|
390
|
+
* }
|
|
391
|
+
* ```
|
|
392
|
+
*
|
|
393
|
+
* @experimental This API may change in future versions
|
|
75
394
|
*/
|
|
76
|
-
smartLink: (input:
|
|
77
|
-
externalOrgId: string;
|
|
78
|
-
hints: {
|
|
79
|
-
companyName?: string;
|
|
80
|
-
domain?: string;
|
|
81
|
-
emails?: string[];
|
|
82
|
-
};
|
|
83
|
-
minConfidence?: number;
|
|
84
|
-
}) => Promise<{
|
|
85
|
-
status: "already_linked";
|
|
86
|
-
customerId: string;
|
|
87
|
-
customerName: string | undefined;
|
|
88
|
-
confidence: number;
|
|
89
|
-
suggestions?: undefined;
|
|
90
|
-
reason?: undefined;
|
|
91
|
-
} | {
|
|
92
|
-
status: "no_match";
|
|
93
|
-
suggestions: never[];
|
|
94
|
-
customerId?: undefined;
|
|
95
|
-
customerName?: undefined;
|
|
96
|
-
confidence?: undefined;
|
|
97
|
-
reason?: undefined;
|
|
98
|
-
} | {
|
|
99
|
-
status: "linked";
|
|
100
|
-
customerId: string;
|
|
101
|
-
customerName: string;
|
|
102
|
-
confidence: number;
|
|
103
|
-
reason: string;
|
|
104
|
-
suggestions?: undefined;
|
|
105
|
-
} | {
|
|
106
|
-
status: "suggestions";
|
|
107
|
-
suggestions: {
|
|
108
|
-
customerId: string;
|
|
109
|
-
customerName: string;
|
|
110
|
-
confidence: number;
|
|
111
|
-
reason: string;
|
|
112
|
-
}[];
|
|
113
|
-
customerId?: undefined;
|
|
114
|
-
customerName?: undefined;
|
|
115
|
-
confidence?: undefined;
|
|
116
|
-
reason?: undefined;
|
|
117
|
-
}>;
|
|
395
|
+
smartLink: (input: SmartLinkInput) => Promise<SmartLinkResult>;
|
|
118
396
|
};
|
|
119
397
|
/**
|
|
120
|
-
* Feature access operations
|
|
398
|
+
* Feature access and entitlement operations.
|
|
399
|
+
*
|
|
400
|
+
* Check what features a company has access to and their current usage.
|
|
401
|
+
* Features are defined in ChatarminOS and assigned via subscription tiers.
|
|
402
|
+
*
|
|
403
|
+
* @example
|
|
404
|
+
* ```typescript
|
|
405
|
+
* // Check if company can use a feature
|
|
406
|
+
* const access = await os.features.check({
|
|
407
|
+
* companyId: company.id,
|
|
408
|
+
* featureCode: 'ai_credit'
|
|
409
|
+
* })
|
|
410
|
+
*
|
|
411
|
+
* if (access.canUse) {
|
|
412
|
+
* // Feature is available
|
|
413
|
+
* console.log(`Remaining: ${access.remaining}`)
|
|
414
|
+
* } else {
|
|
415
|
+
* // Feature is disabled or limit reached
|
|
416
|
+
* console.log('Upgrade required')
|
|
417
|
+
* }
|
|
418
|
+
* ```
|
|
121
419
|
*/
|
|
122
420
|
get features(): {
|
|
123
421
|
/**
|
|
124
|
-
* Check if a company has access to a feature
|
|
125
|
-
*
|
|
422
|
+
* Check if a company has access to a specific feature.
|
|
423
|
+
*
|
|
424
|
+
* Returns detailed access information including whether the feature
|
|
425
|
+
* is enabled, current usage, limits, and whether they can use more.
|
|
426
|
+
*
|
|
427
|
+
* @param input - Check parameters
|
|
428
|
+
* @param input.companyId - Company ID to check
|
|
429
|
+
* @param input.featureCode - Feature code (e.g., "ai_credit")
|
|
430
|
+
* @returns Detailed feature access information
|
|
431
|
+
*
|
|
432
|
+
* @example
|
|
433
|
+
* ```typescript
|
|
434
|
+
* const access = await os.features.check({
|
|
435
|
+
* companyId: 'comp_xxx',
|
|
436
|
+
* featureCode: 'ai_credit'
|
|
437
|
+
* })
|
|
438
|
+
*
|
|
439
|
+
* console.log({
|
|
440
|
+
* enabled: access.isEnabled,
|
|
441
|
+
* canUse: access.canUse,
|
|
442
|
+
* usage: access.currentUsage,
|
|
443
|
+
* limit: access.quantityLimit,
|
|
444
|
+
* remaining: access.remaining,
|
|
445
|
+
* included: access.includedQuantity
|
|
446
|
+
* })
|
|
447
|
+
* ```
|
|
126
448
|
*/
|
|
127
|
-
check: (input: {
|
|
128
|
-
companyId: string;
|
|
129
|
-
featureCode: string;
|
|
130
|
-
}) => Promise<{
|
|
449
|
+
check: (input: FeatureCheckInput) => Promise<{
|
|
131
450
|
featureCode: string;
|
|
132
451
|
isEnabled: boolean;
|
|
133
452
|
hasQuantity: boolean;
|
|
@@ -139,8 +458,26 @@ export declare class ChatarminOS {
|
|
|
139
458
|
canUse: boolean;
|
|
140
459
|
}>;
|
|
141
460
|
/**
|
|
142
|
-
* List all features and their access status for a company
|
|
143
|
-
*
|
|
461
|
+
* List all features and their access status for a company.
|
|
462
|
+
*
|
|
463
|
+
* Returns a complete list of features with their current status,
|
|
464
|
+
* useful for displaying a company's full feature set or building
|
|
465
|
+
* a feature comparison view.
|
|
466
|
+
*
|
|
467
|
+
* @param companyId - Company ID to list features for
|
|
468
|
+
* @returns Array of feature access records
|
|
469
|
+
*
|
|
470
|
+
* @example
|
|
471
|
+
* ```typescript
|
|
472
|
+
* const features = await os.features.listAccess(company.id)
|
|
473
|
+
*
|
|
474
|
+
* for (const f of features) {
|
|
475
|
+
* console.log(`${f.featureName}: ${f.isEnabled ? '✓' : '✗'}`)
|
|
476
|
+
* if (f.quantityLimit) {
|
|
477
|
+
* console.log(` Usage: ${f.currentUsage} / ${f.quantityLimit}`)
|
|
478
|
+
* }
|
|
479
|
+
* }
|
|
480
|
+
* ```
|
|
144
481
|
*/
|
|
145
482
|
listAccess: (companyId: string) => Promise<{
|
|
146
483
|
featureCode: string;
|
|
@@ -155,20 +492,71 @@ export declare class ChatarminOS {
|
|
|
155
492
|
}[]>;
|
|
156
493
|
};
|
|
157
494
|
/**
|
|
158
|
-
* Billing and
|
|
495
|
+
* Billing, usage tracking, and subscription management.
|
|
496
|
+
*
|
|
497
|
+
* Track feature usage for billing, claim subscriptions from Stripe checkout,
|
|
498
|
+
* or link existing Stripe subscriptions to companies.
|
|
499
|
+
*
|
|
500
|
+
* @example Track Usage
|
|
501
|
+
* ```typescript
|
|
502
|
+
* await os.billing.trackUsage({
|
|
503
|
+
* companyId: company.id,
|
|
504
|
+
* featureCode: 'ai_credit',
|
|
505
|
+
* quantity: 1,
|
|
506
|
+
* idempotencyKey: `msg_${messageId}` // Prevent double-counting
|
|
507
|
+
* })
|
|
508
|
+
* ```
|
|
509
|
+
*
|
|
510
|
+
* @example Claim Checkout Subscription
|
|
511
|
+
* ```typescript
|
|
512
|
+
* // After Stripe checkout completes
|
|
513
|
+
* const result = await os.billing.claimCheckout({
|
|
514
|
+
* companyId: company.id,
|
|
515
|
+
* checkoutSessionId: 'cs_xxx'
|
|
516
|
+
* })
|
|
517
|
+
* ```
|
|
518
|
+
*
|
|
519
|
+
* @example Link Existing Subscription
|
|
520
|
+
* ```typescript
|
|
521
|
+
* // When you create subscriptions on your Stripe account
|
|
522
|
+
* const result = await os.billing.linkSubscription({
|
|
523
|
+
* companyId: company.id,
|
|
524
|
+
* stripeSubscriptionId: 'sub_xxx',
|
|
525
|
+
* tierCode: 'pro' // Apply tier features
|
|
526
|
+
* })
|
|
527
|
+
* ```
|
|
159
528
|
*/
|
|
160
529
|
get billing(): {
|
|
161
530
|
/**
|
|
162
|
-
* Track usage for a feature
|
|
163
|
-
*
|
|
531
|
+
* Track usage for a metered feature.
|
|
532
|
+
*
|
|
533
|
+
* Increments the usage counter for a feature and returns the
|
|
534
|
+
* updated usage information. Use idempotency keys to prevent
|
|
535
|
+
* duplicate tracking.
|
|
536
|
+
*
|
|
537
|
+
* @param input - Usage tracking parameters
|
|
538
|
+
* @returns Updated usage information
|
|
539
|
+
* @throws {TRPCError} If feature is not enabled or limit exceeded
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* ```typescript
|
|
543
|
+
* const result = await os.billing.trackUsage({
|
|
544
|
+
* companyId: 'comp_xxx',
|
|
545
|
+
* featureCode: 'ai_credit',
|
|
546
|
+
* quantity: 5,
|
|
547
|
+
* idempotencyKey: `request_${requestId}`,
|
|
548
|
+
* metadata: { model: 'gpt-4' }
|
|
549
|
+
* })
|
|
550
|
+
*
|
|
551
|
+
* console.log({
|
|
552
|
+
* currentUsage: result.currentUsage,
|
|
553
|
+
* remaining: result.remaining,
|
|
554
|
+
* billable: result.billableQuantity,
|
|
555
|
+
* isAtLimit: result.isAtLimit
|
|
556
|
+
* })
|
|
557
|
+
* ```
|
|
164
558
|
*/
|
|
165
|
-
trackUsage: (input: {
|
|
166
|
-
companyId: string;
|
|
167
|
-
featureCode: string;
|
|
168
|
-
quantity?: number;
|
|
169
|
-
idempotencyKey?: string;
|
|
170
|
-
metadata?: Record<string, unknown>;
|
|
171
|
-
}) => Promise<{
|
|
559
|
+
trackUsage: (input: TrackUsageInput) => Promise<{
|
|
172
560
|
success: boolean;
|
|
173
561
|
featureCode: string;
|
|
174
562
|
currentUsage: number;
|
|
@@ -179,13 +567,159 @@ export declare class ChatarminOS {
|
|
|
179
567
|
billableQuantity: number;
|
|
180
568
|
meterId: string;
|
|
181
569
|
}>;
|
|
570
|
+
/**
|
|
571
|
+
* Claim a subscription from a completed Stripe Checkout Session.
|
|
572
|
+
*
|
|
573
|
+
* Use this after a user completes Stripe checkout in your product.
|
|
574
|
+
* This links the subscription and customer to the company in OS.
|
|
575
|
+
*
|
|
576
|
+
* @param input - Claim parameters
|
|
577
|
+
* @returns Result with subscription ID and claim status
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* ```typescript
|
|
581
|
+
* // In your Stripe checkout success handler:
|
|
582
|
+
* const result = await os.billing.claimCheckout({
|
|
583
|
+
* companyId: company.id,
|
|
584
|
+
* checkoutSessionId: session.id // From Stripe callback
|
|
585
|
+
* })
|
|
586
|
+
*
|
|
587
|
+
* if (result.alreadyClaimed) {
|
|
588
|
+
* console.log('Subscription was already claimed')
|
|
589
|
+
* } else {
|
|
590
|
+
* console.log(`Claimed subscription: ${result.subscriptionId}`)
|
|
591
|
+
* }
|
|
592
|
+
* ```
|
|
593
|
+
*/
|
|
594
|
+
claimCheckout: (input: ClaimCheckoutInput) => Promise<{
|
|
595
|
+
success: boolean;
|
|
596
|
+
subscriptionId: string;
|
|
597
|
+
alreadyClaimed: boolean;
|
|
598
|
+
status?: undefined;
|
|
599
|
+
} | {
|
|
600
|
+
success: boolean;
|
|
601
|
+
subscriptionId: string;
|
|
602
|
+
alreadyClaimed: boolean;
|
|
603
|
+
status: import("stripe").Stripe.Subscription.Status;
|
|
604
|
+
}>;
|
|
605
|
+
/**
|
|
606
|
+
* Link an existing Stripe subscription to a company.
|
|
607
|
+
*
|
|
608
|
+
* Use this when you create subscriptions on your product's Stripe
|
|
609
|
+
* account and want OS to track them. Optionally applies tier features.
|
|
610
|
+
*
|
|
611
|
+
* @param input - Link parameters
|
|
612
|
+
* @returns Result with subscription ID, link status, and features applied
|
|
613
|
+
*
|
|
614
|
+
* @example
|
|
615
|
+
* ```typescript
|
|
616
|
+
* // After creating subscription on your Stripe account:
|
|
617
|
+
* const result = await os.billing.linkSubscription({
|
|
618
|
+
* companyId: company.id,
|
|
619
|
+
* stripeSubscriptionId: 'sub_xxx',
|
|
620
|
+
* stripeCustomerId: 'cus_xxx', // Optional
|
|
621
|
+
* tierCode: 'pro', // Apply tier features
|
|
622
|
+
* displayName: 'Pro Plan'
|
|
623
|
+
* })
|
|
624
|
+
*
|
|
625
|
+
* console.log({
|
|
626
|
+
* subscriptionId: result.subscriptionId,
|
|
627
|
+
* isNew: !result.alreadyLinked,
|
|
628
|
+
* featuresApplied: result.featuresApplied
|
|
629
|
+
* })
|
|
630
|
+
* ```
|
|
631
|
+
*/
|
|
632
|
+
linkSubscription: (input: LinkSubscriptionInput) => Promise<{
|
|
633
|
+
success: boolean;
|
|
634
|
+
subscriptionId: string;
|
|
635
|
+
alreadyLinked: boolean;
|
|
636
|
+
status?: undefined;
|
|
637
|
+
tierApplied?: undefined;
|
|
638
|
+
featuresApplied?: undefined;
|
|
639
|
+
} | {
|
|
640
|
+
success: boolean;
|
|
641
|
+
subscriptionId: string;
|
|
642
|
+
alreadyLinked: boolean;
|
|
643
|
+
status: import("stripe").Stripe.Subscription.Status;
|
|
644
|
+
tierApplied: boolean;
|
|
645
|
+
featuresApplied: number;
|
|
646
|
+
}>;
|
|
647
|
+
/**
|
|
648
|
+
* Get billing status for a company.
|
|
649
|
+
*
|
|
650
|
+
* Quick check for subscription status, active features, and
|
|
651
|
+
* billing profile information.
|
|
652
|
+
*
|
|
653
|
+
* @param companyId - Company ID to check
|
|
654
|
+
* @returns Billing status overview
|
|
655
|
+
*
|
|
656
|
+
* @example
|
|
657
|
+
* ```typescript
|
|
658
|
+
* const status = await os.billing.getStatus(company.id)
|
|
659
|
+
*
|
|
660
|
+
* console.log({
|
|
661
|
+
* hasBilling: status.hasBillingProfile,
|
|
662
|
+
* subscriptions: status.activeSubscriptions.length,
|
|
663
|
+
* features: status.enabledFeaturesCount
|
|
664
|
+
* })
|
|
665
|
+
*
|
|
666
|
+
* // Check active tier
|
|
667
|
+
* if (status.activeSubscriptions[0]?.tier) {
|
|
668
|
+
* console.log(`Current tier: ${status.activeSubscriptions[0].tier.name}`)
|
|
669
|
+
* }
|
|
670
|
+
* ```
|
|
671
|
+
*/
|
|
672
|
+
getStatus: (companyId: string) => Promise<{
|
|
673
|
+
hasBillingProfile: boolean;
|
|
674
|
+
stripeCustomerId: string | null;
|
|
675
|
+
activeSubscriptions: {
|
|
676
|
+
id: string;
|
|
677
|
+
status: string;
|
|
678
|
+
stripeSubscriptionId: string | null;
|
|
679
|
+
currentPeriodEnd: Date | null;
|
|
680
|
+
trialEnd: Date | null;
|
|
681
|
+
tier: {
|
|
682
|
+
code: string;
|
|
683
|
+
name: string | null;
|
|
684
|
+
} | null;
|
|
685
|
+
}[];
|
|
686
|
+
enabledFeaturesCount: number;
|
|
687
|
+
}>;
|
|
182
688
|
};
|
|
183
689
|
/**
|
|
184
|
-
*
|
|
690
|
+
* Manual link operations for associating external IDs with companies.
|
|
691
|
+
*
|
|
692
|
+
* Use these when you need direct control over the linking process,
|
|
693
|
+
* bypassing the smart link algorithm.
|
|
694
|
+
*
|
|
695
|
+
* @example
|
|
696
|
+
* ```typescript
|
|
697
|
+
* // Manually link an external org ID to an existing company
|
|
698
|
+
* await os.links.create({
|
|
699
|
+
* companyId: 'comp_xxx',
|
|
700
|
+
* externalOrgId: 'org_abc123',
|
|
701
|
+
* externalUserId: 'user_xyz'
|
|
702
|
+
* })
|
|
703
|
+
* ```
|
|
185
704
|
*/
|
|
186
705
|
get links(): {
|
|
187
706
|
/**
|
|
188
|
-
*
|
|
707
|
+
* Create a manual link between your external org ID and an existing company.
|
|
708
|
+
*
|
|
709
|
+
* Use this when you know the exact company ID and want to create
|
|
710
|
+
* a direct link without smart matching.
|
|
711
|
+
*
|
|
712
|
+
* @param input - Link parameters
|
|
713
|
+
* @returns The created link record
|
|
714
|
+
*
|
|
715
|
+
* @example
|
|
716
|
+
* ```typescript
|
|
717
|
+
* const link = await os.links.create({
|
|
718
|
+
* companyId: 'comp_xxx',
|
|
719
|
+
* externalOrgId: 'org_abc123',
|
|
720
|
+
* externalUserId: 'user_xyz' // Optional: user who created the link
|
|
721
|
+
* })
|
|
722
|
+
* ```
|
|
189
723
|
*/
|
|
190
724
|
create: (input: {
|
|
191
725
|
companyId: string;
|
|
@@ -206,44 +740,80 @@ export declare class ChatarminOS {
|
|
|
206
740
|
} | undefined>;
|
|
207
741
|
};
|
|
208
742
|
/**
|
|
209
|
-
* Subscription
|
|
743
|
+
* Subscription and tier management.
|
|
744
|
+
*
|
|
745
|
+
* Create subscriptions from tier templates, list available tiers,
|
|
746
|
+
* and manage company entitlements.
|
|
210
747
|
*
|
|
211
748
|
* @example
|
|
212
749
|
* ```typescript
|
|
213
|
-
* //
|
|
214
|
-
* const
|
|
215
|
-
* companyId: "comp_xxx",
|
|
216
|
-
* })
|
|
750
|
+
* // List available tiers
|
|
751
|
+
* const tiers = await os.subscriptions.tiers()
|
|
217
752
|
*
|
|
218
|
-
* //
|
|
219
|
-
* const
|
|
220
|
-
* companyId:
|
|
753
|
+
* // Apply a tier to a company
|
|
754
|
+
* const result = await os.subscriptions.create('pro', {
|
|
755
|
+
* companyId: company.id,
|
|
221
756
|
* features: {
|
|
222
|
-
*
|
|
757
|
+
* ai_credit: { included_quantity: 500 }
|
|
223
758
|
* }
|
|
224
759
|
* })
|
|
225
|
-
*
|
|
226
|
-
* // Get available tiers
|
|
227
|
-
* const tiers = await os.subscriptions.tiers()
|
|
228
760
|
* ```
|
|
229
761
|
*/
|
|
230
762
|
get subscriptions(): {
|
|
231
763
|
/**
|
|
232
|
-
*
|
|
764
|
+
* Apply a subscription tier to a company.
|
|
765
|
+
*
|
|
766
|
+
* This grants the company access to all features defined in the tier.
|
|
767
|
+
* Use feature overrides to customize specific feature limits.
|
|
233
768
|
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
769
|
+
* **Note:** This only applies feature access, it doesn't create a
|
|
770
|
+
* Stripe subscription. Use `billing.linkSubscription` for that.
|
|
771
|
+
*
|
|
772
|
+
* @param tierCode - Tier code (e.g., "free", "pro", "enterprise")
|
|
773
|
+
* @param options - Company ID and optional feature overrides
|
|
774
|
+
* @returns Result with tier info and features applied
|
|
775
|
+
*
|
|
776
|
+
* @example
|
|
777
|
+
* ```typescript
|
|
778
|
+
* // Apply tier with defaults
|
|
779
|
+
* await os.subscriptions.create('free', {
|
|
780
|
+
* companyId: company.id
|
|
781
|
+
* })
|
|
782
|
+
*
|
|
783
|
+
* // Apply with custom limits
|
|
784
|
+
* await os.subscriptions.create('pro', {
|
|
785
|
+
* companyId: company.id,
|
|
786
|
+
* features: {
|
|
787
|
+
* ai_credit: { included_quantity: 1000 },
|
|
788
|
+
* seats: { max_quantity: 50 }
|
|
789
|
+
* }
|
|
790
|
+
* })
|
|
791
|
+
* ```
|
|
236
792
|
*/
|
|
237
|
-
create: (tierCode: string, options: {
|
|
238
|
-
companyId: string;
|
|
239
|
-
features?: Record<string, Record<string, unknown>>;
|
|
240
|
-
}) => Promise<{
|
|
793
|
+
create: (tierCode: string, options: ApplyTierInput) => Promise<{
|
|
241
794
|
tierId: string;
|
|
242
795
|
tierName: string;
|
|
243
796
|
featuresApplied: number;
|
|
244
797
|
}>;
|
|
245
798
|
/**
|
|
246
|
-
* Get all available tiers for
|
|
799
|
+
* Get all available tiers for your product.
|
|
800
|
+
*
|
|
801
|
+
* Returns the list of subscription tiers configured in ChatarminOS
|
|
802
|
+
* for your product, including their features.
|
|
803
|
+
*
|
|
804
|
+
* @returns Array of available tiers with features
|
|
805
|
+
*
|
|
806
|
+
* @example
|
|
807
|
+
* ```typescript
|
|
808
|
+
* const tiers = await os.subscriptions.tiers()
|
|
809
|
+
*
|
|
810
|
+
* for (const tier of tiers) {
|
|
811
|
+
* console.log(`${tier.name} (${tier.code})`)
|
|
812
|
+
* for (const feature of tier.features) {
|
|
813
|
+
* console.log(` - ${feature.name}`)
|
|
814
|
+
* }
|
|
815
|
+
* }
|
|
816
|
+
* ```
|
|
247
817
|
*/
|
|
248
818
|
tiers: () => Promise<{
|
|
249
819
|
features: {
|
|
@@ -265,7 +835,28 @@ export declare class ChatarminOS {
|
|
|
265
835
|
product_id: string;
|
|
266
836
|
}[]>;
|
|
267
837
|
/**
|
|
268
|
-
* Get
|
|
838
|
+
* Get detailed information about a specific tier.
|
|
839
|
+
*
|
|
840
|
+
* Returns the tier with all its features, including Stripe price IDs
|
|
841
|
+
* if configured. Use this to get the prices needed to create a
|
|
842
|
+
* Stripe subscription.
|
|
843
|
+
*
|
|
844
|
+
* @param tierCode - Tier code to look up
|
|
845
|
+
* @returns Tier details with features and Stripe prices
|
|
846
|
+
*
|
|
847
|
+
* @example
|
|
848
|
+
* ```typescript
|
|
849
|
+
* const tier = await os.subscriptions.getTier('pro')
|
|
850
|
+
*
|
|
851
|
+
* console.log(tier.stripePriceIds)
|
|
852
|
+
* // ['price_xxx', 'price_yyy']
|
|
853
|
+
*
|
|
854
|
+
* // Use these to create a Stripe subscription
|
|
855
|
+
* const sub = await stripe.subscriptions.create({
|
|
856
|
+
* customer: customerId,
|
|
857
|
+
* items: tier.stripePriceIds.map(price => ({ price }))
|
|
858
|
+
* })
|
|
859
|
+
* ```
|
|
269
860
|
*/
|
|
270
861
|
getTier: (tierCode: string) => Promise<{
|
|
271
862
|
id: string;
|
|
@@ -278,22 +869,57 @@ export declare class ChatarminOS {
|
|
|
278
869
|
hasQuantity: boolean;
|
|
279
870
|
configValues: unknown;
|
|
280
871
|
catalogPriceId: string | null;
|
|
872
|
+
stripe: {
|
|
873
|
+
priceId: string;
|
|
874
|
+
productId: string | null;
|
|
875
|
+
productName: string | null;
|
|
876
|
+
unitAmount: number | null;
|
|
877
|
+
currency: string | null;
|
|
878
|
+
interval: string | null;
|
|
879
|
+
intervalCount: number | null;
|
|
880
|
+
usageType: string | null;
|
|
881
|
+
billingScheme: string | null;
|
|
882
|
+
} | null;
|
|
281
883
|
}[];
|
|
884
|
+
stripePriceIds: string[];
|
|
282
885
|
}>;
|
|
283
886
|
};
|
|
284
887
|
/**
|
|
285
|
-
* Tier operations (
|
|
888
|
+
* Tier operations (convenient access to subscription tiers).
|
|
286
889
|
*
|
|
287
|
-
*
|
|
890
|
+
* Tiers define what features and limits a company gets. Each tier
|
|
891
|
+
* can have associated Stripe prices for billing.
|
|
892
|
+
*
|
|
893
|
+
* @example Get Tier with Stripe Prices
|
|
288
894
|
* ```typescript
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
895
|
+
* const tier = await os.tiers.get('pro')
|
|
896
|
+
*
|
|
897
|
+
* // Create Stripe subscription using tier prices
|
|
898
|
+
* const stripeSub = await stripe.subscriptions.create({
|
|
899
|
+
* customer: stripeCustomerId,
|
|
900
|
+
* items: tier.stripePriceIds.map(price => ({ price }))
|
|
901
|
+
* })
|
|
902
|
+
*
|
|
903
|
+
* // Link back to OS
|
|
904
|
+
* await os.billing.linkSubscription({
|
|
905
|
+
* companyId: company.id,
|
|
906
|
+
* stripeSubscriptionId: stripeSub.id,
|
|
907
|
+
* tierCode: 'pro'
|
|
908
|
+
* })
|
|
292
909
|
* ```
|
|
293
910
|
*/
|
|
294
911
|
get tiers(): {
|
|
295
912
|
/**
|
|
296
|
-
* List all available tiers
|
|
913
|
+
* List all available tiers for your product.
|
|
914
|
+
*
|
|
915
|
+
* @returns Array of tiers with their features
|
|
916
|
+
*
|
|
917
|
+
* @example
|
|
918
|
+
* ```typescript
|
|
919
|
+
* const tiers = await os.tiers.list()
|
|
920
|
+
* console.log(tiers.map(t => t.name))
|
|
921
|
+
* // ['Free', 'Pro', 'Enterprise']
|
|
922
|
+
* ```
|
|
297
923
|
*/
|
|
298
924
|
list: () => Promise<{
|
|
299
925
|
features: {
|
|
@@ -315,7 +941,36 @@ export declare class ChatarminOS {
|
|
|
315
941
|
product_id: string;
|
|
316
942
|
}[]>;
|
|
317
943
|
/**
|
|
318
|
-
* Get tier
|
|
944
|
+
* Get detailed tier information by code.
|
|
945
|
+
*
|
|
946
|
+
* Returns full tier details including:
|
|
947
|
+
* - Features with config values
|
|
948
|
+
* - Stripe price IDs for subscription creation
|
|
949
|
+
* - Stripe product info
|
|
950
|
+
*
|
|
951
|
+
* @param tierCode - Tier code (e.g., "free", "pro")
|
|
952
|
+
* @returns Tier with features and Stripe prices
|
|
953
|
+
*
|
|
954
|
+
* @example
|
|
955
|
+
* ```typescript
|
|
956
|
+
* const tier = await os.tiers.get('pro')
|
|
957
|
+
*
|
|
958
|
+
* // Access features
|
|
959
|
+
* for (const feature of tier.features) {
|
|
960
|
+
* console.log(feature.code, feature.configValues)
|
|
961
|
+
* }
|
|
962
|
+
*
|
|
963
|
+
* // Get Stripe prices for subscription creation
|
|
964
|
+
* console.log(tier.stripePriceIds)
|
|
965
|
+
* // ['price_xxx', 'price_yyy']
|
|
966
|
+
*
|
|
967
|
+
* // Feature-level Stripe info
|
|
968
|
+
* const aiFeature = tier.features.find(f => f.code === 'ai_credit')
|
|
969
|
+
* if (aiFeature?.stripe) {
|
|
970
|
+
* console.log(aiFeature.stripe.priceId)
|
|
971
|
+
* console.log(aiFeature.stripe.unitAmount) // in cents
|
|
972
|
+
* }
|
|
973
|
+
* ```
|
|
319
974
|
*/
|
|
320
975
|
get: (tierCode: string) => Promise<{
|
|
321
976
|
id: string;
|
|
@@ -328,20 +983,146 @@ export declare class ChatarminOS {
|
|
|
328
983
|
hasQuantity: boolean;
|
|
329
984
|
configValues: unknown;
|
|
330
985
|
catalogPriceId: string | null;
|
|
986
|
+
stripe: {
|
|
987
|
+
priceId: string;
|
|
988
|
+
productId: string | null;
|
|
989
|
+
productName: string | null;
|
|
990
|
+
unitAmount: number | null;
|
|
991
|
+
currency: string | null;
|
|
992
|
+
interval: string | null;
|
|
993
|
+
intervalCount: number | null;
|
|
994
|
+
usageType: string | null;
|
|
995
|
+
billingScheme: string | null;
|
|
996
|
+
} | null;
|
|
331
997
|
}[];
|
|
998
|
+
stripePriceIds: string[];
|
|
332
999
|
}>;
|
|
333
1000
|
/**
|
|
334
|
-
* Apply a tier to a company
|
|
1001
|
+
* Apply a tier's features to a company (without Stripe).
|
|
1002
|
+
*
|
|
1003
|
+
* Use this for:
|
|
1004
|
+
* - Free tiers that don't need Stripe
|
|
1005
|
+
* - Trial periods
|
|
1006
|
+
* - Manual entitlement grants
|
|
1007
|
+
*
|
|
1008
|
+
* For paid tiers with Stripe, use `billing.linkSubscription` instead.
|
|
1009
|
+
*
|
|
1010
|
+
* @param tierCode - Tier code to apply
|
|
1011
|
+
* @param options - Company ID and optional feature overrides
|
|
1012
|
+
* @returns Result with applied features count
|
|
1013
|
+
*
|
|
1014
|
+
* @example
|
|
1015
|
+
* ```typescript
|
|
1016
|
+
* // Apply free tier
|
|
1017
|
+
* const result = await os.tiers.apply('free', {
|
|
1018
|
+
* companyId: company.id
|
|
1019
|
+
* })
|
|
1020
|
+
* console.log(`Applied ${result.featuresApplied} features`)
|
|
1021
|
+
*
|
|
1022
|
+
* // Apply with overrides
|
|
1023
|
+
* await os.tiers.apply('trial', {
|
|
1024
|
+
* companyId: company.id,
|
|
1025
|
+
* features: {
|
|
1026
|
+
* ai_credit: { included_quantity: 100 }
|
|
1027
|
+
* }
|
|
1028
|
+
* })
|
|
1029
|
+
* ```
|
|
335
1030
|
*/
|
|
336
|
-
apply: (tierCode: string, options: {
|
|
337
|
-
companyId: string;
|
|
338
|
-
features?: Record<string, Record<string, unknown>>;
|
|
339
|
-
}) => Promise<{
|
|
1031
|
+
apply: (tierCode: string, options: ApplyTierInput) => Promise<{
|
|
340
1032
|
tierId: string;
|
|
341
1033
|
tierName: string;
|
|
342
1034
|
featuresApplied: number;
|
|
343
1035
|
}>;
|
|
344
1036
|
};
|
|
1037
|
+
/**
|
|
1038
|
+
* Complete onboarding flow in a single call.
|
|
1039
|
+
*
|
|
1040
|
+
* This is the recommended way to onboard new customers. It handles:
|
|
1041
|
+
* 1. Smart company matching/creation
|
|
1042
|
+
* 2. Product linking
|
|
1043
|
+
* 3. Subscription claiming/linking
|
|
1044
|
+
* 4. Tier feature application
|
|
1045
|
+
*
|
|
1046
|
+
* **Scenarios:**
|
|
1047
|
+
*
|
|
1048
|
+
* 1. **Stripe Checkout completed** - Pass `checkoutSessionId`
|
|
1049
|
+
* 2. **Free signup** - Pass `tierCode` only
|
|
1050
|
+
* 3. **You create Stripe subscription** - Pass `stripeSubscriptionId` + `tierCode`
|
|
1051
|
+
*
|
|
1052
|
+
* @param input - Onboarding parameters
|
|
1053
|
+
* @returns Result with company info and billing status
|
|
1054
|
+
*
|
|
1055
|
+
* @example Scenario 1: User completed Stripe checkout
|
|
1056
|
+
* ```typescript
|
|
1057
|
+
* const result = await os.onboard({
|
|
1058
|
+
* externalOrgId: 'org_abc123',
|
|
1059
|
+
* hints: {
|
|
1060
|
+
* companyName: 'Acme Inc',
|
|
1061
|
+
* domain: 'acme.com'
|
|
1062
|
+
* },
|
|
1063
|
+
* checkoutSessionId: 'cs_test_xxx' // From Stripe callback
|
|
1064
|
+
* })
|
|
1065
|
+
*
|
|
1066
|
+
* // result.billingStatus.claimed = true
|
|
1067
|
+
* ```
|
|
1068
|
+
*
|
|
1069
|
+
* @example Scenario 2: Free tier signup
|
|
1070
|
+
* ```typescript
|
|
1071
|
+
* const result = await os.onboard({
|
|
1072
|
+
* externalOrgId: 'org_abc123',
|
|
1073
|
+
* hints: {
|
|
1074
|
+
* companyName: 'Acme Inc',
|
|
1075
|
+
* domain: 'acme.com'
|
|
1076
|
+
* },
|
|
1077
|
+
* tierCode: 'free',
|
|
1078
|
+
* contactEmail: 'admin@acme.com',
|
|
1079
|
+
* contactName: 'John Doe'
|
|
1080
|
+
* })
|
|
1081
|
+
*
|
|
1082
|
+
* // result.billingStatus.tierApplied = true
|
|
1083
|
+
* ```
|
|
1084
|
+
*
|
|
1085
|
+
* @example Scenario 3: You create Stripe subscription
|
|
1086
|
+
* ```typescript
|
|
1087
|
+
* // First, get tier prices
|
|
1088
|
+
* const tier = await os.tiers.get('pro')
|
|
1089
|
+
*
|
|
1090
|
+
* // Create subscription on YOUR Stripe account
|
|
1091
|
+
* const stripeSub = await stripe.subscriptions.create({
|
|
1092
|
+
* customer: stripeCustomerId,
|
|
1093
|
+
* items: tier.stripePriceIds.map(price => ({ price }))
|
|
1094
|
+
* })
|
|
1095
|
+
*
|
|
1096
|
+
* // Then onboard with the subscription
|
|
1097
|
+
* const result = await os.onboard({
|
|
1098
|
+
* externalOrgId: 'org_abc123',
|
|
1099
|
+
* hints: { companyName: 'Acme Inc' },
|
|
1100
|
+
* stripeSubscriptionId: stripeSub.id,
|
|
1101
|
+
* stripeCustomerId: stripeCustomerId,
|
|
1102
|
+
* tierCode: 'pro'
|
|
1103
|
+
* })
|
|
1104
|
+
*
|
|
1105
|
+
* // result.billingStatus.linked = true
|
|
1106
|
+
* // result.billingStatus.tierApplied = true
|
|
1107
|
+
* ```
|
|
1108
|
+
*
|
|
1109
|
+
* @example Handle existing customers
|
|
1110
|
+
* ```typescript
|
|
1111
|
+
* const result = await os.onboard({
|
|
1112
|
+
* externalOrgId: 'org_abc123',
|
|
1113
|
+
* hints: { companyName: 'Acme Inc' }
|
|
1114
|
+
* })
|
|
1115
|
+
*
|
|
1116
|
+
* if (result.linkStatus === 'already_linked') {
|
|
1117
|
+
* console.log('Welcome back!')
|
|
1118
|
+
* } else if (result.linkStatus === 'linked') {
|
|
1119
|
+
* console.log('Found existing company, linked!')
|
|
1120
|
+
* } else {
|
|
1121
|
+
* console.log('New company created!')
|
|
1122
|
+
* }
|
|
1123
|
+
* ```
|
|
1124
|
+
*/
|
|
1125
|
+
onboard(input: OnboardInput): Promise<OnboardResult>;
|
|
345
1126
|
}
|
|
346
1127
|
export type { AppRouter };
|
|
347
1128
|
export default ChatarminOS;
|