@wazapi/sdk 0.3.0 → 0.4.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/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AcceptedResult, Channel, Contact, ContactWrite, Conversation, ExecuteFlowInput, Flow, ListParams, Message, Operation, Paginated, SendMessageInput, Template } from './types.js';
1
+ import type { AcceptedResult, Channel, Contact, ContactWrite, Conversation, ConversationDetail, ExecuteFlowInput, Flow, ListParams, Message, Operation, Paginated, SendMessageInput, StoreBatchResult, StoreOrder, StoreOrderStatus, StoreProduct, StoreProductWrite, StoreSummary, Template } from './types.js';
2
2
  export interface WazapiClientOptions {
3
3
  /** Bearer token issued in Settings → Wazapi API (starts with `waz_api_`). */
4
4
  token: string;
@@ -45,7 +45,15 @@ export declare class WazapiClient {
45
45
  getFlow(uuid: string): Promise<Flow>;
46
46
  executeFlow(flowUuid: string, input: ExecuteFlowInput, idempotencyKey?: string): Promise<AcceptedResult>;
47
47
  listConversations(params?: ListParams): Promise<Paginated<Conversation>>;
48
- getConversation(uuid: string): Promise<Conversation>;
48
+ /**
49
+ * Everything about the chat in one call: contact (with tags), assigned agent
50
+ * and group, channel, status and counters. Pass `options.include = 'messages'`
51
+ * to embed the first page of messages — audio messages carry their
52
+ * `transcript` as a first-level field.
53
+ */
54
+ getConversation(uuid: string, options?: {
55
+ include?: 'messages';
56
+ }): Promise<ConversationDetail>;
49
57
  listMessages(conversationUuid: string, params?: ListParams): Promise<Paginated<Message>>;
50
58
  sendMessage(input: SendMessageInput, idempotencyKey?: string): Promise<AcceptedResult>;
51
59
  /** Convenience wrapper for a plain text send. */
@@ -56,6 +64,28 @@ export declare class WazapiClient {
56
64
  language?: string;
57
65
  parameters?: string[];
58
66
  }, idempotencyKey?: string): Promise<AcceptedResult>;
67
+ /** Storefront status, public URL and product/order counts. Requires `store:read`. */
68
+ getStore(): Promise<StoreSummary>;
69
+ listStoreProducts(params?: ListParams): Promise<Paginated<StoreProduct>>;
70
+ getStoreProduct(uuid: string): Promise<StoreProduct>;
71
+ createStoreProduct(input: StoreProductWrite): Promise<StoreProduct>;
72
+ updateStoreProduct(uuid: string, input: StoreProductWrite): Promise<StoreProduct>;
73
+ /**
74
+ * Creates or updates up to 100 products in one call with a per-item result —
75
+ * one invalid product does not fail the batch. Items whose `import_handle`
76
+ * matches an existing product UPDATE it instead of creating a duplicate: this
77
+ * is the migration path for an external catalog (Shopify, an ERP).
78
+ */
79
+ batchStoreProducts(products: StoreProductWrite[]): Promise<StoreBatchResult>;
80
+ listStoreOrders(params?: ListParams): Promise<Paginated<StoreOrder>>;
81
+ getStoreOrder(uuid: string): Promise<StoreOrder>;
82
+ /**
83
+ * Transitions an order through its state machine (novo→confirmado→pago→entregue,
84
+ * cancel from any non-terminal state). An invalid transition throws a
85
+ * `WazapiError` with code `invalid_status_transition` (422). Cancelling
86
+ * restores tracked stock.
87
+ */
88
+ updateStoreOrderStatus(uuid: string, status: Exclude<StoreOrderStatus, 'novo'>): Promise<StoreOrder>;
59
89
  getOperation(uuid: string): Promise<Operation>;
60
90
  /**
61
91
  * Polls an operation until it reaches a terminal status. Resolves with the final
package/dist/client.js CHANGED
@@ -62,8 +62,17 @@ export class WazapiClient {
62
62
  listConversations(params = {}) {
63
63
  return this.request('GET', this.withQuery('/conversations', params));
64
64
  }
65
- async getConversation(uuid) {
66
- const body = await this.request('GET', `/conversations/${encode(uuid)}`);
65
+ /**
66
+ * Everything about the chat in one call: contact (with tags), assigned agent
67
+ * and group, channel, status and counters. Pass `options.include = 'messages'`
68
+ * to embed the first page of messages — audio messages carry their
69
+ * `transcript` as a first-level field.
70
+ */
71
+ async getConversation(uuid, options = {}) {
72
+ const path = options.include
73
+ ? `/conversations/${encode(uuid)}?include=${options.include}`
74
+ : `/conversations/${encode(uuid)}`;
75
+ const body = await this.request('GET', path);
67
76
  return body.data;
68
77
  }
69
78
  listMessages(conversationUuid, params = {}) {
@@ -81,6 +90,55 @@ export class WazapiClient {
81
90
  sendTemplate(channelUuid, phone, template, idempotencyKey) {
82
91
  return this.sendMessage({ channel_uuid: channelUuid, recipient: { phone }, type: 'template', content: template }, idempotencyKey);
83
92
  }
93
+ // ---- Store ------------------------------------------------------------
94
+ /** Storefront status, public URL and product/order counts. Requires `store:read`. */
95
+ async getStore() {
96
+ const body = await this.request('GET', '/store');
97
+ return body.data;
98
+ }
99
+ listStoreProducts(params = {}) {
100
+ return this.request('GET', this.withQuery('/store/products', params));
101
+ }
102
+ async getStoreProduct(uuid) {
103
+ const body = await this.request('GET', `/store/products/${encode(uuid)}`);
104
+ return body.data;
105
+ }
106
+ async createStoreProduct(input) {
107
+ const body = await this.request('POST', '/store/products', {
108
+ body: input,
109
+ });
110
+ return body.data;
111
+ }
112
+ async updateStoreProduct(uuid, input) {
113
+ const body = await this.request('PATCH', `/store/products/${encode(uuid)}`, { body: input });
114
+ return body.data;
115
+ }
116
+ /**
117
+ * Creates or updates up to 100 products in one call with a per-item result —
118
+ * one invalid product does not fail the batch. Items whose `import_handle`
119
+ * matches an existing product UPDATE it instead of creating a duplicate: this
120
+ * is the migration path for an external catalog (Shopify, an ERP).
121
+ */
122
+ batchStoreProducts(products) {
123
+ return this.request('POST', '/store/products/batch', { body: { products } });
124
+ }
125
+ listStoreOrders(params = {}) {
126
+ return this.request('GET', this.withQuery('/store/orders', params));
127
+ }
128
+ async getStoreOrder(uuid) {
129
+ const body = await this.request('GET', `/store/orders/${encode(uuid)}`);
130
+ return body.data;
131
+ }
132
+ /**
133
+ * Transitions an order through its state machine (novo→confirmado→pago→entregue,
134
+ * cancel from any non-terminal state). An invalid transition throws a
135
+ * `WazapiError` with code `invalid_status_transition` (422). Cancelling
136
+ * restores tracked stock.
137
+ */
138
+ async updateStoreOrderStatus(uuid, status) {
139
+ const body = await this.request('POST', `/store/orders/${encode(uuid)}/status`, { body: { status } });
140
+ return body.data;
141
+ }
84
142
  // ---- Operations -------------------------------------------------------
85
143
  async getOperation(uuid) {
86
144
  const body = await this.request('GET', `/operations/${encode(uuid)}`);
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type PublicApiScope = 'channels:read' | 'contacts:read' | 'contacts:write' | 'conversations:read' | 'messages:read' | 'messages:write' | 'templates:read' | 'flows:read' | 'flows:execute' | 'operations:read';
1
+ export type PublicApiScope = 'channels:read' | 'contacts:read' | 'contacts:write' | 'conversations:read' | 'messages:read' | 'messages:write' | 'templates:read' | 'flows:read' | 'flows:execute' | 'operations:read' | 'store:read' | 'store:write';
2
2
  export interface PaginationMeta {
3
3
  next_cursor: string | null;
4
4
  }
@@ -88,12 +88,38 @@ export interface Conversation {
88
88
  created_at: string | null;
89
89
  updated_at: string | null;
90
90
  }
91
+ /**
92
+ * `GET /conversations/{uuid}` — everything about the chat in one call: contact
93
+ * (with tags), assigned agent and group, channel, status and counters. Pass
94
+ * `include: 'messages'` to embed the first page of messages.
95
+ */
96
+ export interface ConversationDetail extends Conversation {
97
+ channel_provider: string | null;
98
+ assigned_agent: {
99
+ uuid: string;
100
+ name: string | null;
101
+ } | null;
102
+ assigned_group: {
103
+ uuid: string;
104
+ name: string;
105
+ } | null;
106
+ message_count: number;
107
+ /** Present only when requested with `include: 'messages'`. */
108
+ messages?: Message[];
109
+ }
91
110
  export interface Message {
92
111
  uuid: string;
93
112
  direction: 'inbound' | 'outbound';
94
113
  type: string;
95
114
  status: string;
96
115
  content: Record<string, unknown>;
116
+ /**
117
+ * Transcription of an inbound audio message, when available. Populated
118
+ * asynchronously after transcription; also delivered via the
119
+ * `message.transcribed` webhook. `null` for non-audio messages and audios
120
+ * not yet transcribed.
121
+ */
122
+ transcript: string | null;
97
123
  provider_message_id: string | null;
98
124
  created_at: string | null;
99
125
  updated_at: string | null;
@@ -158,7 +184,132 @@ export interface AcceptedResult {
158
184
  /** True when the request replayed a previously accepted idempotent operation. */
159
185
  replayed: boolean;
160
186
  }
161
- export type WebhookEventType = 'message.received' | 'message.status.updated' | 'conversation.created' | 'conversation.updated' | 'flow.execution.updated' | 'webhook.test';
187
+ export interface StoreSummary {
188
+ enabled: boolean;
189
+ mode: 'links_only' | 'store_only' | 'both' | null;
190
+ slug: string | null;
191
+ /** Public storefront path (relative, e.g. `/loja/minha-loja`). */
192
+ url: string | null;
193
+ product_count: number;
194
+ order_count: number;
195
+ }
196
+ export interface StoreProductVariant {
197
+ uuid: string;
198
+ label: string;
199
+ price_cents: number | null;
200
+ stock: number | null;
201
+ active: boolean;
202
+ position: number;
203
+ }
204
+ export interface StoreProduct {
205
+ uuid: string;
206
+ name: string;
207
+ description: string | null;
208
+ category_uuid: string | null;
209
+ price_cents: number;
210
+ promo_price_cents: number | null;
211
+ effective_price_cents: number;
212
+ images: string[];
213
+ highlighted: boolean;
214
+ track_stock: boolean;
215
+ stock: number | null;
216
+ active: boolean;
217
+ position: number;
218
+ /**
219
+ * External catalog handle (e.g. Shopify Handle). Products sharing the same
220
+ * handle are updated on re-import/batch instead of duplicated.
221
+ */
222
+ import_handle: string | null;
223
+ variants: StoreProductVariant[];
224
+ created_at: string | null;
225
+ updated_at: string | null;
226
+ }
227
+ export interface StoreProductWrite {
228
+ name: string;
229
+ description?: string | null;
230
+ category_uuid?: string | null;
231
+ price_cents: number;
232
+ promo_price_cents?: number | null;
233
+ highlighted?: boolean;
234
+ track_stock?: boolean;
235
+ stock?: number | null;
236
+ active?: boolean;
237
+ position?: number;
238
+ import_handle?: string | null;
239
+ /**
240
+ * On update the variant list replaces the existing one: variants whose `uuid`
241
+ * is present are kept/updated, the rest are deleted.
242
+ */
243
+ variants?: {
244
+ uuid?: string | null;
245
+ label: string;
246
+ price_cents?: number | null;
247
+ stock?: number | null;
248
+ active?: boolean;
249
+ }[];
250
+ }
251
+ export type StoreOrderStatus = 'novo' | 'confirmado' | 'pago' | 'entregue' | 'cancelado';
252
+ export interface StoreOrderItem {
253
+ product_uuid: string;
254
+ name: string;
255
+ variant_label: string | null;
256
+ quantity: number;
257
+ unit_price_cents: number;
258
+ total_cents: number;
259
+ }
260
+ export type StoreOrderSource = 'storefront' | 'whatsapp_catalog';
261
+ export interface StoreOrder {
262
+ uuid: string;
263
+ /** Short human reference (first 8 chars of the uuid) shown to the customer. */
264
+ ref: string;
265
+ status: StoreOrderStatus;
266
+ /** Where the order was placed: storefront checkout or the native WhatsApp catalog. */
267
+ source: StoreOrderSource;
268
+ /** Provider-side id for orders that originated outside the storefront (WhatsApp catalog order message id). */
269
+ provider_order_id: string | null;
270
+ /**
271
+ * Allowlisted attribution subset stamped at creation (utm_*, click IDs incl.
272
+ * ctwa_clid, ad referral fields). Conversation values win over contact values
273
+ * (last touch over first touch). Null when the order has no attributable source.
274
+ */
275
+ tracking: Record<string, unknown> | null;
276
+ customer_name: string;
277
+ customer_phone: string;
278
+ contact_uuid: string | null;
279
+ /** Inbox conversation opened by the order automation, when available. */
280
+ conversation_uuid: string | null;
281
+ items: StoreOrderItem[];
282
+ subtotal_cents: number;
283
+ shipping_name: string | null;
284
+ shipping_cents: number;
285
+ total_cents: number;
286
+ /** `catalog` = order from the native WhatsApp catalog (payment arranged in chat). */
287
+ payment_method: 'pix' | 'link' | 'on_delivery' | 'catalog';
288
+ notes: string | null;
289
+ created_at: string | null;
290
+ updated_at: string | null;
291
+ }
292
+ export type StoreBatchResultItem = {
293
+ index: number;
294
+ status: 'created' | 'updated';
295
+ uuid: string;
296
+ } | {
297
+ index: number;
298
+ status: 'error';
299
+ error: {
300
+ code: string;
301
+ message: string;
302
+ };
303
+ };
304
+ export interface StoreBatchResult {
305
+ data: StoreBatchResultItem[];
306
+ meta: {
307
+ created: number;
308
+ updated: number;
309
+ failed: number;
310
+ };
311
+ }
312
+ export type WebhookEventType = 'message.received' | 'message.status.updated' | 'conversation.created' | 'conversation.updated' | 'flow.execution.updated' | 'order.created' | 'webhook.test';
162
313
  /**
163
314
  * Allowlisted attribution subset of the contact's and conversation's custom
164
315
  * fields. Conversation values win over contact values (last touch over first
@@ -215,6 +366,24 @@ export interface FlowExecutionUpdatedData {
215
366
  message: string | null;
216
367
  } | null;
217
368
  }
369
+ /** A store order was created — storefront checkout or native WhatsApp catalog. */
370
+ export interface OrderCreatedData extends WebhookContactRefs {
371
+ order_uuid: string;
372
+ ref: string;
373
+ status: string;
374
+ source: StoreOrderSource;
375
+ customer_name: string;
376
+ customer_phone: string;
377
+ contact_uuid: string | null;
378
+ items: StoreOrderItem[];
379
+ subtotal_cents: number;
380
+ shipping_name: string | null;
381
+ shipping_cents: number;
382
+ total_cents: number;
383
+ payment_method: string;
384
+ notes: string | null;
385
+ created_at: string | null;
386
+ }
218
387
  export interface WebhookTestData {
219
388
  integration_uuid: string;
220
389
  message: string;
@@ -232,7 +401,8 @@ export type MessageStatusUpdatedEvent = WebhookEnvelope<'message.status.updated'
232
401
  export type ConversationCreatedEvent = WebhookEnvelope<'conversation.created', ConversationCreatedData>;
233
402
  export type ConversationUpdatedEvent = WebhookEnvelope<'conversation.updated', ConversationUpdatedData>;
234
403
  export type FlowExecutionUpdatedEvent = WebhookEnvelope<'flow.execution.updated', FlowExecutionUpdatedData>;
404
+ export type OrderCreatedEvent = WebhookEnvelope<'order.created', OrderCreatedData>;
235
405
  export type WebhookTestEvent = WebhookEnvelope<'webhook.test', WebhookTestData>;
236
406
  /** Discriminated on `type` — narrow it and `data` narrows with it. */
237
- export type WazapiWebhookEvent = MessageReceivedEvent | MessageStatusUpdatedEvent | ConversationCreatedEvent | ConversationUpdatedEvent | FlowExecutionUpdatedEvent | WebhookTestEvent;
407
+ export type WazapiWebhookEvent = MessageReceivedEvent | MessageStatusUpdatedEvent | ConversationCreatedEvent | ConversationUpdatedEvent | FlowExecutionUpdatedEvent | OrderCreatedEvent | WebhookTestEvent;
238
408
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wazapi/sdk",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Official Node.js SDK for the Wazapi Public API v1",
5
5
  "license": "MIT",
6
6
  "type": "module",