@digisglobal/omnivox-sdk 0.5.0 → 0.6.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/dist/index.d.ts CHANGED
@@ -33,11 +33,289 @@ declare function createApiKeyTokenProvider(apiKey: string): TokenProvider;
33
33
  */
34
34
  declare function createSessionTokenProvider(): TokenProvider;
35
35
 
36
+ /**
37
+ * Canned-responses module — hand-written typed wrapper over the generated client.
38
+ *
39
+ * Exposes the Phase-2 canned-responses resource:
40
+ * - list(opts) → GET /api/v1/canned-responses (paginated)
41
+ * - search(opts) → GET /api/v1/canned-responses?q= (title/keyword search)
42
+ * - create(input) → POST /api/v1/canned-responses
43
+ * - update(id, input) → PATCH /api/v1/canned-responses/:id
44
+ * - delete(id) → DELETE /api/v1/canned-responses/:id
45
+ *
46
+ * Never re-exports symbols from _generated/.
47
+ * Contains no business logic — typed transport only.
48
+ */
49
+
50
+ /** Options to construct the canned-responses module. */
51
+ interface CannedResponsesModuleOptions extends TokenProvider {
52
+ /** Base URL of the Omnivox API (e.g. "https://api.omnivox.io"). */
53
+ baseUrl: string;
54
+ }
55
+ /** Input for creating a canned response. */
56
+ interface CreateCannedResponseInput {
57
+ title: string;
58
+ body: string;
59
+ keywords: string[];
60
+ [key: string]: unknown;
61
+ }
62
+ /** Input for partially updating a canned response. */
63
+ interface UpdateCannedResponseInput {
64
+ title?: string;
65
+ body?: string;
66
+ keywords?: string[];
67
+ [key: string]: unknown;
68
+ }
69
+ /** Canned response resource shape returned by the API. */
70
+ interface CannedResponseItem {
71
+ id: string;
72
+ title: string;
73
+ body: string;
74
+ keywords: string[];
75
+ [key: string]: unknown;
76
+ }
77
+ /** Paginated list response. */
78
+ interface PagedList$5<T> {
79
+ data: T[];
80
+ meta: {
81
+ page: number;
82
+ pageSize: number;
83
+ total: number;
84
+ hasNextPage: boolean;
85
+ };
86
+ }
87
+ /** Pagination options for list(). */
88
+ interface CannedResponseListOpts {
89
+ page: number;
90
+ pageSize: number;
91
+ [key: string]: unknown;
92
+ }
93
+ /** Pagination + search options for search(). */
94
+ interface CannedResponseSearchOpts {
95
+ page: number;
96
+ pageSize: number;
97
+ q: string;
98
+ [key: string]: unknown;
99
+ }
100
+ /**
101
+ * Creates the canned-responses module — a thin typed wrapper over the generated client.
102
+ */
103
+ declare function createCannedResponsesModule(options: CannedResponsesModuleOptions): {
104
+ /**
105
+ * List canned responses (paginated, no search filter).
106
+ * pageSize is clamped to 100 per the API contract.
107
+ * Calls GET /api/v1/canned-responses.
108
+ */
109
+ list(opts: CannedResponseListOpts): Promise<PagedList$5<CannedResponseItem>>;
110
+ /**
111
+ * Search canned responses by title substring or keyword prefix.
112
+ * pageSize is clamped to 100 per the API contract.
113
+ * Calls GET /api/v1/canned-responses?q=<term>.
114
+ */
115
+ search(opts: CannedResponseSearchOpts): Promise<PagedList$5<CannedResponseItem>>;
116
+ /**
117
+ * Create a canned response.
118
+ * Calls POST /api/v1/canned-responses.
119
+ */
120
+ create(input: CreateCannedResponseInput): Promise<CannedResponseItem>;
121
+ /**
122
+ * Partially update a canned response — title, body, and/or keywords.
123
+ * Calls PATCH /api/v1/canned-responses/:id.
124
+ */
125
+ update(id: string, input: UpdateCannedResponseInput): Promise<CannedResponseItem>;
126
+ /**
127
+ * Delete a canned response by id.
128
+ * Calls DELETE /api/v1/canned-responses/:id.
129
+ */
130
+ delete(id: string): Promise<void>;
131
+ };
132
+ /** Return type of createCannedResponsesModule. */
133
+ type CannedResponsesModule = ReturnType<typeof createCannedResponsesModule>;
134
+
135
+ /**
136
+ * Templates module — hand-written typed wrapper over the generated client.
137
+ *
138
+ * Exposes the Phase-2 templates surface via two submodules:
139
+ *
140
+ * whatsapp (WABA-scoped):
141
+ * - authorDraft(tenantId, wabaId, input) → POST /api/v1/tenants/:id/whatsapp-business-accounts/:wabaId/templates
142
+ * - importApproved(tenantId, wabaId) → POST /api/v1/tenants/:id/whatsapp-business-accounts/:wabaId/templates/import
143
+ * - update(tenantId, wabaId, templateId, input) → PATCH /api/v1/tenants/:id/whatsapp-business-accounts/:wabaId/templates/:templateId
144
+ * - history(tenantId, wabaId, templateId) → GET /api/v1/tenants/:id/whatsapp-business-accounts/:wabaId/templates/:templateId/history
145
+ * - submit(tenantId, wabaId, templateId) → POST /api/v1/tenants/:id/whatsapp-business-accounts/:wabaId/templates/:templateId/submit
146
+ *
147
+ * email (tenant-scoped):
148
+ * - create(input) → POST /api/v1/templates/email
149
+ * - list(opts) → GET /api/v1/templates/email
150
+ * - getById(id) → GET /api/v1/templates/email/:id
151
+ * - patch(id, input) → PATCH /api/v1/templates/email/:id
152
+ * - delete(id) → DELETE /api/v1/templates/email/:id
153
+ *
154
+ * Never re-exports symbols from _generated/.
155
+ * Contains no business logic — typed transport only.
156
+ */
157
+
158
+ /** Options to construct the templates module. */
159
+ interface TemplatesModuleOptions extends TokenProvider {
160
+ /** Base URL of the Omnivox API (e.g. "https://api.omnivox.io"). */
161
+ baseUrl: string;
162
+ }
163
+ /** Input for creating a new draft WhatsApp template (version 1). */
164
+ interface AuthorDraftInput {
165
+ name: string;
166
+ language: string;
167
+ category?: string;
168
+ [key: string]: unknown;
169
+ }
170
+ /** Input for updating (forking a new DRAFT version of) a WhatsApp template. */
171
+ interface UpdateWhatsAppTemplateInput {
172
+ body?: string;
173
+ [key: string]: unknown;
174
+ }
175
+ /** A WhatsApp template version history event. */
176
+ interface WhatsAppTemplateHistoryEvent {
177
+ version: number;
178
+ status: string;
179
+ updatedAt: string;
180
+ [key: string]: unknown;
181
+ }
182
+ /** A WhatsApp template item returned by the API. */
183
+ interface WhatsAppTemplateItem {
184
+ id: string;
185
+ name: string;
186
+ language: string;
187
+ status?: string;
188
+ [key: string]: unknown;
189
+ }
190
+ /** Import-approved result. */
191
+ interface ImportApprovedResult {
192
+ imported: number;
193
+ [key: string]: unknown;
194
+ }
195
+ /** Submit result. */
196
+ interface SubmitResult {
197
+ status: string;
198
+ [key: string]: unknown;
199
+ }
200
+ /** Input for creating an Email template. */
201
+ interface CreateEmailTemplateInput {
202
+ name: string;
203
+ subject: string;
204
+ htmlBody?: string;
205
+ textBody?: string;
206
+ variableSchema?: Record<string, unknown>;
207
+ [key: string]: unknown;
208
+ }
209
+ /** Input for partially updating an Email template. */
210
+ interface PatchEmailTemplateInput {
211
+ name?: string;
212
+ subject?: string;
213
+ htmlBody?: string;
214
+ textBody?: string;
215
+ variableSchema?: Record<string, unknown>;
216
+ [key: string]: unknown;
217
+ }
218
+ /** An Email template item returned by the API. */
219
+ interface EmailTemplateItem {
220
+ id: string;
221
+ name: string;
222
+ subject: string;
223
+ htmlBody?: string;
224
+ textBody?: string;
225
+ variableSchema?: Record<string, unknown>;
226
+ [key: string]: unknown;
227
+ }
228
+ /** Paginated list response. */
229
+ interface TemplatesPagedList<T> {
230
+ data: T[];
231
+ meta: {
232
+ page: number;
233
+ pageSize: number;
234
+ total: number;
235
+ hasNextPage: boolean;
236
+ };
237
+ }
238
+ /** Pagination options for email templates list. */
239
+ interface EmailTemplateListOpts {
240
+ page: number;
241
+ pageSize: number;
242
+ [key: string]: unknown;
243
+ }
244
+ /**
245
+ * Creates the templates module — a thin typed wrapper over the generated client.
246
+ * Returns two submodules: `whatsapp` (WABA-scoped) and `email` (tenant-scoped).
247
+ */
248
+ declare function createTemplatesModule(options: TemplatesModuleOptions): {
249
+ /**
250
+ * WhatsApp template submodule — WABA-scoped operations.
251
+ */
252
+ whatsapp: {
253
+ /**
254
+ * Author a new DRAFT template (version 1) under a WhatsApp Business Account.
255
+ * Calls POST /api/v1/tenants/:id/whatsapp-business-accounts/:wabaId/templates.
256
+ */
257
+ authorDraft(tenantId: string, wabaId: string, input: AuthorDraftInput): Promise<WhatsAppTemplateItem>;
258
+ /**
259
+ * Import all APPROVED templates from the WABA into the system (immediately sendable).
260
+ * Calls POST /api/v1/tenants/:id/whatsapp-business-accounts/:wabaId/templates/import.
261
+ */
262
+ importApproved(tenantId: string, wabaId: string): Promise<ImportApprovedResult>;
263
+ /**
264
+ * Fork a new DRAFT version from the latest version of a template (update).
265
+ * Calls PATCH /api/v1/tenants/:id/whatsapp-business-accounts/:wabaId/templates/:templateId.
266
+ */
267
+ update(tenantId: string, wabaId: string, templateId: string, input: UpdateWhatsAppTemplateInput): Promise<WhatsAppTemplateItem>;
268
+ /**
269
+ * List all versions and status events for a template in chronological order.
270
+ * Calls GET /api/v1/tenants/:id/whatsapp-business-accounts/:wabaId/templates/:templateId/history.
271
+ */
272
+ history(tenantId: string, wabaId: string, templateId: string): Promise<WhatsAppTemplateHistoryEvent[]>;
273
+ /**
274
+ * Submit a DRAFT template version to Meta for review and approval (DRAFT → PENDING_APPROVAL).
275
+ * Calls POST /api/v1/tenants/:id/whatsapp-business-accounts/:wabaId/templates/:templateId/submit.
276
+ */
277
+ submit(tenantId: string, wabaId: string, templateId: string): Promise<SubmitResult>;
278
+ };
279
+ /**
280
+ * Email template submodule — tenant-scoped operations.
281
+ */
282
+ email: {
283
+ /**
284
+ * Create an Email template for the authenticated tenant.
285
+ * Calls POST /api/v1/templates/email.
286
+ */
287
+ create(input: CreateEmailTemplateInput): Promise<EmailTemplateItem>;
288
+ /**
289
+ * List Email templates for the authenticated tenant (paginated).
290
+ * Calls GET /api/v1/templates/email.
291
+ */
292
+ list(opts: EmailTemplateListOpts): Promise<TemplatesPagedList<EmailTemplateItem>>;
293
+ /**
294
+ * Get an Email template by id.
295
+ * Calls GET /api/v1/templates/email/:id.
296
+ */
297
+ getById(id: string): Promise<EmailTemplateItem>;
298
+ /**
299
+ * Partially update an Email template — name, subject, htmlBody, textBody, and/or variableSchema; omitted fields unchanged.
300
+ * Calls PATCH /api/v1/templates/email/:id.
301
+ */
302
+ patch(id: string, input: PatchEmailTemplateInput): Promise<EmailTemplateItem>;
303
+ /**
304
+ * Delete an Email template.
305
+ * Calls DELETE /api/v1/templates/email/:id.
306
+ */
307
+ delete(id: string): Promise<void>;
308
+ };
309
+ };
310
+ /** Return type of createTemplatesModule. */
311
+ type TemplatesModule = ReturnType<typeof createTemplatesModule>;
312
+
36
313
  /**
37
314
  * Messages module — hand-written typed wrapper over the generated client.
38
315
  *
39
316
  * Exposes the Phase-1 messaging surface for the messages resource:
40
317
  * - send(input) → POST /api/v1/messages
318
+ * - sendTemplate(input) → POST /api/v1/messages/send-template
41
319
  * - list(opts) → GET /api/v1/messages (pageSize capped at 100)
42
320
  * - get(id) → GET /api/v1/messages/:id
43
321
  * - delete(id) → DELETE /api/v1/messages/:id
@@ -55,8 +333,22 @@ interface MessagesModuleOptions extends TokenProvider {
55
333
  interface SendMessageInput {
56
334
  conversationId: string;
57
335
  body: string;
336
+ /**
337
+ * Optional list of draft attachment UUIDs to link to this message (F11-T05).
338
+ * Omitting the field (or passing []) skips linking.
339
+ */
340
+ attachmentIds?: string[];
58
341
  [key: string]: unknown;
