@roundtable-bb/sdk 0.1.5 → 0.1.9

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.
@@ -1,291 +1,403 @@
1
1
  // AUTO-GENERATED — do not edit manually.
2
2
  // Run `nx run @roundtable-bb/sdk:codegen` to regenerate.
3
3
 
4
- import type { ApiKey, Category, CreateApiKey, CreateCategory, CreateGroup, CreatePost, CreateTenant, CreateThread, CreatedApiKey, GrantPlatformOwner, Group, Id, Notification, PaginatedResponse, PlatformSetting, Post, ReorderCategory, SearchResponse, SearchResultType, SetGroupCategories, SetGroupPermissions, SetThreadReadStatus, SetUserGroups, Tenant, TenantToken, Thread, ThreadReadStatus, UpdateCategory, UpdateGroup, UpdatePlatformSetting, UpdateThread, UpdateUserProfile, UserMembership, UserProfile } from '@roundtable-bb/types'
4
+ import type { Category, CreateApiKey, CreateCategory, CreateGroup, CreatePost, CreateTenant, CreateThread, GrantPlatformOwner, Group, GroupMember, Id, Notification, OwnedTenant, PaginatedResponse, PlatformSetting, Post, ReorderCategory, SearchResponse, SearchResultType, SetCustomDomain, SetGroupCategories, SetGroupPermissions, SetThreadReadStatus, SetUserGroups, Tenant, TenantToken, Thread, ThreadReadStatus, UpdateCategory, UpdateGroup, UpdatePlatformSetting, UpdateThread, UpdateUserProfile, UserMembership, UserProfile } from '@roundtable-bb/types'
5
5
  import { request, type RoundtableClientOpts } from '../request.js'
6
6
 
