waba-toolkit 0.3.0 → 0.3.1
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/ARCHITECTURE.md +783 -0
- package/README.md +213 -579
- package/docs/CLI.md +445 -0
- package/docs/MEDIA.md +576 -0
- package/docs/SENDING.md +635 -0
- package/docs/TROUBLESHOOTING.md +622 -0
- package/docs/WEBHOOKS.md +515 -0
- package/package.json +4 -2
package/docs/SENDING.md
ADDED
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
# Sending Messages Guide
|
|
2
|
+
|
|
3
|
+
Send WhatsApp messages programmatically with type safety.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
> **Prefer CLI?** See [CLI Guide: Sending Messages](CLI.md#sending-messages)
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { WABAApiClient } from 'waba-toolkit';
|
|
13
|
+
|
|
14
|
+
const client = new WABAApiClient({
|
|
15
|
+
accessToken: process.env.META_ACCESS_TOKEN,
|
|
16
|
+
phoneNumberId: '1234567890', // Your business phone number ID
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Send text
|
|
20
|
+
const response = await client.sendTextMessage(
|
|
21
|
+
'1234567890',
|
|
22
|
+
'Hello from waba-toolkit!'
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
console.log('Message ID:', response.messages[0].id);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Initialize Client
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { WABAApiClient } from 'waba-toolkit';
|
|
34
|
+
|
|
35
|
+
const client = new WABAApiClient({
|
|
36
|
+
accessToken: string, // Required: Meta access token
|
|
37
|
+
phoneNumberId: string, // Required: Your business phone number ID
|
|
38
|
+
apiVersion?: string, // Optional: Default 'v22.0'
|
|
39
|
+
baseUrl?: string, // Optional: Default 'https://graph.facebook.com'
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Text Messages
|
|
46
|
+
|
|
47
|
+
### Basic Text
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
await client.sendTextMessage(
|
|
51
|
+
'1234567890', // Recipient phone number
|
|
52
|
+
'Hello World' // Message text
|
|
53
|
+
);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### With URL Preview
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
await client.sendTextMessage(
|
|
60
|
+
'1234567890',
|
|
61
|
+
'Check this out: https://example.com',
|
|
62
|
+
{ previewUrl: true }
|
|
63
|
+
);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Reply to Message
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
await client.sendTextMessage(
|
|
70
|
+
'1234567890',
|
|
71
|
+
'Got your message!',
|
|
72
|
+
{
|
|
73
|
+
context: {
|
|
74
|
+
message_id: 'wamid.HBgLMTY...', // Original message ID
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Template Messages
|
|
83
|
+
|
|
84
|
+
Send pre-approved template messages:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
await client.sendTemplateMessage('1234567890', {
|
|
88
|
+
name: 'hello_world', // Template name
|
|
89
|
+
language: { code: 'en_US' }, // Language code
|
|
90
|
+
components: [ // Optional: Parameters
|
|
91
|
+
{
|
|
92
|
+
type: 'body',
|
|
93
|
+
parameters: [
|
|
94
|
+
{ type: 'text', text: 'John Doe' },
|
|
95
|
+
{ type: 'text', text: 'Order #12345' },
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Template with Header Image
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
await client.sendTemplateMessage('1234567890', {
|
|
106
|
+
name: 'order_confirmation',
|
|
107
|
+
language: { code: 'en' },
|
|
108
|
+
components: [
|
|
109
|
+
{
|
|
110
|
+
type: 'header',
|
|
111
|
+
parameters: [
|
|
112
|
+
{
|
|
113
|
+
type: 'image',
|
|
114
|
+
image: {
|
|
115
|
+
link: 'https://example.com/product.jpg',
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
type: 'body',
|
|
122
|
+
parameters: [
|
|
123
|
+
{ type: 'text', text: 'John' },
|
|
124
|
+
{ type: 'text', text: 'ORD-12345' },
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Template with Buttons
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
await client.sendTemplateMessage('1234567890', {
|
|
135
|
+
name: 'appointment_reminder',
|
|
136
|
+
language: { code: 'en_US' },
|
|
137
|
+
components: [
|
|
138
|
+
{
|
|
139
|
+
type: 'body',
|
|
140
|
+
parameters: [
|
|
141
|
+
{ type: 'text', text: 'Tomorrow at 3 PM' },
|
|
142
|
+
],
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: 'button',
|
|
146
|
+
sub_type: 'url',
|
|
147
|
+
index: '0',
|
|
148
|
+
parameters: [
|
|
149
|
+
{
|
|
150
|
+
type: 'text',
|
|
151
|
+
text: 'abc123', // Dynamic URL parameter
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Media Messages
|
|
162
|
+
|
|
163
|
+
### Image
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
await client.sendMessage({
|
|
167
|
+
messaging_product: 'whatsapp',
|
|
168
|
+
to: '1234567890',
|
|
169
|
+
type: 'image',
|
|
170
|
+
image: {
|
|
171
|
+
link: 'https://example.com/photo.jpg',
|
|
172
|
+
caption: 'Amazing view!',
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Video
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
await client.sendMessage({
|
|
181
|
+
messaging_product: 'whatsapp',
|
|
182
|
+
to: '1234567890',
|
|
183
|
+
type: 'video',
|
|
184
|
+
video: {
|
|
185
|
+
link: 'https://example.com/video.mp4',
|
|
186
|
+
caption: 'Check out this video',
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Document
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
await client.sendMessage({
|
|
195
|
+
messaging_product: 'whatsapp',
|
|
196
|
+
to: '1234567890',
|
|
197
|
+
type: 'document',
|
|
198
|
+
document: {
|
|
199
|
+
link: 'https://example.com/invoice.pdf',
|
|
200
|
+
caption: 'Your invoice',
|
|
201
|
+
filename: 'invoice-12345.pdf',
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Audio
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
await client.sendMessage({
|
|
210
|
+
messaging_product: 'whatsapp',
|
|
211
|
+
to: '1234567890',
|
|
212
|
+
type: 'audio',
|
|
213
|
+
audio: {
|
|
214
|
+
link: 'https://example.com/audio.mp3',
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Interactive Messages
|
|
222
|
+
|
|
223
|
+
### Buttons
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
await client.sendMessage({
|
|
227
|
+
messaging_product: 'whatsapp',
|
|
228
|
+
to: '1234567890',
|
|
229
|
+
type: 'interactive',
|
|
230
|
+
interactive: {
|
|
231
|
+
type: 'button',
|
|
232
|
+
body: {
|
|
233
|
+
text: 'Would you like to continue?',
|
|
234
|
+
},
|
|
235
|
+
action: {
|
|
236
|
+
buttons: [
|
|
237
|
+
{
|
|
238
|
+
type: 'reply',
|
|
239
|
+
reply: {
|
|
240
|
+
id: 'yes',
|
|
241
|
+
title: 'Yes',
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
type: 'reply',
|
|
246
|
+
reply: {
|
|
247
|
+
id: 'no',
|
|
248
|
+
title: 'No',
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
],
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### List
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
await client.sendMessage({
|
|
261
|
+
messaging_product: 'whatsapp',
|
|
262
|
+
to: '1234567890',
|
|
263
|
+
type: 'interactive',
|
|
264
|
+
interactive: {
|
|
265
|
+
type: 'list',
|
|
266
|
+
header: {
|
|
267
|
+
type: 'text',
|
|
268
|
+
text: 'Menu',
|
|
269
|
+
},
|
|
270
|
+
body: {
|
|
271
|
+
text: 'Choose an option',
|
|
272
|
+
},
|
|
273
|
+
footer: {
|
|
274
|
+
text: 'Powered by waba-toolkit',
|
|
275
|
+
},
|
|
276
|
+
action: {
|
|
277
|
+
button: 'View Options',
|
|
278
|
+
sections: [
|
|
279
|
+
{
|
|
280
|
+
title: 'Main Options',
|
|
281
|
+
rows: [
|
|
282
|
+
{
|
|
283
|
+
id: 'option1',
|
|
284
|
+
title: 'Option 1',
|
|
285
|
+
description: 'Description for option 1',
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
id: 'option2',
|
|
289
|
+
title: 'Option 2',
|
|
290
|
+
description: 'Description for option 2',
|
|
291
|
+
},
|
|
292
|
+
],
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
});
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Location Messages
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
await client.sendMessage({
|
|
306
|
+
messaging_product: 'whatsapp',
|
|
307
|
+
to: '1234567890',
|
|
308
|
+
type: 'location',
|
|
309
|
+
location: {
|
|
310
|
+
latitude: 37.7749,
|
|
311
|
+
longitude: -122.4194,
|
|
312
|
+
name: 'San Francisco',
|
|
313
|
+
address: 'California, USA',
|
|
314
|
+
},
|
|
315
|
+
});
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Contact Messages
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
await client.sendMessage({
|
|
324
|
+
messaging_product: 'whatsapp',
|
|
325
|
+
to: '1234567890',
|
|
326
|
+
type: 'contacts',
|
|
327
|
+
contacts: [
|
|
328
|
+
{
|
|
329
|
+
name: {
|
|
330
|
+
formatted_name: 'John Doe',
|
|
331
|
+
first_name: 'John',
|
|
332
|
+
last_name: 'Doe',
|
|
333
|
+
},
|
|
334
|
+
phones: [
|
|
335
|
+
{
|
|
336
|
+
phone: '+1 555 0100',
|
|
337
|
+
type: 'MOBILE',
|
|
338
|
+
},
|
|
339
|
+
],
|
|
340
|
+
emails: [
|
|
341
|
+
{
|
|
342
|
+
email: 'john@example.com',
|
|
343
|
+
type: 'WORK',
|
|
344
|
+
},
|
|
345
|
+
],
|
|
346
|
+
},
|
|
347
|
+
],
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## Reaction Messages
|
|
354
|
+
|
|
355
|
+
React to a message:
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
await client.sendMessage({
|
|
359
|
+
messaging_product: 'whatsapp',
|
|
360
|
+
to: '1234567890',
|
|
361
|
+
type: 'reaction',
|
|
362
|
+
reaction: {
|
|
363
|
+
message_id: 'wamid.HBgLMTY...', // Message to react to
|
|
364
|
+
emoji: '👍',
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
Remove reaction:
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
await client.sendMessage({
|
|
373
|
+
messaging_product: 'whatsapp',
|
|
374
|
+
to: '1234567890',
|
|
375
|
+
type: 'reaction',
|
|
376
|
+
reaction: {
|
|
377
|
+
message_id: 'wamid.HBgLMTY...',
|
|
378
|
+
emoji: '', // Empty emoji removes reaction
|
|
379
|
+
},
|
|
380
|
+
});
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Error Handling
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
import { WABAAuthError, WABASendError } from 'waba-toolkit';
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
await client.sendTextMessage('1234567890', 'Hello');
|
|
392
|
+
} catch (error) {
|
|
393
|
+
if (error instanceof WABAAuthError) {
|
|
394
|
+
console.error('Authentication failed:', error.statusCode);
|
|
395
|
+
// Check your access token
|
|
396
|
+
} else if (error instanceof WABASendError) {
|
|
397
|
+
console.error('Send failed:', error.statusCode);
|
|
398
|
+
console.error('Details:', error.errorPayload);
|
|
399
|
+
// Check error code and message
|
|
400
|
+
} else {
|
|
401
|
+
console.error('Unknown error:', error);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Common Error Codes
|
|
407
|
+
|
|
408
|
+
| Code | Description | Solution |
|
|
409
|
+
|------|-------------|----------|
|
|
410
|
+
| 100 | Invalid parameter | Check phone number format |
|
|
411
|
+
| 131047 | Re-engagement message | Need approved template (>24hrs) |
|
|
412
|
+
| 131053 | Recipient not on WhatsApp | Verify phone number |
|
|
413
|
+
| 190 | Access token expired | Refresh token |
|
|
414
|
+
| 368 | Temporarily blocked | Reduce send rate |
|
|
415
|
+
|
|
416
|
+
> **More help?** See [Troubleshooting: Message Sending Issues](TROUBLESHOOTING.md#message-sending-issues)
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## Response Format
|
|
421
|
+
|
|
422
|
+
All send methods return:
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
{
|
|
426
|
+
messaging_product: 'whatsapp',
|
|
427
|
+
contacts: [
|
|
428
|
+
{
|
|
429
|
+
input: '1234567890', // Phone as you provided
|
|
430
|
+
wa_id: '1234567890', // WhatsApp ID (normalized)
|
|
431
|
+
},
|
|
432
|
+
],
|
|
433
|
+
messages: [
|
|
434
|
+
{
|
|
435
|
+
id: 'wamid.HBgLMTY...', // Message ID (WAMID)
|
|
436
|
+
},
|
|
437
|
+
],
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Use the message ID to track delivery status.
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
## Phone Management
|
|
446
|
+
|
|
447
|
+
### Register Phone
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
await client.registerPhone('123456'); // 6-digit PIN
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### Deregister Phone
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
await client.deregisterPhone();
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### List Phone Numbers
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
const phones = await client.listPhoneNumbers('YOUR_WABA_ID');
|
|
463
|
+
|
|
464
|
+
phones.data.forEach((phone) => {
|
|
465
|
+
console.log('ID:', phone.id);
|
|
466
|
+
console.log('Display:', phone.display_phone_number);
|
|
467
|
+
console.log('Quality:', phone.quality_rating);
|
|
468
|
+
console.log('Name:', phone.verified_name);
|
|
469
|
+
});
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## Best Practices
|
|
475
|
+
|
|
476
|
+
### 1. Template Messages for First Contact
|
|
477
|
+
|
|
478
|
+
Send templates if >24 hours since last customer message:
|
|
479
|
+
|
|
480
|
+
```typescript
|
|
481
|
+
async function sendMessage(to: string, text: string) {
|
|
482
|
+
const lastMessageTime = await getLastMessageTime(to);
|
|
483
|
+
const hoursSince = (Date.now() - lastMessageTime) / 1000 / 60 / 60;
|
|
484
|
+
|
|
485
|
+
if (hoursSince > 24) {
|
|
486
|
+
// Use template
|
|
487
|
+
await client.sendTemplateMessage(to, {
|
|
488
|
+
name: 're_engagement',
|
|
489
|
+
language: { code: 'en' },
|
|
490
|
+
});
|
|
491
|
+
} else {
|
|
492
|
+
// Use text
|
|
493
|
+
await client.sendTextMessage(to, text);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### 2. Rate Limiting
|
|
499
|
+
|
|
500
|
+
Respect Meta's rate limits:
|
|
501
|
+
|
|
502
|
+
```typescript
|
|
503
|
+
import pLimit from 'p-limit';
|
|
504
|
+
|
|
505
|
+
const limit = pLimit(10); // Max 10 concurrent requests
|
|
506
|
+
|
|
507
|
+
const recipients = ['123', '456', '789'];
|
|
508
|
+
const promises = recipients.map((to) =>
|
|
509
|
+
limit(() => client.sendTextMessage(to, 'Hello'))
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
await Promise.all(promises);
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
### 3. Store Message IDs
|
|
516
|
+
|
|
517
|
+
Track delivery status:
|
|
518
|
+
|
|
519
|
+
```typescript
|
|
520
|
+
const response = await client.sendTextMessage(to, text);
|
|
521
|
+
const messageId = response.messages[0].id;
|
|
522
|
+
|
|
523
|
+
await db.saveMessage({
|
|
524
|
+
messageId,
|
|
525
|
+
recipient: to,
|
|
526
|
+
text,
|
|
527
|
+
sentAt: new Date(),
|
|
528
|
+
status: 'sent',
|
|
529
|
+
});
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### 4. Handle Retries
|
|
533
|
+
|
|
534
|
+
Retry on transient errors:
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
import pRetry from 'p-retry';
|
|
538
|
+
|
|
539
|
+
await pRetry(
|
|
540
|
+
() => client.sendTextMessage(to, text),
|
|
541
|
+
{
|
|
542
|
+
retries: 3,
|
|
543
|
+
onFailedAttempt: (error) => {
|
|
544
|
+
console.log(`Attempt ${error.attemptNumber} failed`);
|
|
545
|
+
},
|
|
546
|
+
}
|
|
547
|
+
);
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
|
|
552
|
+
## Examples
|
|
553
|
+
|
|
554
|
+
### Send OTP Template
|
|
555
|
+
|
|
556
|
+
```typescript
|
|
557
|
+
await client.sendTemplateMessage(phoneNumber, {
|
|
558
|
+
name: 'otp_template',
|
|
559
|
+
language: { code: 'en' },
|
|
560
|
+
components: [
|
|
561
|
+
{
|
|
562
|
+
type: 'body',
|
|
563
|
+
parameters: [
|
|
564
|
+
{ type: 'text', text: otpCode },
|
|
565
|
+
],
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
type: 'button',
|
|
569
|
+
sub_type: 'url',
|
|
570
|
+
index: '0',
|
|
571
|
+
parameters: [
|
|
572
|
+
{ type: 'text', text: otpCode }, // Autofill code
|
|
573
|
+
],
|
|
574
|
+
},
|
|
575
|
+
],
|
|
576
|
+
});
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### Send Order Confirmation
|
|
580
|
+
|
|
581
|
+
```typescript
|
|
582
|
+
await client.sendTemplateMessage(customerId, {
|
|
583
|
+
name: 'order_confirmation',
|
|
584
|
+
language: { code: 'en' },
|
|
585
|
+
components: [
|
|
586
|
+
{
|
|
587
|
+
type: 'header',
|
|
588
|
+
parameters: [
|
|
589
|
+
{
|
|
590
|
+
type: 'image',
|
|
591
|
+
image: { link: productImageUrl },
|
|
592
|
+
},
|
|
593
|
+
],
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
type: 'body',
|
|
597
|
+
parameters: [
|
|
598
|
+
{ type: 'text', text: customerName },
|
|
599
|
+
{ type: 'text', text: orderId },
|
|
600
|
+
{ type: 'text', text: deliveryDate },
|
|
601
|
+
],
|
|
602
|
+
},
|
|
603
|
+
],
|
|
604
|
+
});
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
### Send Delivery Update with Location
|
|
608
|
+
|
|
609
|
+
```typescript
|
|
610
|
+
// Send text
|
|
611
|
+
await client.sendTextMessage(
|
|
612
|
+
customerId,
|
|
613
|
+
'Your order is out for delivery!'
|
|
614
|
+
);
|
|
615
|
+
|
|
616
|
+
// Send driver location
|
|
617
|
+
await client.sendMessage({
|
|
618
|
+
messaging_product: 'whatsapp',
|
|
619
|
+
to: customerId,
|
|
620
|
+
type: 'location',
|
|
621
|
+
location: {
|
|
622
|
+
latitude: driverLat,
|
|
623
|
+
longitude: driverLng,
|
|
624
|
+
name: 'Driver Location',
|
|
625
|
+
},
|
|
626
|
+
});
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
## Next Steps
|
|
632
|
+
|
|
633
|
+
- [Webhook Processing](WEBHOOKS.md) - Handle incoming messages
|
|
634
|
+
- [CLI Guide](CLI.md) - Use CLI to send messages
|
|
635
|
+
- [API Reference](../API_REFERENCE.md) - Complete type documentation
|