59
342
  }
343
+ /** Input for sending a template message in a conversation. */
344
+ interface SendTemplateInput {
345
+ conversationId: string;
346
+ templateId: string;
347
+ /** Positional variables for WhatsApp templates (index-ordered). */
348
+ variables?: string[];
349
+ /** Named variables for Email templates (key = variable name from variableSchema). */
350
+ emailVariables?: Record<string, string>;
351
+ }
60
352
  /** Message resource shape returned by the API. */
61
353
  interface MessageItem {
62
354
  id: string;
@@ -106,6 +398,13 @@ declare function createMessagesModule(options: MessagesModuleOptions): {
106
398
  * Calls DELETE /api/v1/messages/:id.
107
399
  */
108
400
  delete(id: string): Promise<void>;
401
+ /**
402
+ * Send a template message in a conversation (WhatsApp or Email).
403
+ * Branches on the conversation channel type — WhatsApp uses positional
404
+ * `variables`; Email uses named `emailVariables`.
405
+ * Calls POST /api/v1/messages/send-template.
406
+ */
407
+ sendTemplate(input: SendTemplateInput): Promise<MessageItem>;
109
408
  };
110
409
  /** Return type of createMessagesModule. */
111
410
  type MessagesModule = ReturnType<typeof createMessagesModule>;
@@ -120,6 +419,7 @@ type MessagesModule = ReturnType<typeof createMessagesModule>;
120
419
  * - assign(id, input) → PATCH /api/v1/conversations/:id/assign
121
420
  * - listLobby(opts) → GET /api/v1/conversations/lobby (pageSize capped at 100)
122
421
  * - pickup(entryId, input) → POST /api/v1/conversations/lobby/:entryId/pickup
422
+ * - whatsappRecoveryOptions(id) → GET /api/v1/conversations/:id/whatsapp-recovery-options
123
423
  *
124
424
  * Never re-exports symbols from _generated/.
125
425
  * Contains no business logic — typed transport only.
@@ -193,6 +493,17 @@ interface LobbyListOpts {
193
493
  page: number;
194
494
  pageSize: number;
195
495
  }
496
+ /**
497
+ * A single WhatsApp template eligible to re-open an expired 24-hour
498
+ * customer-service window. Mirrors RecoveryOptionResult from the API service.
499
+ */
500
+ interface WhatsAppRecoveryOption {
501
+ templateId: string;
502
+ name: string;
503
+ language: string;
504
+ versionId: string;
505
+ versionNumber: number;
506
+ }
196
507
  /**
197
508
  * Creates the conversations module — a thin typed wrapper over the generated client.
198
509
  */
@@ -238,6 +549,13 @@ declare function createConversationsModule(options: ConversationsModuleOptions):
238
549
  pickup(entryId: string, input: PickupInput): Promise<{
239
550
  data: ConversationItem;
240
551
  }>;
552
+ /**
553
+ * List APPROVED + SENDABLE WhatsApp templates eligible to re-open an
554
+ * expired 24-hour customer-service window for the given conversation.
555
+ * Returns an empty array when the channel is not WhatsApp or has no linked WABA.
556
+ * Calls GET /api/v1/conversations/:id/whatsapp-recovery-options.
557
+ */
558
+ whatsappRecoveryOptions(id: string): Promise<WhatsAppRecoveryOption[]>;
241
559
  };