7
- export class RoundtableClient {
7
+ export class AcpClient {
8
8
  constructor(private readonly opts: RoundtableClientOpts) {}
9
9
 
10
10
  /** Export a signed tenant backup (platform owners only) */
11
- backupTenant(params: { id: string }, query?: { includeContent?: boolean }): Promise<unknown> {
12
- return request(this.opts, 'GET', `/tenants/${params.id}/backup`, { query, useCredentials: true })
11
+ backupTenant(params: { tenantId: string }, query?: { includeContent?: boolean }): Promise<unknown> {
12
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/backup`, { query, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
13
13
  }
14
14
 
15
15
  /** Count read and unread notifications */
16
16
  countNotifications(): Promise<unknown> {
17
- return request(this.opts, 'GET', '/notifications/count', { useCredentials: true })
17
+ return request(this.opts, 'GET', '/api/notifications/count', { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true, acceptsTenantJwt: true } })
18
18
  }
19
19
 
20
20
  /** Create a platform-scoped API key (returned once in full) */
21
- createApiKey(body: CreateApiKey): Promise<CreatedApiKey> {
22
- return request(this.opts, 'POST', '/platform/api-keys', { body, useCredentials: true })
21
+ createApiKey(body: CreateApiKey): Promise<unknown> {
22
+ return request(this.opts, 'POST', '/api/platform/api-keys', { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
23
23
  }
24
24
 
25
25
  /** Create a category (requires category.create permission) */
26
- createCategory(body: CreateCategory): Promise<Category> {
27
- return request(this.opts, 'POST', '/categories', { body, useCredentials: true })
26
+ createCategory(params: { tenantId: string }, body: CreateCategory): Promise<Category> {
27
+ return request(this.opts, 'POST', `/api/tenants/${params.tenantId}/categories`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
28
28
  }
29
29
 
30
30
  /** Create a group (requires group.create permission) */
31
- createGroup(body: CreateGroup): Promise<Group> {
32
- return request(this.opts, 'POST', '/groups', { body, useCredentials: true })
31
+ createGroup(params: { tenantId: string }, body: CreateGroup): Promise<Group> {
32
+ return request(this.opts, 'POST', `/api/tenants/${params.tenantId}/groups`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
33
33
  }
34
34
 
35
35
  /** Create a post in a thread */
36
- createPost(params: { threadId: string }, body: CreatePost): Promise<Post> {
37
- if (!this.opts.token) throw new Error('createPost requires a token (API key or JWT)')
38
- return request(this.opts, 'POST', `/threads/${params.threadId}/posts`, { body })
36
+ createPost(params: { tenantId: string; threadId: string }, body: CreatePost): Promise<Post> {
37
+ return request(this.opts, 'POST', `/api/tenants/${params.tenantId}/threads/${params.threadId}/posts`, { body, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
39
38
  }
40
39
 
41
40
  /** Create a new tenant (requires allow_tenant_creation platform setting or platform owner) */
42
41
  createTenant(body: CreateTenant): Promise<Tenant> {
43
- return request(this.opts, 'POST', '/tenants', { body, useCredentials: true })
42
+ return request(this.opts, 'POST', '/api/tenants', { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
44
43
  }
45
44
 
46
45
  /** Create a thread (and its first post) */
47
- createThread(params: { categoryId: string }, body: CreateThread): Promise<Thread> {
48
- if (!this.opts.token) throw new Error('createThread requires a token (API key or JWT)')
49
- return request(this.opts, 'POST', `/categories/${params.categoryId}/threads`, { body })
46
+ createThread(params: { tenantId: string; categoryId: string }, body: CreateThread): Promise<Thread> {
47
+ return request(this.opts, 'POST', `/api/tenants/${params.tenantId}/categories/${params.categoryId}/threads`, { body, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
50
48
  }
51
49
 
52
50
  /** Delete a platform-scoped API key */
53
- deleteApiKey(params: { id: string }): Promise<void> {
54
- return request(this.opts, 'DELETE', `/platform/api-keys/${params.id}`, { useCredentials: true })
51
+ deleteApiKey(params: { keyId: string }): Promise<void> {
52
+ return request(this.opts, 'DELETE', `/api/platform/api-keys/${params.keyId}`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
55
53
  }
56
54
 
57
55
  /** Delete a category (requires category.delete permission) */
58
- deleteCategory(params: { id: string }): Promise<void> {
59
- return request(this.opts, 'DELETE', `/categories/${params.id}`, { useCredentials: true })
56
+ deleteCategory(params: { tenantId: string; categoryId: string }): Promise<void> {
57
+ return request(this.opts, 'DELETE', `/api/tenants/${params.tenantId}/categories/${params.categoryId}`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
60
58
  }
61
59
 
62
60
  /** Delete a group (requires group.delete permission) */
63
- deleteGroup(params: { id: string }): Promise<void> {
64
- return request(this.opts, 'DELETE', `/groups/${params.id}`, { useCredentials: true })
61
+ deleteGroup(params: { tenantId: string; groupId: string }): Promise<void> {
62
+ return request(this.opts, 'DELETE', `/api/tenants/${params.tenantId}/groups/${params.groupId}`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
65
63
  }
66
64
 
67
65
  /** Delete a notification */
68
- deleteNotification(params: { id: string }): Promise<void> {
69
- return request(this.opts, 'DELETE', `/notifications/${params.id}`, { useCredentials: true })
66
+ deleteNotification(params: { notificationId: string }): Promise<void> {
67
+ return request(this.opts, 'DELETE', `/api/notifications/${params.notificationId}`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
70
68
  }
71
69
 
72
70
  /** Soft-delete a post */
73
- deletePost(params: { id: string }): Promise<void> {
74
- if (!this.opts.token) throw new Error('deletePost requires a token (API key or JWT)')
75
- return request(this.opts, 'DELETE', `/posts/${params.id}`)
71
+ deletePost(params: { tenantId: string; postId: string }): Promise<void> {
72
+ return request(this.opts, 'DELETE', `/api/tenants/${params.tenantId}/posts/${params.postId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
76
73
  }
77
74
 
78
75
  /** Delete a thread */
79
- deleteThread(params: { id: string }): Promise<void> {
80
- if (!this.opts.token) throw new Error('deleteThread requires a token (API key or JWT)')
81
- return request(this.opts, 'DELETE', `/threads/${params.id}`)
76
+ deleteThread(params: { tenantId: string; threadId: string }): Promise<void> {
77
+ return request(this.opts, 'DELETE', `/api/tenants/${params.tenantId}/threads/${params.threadId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
82
78
  }
83
79
 
84
80
  /** Exchange session cookie for a short-lived tenant JWT */
85
81
  exchangeTenantToken(): Promise<TenantToken> {
86
- return request(this.opts, 'POST', '/tenant-token', { useCredentials: true })
82
+ return request(this.opts, 'POST', '/api/tenant-token', { routeAuth: { acceptsBetterAuth: true } })
87
83
  }
88
84
 
89
85
  /** Get a single category */
90
- getCategory(params: { id: string }): Promise<Category> {
91
- if (!this.opts.token) throw new Error('getCategory requires a token (API key or JWT)')
92
- return request(this.opts, 'GET', `/categories/${params.id}`)
86
+ getCategory(params: { tenantId: string; categoryId: string }): Promise<Category> {
87
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/categories/${params.categoryId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
93
88
  }
94
89
 
95
90
  /** Get a group */
96
- getGroup(params: { id: string }): Promise<Group> {
97
- if (!this.opts.token) throw new Error('getGroup requires a token (API key or JWT)')
98
- return request(this.opts, 'GET', `/groups/${params.id}`)
91
+ getGroup(params: { tenantId: string; groupId: string }): Promise<Group> {
92
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/groups/${params.groupId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
99
93
  }
100
94
 
101
95
  /** Get own profile */
102
96
  getMe(): Promise<UserProfile> {
103
- if (!this.opts.token) throw new Error('getMe requires a token (API key or JWT)')
104
- return request(this.opts, 'GET', '/users/me')
97
+ return request(this.opts, 'GET', '/api/users/me', { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true, acceptsTenantJwt: true } })
105
98
  }
106
99
 
107
100
  /** Get the current owner of a tenant */
108
- getTenantOwner(params: { id: string }): Promise<unknown> {
109
- return request(this.opts, 'GET', `/tenants/${params.id}/owner`, { useCredentials: true })
101
+ getTenantOwner(params: { tenantId: string }): Promise<unknown> {
102
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/owner`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
110
103
  }
111
104
 
112
105
  /** Get a single thread */
113
- getThread(params: { id: string }): Promise<Thread> {
114
- if (!this.opts.token) throw new Error('getThread requires a token (API key or JWT)')
115
- return request(this.opts, 'GET', `/threads/${params.id}`)
106
+ getThread(params: { tenantId: string; threadId: string }): Promise<Thread> {
107
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/threads/${params.threadId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
116
108
  }
117
109
 
118
110
  /** Get read status for the current user in a thread */
119
- getThreadReadStatus(params: { id: string }): Promise<ThreadReadStatus> {
120
- if (!this.opts.token) throw new Error('getThreadReadStatus requires a token (API key or JWT)')
121
- return request(this.opts, 'GET', `/threads/${params.id}/read-status`)
111
+ getThreadReadStatus(params: { tenantId: string; threadId: string }): Promise<ThreadReadStatus> {
112
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/threads/${params.threadId}/read-status`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
122
113
  }
123
114
 
124
115
  /** Get a user profile by ID */
125
- getUser(params: { id: string }): Promise<UserProfile> {
126
- if (!this.opts.token) throw new Error('getUser requires a token (API key or JWT)')
127
- return request(this.opts, 'GET', `/users/${params.id}`)
116
+ getUser(params: { userId: string }): Promise<UserProfile> {
117
+ return request(this.opts, 'GET', `/api/users/${params.userId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
128
118
  }
129
119
 
130
120
  /** Get user group memberships in the current tenant */
131
- getUserMembership(params: { id: string }): Promise<UserMembership> {
132
- if (!this.opts.token) throw new Error('getUserMembership requires a token (API key or JWT)')
133
- return request(this.opts, 'GET', `/users/${params.id}/membership`)
121
+ getUserMembership(params: { tenantId: string; userId: string }): Promise<UserMembership> {
122
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/users/${params.userId}/membership`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
134
123
  }
135
124
 
136
125
  /** Grant platform owner status to a user (platform owners only) */
137
126
  grantPlatformOwner(body: GrantPlatformOwner): Promise<void> {
138
- return request(this.opts, 'POST', '/platform/owners', { body, useCredentials: true })
127
+ return request(this.opts, 'POST', '/api/platform/owners', { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
139
128
  }
140
129
 
141
130
  /** List your platform-scoped API keys */
142
- listApiKeys(): Promise<ApiKey[]> {
143
- return request(this.opts, 'GET', '/platform/api-keys', { useCredentials: true })
131
+ listApiKeys(): Promise<unknown> {
132
+ return request(this.opts, 'GET', '/api/platform/api-keys', { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
144
133
  }
145
134
 
146
135
  /** List visible categories for the requesting user */
147
- listCategories(): Promise<Category[]> {
148
- if (!this.opts.token) throw new Error('listCategories requires a token (API key or JWT)')
149
- return request(this.opts, 'GET', '/categories')
136
+ listCategories(params: { tenantId: string }): Promise<Category[]> {
137
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/categories`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true, acceptsTenantJwt: true } })
138
+ }
139
+
140
+ /** List members of a group */
141
+ listGroupMembers(params: { tenantId: string; groupId: string }): Promise<GroupMember[]> {
142
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/groups/${params.groupId}/members`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true, acceptsTenantJwt: true } })
150
143
  }
151
144
 
152
145
  /** List groups */
153
- listGroups(): Promise<Group[]> {
154
- if (!this.opts.token) throw new Error('listGroups requires a token (API key or JWT)')
155
- return request(this.opts, 'GET', '/groups')
146
+ listGroups(params: { tenantId: string }): Promise<Group[]> {
147
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/groups`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true, acceptsTenantJwt: true } })
156
148
  }
157
149
 
158
150
  /** Get unified notification inbox */
159
151
  listNotifications(query?: { cursor?: Id; limit?: number; unreadOnly?: boolean }): Promise<PaginatedResponse<Notification>> {
160
- return request(this.opts, 'GET', '/notifications', { query, useCredentials: true })
152
+ return request(this.opts, 'GET', '/api/notifications', { query, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
161
153
  }
162
154
 
163
155
  /** List platform owner user IDs (platform owners only) */
164
156
  listPlatformOwners(): Promise<string[]> {
165
- return request(this.opts, 'GET', '/platform/owners', { useCredentials: true })
157
+ return request(this.opts, 'GET', '/api/platform/owners', { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
166
158
  }
167
159
 
168
160
  /** List all platform settings (platform owners only) */
169
161
  listPlatformSettings(): Promise<PlatformSetting[]> {
170
- return request(this.opts, 'GET', '/platform/settings', { useCredentials: true })
162
+ return request(this.opts, 'GET', '/api/platform/settings', { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
171
163
  }
172
164
 
173
165
  /** List posts in a thread — cursor pagination or anchor via ?from=postId */
174
- listPosts(params: { threadId: string }, query?: { cursor?: Id; limit?: number; from?: Id }): Promise<PaginatedResponse<Post>> {
175
- if (!this.opts.token) throw new Error('listPosts requires a token (API key or JWT)')
176
- return request(this.opts, 'GET', `/threads/${params.threadId}/posts`, { query })
166
+ listPosts(params: { tenantId: string; threadId: string }, query?: { cursor?: Id; limit?: number; from?: Id }): Promise<PaginatedResponse<Post>> {
167
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/threads/${params.threadId}/posts`, { query, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
168
+ }
169
+
170
+ /** List tenants owned by the current user (platform owners see all) */
171
+ listTenants(query?: { search?: string }): Promise<OwnedTenant[]> {
172
+ return request(this.opts, 'GET', '/api/tenants', { query, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
177
173
  }
178
174
 
179
175
  /** List threads in a category */
180
- listThreads(params: { categoryId: string }, query?: { cursor?: Id; limit?: number }): Promise<PaginatedResponse<Thread>> {
181
- if (!this.opts.token) throw new Error('listThreads requires a token (API key or JWT)')
182
- return request(this.opts, 'GET', `/categories/${params.categoryId}/threads`, { query })
176
+ listThreads(params: { tenantId: string; categoryId: string }, query?: { cursor?: Id; limit?: number }): Promise<PaginatedResponse<Thread>> {
177
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/categories/${params.categoryId}/threads`, { query, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
183
178
  }
184
179
 
185
180
  /** Mark a notification as read */
186
- markNotificationRead(params: { id: string }): Promise<Notification> {
187
- return request(this.opts, 'PATCH', `/notifications/${params.id}/read`, { useCredentials: true })
181
+ markNotificationRead(params: { notificationId: string }): Promise<Notification> {
182
+ return request(this.opts, 'PATCH', `/api/notifications/${params.notificationId}/read`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
188
183
  }
189
184
 
190
185
  /** Set the position of each category (requires category.edit permission) */
191
- reorderCategories(body: ReorderCategory): Promise<void> {
192
- return request(this.opts, 'PUT', '/categories/reorder', { body, useCredentials: true })
186
+ reorderCategories(params: { tenantId: string }, body: ReorderCategory): Promise<void> {
187
+ return request(this.opts, 'PUT', `/api/tenants/${params.tenantId}/categories/reorder`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
193
188
  }
194
189
 
195
190
  /** Set the position of each group (requires group.edit permission) */
196
- reorderGroups(body: ReorderCategory): Promise<void> {
197
- return request(this.opts, 'PUT', '/groups/reorder', { body, useCredentials: true })
191
+ reorderGroups(params: { tenantId: string }, body: ReorderCategory): Promise<void> {
192
+ return request(this.opts, 'PUT', `/api/tenants/${params.tenantId}/groups/reorder`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
198
193
  }
199
194
 
200
195
  /** Restore a tenant from a signed backup (platform owners only) */
201
- restoreTenant(params: { id: string }, body: unknown): Promise<unknown> {
202
- return request(this.opts, 'POST', `/tenants/${params.id}/restore`, { body, useCredentials: true })
196
+ restoreTenant(params: { tenantId: string }, body: unknown): Promise<unknown> {
197
+ return request(this.opts, 'POST', `/api/tenants/${params.tenantId}/restore`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
203
198
  }
204
199
 
205
200
  /** Revoke platform owner status from a user (platform owners only) */
206
201
  revokePlatformOwner(params: { userId: string }): Promise<void> {
207
- return request(this.opts, 'DELETE', `/platform/owners/${params.userId}`, { useCredentials: true })
202
+ return request(this.opts, 'DELETE', `/api/platform/owners/${params.userId}`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
208
203
  }
209
204
 
210
205
  /** Full-text search across threads and posts (visible categories only) */
211
- search(query?: { q: string; type?: SearchResultType; categoryId?: Id; limit?: number }): Promise<SearchResponse> {
212
- if (!this.opts.token) throw new Error('search requires a token (API key or JWT)')
213
- return request(this.opts, 'GET', '/search', { query })
206
+ search(params: { tenantId: string }, query?: { q: string; type?: SearchResultType; categoryId?: Id; limit?: number }): Promise<SearchResponse> {
207
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/search`, { query, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
214
208
  }
215
209
 
216
210
  /** Set category visibility for a group (requires group.edit permission) */
217
- setGroupCategories(params: { id: string }, body: SetGroupCategories): Promise<Group> {
218
- if (!this.opts.token) throw new Error('setGroupCategories requires a token (API key or JWT)')
219
- return request(this.opts, 'PUT', `/groups/${params.id}/categories`, { body })
211
+ setGroupCategories(params: { tenantId: string; groupId: string }, body: SetGroupCategories): Promise<Group> {
212
+ return request(this.opts, 'PUT', `/api/tenants/${params.tenantId}/groups/${params.groupId}/categories`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
220
213
  }
221
214
 
222
215
  /** Replace all permissions for a group (requires group.edit permission) */
223
- setGroupPermissions(params: { id: string }, body: SetGroupPermissions): Promise<Group> {
224
- if (!this.opts.token) throw new Error('setGroupPermissions requires a token (API key or JWT)')
225
- return request(this.opts, 'PUT', `/groups/${params.id}/permissions`, { body })
216
+ setGroupPermissions(params: { tenantId: string; groupId: string }, body: SetGroupPermissions): Promise<Group> {
217
+ return request(this.opts, 'PUT', `/api/tenants/${params.tenantId}/groups/${params.groupId}/permissions`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
218
+ }
219
+
220
+ /** Set or remove the custom domain for a tenant */
221
+ setTenantCustomDomain(params: { tenantId: string }, body: SetCustomDomain): Promise<void> {
222
+ return request(this.opts, 'PUT', `/api/tenants/${params.tenantId}/custom-domain`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
226
223
  }
227
224
 
228
225
  /** Mark a thread as read up to a given post */
229
- setThreadReadStatus(params: { id: string }, body: SetThreadReadStatus): Promise<void> {
230
- if (!this.opts.token) throw new Error('setThreadReadStatus requires a token (API key or JWT)')
231
- return request(this.opts, 'PUT', `/threads/${params.id}/read-status`, { body })
226
+ setThreadReadStatus(params: { tenantId: string; threadId: string }, body: SetThreadReadStatus): Promise<void> {
227
+ return request(this.opts, 'PUT', `/api/tenants/${params.tenantId}/threads/${params.threadId}/read-status`, { body, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
232
228
  }
233
229
 
234
230
  /** Replace user group assignments in the current tenant (requires group.assign permission) */
235
- setUserGroups(params: { id: string }, body: SetUserGroups): Promise<UserMembership> {
236
- if (!this.opts.token) throw new Error('setUserGroups requires a token (API key or JWT)')
237
- return request(this.opts, 'PUT', `/users/${params.id}/membership`, { body })
231
+ setUserGroups(params: { tenantId: string; userId: string }, body: SetUserGroups): Promise<UserMembership> {
232
+ return request(this.opts, 'PUT', `/api/tenants/${params.tenantId}/users/${params.userId}/membership`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
238
233
  }
239
234
 
240
235
  /** Subscribe to a thread */
241
- subscribeThread(params: { id: string }): Promise<void> {
242
- if (!this.opts.token) throw new Error('subscribeThread requires a token (API key or JWT)')
243
- return request(this.opts, 'POST', `/threads/${params.id}/subscribe`)
236
+ subscribeThread(params: { tenantId: string; threadId: string }): Promise<void> {
237
+ return request(this.opts, 'POST', `/api/tenants/${params.tenantId}/threads/${params.threadId}/subscribe`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
244
238
  }
245
239
 
246
240
  /** Transfer tenant ownership to another existing user (only the current owner can do this) */
247
- transferTenantOwner(params: { id: string }, body: GrantPlatformOwner): Promise<void> {
248
- return request(this.opts, 'PUT', `/tenants/${params.id}/owner`, { body, useCredentials: true })
241
+ transferTenantOwner(params: { tenantId: string }, body: GrantPlatformOwner): Promise<void> {
242
+ return request(this.opts, 'PUT', `/api/tenants/${params.tenantId}/owner`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
249
243
  }
250
244
 
251
245
  /** Unsubscribe from a thread */
252
- unsubscribeThread(params: { id: string }): Promise<void> {
253
- if (!this.opts.token) throw new Error('unsubscribeThread requires a token (API key or JWT)')
254
- return request(this.opts, 'DELETE', `/threads/${params.id}/subscribe`)
246
+ unsubscribeThread(params: { tenantId: string; threadId: string }): Promise<void> {
247
+ return request(this.opts, 'DELETE', `/api/tenants/${params.tenantId}/threads/${params.threadId}/subscribe`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
255
248
  }
256
249
 
257
250
  /** Update a category (requires category.edit permission) */
258
- updateCategory(params: { id: string }, body: UpdateCategory): Promise<Category> {
259
- if (!this.opts.token) throw new Error('updateCategory requires a token (API key or JWT)')
260
- return request(this.opts, 'PATCH', `/categories/${params.id}`, { body })
251
+ updateCategory(params: { tenantId: string; categoryId: string }, body: UpdateCategory): Promise<Category> {
252
+ return request(this.opts, 'PATCH', `/api/tenants/${params.tenantId}/categories/${params.categoryId}`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
261
253
  }
262
254
 
263
255
  /** Update a group (requires group.edit permission) */
264
- updateGroup(params: { id: string }, body: UpdateGroup): Promise<Group> {
265
- if (!this.opts.token) throw new Error('updateGroup requires a token (API key or JWT)')
266
- return request(this.opts, 'PATCH', `/groups/${params.id}`, { body })
256
+ updateGroup(params: { tenantId: string; groupId: string }, body: UpdateGroup): Promise<Group> {
257
+ return request(this.opts, 'PATCH', `/api/tenants/${params.tenantId}/groups/${params.groupId}`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
267
258
  }
268
259
 
269
260
  /** Update own profile */
270
261
  updateMe(body: UpdateUserProfile): Promise<UserProfile> {
271
- if (!this.opts.token) throw new Error('updateMe requires a token (API key or JWT)')
272
- return request(this.opts, 'PATCH', '/users/me', { body })
262
+ return request(this.opts, 'PATCH', '/api/users/me', { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
273
263
  }
274
264
 
275
265
  /** Update a platform setting (platform owners only) */
276
266
  updatePlatformSetting(params: { key: string }, body: UpdatePlatformSetting): Promise<PlatformSetting> {
277
- return request(this.opts, 'PATCH', `/platform/settings/${params.key}`, { body, useCredentials: true })
267
+ return request(this.opts, 'PATCH', `/api/platform/settings/${params.key}`, { body, routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true } })
268
+ }
269
+
270
+ /** Edit a post (author or post.edit permission) */
271
+ updatePost(params: { tenantId: string; postId: string }, body: CreatePost): Promise<Post> {
272
+ return request(this.opts, 'PATCH', `/api/tenants/${params.tenantId}/posts/${params.postId}`, { body, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
273
+ }
274
+
275
+ /** Update a thread (title, pin, lock, move) */
276
+ updateThread(params: { tenantId: string; threadId: string }, body: UpdateThread): Promise<Thread> {
277
+ return request(this.opts, 'PATCH', `/api/tenants/${params.tenantId}/threads/${params.threadId}`, { body, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
278
+ }
279
+ }
280
+
281
+ export class TenantClient {
282
+ constructor(private readonly opts: RoundtableClientOpts) {}
283
+
284
+ /** Count read and unread notifications */
285
+ countNotifications(): Promise<unknown> {
286
+ return request(this.opts, 'GET', '/api/notifications/count', { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true, acceptsTenantJwt: true } })
287
+ }
288
+
289
+ /** Create a post in a thread */
290
+ createPost(params: { tenantId: string; threadId: string }, body: CreatePost): Promise<Post> {
291
+ return request(this.opts, 'POST', `/api/tenants/${params.tenantId}/threads/${params.threadId}/posts`, { body, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
292
+ }
293
+
294
+ /** Create a thread (and its first post) */
295
+ createThread(params: { tenantId: string; categoryId: string }, body: CreateThread): Promise<Thread> {
296
+ return request(this.opts, 'POST', `/api/tenants/${params.tenantId}/categories/${params.categoryId}/threads`, { body, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
297
+ }
298
+
299
+ /** Soft-delete a post */
300
+ deletePost(params: { tenantId: string; postId: string }): Promise<void> {
301
+ return request(this.opts, 'DELETE', `/api/tenants/${params.tenantId}/posts/${params.postId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
302
+ }
303
+
304
+ /** Delete a thread */
305
+ deleteThread(params: { tenantId: string; threadId: string }): Promise<void> {
306
+ return request(this.opts, 'DELETE', `/api/tenants/${params.tenantId}/threads/${params.threadId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
307
+ }
308
+
309
+ /** Exchange session cookie for a short-lived tenant JWT */
310
+ exchangeTenantToken(): Promise<TenantToken> {
311
+ return request(this.opts, 'POST', '/api/tenant-token', { routeAuth: { acceptsBetterAuth: true, tenantUseCredentials: true } })
312
+ }
313
+
314
+ /** Get a single category */
315
+ getCategory(params: { tenantId: string; categoryId: string }): Promise<Category> {
316
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/categories/${params.categoryId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
317
+ }
318
+
319
+ /** Get a group */
320
+ getGroup(params: { tenantId: string; groupId: string }): Promise<Group> {
321
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/groups/${params.groupId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
322
+ }
323
+
324
+ /** Get own profile */
325
+ getMe(): Promise<UserProfile> {
326
+ return request(this.opts, 'GET', '/api/users/me', { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true, acceptsTenantJwt: true } })
327
+ }
328
+
329
+ /** Get a single thread */
330
+ getThread(params: { tenantId: string; threadId: string }): Promise<Thread> {
331
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/threads/${params.threadId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
332
+ }
333
+
334
+ /** Get read status for the current user in a thread */
335
+ getThreadReadStatus(params: { tenantId: string; threadId: string }): Promise<ThreadReadStatus> {
336
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/threads/${params.threadId}/read-status`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
337
+ }
338
+
339
+ /** Get a user profile by ID */
340
+ getUser(params: { userId: string }): Promise<UserProfile> {
341
+ return request(this.opts, 'GET', `/api/users/${params.userId}`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
342
+ }
343
+
344
+ /** Get user group memberships in the current tenant */
345
+ getUserMembership(params: { tenantId: string; userId: string }): Promise<UserMembership> {
346
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/users/${params.userId}/membership`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
347
+ }
348
+
349
+ /** List visible categories for the requesting user */
350
+ listCategories(params: { tenantId: string }): Promise<Category[]> {
351
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/categories`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true, acceptsTenantJwt: true } })
352
+ }
353
+
354
+ /** List members of a group */
355
+ listGroupMembers(params: { tenantId: string; groupId: string }): Promise<GroupMember[]> {
356
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/groups/${params.groupId}/members`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true, acceptsTenantJwt: true } })
357
+ }
358
+
359
+ /** List groups */
360
+ listGroups(params: { tenantId: string }): Promise<Group[]> {
361
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/groups`, { routeAuth: { acceptsApiKey: true, acceptsBetterAuth: true, acceptsTenantJwt: true } })
362
+ }
363
+
364
+ /** List posts in a thread — cursor pagination or anchor via ?from=postId */
365
+ listPosts(params: { tenantId: string; threadId: string }, query?: { cursor?: Id; limit?: number; from?: Id }): Promise<PaginatedResponse<Post>> {
366
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/threads/${params.threadId}/posts`, { query, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
367
+ }
368
+
369
+ /** List threads in a category */
370
+ listThreads(params: { tenantId: string; categoryId: string }, query?: { cursor?: Id; limit?: number }): Promise<PaginatedResponse<Thread>> {
371
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/categories/${params.categoryId}/threads`, { query, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
372
+ }
373
+
374
+ /** Full-text search across threads and posts (visible categories only) */
375
+ search(params: { tenantId: string }, query?: { q: string; type?: SearchResultType; categoryId?: Id; limit?: number }): Promise<SearchResponse> {
376
+ return request(this.opts, 'GET', `/api/tenants/${params.tenantId}/search`, { query, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
377
+ }
378
+
379
+ /** Mark a thread as read up to a given post */
380
+ setThreadReadStatus(params: { tenantId: string; threadId: string }, body: SetThreadReadStatus): Promise<void> {
381
+ return request(this.opts, 'PUT', `/api/tenants/${params.tenantId}/threads/${params.threadId}/read-status`, { body, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
382
+ }
383
+
384
+ /** Subscribe to a thread */
385
+ subscribeThread(params: { tenantId: string; threadId: string }): Promise<void> {
386
+ return request(this.opts, 'POST', `/api/tenants/${params.tenantId}/threads/${params.threadId}/subscribe`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
387
+ }
388
+
389
+ /** Unsubscribe from a thread */
390
+ unsubscribeThread(params: { tenantId: string; threadId: string }): Promise<void> {
391
+ return request(this.opts, 'DELETE', `/api/tenants/${params.tenantId}/threads/${params.threadId}/subscribe`, { routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
278
392
  }
279
393
 
280
394
  /** Edit a post (author or post.edit permission) */
281
- updatePost(params: { id: string }, body: CreatePost): Promise<Post> {
282
- if (!this.opts.token) throw new Error('updatePost requires a token (API key or JWT)')
283
- return request(this.opts, 'PATCH', `/posts/${params.id}`, { body })
395
+ updatePost(params: { tenantId: string; postId: string }, body: CreatePost): Promise<Post> {
396
+ return request(this.opts, 'PATCH', `/api/tenants/${params.tenantId}/posts/${params.postId}`, { body, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
284
397
  }
285
398
 
286
399
  /** Update a thread (title, pin, lock, move) */
287
- updateThread(params: { id: string }, body: UpdateThread): Promise<Thread> {
288
- if (!this.opts.token) throw new Error('updateThread requires a token (API key or JWT)')
289
- return request(this.opts, 'PATCH', `/threads/${params.id}`, { body })
400
+ updateThread(params: { tenantId: string; threadId: string }, body: UpdateThread): Promise<Thread> {
401
+ return request(this.opts, 'PATCH', `/api/tenants/${params.tenantId}/threads/${params.threadId}`, { body, routeAuth: { acceptsApiKey: true, acceptsTenantJwt: true } })
290
402
  }
291
403
  }
package/src/index.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { RoundtableClient } from './generated/client.js'
1
+ export { AcpClient, TenantClient } from './generated/client.js'
2
2
  export type { RoundtableClientOpts } from './request.js'
3
3
  export type * from '@roundtable-bb/types'
package/src/request.ts CHANGED
@@ -3,12 +3,45 @@ export interface RoundtableClientOpts {
3
3
  token?: string
4
4
  }
5
5
 
6
+ interface RouteAuth {
7
+ acceptsApiKey?: boolean
8
+ acceptsBetterAuth?: boolean
9
+ acceptsTenantJwt?: boolean
10
+ requiresToken?: boolean
11
+ tenantUseCredentials?: boolean
12
+ }
13
+
6
14
  export async function request<T>(
7
15
  opts: RoundtableClientOpts,
8
16
  method: string,
9
17
  path: string,
10
- options?: { body?: unknown; query?: Record<string, unknown>; useCredentials?: boolean },
18
+ options?: {
19
+ body?: unknown
20
+ query?: Record<string, unknown>
21
+ useCredentials?: boolean
22
+ routeAuth?: RouteAuth
23
+ },
11
24
  ): Promise<T> {
25
+ const routeAuth = options?.routeAuth
26
+ let useCredentials = options?.useCredentials ?? false
27
+
28
+ // Decide auth strategy
29
+ if (routeAuth) {
30
+ // TenantClient: use credentials if explicitly required by route
31
+ if (routeAuth.tenantUseCredentials) {
32
+ useCredentials = true
33
+ }
34
+ // If token is available, use it (prefer token over credentials)
35
+ else if (opts.token && routeAuth.acceptsApiKey) {
36
+ useCredentials = false
37
+ }
38
+ // If no token but route accepts better-auth: use credentials
39
+ else if (!opts.token && routeAuth.acceptsBetterAuth) {
40
+ useCredentials = true
41
+ }
42
+ // Otherwise: make request without auth (backend will respond 401/403 if needed)
43
+ }
44
+
12
45
  const url = new URL(`${opts.baseUrl}${path}`)
13
46
  if (options?.query) {
14
47
  for (const [k, v] of Object.entries(options.query)) {
@@ -18,10 +51,10 @@ export async function request<T>(
18
51
 
19
52
  const res = await fetch(url.toString(), {
20
53
  method,
21
- credentials: options?.useCredentials ? 'include' : undefined,
54
+ credentials: useCredentials ? 'include' : undefined,
22
55
  headers: {
23
56
  ...(options?.body !== undefined ? { 'Content-Type': 'application/json' } : {}),
24
- ...(opts.token ? { Authorization: `Bearer ${opts.token}` } : {}),
57
+ ...(opts.token && !useCredentials ? { Authorization: `Bearer ${opts.token}` } : {}),
25
58
  },
26
59
  body: options?.body !== undefined ? JSON.stringify(options.body) : undefined,
27
60
  })