@chatarmin/os 0.1.10 → 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 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
- /** API key generated in the OS admin for your product */
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
- /** Base URL of the OS API (default: https://os.chatarmin.com/api/v1) */
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({ apiKey: process.env.OS_API_KEY! })
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
- * // Resolve company by your org ID
20
- * const company = await os.companies.getByProductLink({ externalOrgId: 'org_123' })
242
+ * console.log(result.companyId) // Use this for all future API calls
243
+ * ```
21
244
  *
22
- * // Track usage
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
- * Get company by their external org ID in your product
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
- * @experimental
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
- * Returns detailed access info including usage and limits
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
- * Useful for showing a company's full feature set
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 usage tracking
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
- * Returns updated usage info after tracking
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
- * Link operations - manually link external IDs to companies
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
- * Simple link: associate external org ID with an existing company
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 operations
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
- * // Create subscription from a tier template
214
- * const sub = await os.subscriptions.create("free", {
215
- * companyId: "comp_xxx",
216
- * })
750
+ * // List available tiers
751
+ * const tiers = await os.subscriptions.tiers()
217
752
  *
218
- * // Create with overrides
219
- * const sub = await os.subscriptions.create("pro", {
220
- * companyId: "comp_xxx",
753
+ * // Apply a tier to a company
754
+ * const result = await os.subscriptions.create('pro', {
755
+ * companyId: company.id,
221
756
  * features: {
222
- * ai_agent: { included_quantity: 200 }
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
- * Create or apply a subscription tier to a company
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
- * @param tierCode - The tier code (e.g., "free", "pro", "enterprise")
235
- * @param options - Subscription options including companyId and optional overrides
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 the current product
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 tier details by code
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 (alias for subscriptions.tiers for convenience)
888
+ * Tier operations (convenient access to subscription tiers).
286
889
  *
287
- * @example
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
- * // Get tier details
290
- * const freeTier = await os.tiers.get("free")
291
- * console.log(freeTier.features)
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 details by code
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;