242
560
  /** Return type of createConversationsModule. */
243
561
  type ConversationsModule = ReturnType<typeof createConversationsModule>;
@@ -550,6 +868,203 @@ declare function createTenantsModule(options: TenantsModuleOptions): {
550
868
  /** Return type of createTenantsModule. */
551
869
  type TenantsModule = ReturnType<typeof createTenantsModule>;
552
870
 
871
+ /**
872
+ * WS-only event payload registry — single source of truth for the four
873
+ * WS-only events that have no REST/openapi counterpart and therefore no
874
+ * orval → _generated pipeline:
875
+ *
876
+ * typing:indicator · message:read:update · participant:joined · participant:left
877
+ *
878
+ * The runtime constant {@link WS_EVENT_REGISTRY} must stay byte-identical with
879
+ * ws-event-shapes.fixture.json. Two contract tests enforce this:
880
+ *
881
+ * 1. packages/sdk/src/ws/ws-event-registry.test.ts — asserts WS_EVENT_REGISTRY
882
+ * matches the fixture at the SDK level.
883
+ * 2. apps/api/tests/contract/ws-event-shapes.test.ts — asserts the ChatGateway
884
+ * source emits each event with exactly the fields listed in the fixture.
885
+ *
886
+ * Any divergence — whether the gateway changes an emit payload or this registry
887
+ * drifts from the fixture — fails CI before the change can ship.
888
+ *
889
+ * Typed transport only — no imports from apps/api/, no _generated/ re-exports,
890
+ * no business logic.
891
+ */
892
+ /**
893
+ * Payload for the `typing:indicator` server → client event.
894
+ * Emitted by the gateway when an agent starts or stops typing in a conversation.
895
+ */
896
+ interface TypingIndicatorPayload {
897
+ conversationId: string;
898
+ actor: unknown;
899
+ state: 'start' | 'stop';
900
+ }
901
+ /**
902
+ * Payload for the `message:read:update` server → client event.
903
+ * Emitted when an agent's read cursor advances in a conversation.
904
+ */
905
+ interface MessageReadUpdatePayload {
906
+ conversationId: string;
907
+ agentId: string;
908
+ lastReadMessageId: string;
909
+ readAt: string;
910
+ [key: string]: unknown;
911
+ }
912
+ /**
913
+ * Payload for the `participant:joined` and `participant:left` server → client events.
914
+ * Emitted when an agent enters or leaves a conversation room.
915
+ */
916
+ interface ParticipantPayload {
917
+ conversationId: string;
918
+ actor: unknown;
919
+ [key: string]: unknown;
920
+ }
921
+
922
+ /**
923
+ * WebSocket client — hand-written typed wrapper over socket.io-client.
924
+ *
925
+ * Connects to the Omnivox API's `/ws/chat` namespace. Reconnection with
926
+ * exponential backoff + jitter (cap 30 s) is configured automatically —
927
+ * the consumer never needs to wire reconnect logic.
928
+ *
929
+ * Event payloads for the four WS-only events (typing:indicator,
930
+ * message:read:update, participant:joined, participant:left) are defined once
931
+ * in ws-event-registry.ts and imported here. All other payload types
932
+ * (message:new, message:status, conversation:update) are defined locally
933
+ * because they mirror the REST openapi view contracts.
934
+ *
935
+ * Never re-exports symbols from _generated/.
936
+ * Contains no business logic — typed transport only.
937
+ */
938
+
939
+ /** Authentication credential for the WebSocket handshake. */
940
+ type WsAuth = {
941
+ token: string;
942
+ } | {
943
+ apiKey: string;
944
+ };
945
+ /** Observable connection state for the WebSocket client. */
946
+ type WsConnectionState = 'connecting' | 'connected' | 'reconnecting' | 'disconnected';
947
+ /** Options to construct the WS client. */
948
+ interface WsClientOptions {
949
+ /**
950
+ * Base URL of the Omnivox API (e.g. "https://api.omnivox.io").
951
+ * The WS client appends `/ws/chat` to form the namespace URL.
952
+ */
953
+ baseUrl: string;
954
+ /**
955
+ * Authentication for the Socket.IO handshake.
956
+ * Pass `{ token }` for session/OIDC auth or `{ apiKey }` for API-key auth.
957
+ * These map directly to `socket.handshake.auth.token` /
958
+ * `socket.handshake.auth.apiKey` on the server.
959
+ *
960
+ * Omit entirely when authenticating via an HttpOnly session cookie — the
961
+ * browser sends the cookie automatically when `withCredentials` is true.
962
+ */
963
+ auth?: WsAuth;
964
+ /**
965
+ * When true, socket.io-client sends credentials (cookies, TLS client certs)
966
+ * on the polling/WebSocket handshake requests. Required for the Console,
967
+ * which authenticates via an HttpOnly SESSION COOKIE with no explicit token.
968
+ *
969
+ * Defaults to false (matches socket.io-client's default).
970
+ */
971
+ withCredentials?: boolean;
972
+ }
973
+ /** Payload for the `message:status` server event. */
974
+ interface MessageStatusPayload {
975
+ messageId: string;
976
+ conversationId: string;
977
+ status: string;
978
+ [key: string]: unknown;
979
+ }
980
+ /**
981
+ * Maps every server-emitted event name to its payload type.
982
+ *
983
+ * `message:new` and `conversation:update` reuse the SDK's MessageItem /
984
+ * ConversationItem types which mirror the openapi view contracts.
985
+ * All other payload types are defined locally — only the mapping is hand-written.
986
+ */
987
+ interface WsEventPayloads {
988
+ 'message:new': MessageItem;
989
+ 'message:status': MessageStatusPayload;
990
+ 'conversation:update': ConversationItem;
991
+ 'message:read:update': MessageReadUpdatePayload;
992
+ 'participant:joined': ParticipantPayload;
993
+ 'participant:left': ParticipantPayload;
994
+ 'typing:indicator': TypingIndicatorPayload;
995
+ }
996
+ /** The WebSocket client returned by {@link createWsClient}. */
997
+ interface WsClient {
998
+ /** Current connection state — safe to read synchronously at any time. */
999
+ readonly state: WsConnectionState;
1000
+ /**
1001
+ * Subscribe to connection state changes.
1002
+ * Returns an unsubscribe function. Call it to stop receiving notifications.
1003
+ */
1004
+ onStateChange(listener: (state: WsConnectionState) => void): () => void;
1005
+ /**
1006
+ * Subscribe to a typed server event.
1007
+ * Returns an unsubscribe function. Call it to remove the handler.
1008
+ *
1009
+ * @example
1010
+ * const unsub = client.on('message:new', (msg) => console.log(msg.id))
1011
+ * // later:
1012
+ * unsub()
1013
+ */
1014
+ on<K extends keyof WsEventPayloads>(event: K, handler: (payload: WsEventPayloads[K]) => void): () => void;
1015
+ /**
1016
+ * Request to join a conversation room.
1017
+ * Emits `conversation:join` to the server; the server verifies ownership
1018
+ * before adding the socket to the room.
1019
+ */
1020
+ joinConversation(conversationId: string): void;
1021
+ /**
1022
+ * Request to leave a conversation room.
1023
+ * Emits `conversation:leave` to the server.
1024
+ */
1025
+ leaveConversation(conversationId: string): void;
1026
+ /**
1027
+ * Signal that the local agent started typing in a conversation.
1028
+ * Emits `typing:start` to the server.
1029
+ */
1030
+ typingStart(conversationId: string): void;
1031
+ /**
1032
+ * Signal that the local agent stopped typing in a conversation.
1033
+ * Emits `typing:stop` to the server.
1034
+ */
1035
+ typingStop(conversationId: string): void;
1036
+ /**
1037
+ * Mark messages as read up to and including `lastReadMessageId`.
1038
+ * Emits `message:read` to the server.
1039
+ */
1040
+ markRead(conversationId: string, lastReadMessageId: string): void;
1041
+ /**
1042
+ * Disconnect the socket and release all internal resources.
1043
+ * After calling this, the client is unusable.
1044
+ */
1045
+ disconnect(): void;
1046
+ }
1047
+ /**
1048
+ * Creates a WebSocket client connected to `<baseUrl>/ws/chat`.
1049
+ *
1050
+ * Reconnection is fully automatic — the consumer must not wire reconnect logic.
1051
+ * The socket reconnects with exponential backoff starting at 1 s, doubling
1052
+ * each attempt with ±50 % jitter, capped at 30 s. Socket.IO handles all
1053
+ * transport-level retry internally.
1054
+ *
1055
+ * @example
1056
+ * const ws = createWsClient({
1057
+ * baseUrl: 'https://api.omnivox.io',
1058
+ * auth: { apiKey: 'ovx_live_abc123' },
1059
+ * })
1060
+ *
1061
+ * const unsub = ws.on('message:new', (msg) => console.log(msg))
1062
+ * ws.joinConversation('conv_001')
1063
+ */
1064
+ declare function createWsClient(options: WsClientOptions): WsClient;
1065
+ /** Return type of {@link createWsClient}. */
1066
+ type WsClientInstance = ReturnType<typeof createWsClient>;
1067
+
553
1068
  /** Options for {@link createOmnivoxClient}. */
554
1069
  interface OmnivoxClientOptions {
555
1070
  /** Base URL of the Omnivox API (e.g. "https://api.omnivox.io"). */
@@ -560,6 +1075,7 @@ interface OmnivoxClientOptions {
560
1075
  */
561
1076
  tokenProvider: TokenProvider;
562
1077
  }
1078
+
563
1079
  /**
564
1080
  * Creates a composed Omnivox client exposing every Phase-1 resource module.
565
1081
  * The token provider is read per request (not captured at construction), so
@@ -614,13 +1130,66 @@ declare function createOmnivoxClient(options: OmnivoxClientOptions): {
614
1130
  pickup(entryId: string, input: PickupInput): Promise<{
615
1131
  data: ConversationItem;
616
1132
  }>;
1133
+ whatsappRecoveryOptions(id: string): Promise<WhatsAppRecoveryOption[]>;
617
1134
  };
618
1135
  messages: {
619
1136
  send(input: SendMessageInput): Promise<MessageItem>;
620
1137
  list(opts: MessageListOpts): Promise<PagedList$4<MessageItem>>;
621
1138
  get(id: string): Promise<MessageItem>;
622
1139
  delete(id: string): Promise<void>;
1140
+ sendTemplate(input: SendTemplateInput): Promise<MessageItem>;
1141
+ };
1142
+ templates: {
1143
+ whatsapp: {
1144
+ authorDraft(tenantId: string, wabaId: string, input: AuthorDraftInput): Promise<WhatsAppTemplateItem>;
1145
+ importApproved(tenantId: string, wabaId: string): Promise<ImportApprovedResult>;
1146
+ update(tenantId: string, wabaId: string, templateId: string, input: UpdateWhatsAppTemplateInput): Promise<WhatsAppTemplateItem>;
1147
+ history(tenantId: string, wabaId: string, templateId: string): Promise<WhatsAppTemplateHistoryEvent[]>;
1148
+ submit(tenantId: string, wabaId: string, templateId: string): Promise<SubmitResult>;
1149
+ };
1150
+ email: {
1151
+ create(input: CreateEmailTemplateInput): Promise<EmailTemplateItem>;
1152
+ list(opts: EmailTemplateListOpts): Promise<TemplatesPagedList<EmailTemplateItem>>;
1153
+ getById(id: string): Promise<EmailTemplateItem>;
1154
+ patch(id: string, input: PatchEmailTemplateInput): Promise<EmailTemplateItem>;
1155
+ delete(id: string): Promise<void>;
1156
+ };
1157
+ };
1158
+ cannedResponses: {
1159
+ list(opts: CannedResponseListOpts): Promise<PagedList$5<CannedResponseItem>>;
1160
+ search(opts: CannedResponseSearchOpts): Promise<PagedList$5<CannedResponseItem>>;
1161
+ create(input: CreateCannedResponseInput): Promise<CannedResponseItem>;
1162
+ update(id: string, input: UpdateCannedResponseInput): Promise<CannedResponseItem>;
1163
+ delete(id: string): Promise<void>;
1164
+ };
1165
+ attachments: {
1166
+ upload(file: Blob | Uint8Array, _opts?: Record<string, unknown>): Promise<AttachmentUploadResult>;
1167
+ url(id: string): Promise<AttachmentUrlResult>;
623
1168
  };
1169
+ whatsappBusinessAccounts: {
1170
+ list(tenantId: string): Promise<WhatsAppBusinessAccountItem[]>;
1171
+ get(tenantId: string, wabaRowId: string): Promise<WhatsAppBusinessAccountItem>;
1172
+ };
1173
+ /**
1174
+ * Creates a WebSocket client connected to the `/ws/chat` namespace.
1175
+ *
1176
+ * Call this factory once and reuse the returned client. Reconnection with
1177
+ * exponential backoff + jitter (cap 30 s) is fully automatic.
1178
+ *
1179
+ * For API-key or token auth, pass the credential explicitly:
1180
+ * @example
1181
+ * const ws = client.connect({ apiKey: 'ovx_live_abc' })
1182
+ * ws.on('message:new', (msg) => console.log(msg))
1183
+ * ws.joinConversation('conv_001')
1184
+ *
1185
+ * For session/cookie auth (Console), call with no argument — the token
1186
+ * provider's `getCredentials() === 'include'` signals cookie mode and
1187
+ * `withCredentials` is set automatically:
1188
+ * @example
1189
+ * const ws = client.connect()
1190
+ * ws.on('message:new', (msg) => console.log(msg))
1191
+ */
1192
+ connect: (auth?: WsAuth) => WsClient;
624
1193
  };
625
1194
  /** Composed client returned by {@link createOmnivoxClient}. */
626
1195
  type OmnivoxClient = ReturnType<typeof createOmnivoxClient>;
@@ -896,4 +1465,127 @@ declare function createChannelsModule(options: ChannelsModuleOptions): {
896
1465
  /** Return type of createChannelsModule. */
897
1466
  type ChannelsModule = ReturnType<typeof createChannelsModule>;
898
1467
 
899
- export { type AddIdentityInput, type AgentItem, type AgentsModule, type AgentsModuleOptions, type ApiKeyItem, type AssignInput, type AuthMeAgent, type AuthMeModule, type AuthMeModuleOptions, type AuthMeResponse, type AuthMeTenant, type BasicEmailChannelConfig, type BasicEmailChannelSecret, type Channel, type ChannelListItem, type ChannelStatus, type ChannelType, type ChannelsModule, type ChannelsModuleOptions, type ContactIdentity, type ContactIdentityInput, type ContactItem, type ContactSearchOpts, type ContactsMetadata, type ContactsModule, type ContactsModuleOptions, type ConversationItem, type ConversationListOpts, type ConversationsModule, type ConversationsModuleOptions, type CreateAgentInput, type CreateApiKeyInput, type CreateApiKeyResponse, type CreateChannelBody, type CreateContactInput, type CreateEmailChannelBody, type CreateWhatsAppChannelBody, type CredentialsMode, type EmailChannelConfig, type EmailChannelSecret, type EmailImapConfig, type EmailSmtpConfig, type LobbyEntry, type LobbyListOpts, type MessageItem, type MessageListOpts, type MessagesModule, type MessagesModuleOptions, type OAuth2CertificateEmailChannelSecret, type OAuth2ClientSecretEmailChannelSecret, type OAuth2EmailChannelConfig, type OAuth2EmailChannelSecret, type OmnivoxClient, type OmnivoxClientOptions, OmnivoxRequestError, type PageOpts, type PageParams, type PagedResponse, type PatchContactInput, type PickupInput, type ReopenOrCreateInput, type RevokeApiKeyResponse, type SendMessageInput, type TenantsModule, type TenantsModuleOptions, type TokenProvider, type UpdateChannelBody, type UpdateStatusInput, type WhatsAppChannelConfig, buildPageParams, createAgentsModule, createApiKeyTokenProvider, createAuthMeModule, createChannelsModule, createContactsModule, createConversationsModule, createMessagesModule, createOmnivoxClient, createSessionTokenProvider, createTenantsModule, iteratePages };
1468
+ /**
1469
+ * Attachments module — hand-written typed wrapper over the generated client.
1470
+ *
1471
+ * Exposes the Phase-2 attachment surface:
1472
+ * - upload(file, opts?) → POST /api/v1/attachments (multipart/form-data)
1473
+ * - url(id) → GET /api/v1/attachments/:id/url
1474
+ *
1475
+ * Upload works in both Node 22+ (Blob/Uint8Array) and the browser (File/Blob).
1476
+ * Content-Type is NOT set manually — fetch sets the multipart boundary.
1477
+ *
1478
+ * Never re-exports symbols from _generated/.
1479
+ * Contains no business logic — typed transport only.
1480
+ */
1481
+
1482
+ /** Options to construct the attachments module. */
1483
+ interface AttachmentsModuleOptions extends TokenProvider {
1484
+ /** Base URL of the Omnivox API (e.g. "https://api.omnivox.io"). */
1485
+ baseUrl: string;
1486
+ }
1487
+ /** Response shape returned by POST /api/v1/attachments. */
1488
+ interface AttachmentUploadResult {
1489
+ /** Opaque attachment identifier. Pass this to the send-message endpoint. */
1490
+ attachmentId: string;
1491
+ /** MIME type detected by the API. */
1492
+ mimeType: string;
1493
+ /** File size in bytes. */
1494
+ sizeBytes: number;
1495
+ }
1496
+ /** Response shape returned by GET /api/v1/attachments/:id/url. */
1497
+ interface AttachmentUrlResult {
1498
+ /** Short-lived presigned GET URL (TTL ≤ 15 min). */
1499
+ url: string;
1500
+ /** ISO-8601 string at which the presigned URL expires. */
1501
+ expiresAt: string;
1502
+ }
1503
+ /**
1504
+ * Creates the attachments module — a thin typed wrapper over the generated client.
1505
+ */
1506
+ declare function createAttachmentsModule(options: AttachmentsModuleOptions): {
1507
+ /**
1508
+ * Upload a file as a draft attachment.
1509
+ *
1510
+ * Accepts a Blob or File (browser) or a Uint8Array wrapped in a Blob (Node 22+).
1511
+ * Content-Type is intentionally omitted from headers so that fetch (both
1512
+ * Node 22 built-in and browser) can set the multipart/form-data boundary.
1513
+ *
1514
+ * Calls POST /api/v1/attachments.
1515
+ */
1516
+ upload(file: Blob | Uint8Array, _opts?: Record<string, unknown>): Promise<AttachmentUploadResult>;
1517
+ /**
1518
+ * Get a short-lived presigned download URL for a stored attachment.
1519
+ * The URL is valid for ≤ 15 minutes (NF-09).
1520
+ *
1521
+ * Calls GET /api/v1/attachments/:id/url.
1522
+ */
1523
+ url(id: string): Promise<AttachmentUrlResult>;
1524
+ };
1525
+ /** Return type of createAttachmentsModule. */
1526
+ type AttachmentsModule = ReturnType<typeof createAttachmentsModule>;
1527
+
1528
+ /**
1529
+ * WhatsApp Business Accounts module — hand-written typed wrapper over the generated client.
1530
+ *
1531
+ * Exposes the WABA read surface (WABA-as-identity, tenant-scoped):
1532
+ * - list(tenantId) → GET /api/v1/tenants/:id/whatsapp-business-accounts
1533
+ * - get(tenantId, wabaRowId) → GET /api/v1/tenants/:id/whatsapp-business-accounts/:wabaRowId
1534
+ *
1535
+ * The Console's WhatsApp templates page uses this to let an admin pick a WABA
1536
+ * before authoring templates (`sdk.templates.whatsapp.*` requires a `wabaId`).
1537
+ *
1538
+ * Never re-exports symbols from _generated/.
1539
+ * Contains no business logic — typed transport only.
1540
+ */
1541
+
1542
+ /** Options to construct the WhatsApp Business Accounts module. */
1543
+ interface WhatsAppBusinessAccountsModuleOptions extends TokenProvider {
1544
+ /** Base URL of the Omnivox API (e.g. "https://api.omnivox.io"). */
1545
+ baseUrl: string;
1546
+ }
1547
+ /**
1548
+ * Non-secret WABA view returned by the API.
1549
+ * Never includes `secretRef` or any secret material (ADR-0011).
1550
+ */
1551
+ interface WhatsAppBusinessAccountItem {
1552
+ /** Row id (internal, use this for template API calls as `wabaId`). */
1553
+ id: string;
1554
+ /** The Meta WABA id string stored on the row. */
1555
+ wabaId: string;
1556
+ /** Human-readable display name set by the tenant admin. */
1557
+ name: string;
1558
+ /** ISO 8601 creation timestamp. */
1559
+ createdAt: string;
1560
+ /** ISO 8601 last-updated timestamp. */
1561
+ updatedAt: string;
1562
+ }
1563
+ /**
1564
+ * Creates the WhatsApp Business Accounts module — a thin typed wrapper over
1565
+ * the generated client. Covers the WABA read surface (list + get by row id).
1566
+ */
1567
+ declare function createWhatsAppBusinessAccountsModule(options: WhatsAppBusinessAccountsModuleOptions): {
1568
+ /**
1569
+ * List all WhatsApp Business Accounts for the tenant.
1570
+ * Returns a non-secret view — no secretRef is exposed.
1571
+ * Calls GET /api/v1/tenants/:id/whatsapp-business-accounts.
1572
+ *
1573
+ * @example
1574
+ * const wabas = await sdk.whatsappBusinessAccounts.list('ten_acmecorp')
1575
+ * // pick wabas[0].id as the wabaId for sdk.templates.whatsapp.*
1576
+ */
1577
+ list(tenantId: string): Promise<WhatsAppBusinessAccountItem[]>;
1578
+ /**
1579
+ * Get a single WhatsApp Business Account by its row id.
1580
+ * Returns a non-secret view — no secretRef is exposed.
1581
+ * Calls GET /api/v1/tenants/:id/whatsapp-business-accounts/:wabaRowId.
1582
+ *
1583
+ * @example
1584
+ * const waba = await sdk.whatsappBusinessAccounts.get('ten_acmecorp', 'waba_row_001')
1585
+ */
1586
+ get(tenantId: string, wabaRowId: string): Promise<WhatsAppBusinessAccountItem>;
1587
+ };
1588
+ /** Return type of createWhatsAppBusinessAccountsModule. */
1589
+ type WhatsAppBusinessAccountsModule = ReturnType<typeof createWhatsAppBusinessAccountsModule>;
1590
+
1591
+ export { type AddIdentityInput, type AgentItem, type AgentsModule, type AgentsModuleOptions, type ApiKeyItem, type AssignInput, type AttachmentUploadResult, type AttachmentUrlResult, type AttachmentsModule, type AttachmentsModuleOptions, type AuthMeAgent, type AuthMeModule, type AuthMeModuleOptions, type AuthMeResponse, type AuthMeTenant, type AuthorDraftInput, type BasicEmailChannelConfig, type BasicEmailChannelSecret, type CannedResponseItem, type CannedResponseListOpts, type CannedResponseSearchOpts, type CannedResponsesModule, type CannedResponsesModuleOptions, type Channel, type ChannelListItem, type ChannelStatus, type ChannelType, type ChannelsModule, type ChannelsModuleOptions, type ContactIdentity, type ContactIdentityInput, type ContactItem, type ContactSearchOpts, type ContactsMetadata, type ContactsModule, type ContactsModuleOptions, type ConversationItem, type ConversationListOpts, type ConversationsModule, type ConversationsModuleOptions, type CreateAgentInput, type CreateApiKeyInput, type CreateApiKeyResponse, type CreateCannedResponseInput, type CreateChannelBody, type CreateContactInput, type CreateEmailChannelBody, type CreateEmailTemplateInput, type CreateWhatsAppChannelBody, type CredentialsMode, type EmailChannelConfig, type EmailChannelSecret, type EmailImapConfig, type EmailSmtpConfig, type EmailTemplateItem, type EmailTemplateListOpts, type ImportApprovedResult, type LobbyEntry, type LobbyListOpts, type MessageItem, type MessageListOpts, type MessageReadUpdatePayload, type MessageStatusPayload, type MessagesModule, type MessagesModuleOptions, type OAuth2CertificateEmailChannelSecret, type OAuth2ClientSecretEmailChannelSecret, type OAuth2EmailChannelConfig, type OAuth2EmailChannelSecret, type OmnivoxClient, type OmnivoxClientOptions, OmnivoxRequestError, type PageOpts, type PageParams, type PagedResponse, type ParticipantPayload, type PatchContactInput, type PatchEmailTemplateInput, type PickupInput, type ReopenOrCreateInput, type RevokeApiKeyResponse, type SendMessageInput, type SendTemplateInput, type SubmitResult, type TemplatesModule, type TemplatesModuleOptions, type TenantsModule, type TenantsModuleOptions, type TokenProvider, type TypingIndicatorPayload, type UpdateCannedResponseInput, type UpdateChannelBody, type UpdateStatusInput, type UpdateWhatsAppTemplateInput, type WhatsAppBusinessAccountItem, type WhatsAppBusinessAccountsModule, type WhatsAppBusinessAccountsModuleOptions, type WhatsAppChannelConfig, type WhatsAppRecoveryOption, type WhatsAppTemplateHistoryEvent, type WhatsAppTemplateItem, type WsAuth, type WsClient, type WsClientInstance, type WsClientOptions, type WsConnectionState, type WsEventPayloads, buildPageParams, createAgentsModule, createApiKeyTokenProvider, createAttachmentsModule, createAuthMeModule, createCannedResponsesModule, createChannelsModule, createContactsModule, createConversationsModule, createMessagesModule, createOmnivoxClient, createSessionTokenProvider, createTemplatesModule, createTenantsModule, createWhatsAppBusinessAccountsModule, createWsClient, iteratePages };