@advizorconnect/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/CHANGELOG.md +21 -0
- package/README.md +191 -0
- package/dist/client.d.ts +483 -0
- package/dist/client.js +469 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.js +16 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +3 -0
- package/dist/retry.d.ts +23 -0
- package/dist/retry.js +39 -0
- package/package.json +27 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — 2026-03-02
|
|
4
|
+
|
|
5
|
+
Initial release.
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- **32 typed methods** across 7 API tag groups:
|
|
10
|
+
- Integration (2): list/get group advisors
|
|
11
|
+
- Sessions (13): full call lifecycle from create through end-and-capture
|
|
12
|
+
- Owner / API Keys (4): CRUD + rotation with overlap windows
|
|
13
|
+
- Widget (3): token minting, config, advisor listing
|
|
14
|
+
- Owner / Widget (2): security settings (allowed origins)
|
|
15
|
+
- Owner / Invites (5): create, list, rotate, revoke, send
|
|
16
|
+
- Owner / Groups (4): slug management, settings
|
|
17
|
+
- **`V1SdkError`** with structured fields: `status`, `message`, `code`, `requestId`, `retryable`
|
|
18
|
+
- **AbortController timeout** — 20s default, configurable via `timeoutMs`
|
|
19
|
+
- **Custom fetch injection** — pass your own `fetchImpl` for testing or custom HTTP clients
|
|
20
|
+
- **Generated types** from OpenAPI v1 spec via `openapi-typescript`
|
|
21
|
+
- **Tree-shakeable** ESM package with `sideEffects: false`
|
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# @advizorconnect/sdk
|
|
2
|
+
|
|
3
|
+
Typed TypeScript SDK for the Advizor Connect v1 integration API. Build custom caller experiences on top of the Advizor Connect platform.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @advizorconnect/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { createV1Client } from '@advizorconnect/sdk';
|
|
15
|
+
|
|
16
|
+
const client = createV1Client({
|
|
17
|
+
baseUrl: 'https://api.advizor-connect.com',
|
|
18
|
+
apiKey: 'your-api-key', // from owner dashboard → Settings → API Keys
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// List available advisors
|
|
22
|
+
const { advisors } = await client.listGroupAdvisors({
|
|
23
|
+
groupId: 'your-group-id',
|
|
24
|
+
onlineStatus: 'available',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Create a session with the first available advisor
|
|
28
|
+
const { session } = await client.createSession({
|
|
29
|
+
groupId: 'your-group-id',
|
|
30
|
+
advisorId: advisors[0].id,
|
|
31
|
+
callerPhone: '+15551234567',
|
|
32
|
+
idempotencyKey: crypto.randomUUID(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
console.log('Session created:', session.id, session.status);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Authentication
|
|
39
|
+
|
|
40
|
+
All API calls require a group API key passed as a Bearer token. Create API keys from the owner dashboard under **Settings → API Keys**.
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
const client = createV1Client({
|
|
44
|
+
baseUrl: 'https://api.advizor-connect.com',
|
|
45
|
+
apiKey: process.env.ADVIZOR_CONNECT_API_KEY!,
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Client Options
|
|
50
|
+
|
|
51
|
+
| Option | Type | Default | Description |
|
|
52
|
+
|--------|------|---------|-------------|
|
|
53
|
+
| `baseUrl` | `string` | *required* | API server URL |
|
|
54
|
+
| `apiKey` | `string` | *required* | Group API key (Bearer token) |
|
|
55
|
+
| `fetchImpl` | `typeof fetch` | `globalThis.fetch` | Custom fetch implementation |
|
|
56
|
+
| `timeoutMs` | `number` | `20000` | Request timeout in milliseconds |
|
|
57
|
+
|
|
58
|
+
## API Methods
|
|
59
|
+
|
|
60
|
+
### Integration
|
|
61
|
+
|
|
62
|
+
| Method | Description |
|
|
63
|
+
|--------|-------------|
|
|
64
|
+
| `listGroupAdvisors({ groupId, sort?, order?, onlineStatus?, minBillableMinutes30d? })` | List advisors in a group with optional filters |
|
|
65
|
+
| `getGroupAdvisor({ groupId, advisorId })` | Get a single advisor's details |
|
|
66
|
+
|
|
67
|
+
### Sessions
|
|
68
|
+
|
|
69
|
+
| Method | Description |
|
|
70
|
+
|--------|-------------|
|
|
71
|
+
| `createSession({ groupId, advisorId, callerPhone, idempotencyKey, ... })` | Create a new call session |
|
|
72
|
+
| `getSession({ sessionId })` | Get session details and status |
|
|
73
|
+
| `getSessionLedger({ sessionId })` | Get billing ledger for a session |
|
|
74
|
+
| `sendOtp({ sessionId })` | Send OTP to caller's phone |
|
|
75
|
+
| `verifyPhone({ sessionId, otp })` | Verify caller phone with OTP code |
|
|
76
|
+
| `createStripeIntent({ sessionId, holdCents? })` | Create a Stripe PaymentIntent for hold |
|
|
77
|
+
| `createPayPalOrder({ sessionId, holdCents? })` | Create a PayPal order for hold |
|
|
78
|
+
| `authorizePayPalOrder({ sessionId, orderId })` | Authorize a PayPal order |
|
|
79
|
+
| `authorizeHold({ sessionId, paymentIntentId?, holdCents? })` | Confirm payment hold authorization |
|
|
80
|
+
| `startConnecting({ sessionId })` | Initiate telephony bridge |
|
|
81
|
+
| `markConnected({ sessionId })` | Mark session as connected (call active) |
|
|
82
|
+
| `tick({ sessionId, asOfIso? })` | Record a billing tick (~60s intervals) |
|
|
83
|
+
| `endAndCapture({ sessionId, reason? })` | End the call and capture payment |
|
|
84
|
+
| `submitSessionReview({ sessionId, rating, body?, authorName? })` | Submit a post-call review |
|
|
85
|
+
|
|
86
|
+
### Owner / API Keys
|
|
87
|
+
|
|
88
|
+
| Method | Description |
|
|
89
|
+
|--------|-------------|
|
|
90
|
+
| `listApiKeys({ groupId })` | List all API keys for a group |
|
|
91
|
+
| `createApiKey({ groupId, name, scopes?, expiresAt? })` | Create a new API key |
|
|
92
|
+
| `rotateApiKey({ groupId, keyId, overlapSeconds?, name?, expiresAt? })` | Rotate an API key with overlap window |
|
|
93
|
+
| `revokeApiKey({ groupId, keyId })` | Revoke an API key |
|
|
94
|
+
|
|
95
|
+
### Widget
|
|
96
|
+
|
|
97
|
+
| Method | Description |
|
|
98
|
+
|--------|-------------|
|
|
99
|
+
| `mintWidgetToken({ groupId })` | Mint a short-lived widget auth token |
|
|
100
|
+
| `getWidgetConfig({ groupId })` | Get widget configuration |
|
|
101
|
+
| `listWidgetAdvisors({ groupId })` | List advisors visible in the widget |
|
|
102
|
+
| `getWidgetSecurity({ groupId })` | Get widget security settings |
|
|
103
|
+
| `updateWidgetSecurity({ groupId, allowedOrigins })` | Update allowed origins for widget |
|
|
104
|
+
|
|
105
|
+
### Owner / Invites
|
|
106
|
+
|
|
107
|
+
| Method | Description |
|
|
108
|
+
|--------|-------------|
|
|
109
|
+
| `createInvite({ groupId, email? })` | Create an advisor invite |
|
|
110
|
+
| `listInvites({ groupId, status? })` | List invites for a group |
|
|
111
|
+
| `rotateInvite({ groupId, inviteId })` | Rotate invite token |
|
|
112
|
+
| `revokeInvite({ groupId, inviteId })` | Revoke an invite |
|
|
113
|
+
| `sendInvite({ groupId, inviteId })` | Send invite email |
|
|
114
|
+
|
|
115
|
+
### Owner / Groups
|
|
116
|
+
|
|
117
|
+
| Method | Description |
|
|
118
|
+
|--------|-------------|
|
|
119
|
+
| `getGroupBySlug({ slug })` | Look up a group by its URL slug |
|
|
120
|
+
| `updateGroupSlug({ groupId, slug })` | Change a group's URL slug |
|
|
121
|
+
| `getGroupSettings({ groupId })` | Get group settings |
|
|
122
|
+
| `updateGroupSettings({ groupId, requireCallerOtp? })` | Update group settings |
|
|
123
|
+
|
|
124
|
+
## Error Handling
|
|
125
|
+
|
|
126
|
+
All API errors throw `V1SdkError` with structured fields:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { V1SdkError } from '@advizorconnect/sdk';
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
await client.createSession({ ... });
|
|
133
|
+
} catch (err) {
|
|
134
|
+
if (err instanceof V1SdkError) {
|
|
135
|
+
console.error('Status:', err.status); // HTTP status code
|
|
136
|
+
console.error('Message:', err.message); // Human-readable message
|
|
137
|
+
console.error('Code:', err.code); // Machine-readable error code
|
|
138
|
+
console.error('Request ID:', err.requestId); // For support reference
|
|
139
|
+
console.error('Retryable:', err.retryable); // Whether to retry
|
|
140
|
+
|
|
141
|
+
if (err.retryable) {
|
|
142
|
+
// Safe to retry with backoff
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## TypeScript Types
|
|
149
|
+
|
|
150
|
+
The SDK exports generated types from the OpenAPI spec for full type safety:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import type {
|
|
154
|
+
IntegrationAdvisor,
|
|
155
|
+
SessionEnvelope,
|
|
156
|
+
ApiSession,
|
|
157
|
+
LedgerEvent,
|
|
158
|
+
ApiKeyRecord,
|
|
159
|
+
InviteRecord,
|
|
160
|
+
} from '@advizorconnect/sdk';
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
For advanced usage, raw OpenAPI path/component types are also available:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import type { paths, components, operations } from '@advizorconnect/sdk';
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Session Lifecycle
|
|
170
|
+
|
|
171
|
+
A typical call session follows this sequence:
|
|
172
|
+
|
|
173
|
+
1. **Create session** — `createSession()`
|
|
174
|
+
2. **Verify caller** — `sendOtp()` → `verifyPhone()`
|
|
175
|
+
3. **Authorize payment** — `createStripeIntent()` → `authorizeHold()`
|
|
176
|
+
4. **Connect call** — `startConnecting()` → `markConnected()`
|
|
177
|
+
5. **Bill during call** — `tick()` every ~60 seconds
|
|
178
|
+
6. **End and capture** — `endAndCapture()`
|
|
179
|
+
|
|
180
|
+
See the [Session Lifecycle Guide](../../docs/sdk-session-lifecycle.md) for detailed code examples and state machine documentation.
|
|
181
|
+
|
|
182
|
+
For a complete working example, see the [Paimoney reference app](../../examples/paimoney/) — a production-grade Next.js application demonstrating the BFF proxy integration pattern.
|
|
183
|
+
|
|
184
|
+
## Requirements
|
|
185
|
+
|
|
186
|
+
- Node.js 18+ (or any runtime with global `fetch`)
|
|
187
|
+
- API key from the owner dashboard
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
Proprietary. See LICENSE for details.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
import type { components } from './generated/v1.js';
|
|
2
|
+
type FetchLike = typeof fetch;
|
|
3
|
+
export type V1ClientOptions = {
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
apiKey: string;
|
|
6
|
+
fetchImpl?: FetchLike;
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
};
|
|
9
|
+
export type ApiKeyRecord = components['schemas']['ApiKeyRecord'];
|
|
10
|
+
export type InviteRecord = components['schemas']['InviteRecord'];
|
|
11
|
+
export type GroupSettingsResponse = components['schemas']['GroupSettingsResponse'];
|
|
12
|
+
export type WidgetConfigResponse = components['schemas']['WidgetConfigResponse'];
|
|
13
|
+
export type WidgetAdvisor = components['schemas']['WidgetAdvisor'];
|
|
14
|
+
export type WidgetSecurityConfig = components['schemas']['WidgetSecurityConfig'];
|
|
15
|
+
export type IntegrationAdvisor = components['schemas']['IntegrationAdvisor'];
|
|
16
|
+
export type IntegrationAdvisorFeedResponse = components['schemas']['IntegrationAdvisorFeedResponse'];
|
|
17
|
+
export type SessionEnvelope = components['schemas']['SessionEnvelope'];
|
|
18
|
+
export type ApiSession = components['schemas']['ApiSession'];
|
|
19
|
+
export type LedgerEvent = components['schemas']['LedgerEvent'];
|
|
20
|
+
export type ErrorResponse = components['schemas']['ErrorResponse'];
|
|
21
|
+
export declare function createV1Client(options: V1ClientOptions): {
|
|
22
|
+
listGroupAdvisors(input: {
|
|
23
|
+
groupId: string;
|
|
24
|
+
sort?: "billable_minutes_30d" | "online_status" | "alphabetical";
|
|
25
|
+
order?: "asc" | "desc";
|
|
26
|
+
onlineStatus?: "online" | "offline" | "available" | "busy";
|
|
27
|
+
minBillableMinutes30d?: number;
|
|
28
|
+
}): Promise<{
|
|
29
|
+
groupId: string;
|
|
30
|
+
groupSlug: string;
|
|
31
|
+
advisors: components["schemas"]["IntegrationAdvisor"][];
|
|
32
|
+
count: number;
|
|
33
|
+
sort?: {
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
};
|
|
36
|
+
filter?: {
|
|
37
|
+
[key: string]: unknown;
|
|
38
|
+
};
|
|
39
|
+
} & {
|
|
40
|
+
[key: string]: unknown;
|
|
41
|
+
}>;
|
|
42
|
+
getGroupAdvisor(input: {
|
|
43
|
+
groupId: string;
|
|
44
|
+
advisorId: string;
|
|
45
|
+
}): Promise<{
|
|
46
|
+
id: string;
|
|
47
|
+
groupId: string;
|
|
48
|
+
name: string;
|
|
49
|
+
avatarUrl?: string | null;
|
|
50
|
+
headline?: string | null;
|
|
51
|
+
status: "available" | "busy" | "offline";
|
|
52
|
+
available: boolean;
|
|
53
|
+
billableMinutes30d?: number;
|
|
54
|
+
lastLoginAt?: string | null;
|
|
55
|
+
} & {
|
|
56
|
+
[key: string]: unknown;
|
|
57
|
+
}>;
|
|
58
|
+
createSession(input: {
|
|
59
|
+
groupId: string;
|
|
60
|
+
advisorId: string;
|
|
61
|
+
callerPhone: string;
|
|
62
|
+
idempotencyKey: string;
|
|
63
|
+
callerUsername?: string;
|
|
64
|
+
callerEmail?: string;
|
|
65
|
+
}): Promise<{
|
|
66
|
+
session: components["schemas"]["ApiSession"];
|
|
67
|
+
} & {
|
|
68
|
+
[key: string]: unknown;
|
|
69
|
+
}>;
|
|
70
|
+
getSession(input: {
|
|
71
|
+
sessionId: string;
|
|
72
|
+
}): Promise<{
|
|
73
|
+
session: components["schemas"]["ApiSession"];
|
|
74
|
+
} & {
|
|
75
|
+
[key: string]: unknown;
|
|
76
|
+
}>;
|
|
77
|
+
getSessionLedger(input: {
|
|
78
|
+
sessionId: string;
|
|
79
|
+
}): Promise<{
|
|
80
|
+
events: components["schemas"]["LedgerEvent"][];
|
|
81
|
+
}>;
|
|
82
|
+
sendOtp(input: {
|
|
83
|
+
sessionId: string;
|
|
84
|
+
}): Promise<{
|
|
85
|
+
[key: string]: unknown;
|
|
86
|
+
}>;
|
|
87
|
+
verifyPhone(input: {
|
|
88
|
+
sessionId: string;
|
|
89
|
+
otp: string;
|
|
90
|
+
}): Promise<{
|
|
91
|
+
session: components["schemas"]["ApiSession"];
|
|
92
|
+
} & {
|
|
93
|
+
[key: string]: unknown;
|
|
94
|
+
}>;
|
|
95
|
+
createStripeIntent(input: {
|
|
96
|
+
sessionId: string;
|
|
97
|
+
holdCents?: 2500 | 5000;
|
|
98
|
+
}): Promise<{
|
|
99
|
+
paymentIntentId: string;
|
|
100
|
+
clientSecret: string;
|
|
101
|
+
holdCents: number;
|
|
102
|
+
currency: string;
|
|
103
|
+
}>;
|
|
104
|
+
createPayPalOrder(input: {
|
|
105
|
+
sessionId: string;
|
|
106
|
+
holdCents?: 2500 | 5000;
|
|
107
|
+
}): Promise<{
|
|
108
|
+
orderId: string;
|
|
109
|
+
holdCents: number;
|
|
110
|
+
currency: string;
|
|
111
|
+
}>;
|
|
112
|
+
authorizePayPalOrder(input: {
|
|
113
|
+
sessionId: string;
|
|
114
|
+
orderId: string;
|
|
115
|
+
}): Promise<{
|
|
116
|
+
session: components["schemas"]["ApiSession"];
|
|
117
|
+
} & {
|
|
118
|
+
[key: string]: unknown;
|
|
119
|
+
}>;
|
|
120
|
+
authorizeHold(input: {
|
|
121
|
+
sessionId: string;
|
|
122
|
+
paymentIntentId?: string;
|
|
123
|
+
holdCents?: number;
|
|
124
|
+
}): Promise<{
|
|
125
|
+
session: components["schemas"]["ApiSession"];
|
|
126
|
+
} & {
|
|
127
|
+
[key: string]: unknown;
|
|
128
|
+
}>;
|
|
129
|
+
startConnecting(input: {
|
|
130
|
+
sessionId: string;
|
|
131
|
+
}): Promise<{
|
|
132
|
+
session: components["schemas"]["ApiSession"];
|
|
133
|
+
} & {
|
|
134
|
+
[key: string]: unknown;
|
|
135
|
+
}>;
|
|
136
|
+
markConnected(input: {
|
|
137
|
+
sessionId: string;
|
|
138
|
+
}): Promise<{
|
|
139
|
+
session: components["schemas"]["ApiSession"];
|
|
140
|
+
} & {
|
|
141
|
+
[key: string]: unknown;
|
|
142
|
+
}>;
|
|
143
|
+
tick(input: {
|
|
144
|
+
sessionId: string;
|
|
145
|
+
asOfIso?: string;
|
|
146
|
+
}): Promise<{
|
|
147
|
+
session: components["schemas"]["ApiSession"];
|
|
148
|
+
} & {
|
|
149
|
+
[key: string]: unknown;
|
|
150
|
+
}>;
|
|
151
|
+
endAndCapture(input: {
|
|
152
|
+
sessionId: string;
|
|
153
|
+
reason?: string;
|
|
154
|
+
}): Promise<{
|
|
155
|
+
session: components["schemas"]["ApiSession"];
|
|
156
|
+
} & {
|
|
157
|
+
[key: string]: unknown;
|
|
158
|
+
}>;
|
|
159
|
+
submitSessionReview(input: {
|
|
160
|
+
sessionId: string;
|
|
161
|
+
rating: number;
|
|
162
|
+
body?: string;
|
|
163
|
+
authorName?: string;
|
|
164
|
+
}): Promise<{
|
|
165
|
+
ok: boolean;
|
|
166
|
+
duplicate?: boolean;
|
|
167
|
+
review?: {
|
|
168
|
+
[key: string]: unknown;
|
|
169
|
+
};
|
|
170
|
+
}>;
|
|
171
|
+
listApiKeys(input: {
|
|
172
|
+
groupId: string;
|
|
173
|
+
}): Promise<{
|
|
174
|
+
keys: components["schemas"]["ApiKeyRecord"][];
|
|
175
|
+
availableScopes: string[];
|
|
176
|
+
}>;
|
|
177
|
+
createApiKey(input: {
|
|
178
|
+
groupId: string;
|
|
179
|
+
name: string;
|
|
180
|
+
scopes?: string[];
|
|
181
|
+
expiresAt?: string;
|
|
182
|
+
}): Promise<{
|
|
183
|
+
key: components["schemas"]["ApiKeyRecord"];
|
|
184
|
+
apiKey: string;
|
|
185
|
+
availableScopes: string[];
|
|
186
|
+
}>;
|
|
187
|
+
rotateApiKey(input: {
|
|
188
|
+
groupId: string;
|
|
189
|
+
keyId: string;
|
|
190
|
+
overlapSeconds?: number;
|
|
191
|
+
name?: string;
|
|
192
|
+
expiresAt?: string;
|
|
193
|
+
}): Promise<{
|
|
194
|
+
key: components["schemas"]["ApiKeyRecord"];
|
|
195
|
+
apiKey: string;
|
|
196
|
+
previousKey: {
|
|
197
|
+
id: string;
|
|
198
|
+
expiresAt?: string | null;
|
|
199
|
+
};
|
|
200
|
+
}>;
|
|
201
|
+
revokeApiKey(input: {
|
|
202
|
+
groupId: string;
|
|
203
|
+
keyId: string;
|
|
204
|
+
}): Promise<{
|
|
205
|
+
ok: boolean;
|
|
206
|
+
revokedAt?: string | null;
|
|
207
|
+
expiresAt?: string | null;
|
|
208
|
+
}>;
|
|
209
|
+
mintWidgetToken(input: {
|
|
210
|
+
groupId: string;
|
|
211
|
+
}): Promise<{
|
|
212
|
+
token: string;
|
|
213
|
+
expiresAt: string;
|
|
214
|
+
mode: "preview" | "embed";
|
|
215
|
+
}>;
|
|
216
|
+
getWidgetConfig(input: {
|
|
217
|
+
groupId: string;
|
|
218
|
+
}): Promise<{
|
|
219
|
+
groupId: string;
|
|
220
|
+
groupSlug: string;
|
|
221
|
+
groupName: string;
|
|
222
|
+
theme: {
|
|
223
|
+
[key: string]: unknown;
|
|
224
|
+
};
|
|
225
|
+
requireCallerOtp: boolean;
|
|
226
|
+
embedTemplate: {
|
|
227
|
+
[key: string]: unknown;
|
|
228
|
+
};
|
|
229
|
+
}>;
|
|
230
|
+
listWidgetAdvisors(input: {
|
|
231
|
+
groupId: string;
|
|
232
|
+
}): Promise<{
|
|
233
|
+
groupId: string;
|
|
234
|
+
groupSlug: string;
|
|
235
|
+
advisors: components["schemas"]["WidgetAdvisor"][];
|
|
236
|
+
count: number;
|
|
237
|
+
}>;
|
|
238
|
+
getWidgetSecurity(input: {
|
|
239
|
+
groupId: string;
|
|
240
|
+
}): Promise<{
|
|
241
|
+
security: components["schemas"]["WidgetSecurityConfig"];
|
|
242
|
+
previewOrigin: string;
|
|
243
|
+
}>;
|
|
244
|
+
updateWidgetSecurity(input: {
|
|
245
|
+
groupId: string;
|
|
246
|
+
allowedOrigins: string[];
|
|
247
|
+
}): Promise<{
|
|
248
|
+
security: components["schemas"]["WidgetSecurityConfig"];
|
|
249
|
+
previewOrigin: string;
|
|
250
|
+
}>;
|
|
251
|
+
createInvite(input: {
|
|
252
|
+
groupId: string;
|
|
253
|
+
email?: string;
|
|
254
|
+
}): Promise<{
|
|
255
|
+
invite: components["schemas"]["InviteRecord"];
|
|
256
|
+
}>;
|
|
257
|
+
listInvites(input: {
|
|
258
|
+
groupId: string;
|
|
259
|
+
status?: string;
|
|
260
|
+
}): Promise<{
|
|
261
|
+
invites: components["schemas"]["InviteRecord"][];
|
|
262
|
+
}>;
|
|
263
|
+
rotateInvite(input: {
|
|
264
|
+
groupId: string;
|
|
265
|
+
inviteId: string;
|
|
266
|
+
}): Promise<{
|
|
267
|
+
ok: boolean;
|
|
268
|
+
inviteId: string;
|
|
269
|
+
invite: components["schemas"]["InviteRecord"];
|
|
270
|
+
}>;
|
|
271
|
+
revokeInvite(input: {
|
|
272
|
+
groupId: string;
|
|
273
|
+
inviteId: string;
|
|
274
|
+
}): Promise<{
|
|
275
|
+
ok: boolean;
|
|
276
|
+
inviteId: string;
|
|
277
|
+
revokedAt?: string | null;
|
|
278
|
+
}>;
|
|
279
|
+
sendInvite(input: {
|
|
280
|
+
groupId: string;
|
|
281
|
+
inviteId: string;
|
|
282
|
+
}): Promise<{
|
|
283
|
+
ok: boolean;
|
|
284
|
+
inviteId: string;
|
|
285
|
+
resendEmailId: string;
|
|
286
|
+
}>;
|
|
287
|
+
getGroupBySlug(input: {
|
|
288
|
+
slug: string;
|
|
289
|
+
}): Promise<{
|
|
290
|
+
group: {
|
|
291
|
+
id: string;
|
|
292
|
+
slug: string;
|
|
293
|
+
name: string;
|
|
294
|
+
theme?: {
|
|
295
|
+
[key: string]: unknown;
|
|
296
|
+
} | null;
|
|
297
|
+
isPersonal?: boolean;
|
|
298
|
+
requireCallerOtp?: boolean;
|
|
299
|
+
};
|
|
300
|
+
requestedSlug: string;
|
|
301
|
+
canonicalSlug: string;
|
|
302
|
+
isAlias: boolean;
|
|
303
|
+
}>;
|
|
304
|
+
updateGroupSlug(input: {
|
|
305
|
+
groupId: string;
|
|
306
|
+
slug: string;
|
|
307
|
+
}): Promise<{
|
|
308
|
+
group: {
|
|
309
|
+
[key: string]: unknown;
|
|
310
|
+
};
|
|
311
|
+
}>;
|
|
312
|
+
getGroupSettings(input: {
|
|
313
|
+
groupId: string;
|
|
314
|
+
}): Promise<{
|
|
315
|
+
settings: components["schemas"]["GroupSettingsResponse"];
|
|
316
|
+
}>;
|
|
317
|
+
updateGroupSettings(input: {
|
|
318
|
+
groupId: string;
|
|
319
|
+
requireCallerOtp?: boolean;
|
|
320
|
+
}): Promise<{
|
|
321
|
+
settings: components["schemas"]["GroupSettingsResponse"];
|
|
322
|
+
}>;
|
|
323
|
+
listOwnerAdvisors(input: {
|
|
324
|
+
groupId: string;
|
|
325
|
+
}): Promise<{
|
|
326
|
+
advisors: {
|
|
327
|
+
[key: string]: unknown;
|
|
328
|
+
}[];
|
|
329
|
+
}>;
|
|
330
|
+
moderateAdvisor(input: {
|
|
331
|
+
groupId: string;
|
|
332
|
+
advisorId: string;
|
|
333
|
+
action: "approve" | "reject" | "suspend" | "unsuspend";
|
|
334
|
+
reason?: string;
|
|
335
|
+
note?: string;
|
|
336
|
+
}): Promise<{
|
|
337
|
+
ok: boolean;
|
|
338
|
+
advisor: {
|
|
339
|
+
[key: string]: unknown;
|
|
340
|
+
};
|
|
341
|
+
}>;
|
|
342
|
+
listAdvisorModerationEvents(input: {
|
|
343
|
+
groupId: string;
|
|
344
|
+
advisorId: string;
|
|
345
|
+
before?: string;
|
|
346
|
+
limit?: number;
|
|
347
|
+
}): Promise<{
|
|
348
|
+
events: {
|
|
349
|
+
[key: string]: unknown;
|
|
350
|
+
}[];
|
|
351
|
+
}>;
|
|
352
|
+
listGroupModerationEvents(input: {
|
|
353
|
+
groupId: string;
|
|
354
|
+
before?: string;
|
|
355
|
+
limit?: number;
|
|
356
|
+
}): Promise<{
|
|
357
|
+
events: {
|
|
358
|
+
[key: string]: unknown;
|
|
359
|
+
}[];
|
|
360
|
+
}>;
|
|
361
|
+
removeAdvisor(input: {
|
|
362
|
+
groupId: string;
|
|
363
|
+
advisorId: string;
|
|
364
|
+
reason?: string;
|
|
365
|
+
}): Promise<{
|
|
366
|
+
ok: boolean;
|
|
367
|
+
}>;
|
|
368
|
+
updateGroupTheme(input: {
|
|
369
|
+
groupId: string;
|
|
370
|
+
theme: Record<string, unknown>;
|
|
371
|
+
}): Promise<{
|
|
372
|
+
group: {
|
|
373
|
+
[key: string]: unknown;
|
|
374
|
+
};
|
|
375
|
+
}>;
|
|
376
|
+
getSetupState(input: {
|
|
377
|
+
groupId: string;
|
|
378
|
+
}): Promise<{
|
|
379
|
+
setupState: {
|
|
380
|
+
[key: string]: unknown;
|
|
381
|
+
};
|
|
382
|
+
}>;
|
|
383
|
+
updateSetupState(input: {
|
|
384
|
+
groupId: string;
|
|
385
|
+
setupState: Record<string, unknown>;
|
|
386
|
+
}): Promise<{
|
|
387
|
+
setupState: {
|
|
388
|
+
[key: string]: unknown;
|
|
389
|
+
};
|
|
390
|
+
}>;
|
|
391
|
+
getAnalyticsOverview(input: {
|
|
392
|
+
groupId: string;
|
|
393
|
+
}): Promise<{
|
|
394
|
+
[key: string]: unknown;
|
|
395
|
+
}>;
|
|
396
|
+
getAnalyticsRevenue(input: {
|
|
397
|
+
groupId: string;
|
|
398
|
+
}): Promise<{
|
|
399
|
+
[key: string]: unknown;
|
|
400
|
+
}>;
|
|
401
|
+
getAnalyticsSessions(input: {
|
|
402
|
+
groupId: string;
|
|
403
|
+
page?: number;
|
|
404
|
+
limit?: number;
|
|
405
|
+
}): Promise<{
|
|
406
|
+
[key: string]: unknown;
|
|
407
|
+
}>;
|
|
408
|
+
getWidgetEventAnalytics(input: {
|
|
409
|
+
groupId: string;
|
|
410
|
+
since?: string;
|
|
411
|
+
limit?: number;
|
|
412
|
+
}): Promise<{
|
|
413
|
+
events: {
|
|
414
|
+
[key: string]: unknown;
|
|
415
|
+
}[];
|
|
416
|
+
}>;
|
|
417
|
+
listOwnerPayouts(input: {
|
|
418
|
+
groupId: string;
|
|
419
|
+
page?: number;
|
|
420
|
+
limit?: number;
|
|
421
|
+
}): Promise<{
|
|
422
|
+
payouts: {
|
|
423
|
+
[key: string]: unknown;
|
|
424
|
+
}[];
|
|
425
|
+
total: number;
|
|
426
|
+
page: number;
|
|
427
|
+
limit: number;
|
|
428
|
+
}>;
|
|
429
|
+
batchCreateOwnerInvites(input: {
|
|
430
|
+
groupId: string;
|
|
431
|
+
emails: string[];
|
|
432
|
+
}): Promise<{
|
|
433
|
+
results: {
|
|
434
|
+
[key: string]: unknown;
|
|
435
|
+
}[];
|
|
436
|
+
}>;
|
|
437
|
+
previewInvite(input: {
|
|
438
|
+
token: string;
|
|
439
|
+
}): Promise<{
|
|
440
|
+
[key: string]: unknown;
|
|
441
|
+
}>;
|
|
442
|
+
acceptInvite(input: {
|
|
443
|
+
token: string;
|
|
444
|
+
}): Promise<{
|
|
445
|
+
[key: string]: unknown;
|
|
446
|
+
}>;
|
|
447
|
+
createWidgetCallback(input: {
|
|
448
|
+
groupId: string;
|
|
449
|
+
body: Record<string, unknown>;
|
|
450
|
+
}): Promise<{
|
|
451
|
+
[key: string]: unknown;
|
|
452
|
+
}>;
|
|
453
|
+
getWidgetCallbackStatus(input: {
|
|
454
|
+
groupId: string;
|
|
455
|
+
phone: string;
|
|
456
|
+
}): Promise<{
|
|
457
|
+
[key: string]: unknown;
|
|
458
|
+
}>;
|
|
459
|
+
ingestWidgetEvent(input: {
|
|
460
|
+
groupId: string;
|
|
461
|
+
eventType: string;
|
|
462
|
+
sessionId: string;
|
|
463
|
+
eventData?: Record<string, unknown>;
|
|
464
|
+
}): Promise<{
|
|
465
|
+
ok: boolean;
|
|
466
|
+
}>;
|
|
467
|
+
getGroupSitemap(input: {
|
|
468
|
+
groupSlug: string;
|
|
469
|
+
}): Promise<never>;
|
|
470
|
+
getAdvisorJsonLd(input: {
|
|
471
|
+
groupSlug: string;
|
|
472
|
+
advisorId: string;
|
|
473
|
+
}): Promise<never>;
|
|
474
|
+
getTaxonomy(): Promise<{
|
|
475
|
+
[key: string]: unknown;
|
|
476
|
+
}>;
|
|
477
|
+
generateWidgetEmbedCode(input: {
|
|
478
|
+
groupId: string;
|
|
479
|
+
}): Promise<{
|
|
480
|
+
[key: string]: unknown;
|
|
481
|
+
}>;
|
|
482
|
+
};
|
|
483
|
+
export {};
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
import { V1SdkError } from './errors.js';
|
|
2
|
+
function withQuery(path, query) {
|
|
3
|
+
if (!query)
|
|
4
|
+
return path;
|
|
5
|
+
const params = new URLSearchParams();
|
|
6
|
+
for (const [k, v] of Object.entries(query)) {
|
|
7
|
+
if (v == null)
|
|
8
|
+
continue;
|
|
9
|
+
params.set(k, String(v));
|
|
10
|
+
}
|
|
11
|
+
const qs = params.toString();
|
|
12
|
+
return qs ? `${path}?${qs}` : path;
|
|
13
|
+
}
|
|
14
|
+
async function parseResponseBody(res) {
|
|
15
|
+
const text = await res.text();
|
|
16
|
+
if (!text)
|
|
17
|
+
return null;
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(text);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return text;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function createV1Client(options) {
|
|
26
|
+
const baseUrl = options.baseUrl.replace(/\/$/, '');
|
|
27
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
28
|
+
const timeoutMs = options.timeoutMs ?? 20_000;
|
|
29
|
+
async function request(input) {
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
32
|
+
try {
|
|
33
|
+
const res = await fetchImpl(withQuery(`${baseUrl}${input.path}`, input.query), {
|
|
34
|
+
method: input.method,
|
|
35
|
+
signal: controller.signal,
|
|
36
|
+
headers: {
|
|
37
|
+
Authorization: `Bearer ${options.apiKey}`,
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
},
|
|
40
|
+
body: input.body == null ? undefined : JSON.stringify(input.body),
|
|
41
|
+
});
|
|
42
|
+
const body = await parseResponseBody(res);
|
|
43
|
+
if (!res.ok) {
|
|
44
|
+
const envelope = body && typeof body === 'object' ? body : null;
|
|
45
|
+
const message = (envelope && typeof envelope.message === 'string' && envelope.message)
|
|
46
|
+
|| (envelope && typeof envelope.error === 'string' && envelope.error)
|
|
47
|
+
|| `Request failed (${res.status})`;
|
|
48
|
+
throw new V1SdkError({
|
|
49
|
+
status: res.status,
|
|
50
|
+
message,
|
|
51
|
+
body,
|
|
52
|
+
code: envelope && typeof envelope.code === 'string' ? envelope.code : null,
|
|
53
|
+
requestId: envelope && typeof envelope.requestId === 'string' ? envelope.requestId : null,
|
|
54
|
+
retryable: envelope && typeof envelope.retryable === 'boolean' ? envelope.retryable : null,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return body;
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
clearTimeout(timeout);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const e = encodeURIComponent;
|
|
64
|
+
return {
|
|
65
|
+
// ── Integration (2) ──────────────────────────────────────────────
|
|
66
|
+
listGroupAdvisors(input) {
|
|
67
|
+
return request({
|
|
68
|
+
method: 'GET',
|
|
69
|
+
path: `/v1/integration/groups/${e(input.groupId)}/advisors`,
|
|
70
|
+
query: {
|
|
71
|
+
sort: input.sort,
|
|
72
|
+
order: input.order,
|
|
73
|
+
onlineStatus: input.onlineStatus,
|
|
74
|
+
minBillableMinutes30d: input.minBillableMinutes30d,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
getGroupAdvisor(input) {
|
|
79
|
+
return request({
|
|
80
|
+
method: 'GET',
|
|
81
|
+
path: `/v1/integration/groups/${e(input.groupId)}/advisors/${e(input.advisorId)}`,
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
// ── Sessions (13) ────────────────────────────────────────────────
|
|
85
|
+
createSession(input) {
|
|
86
|
+
return request({
|
|
87
|
+
method: 'POST',
|
|
88
|
+
path: '/v1/sessions',
|
|
89
|
+
body: input,
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
getSession(input) {
|
|
93
|
+
return request({
|
|
94
|
+
method: 'GET',
|
|
95
|
+
path: `/v1/sessions/${e(input.sessionId)}`,
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
getSessionLedger(input) {
|
|
99
|
+
return request({
|
|
100
|
+
method: 'GET',
|
|
101
|
+
path: `/v1/sessions/${e(input.sessionId)}/ledger`,
|
|
102
|
+
});
|
|
103
|
+
},
|
|
104
|
+
sendOtp(input) {
|
|
105
|
+
return request({
|
|
106
|
+
method: 'POST',
|
|
107
|
+
path: `/v1/sessions/${e(input.sessionId)}/otp/send`,
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
verifyPhone(input) {
|
|
111
|
+
return request({
|
|
112
|
+
method: 'POST',
|
|
113
|
+
path: `/v1/sessions/${e(input.sessionId)}/verify-phone`,
|
|
114
|
+
body: { otp: input.otp },
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
createStripeIntent(input) {
|
|
118
|
+
return request({
|
|
119
|
+
method: 'POST',
|
|
120
|
+
path: `/v1/sessions/${e(input.sessionId)}/payments/create-intent`,
|
|
121
|
+
body: input.holdCents != null ? { holdCents: input.holdCents } : {},
|
|
122
|
+
});
|
|
123
|
+
},
|
|
124
|
+
createPayPalOrder(input) {
|
|
125
|
+
return request({
|
|
126
|
+
method: 'POST',
|
|
127
|
+
path: `/v1/sessions/${e(input.sessionId)}/payments/paypal/create-order`,
|
|
128
|
+
body: input.holdCents != null ? { holdCents: input.holdCents } : {},
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
authorizePayPalOrder(input) {
|
|
132
|
+
return request({
|
|
133
|
+
method: 'POST',
|
|
134
|
+
path: `/v1/sessions/${e(input.sessionId)}/payments/paypal/authorize`,
|
|
135
|
+
body: { orderId: input.orderId },
|
|
136
|
+
});
|
|
137
|
+
},
|
|
138
|
+
authorizeHold(input) {
|
|
139
|
+
return request({
|
|
140
|
+
method: 'POST',
|
|
141
|
+
path: `/v1/sessions/${e(input.sessionId)}/authorize-hold`,
|
|
142
|
+
body: {
|
|
143
|
+
paymentIntentId: input.paymentIntentId,
|
|
144
|
+
holdCents: input.holdCents,
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
startConnecting(input) {
|
|
149
|
+
return request({
|
|
150
|
+
method: 'POST',
|
|
151
|
+
path: `/v1/sessions/${e(input.sessionId)}/start-connecting`,
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
markConnected(input) {
|
|
155
|
+
return request({
|
|
156
|
+
method: 'POST',
|
|
157
|
+
path: `/v1/sessions/${e(input.sessionId)}/mark-connected`,
|
|
158
|
+
});
|
|
159
|
+
},
|
|
160
|
+
tick(input) {
|
|
161
|
+
return request({
|
|
162
|
+
method: 'POST',
|
|
163
|
+
path: `/v1/sessions/${e(input.sessionId)}/tick`,
|
|
164
|
+
body: input.asOfIso ? { asOfIso: input.asOfIso } : {},
|
|
165
|
+
});
|
|
166
|
+
},
|
|
167
|
+
endAndCapture(input) {
|
|
168
|
+
return request({
|
|
169
|
+
method: 'POST',
|
|
170
|
+
path: `/v1/sessions/${e(input.sessionId)}/end-and-capture`,
|
|
171
|
+
body: input.reason ? { reason: input.reason } : {},
|
|
172
|
+
});
|
|
173
|
+
},
|
|
174
|
+
submitSessionReview(input) {
|
|
175
|
+
return request({
|
|
176
|
+
method: 'POST',
|
|
177
|
+
path: `/v1/sessions/${e(input.sessionId)}/reviews`,
|
|
178
|
+
body: {
|
|
179
|
+
rating: input.rating,
|
|
180
|
+
body: input.body,
|
|
181
|
+
authorName: input.authorName,
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
},
|
|
185
|
+
// ── Owner / API Keys (4) ─────────────────────────────────────────
|
|
186
|
+
listApiKeys(input) {
|
|
187
|
+
return request({
|
|
188
|
+
method: 'GET',
|
|
189
|
+
path: `/v1/owner/groups/${e(input.groupId)}/api-keys`,
|
|
190
|
+
});
|
|
191
|
+
},
|
|
192
|
+
createApiKey(input) {
|
|
193
|
+
return request({
|
|
194
|
+
method: 'POST',
|
|
195
|
+
path: `/v1/owner/groups/${e(input.groupId)}/api-keys`,
|
|
196
|
+
body: { name: input.name, scopes: input.scopes, expiresAt: input.expiresAt },
|
|
197
|
+
});
|
|
198
|
+
},
|
|
199
|
+
rotateApiKey(input) {
|
|
200
|
+
return request({
|
|
201
|
+
method: 'POST',
|
|
202
|
+
path: `/v1/owner/groups/${e(input.groupId)}/api-keys/${e(input.keyId)}/rotate`,
|
|
203
|
+
body: {
|
|
204
|
+
overlapSeconds: input.overlapSeconds,
|
|
205
|
+
name: input.name,
|
|
206
|
+
expiresAt: input.expiresAt,
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
revokeApiKey(input) {
|
|
211
|
+
return request({
|
|
212
|
+
method: 'POST',
|
|
213
|
+
path: `/v1/owner/groups/${e(input.groupId)}/api-keys/${e(input.keyId)}/revoke`,
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
// ── Widget (3) + Owner / Widget (2) ──────────────────────────────
|
|
217
|
+
mintWidgetToken(input) {
|
|
218
|
+
return request({
|
|
219
|
+
method: 'POST',
|
|
220
|
+
path: `/v1/widget/${e(input.groupId)}/auth/token`,
|
|
221
|
+
});
|
|
222
|
+
},
|
|
223
|
+
getWidgetConfig(input) {
|
|
224
|
+
return request({
|
|
225
|
+
method: 'GET',
|
|
226
|
+
path: `/v1/widget/${e(input.groupId)}/config`,
|
|
227
|
+
});
|
|
228
|
+
},
|
|
229
|
+
listWidgetAdvisors(input) {
|
|
230
|
+
return request({
|
|
231
|
+
method: 'GET',
|
|
232
|
+
path: `/v1/widget/${e(input.groupId)}/advisors`,
|
|
233
|
+
});
|
|
234
|
+
},
|
|
235
|
+
getWidgetSecurity(input) {
|
|
236
|
+
return request({
|
|
237
|
+
method: 'GET',
|
|
238
|
+
path: `/v1/owner/groups/${e(input.groupId)}/widget/security`,
|
|
239
|
+
});
|
|
240
|
+
},
|
|
241
|
+
updateWidgetSecurity(input) {
|
|
242
|
+
return request({
|
|
243
|
+
method: 'PUT',
|
|
244
|
+
path: `/v1/owner/groups/${e(input.groupId)}/widget/security`,
|
|
245
|
+
body: { allowedOrigins: input.allowedOrigins },
|
|
246
|
+
});
|
|
247
|
+
},
|
|
248
|
+
// ── Owner / Invites (5) ──────────────────────────────────────────
|
|
249
|
+
createInvite(input) {
|
|
250
|
+
return request({
|
|
251
|
+
method: 'POST',
|
|
252
|
+
path: `/v1/owner/groups/${e(input.groupId)}/invites`,
|
|
253
|
+
body: input.email ? { email: input.email } : {},
|
|
254
|
+
});
|
|
255
|
+
},
|
|
256
|
+
listInvites(input) {
|
|
257
|
+
return request({
|
|
258
|
+
method: 'GET',
|
|
259
|
+
path: `/v1/owner/groups/${e(input.groupId)}/invites`,
|
|
260
|
+
query: { status: input.status },
|
|
261
|
+
});
|
|
262
|
+
},
|
|
263
|
+
rotateInvite(input) {
|
|
264
|
+
return request({
|
|
265
|
+
method: 'POST',
|
|
266
|
+
path: `/v1/owner/groups/${e(input.groupId)}/invites/${e(input.inviteId)}/rotate`,
|
|
267
|
+
});
|
|
268
|
+
},
|
|
269
|
+
revokeInvite(input) {
|
|
270
|
+
return request({
|
|
271
|
+
method: 'POST',
|
|
272
|
+
path: `/v1/owner/groups/${e(input.groupId)}/invites/${e(input.inviteId)}/revoke`,
|
|
273
|
+
});
|
|
274
|
+
},
|
|
275
|
+
sendInvite(input) {
|
|
276
|
+
return request({
|
|
277
|
+
method: 'POST',
|
|
278
|
+
path: `/v1/owner/groups/${e(input.groupId)}/invites/${e(input.inviteId)}/send`,
|
|
279
|
+
});
|
|
280
|
+
},
|
|
281
|
+
// ── Owner / Groups (4) ───────────────────────────────────────────
|
|
282
|
+
getGroupBySlug(input) {
|
|
283
|
+
return request({
|
|
284
|
+
method: 'GET',
|
|
285
|
+
path: `/v1/groups/by-slug/${e(input.slug)}`,
|
|
286
|
+
});
|
|
287
|
+
},
|
|
288
|
+
updateGroupSlug(input) {
|
|
289
|
+
return request({
|
|
290
|
+
method: 'PATCH',
|
|
291
|
+
path: `/v1/owner/groups/${e(input.groupId)}/slug`,
|
|
292
|
+
body: { slug: input.slug },
|
|
293
|
+
});
|
|
294
|
+
},
|
|
295
|
+
getGroupSettings(input) {
|
|
296
|
+
return request({
|
|
297
|
+
method: 'GET',
|
|
298
|
+
path: `/v1/owner/groups/${e(input.groupId)}/settings`,
|
|
299
|
+
});
|
|
300
|
+
},
|
|
301
|
+
updateGroupSettings(input) {
|
|
302
|
+
return request({
|
|
303
|
+
method: 'PATCH',
|
|
304
|
+
path: `/v1/owner/groups/${e(input.groupId)}/settings`,
|
|
305
|
+
body: {
|
|
306
|
+
requireCallerOtp: input.requireCallerOtp,
|
|
307
|
+
},
|
|
308
|
+
});
|
|
309
|
+
},
|
|
310
|
+
// ── Owner / Advisors (5) ────────────────────────────────────────
|
|
311
|
+
listOwnerAdvisors(input) {
|
|
312
|
+
return request({
|
|
313
|
+
method: 'GET',
|
|
314
|
+
path: `/v1/owner/groups/${e(input.groupId)}/advisors`,
|
|
315
|
+
});
|
|
316
|
+
},
|
|
317
|
+
moderateAdvisor(input) {
|
|
318
|
+
return request({
|
|
319
|
+
method: 'POST',
|
|
320
|
+
path: `/v1/owner/groups/${e(input.groupId)}/advisors/${e(input.advisorId)}/moderate`,
|
|
321
|
+
body: { action: input.action, reason: input.reason, note: input.note },
|
|
322
|
+
});
|
|
323
|
+
},
|
|
324
|
+
listAdvisorModerationEvents(input) {
|
|
325
|
+
return request({
|
|
326
|
+
method: 'GET',
|
|
327
|
+
path: `/v1/owner/groups/${e(input.groupId)}/advisors/${e(input.advisorId)}/events`,
|
|
328
|
+
query: { before: input.before, limit: input.limit },
|
|
329
|
+
});
|
|
330
|
+
},
|
|
331
|
+
listGroupModerationEvents(input) {
|
|
332
|
+
return request({
|
|
333
|
+
method: 'GET',
|
|
334
|
+
path: `/v1/owner/groups/${e(input.groupId)}/events`,
|
|
335
|
+
query: { before: input.before, limit: input.limit },
|
|
336
|
+
});
|
|
337
|
+
},
|
|
338
|
+
removeAdvisor(input) {
|
|
339
|
+
return request({
|
|
340
|
+
method: 'POST',
|
|
341
|
+
path: `/v1/owner/groups/${e(input.groupId)}/advisors/${e(input.advisorId)}`,
|
|
342
|
+
body: input.reason ? { reason: input.reason } : {},
|
|
343
|
+
});
|
|
344
|
+
},
|
|
345
|
+
// ── Owner / Setup & Theme (3) ───────────────────────────────────
|
|
346
|
+
updateGroupTheme(input) {
|
|
347
|
+
return request({
|
|
348
|
+
method: 'PATCH',
|
|
349
|
+
path: `/v1/owner/groups/${e(input.groupId)}/theme`,
|
|
350
|
+
body: { theme: input.theme },
|
|
351
|
+
});
|
|
352
|
+
},
|
|
353
|
+
getSetupState(input) {
|
|
354
|
+
return request({
|
|
355
|
+
method: 'GET',
|
|
356
|
+
path: `/v1/owner/groups/${e(input.groupId)}/setup-state`,
|
|
357
|
+
});
|
|
358
|
+
},
|
|
359
|
+
updateSetupState(input) {
|
|
360
|
+
return request({
|
|
361
|
+
method: 'PATCH',
|
|
362
|
+
path: `/v1/owner/groups/${e(input.groupId)}/setup-state`,
|
|
363
|
+
body: { setupState: input.setupState },
|
|
364
|
+
});
|
|
365
|
+
},
|
|
366
|
+
// ── Owner / Analytics (4) ────────────────────────────────────────
|
|
367
|
+
getAnalyticsOverview(input) {
|
|
368
|
+
return request({
|
|
369
|
+
method: 'GET',
|
|
370
|
+
path: `/v1/owner/groups/${e(input.groupId)}/analytics/overview`,
|
|
371
|
+
});
|
|
372
|
+
},
|
|
373
|
+
getAnalyticsRevenue(input) {
|
|
374
|
+
return request({
|
|
375
|
+
method: 'GET',
|
|
376
|
+
path: `/v1/owner/groups/${e(input.groupId)}/analytics/revenue`,
|
|
377
|
+
});
|
|
378
|
+
},
|
|
379
|
+
getAnalyticsSessions(input) {
|
|
380
|
+
return request({
|
|
381
|
+
method: 'GET',
|
|
382
|
+
path: `/v1/owner/groups/${e(input.groupId)}/analytics/sessions`,
|
|
383
|
+
query: { page: input.page, limit: input.limit },
|
|
384
|
+
});
|
|
385
|
+
},
|
|
386
|
+
getWidgetEventAnalytics(input) {
|
|
387
|
+
return request({
|
|
388
|
+
method: 'GET',
|
|
389
|
+
path: `/v1/owner/groups/${e(input.groupId)}/analytics/widget-events`,
|
|
390
|
+
query: { since: input.since, limit: input.limit },
|
|
391
|
+
});
|
|
392
|
+
},
|
|
393
|
+
// ── Owner / Payouts (1) ──────────────────────────────────────────
|
|
394
|
+
listOwnerPayouts(input) {
|
|
395
|
+
return request({
|
|
396
|
+
method: 'GET',
|
|
397
|
+
path: `/v1/owner/groups/${e(input.groupId)}/payouts`,
|
|
398
|
+
query: { page: input.page, limit: input.limit },
|
|
399
|
+
});
|
|
400
|
+
},
|
|
401
|
+
// ── Owner / Invites (Batch + Public invite flow) ────────────────
|
|
402
|
+
batchCreateOwnerInvites(input) {
|
|
403
|
+
return request({
|
|
404
|
+
method: 'POST',
|
|
405
|
+
path: `/v1/owner/groups/${e(input.groupId)}/invites/batch`,
|
|
406
|
+
body: { emails: input.emails },
|
|
407
|
+
});
|
|
408
|
+
},
|
|
409
|
+
previewInvite(input) {
|
|
410
|
+
return request({
|
|
411
|
+
method: 'GET',
|
|
412
|
+
path: `/v1/invites/${e(input.token)}/preview`,
|
|
413
|
+
});
|
|
414
|
+
},
|
|
415
|
+
acceptInvite(input) {
|
|
416
|
+
return request({
|
|
417
|
+
method: 'POST',
|
|
418
|
+
path: `/v1/invites/${e(input.token)}/accept`,
|
|
419
|
+
});
|
|
420
|
+
},
|
|
421
|
+
// ── Widget events + callbacks (3) ────────────────────────────────
|
|
422
|
+
createWidgetCallback(input) {
|
|
423
|
+
return request({
|
|
424
|
+
method: 'POST',
|
|
425
|
+
path: `/v1/widget/${e(input.groupId)}/callbacks`,
|
|
426
|
+
body: input.body,
|
|
427
|
+
});
|
|
428
|
+
},
|
|
429
|
+
getWidgetCallbackStatus(input) {
|
|
430
|
+
return request({
|
|
431
|
+
method: 'GET',
|
|
432
|
+
path: `/v1/widget/${e(input.groupId)}/callbacks/status`,
|
|
433
|
+
query: { phone: input.phone },
|
|
434
|
+
});
|
|
435
|
+
},
|
|
436
|
+
ingestWidgetEvent(input) {
|
|
437
|
+
return request({
|
|
438
|
+
method: 'POST',
|
|
439
|
+
path: `/v1/widget/${e(input.groupId)}/events`,
|
|
440
|
+
body: { eventType: input.eventType, sessionId: input.sessionId, eventData: input.eventData },
|
|
441
|
+
});
|
|
442
|
+
},
|
|
443
|
+
// ── SEO + taxonomy + widget generation (4) ───────────────────────
|
|
444
|
+
getGroupSitemap(input) {
|
|
445
|
+
return request({
|
|
446
|
+
method: 'GET',
|
|
447
|
+
path: `/v1/seo/groups/${e(input.groupSlug)}/sitemap.xml`,
|
|
448
|
+
});
|
|
449
|
+
},
|
|
450
|
+
getAdvisorJsonLd(input) {
|
|
451
|
+
return request({
|
|
452
|
+
method: 'GET',
|
|
453
|
+
path: `/v1/seo/groups/${e(input.groupSlug)}/advisors/${e(input.advisorId)}/jsonld`,
|
|
454
|
+
});
|
|
455
|
+
},
|
|
456
|
+
getTaxonomy() {
|
|
457
|
+
return request({
|
|
458
|
+
method: 'GET',
|
|
459
|
+
path: '/v1/taxonomy',
|
|
460
|
+
});
|
|
461
|
+
},
|
|
462
|
+
generateWidgetEmbedCode(input) {
|
|
463
|
+
return request({
|
|
464
|
+
method: 'POST',
|
|
465
|
+
path: `/v1/owner/groups/${e(input.groupId)}/widget/generate`,
|
|
466
|
+
});
|
|
467
|
+
},
|
|
468
|
+
};
|
|
469
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class V1SdkError extends Error {
|
|
2
|
+
status: number;
|
|
3
|
+
body: unknown;
|
|
4
|
+
code: string | null;
|
|
5
|
+
requestId: string | null;
|
|
6
|
+
retryable: boolean | null;
|
|
7
|
+
constructor(input: {
|
|
8
|
+
status: number;
|
|
9
|
+
message: string;
|
|
10
|
+
body: unknown;
|
|
11
|
+
code?: string | null;
|
|
12
|
+
requestId?: string | null;
|
|
13
|
+
retryable?: boolean | null;
|
|
14
|
+
});
|
|
15
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export class V1SdkError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
body;
|
|
4
|
+
code;
|
|
5
|
+
requestId;
|
|
6
|
+
retryable;
|
|
7
|
+
constructor(input) {
|
|
8
|
+
super(input.message);
|
|
9
|
+
this.name = 'V1SdkError';
|
|
10
|
+
this.status = input.status;
|
|
11
|
+
this.body = input.body;
|
|
12
|
+
this.code = input.code ?? null;
|
|
13
|
+
this.requestId = input.requestId ?? null;
|
|
14
|
+
this.retryable = input.retryable ?? null;
|
|
15
|
+
}
|
|
16
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { V1SdkError } from './errors.js';
|
|
2
|
+
export { createV1Client } from './client.js';
|
|
3
|
+
export type { V1ClientOptions } from './client.js';
|
|
4
|
+
export { withRetry } from './retry.js';
|
|
5
|
+
export type { RetryOptions } from './retry.js';
|
|
6
|
+
export type { ApiKeyRecord, InviteRecord, GroupSettingsResponse, WidgetConfigResponse, WidgetAdvisor, WidgetSecurityConfig, IntegrationAdvisor, IntegrationAdvisorFeedResponse, SessionEnvelope, ApiSession, LedgerEvent, ErrorResponse, } from './client.js';
|
|
7
|
+
export type { paths, components, operations } from './generated/v1.js';
|
package/dist/index.js
ADDED
package/dist/retry.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type RetryOptions = {
|
|
2
|
+
/** Maximum number of attempts (including the first). Default: 3 */
|
|
3
|
+
maxAttempts?: number;
|
|
4
|
+
/** Base backoff delay in milliseconds. Default: 1000 */
|
|
5
|
+
backoffMs?: number;
|
|
6
|
+
/** Maximum backoff delay in milliseconds. Default: 30000 */
|
|
7
|
+
maxBackoffMs?: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Retry an async function with exponential backoff and jitter.
|
|
11
|
+
*
|
|
12
|
+
* Only retries on `V1SdkError` where `retryable === true`.
|
|
13
|
+
* All other errors are thrown immediately.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const session = await withRetry(
|
|
18
|
+
* () => client.getSession({ sessionId: 'sess_abc' }),
|
|
19
|
+
* { maxAttempts: 5, backoffMs: 500 },
|
|
20
|
+
* );
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
|
package/dist/retry.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { V1SdkError } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Retry an async function with exponential backoff and jitter.
|
|
4
|
+
*
|
|
5
|
+
* Only retries on `V1SdkError` where `retryable === true`.
|
|
6
|
+
* All other errors are thrown immediately.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const session = await withRetry(
|
|
11
|
+
* () => client.getSession({ sessionId: 'sess_abc' }),
|
|
12
|
+
* { maxAttempts: 5, backoffMs: 500 },
|
|
13
|
+
* );
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export async function withRetry(fn, options) {
|
|
17
|
+
const maxAttempts = options?.maxAttempts ?? 3;
|
|
18
|
+
const backoffMs = options?.backoffMs ?? 1000;
|
|
19
|
+
const maxBackoffMs = options?.maxBackoffMs ?? 30_000;
|
|
20
|
+
let lastError;
|
|
21
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
22
|
+
try {
|
|
23
|
+
return await fn();
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
lastError = err;
|
|
27
|
+
const isRetryable = err instanceof V1SdkError && err.retryable === true;
|
|
28
|
+
if (!isRetryable || attempt === maxAttempts) {
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
// Exponential backoff with jitter: delay = min(base * 2^(attempt-1) + jitter, max)
|
|
32
|
+
const exponentialDelay = backoffMs * Math.pow(2, attempt - 1);
|
|
33
|
+
const jitter = Math.random() * backoffMs;
|
|
34
|
+
const delay = Math.min(exponentialDelay + jitter, maxBackoffMs);
|
|
35
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
throw lastError;
|
|
39
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@advizorconnect/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Typed SDK for Advizor Connect v1 integration APIs",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"CHANGELOG.md"
|
|
19
|
+
],
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc -p tsconfig.json"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
}
|
|
27
|
+
}
|