@wazzapi/wazzapi 0.2.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/README.md +232 -0
- package/advanced-examples/custom-fetch.ts +40 -0
- package/advanced-examples/download-media.ts +27 -0
- package/advanced-examples/http-webhook-server.ts +80 -0
- package/dist/index.cjs +1550 -0
- package/dist/index.d.cts +1012 -0
- package/dist/index.d.ts +1012 -0
- package/dist/index.js +1461 -0
- package/docs/README.md +61 -0
- package/docs/authentication.md +37 -0
- package/docs/client.md +68 -0
- package/docs/contacts.md +194 -0
- package/docs/errors.md +57 -0
- package/docs/groups.md +233 -0
- package/docs/media.md +38 -0
- package/docs/messages.md +151 -0
- package/docs/templates.md +76 -0
- package/docs/webhooks.md +101 -0
- package/examples/create-template.ts +10 -0
- package/examples/list-contacts.ts +8 -0
- package/examples/preview-template.ts +9 -0
- package/examples/send-message.ts +10 -0
- package/examples/verify-webhook.ts +33 -0
- package/package.json +57 -0
package/docs/messages.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Messages
|
|
2
|
+
|
|
3
|
+
Send and manage WhatsApp messages.
|
|
4
|
+
|
|
5
|
+
## Send a text message
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { WazzapiClient } from "@wazzapi/wazzapi";
|
|
9
|
+
|
|
10
|
+
const client = new WazzapiClient({ apiKey: process.env.WAZZAPI_API_KEY });
|
|
11
|
+
const response = await client.messages.send({
|
|
12
|
+
phone_number: "+6281234567890",
|
|
13
|
+
whatsapp_account_id: "your-whatsapp-account-id",
|
|
14
|
+
content: "Hello from WazzAPI!",
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
console.log(response.message_id);
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Send media
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
await client.messages.sendImage({
|
|
24
|
+
phone_number: "+6281234567890",
|
|
25
|
+
whatsapp_account_id: "your-whatsapp-account-id",
|
|
26
|
+
media_url: "https://example.com/image.jpg",
|
|
27
|
+
caption: "Check this out",
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
await client.messages.sendVideo({
|
|
31
|
+
phone_number: "+6281234567890",
|
|
32
|
+
whatsapp_account_id: "your-whatsapp-account-id",
|
|
33
|
+
media_url: "https://example.com/video.mp4",
|
|
34
|
+
caption: "Watch this",
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
await client.messages.sendDocument({
|
|
38
|
+
phone_number: "+6281234567890",
|
|
39
|
+
whatsapp_account_id: "your-whatsapp-account-id",
|
|
40
|
+
media_url: "https://example.com/doc.pdf",
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
await client.messages.sendVoice({
|
|
44
|
+
phone_number: "+6281234567890",
|
|
45
|
+
whatsapp_account_id: "your-whatsapp-account-id",
|
|
46
|
+
media_url: "https://example.com/voice.ogg",
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Send a location
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
await client.messages.sendLocation({
|
|
54
|
+
phone_number: "+6281234567890",
|
|
55
|
+
whatsapp_account_id: "your-whatsapp-account-id",
|
|
56
|
+
latitude: -6.2088,
|
|
57
|
+
longitude: 106.8456,
|
|
58
|
+
location_title: "Jakarta",
|
|
59
|
+
location_address: "Indonesia",
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Send a contact card
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
await client.messages.sendContact({
|
|
67
|
+
phone_number: "+6281234567890",
|
|
68
|
+
whatsapp_account_id: "your-whatsapp-account-id",
|
|
69
|
+
contacts: [{ name: "Alice", phone_number: "+6281234567891" }],
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Send interactive buttons
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
await client.messages.sendButtons({
|
|
77
|
+
phone_number: "+6281234567890",
|
|
78
|
+
whatsapp_account_id: "your-whatsapp-account-id",
|
|
79
|
+
body: "Choose an option:",
|
|
80
|
+
buttons: [
|
|
81
|
+
{ id: "yes", title: "Yes" },
|
|
82
|
+
{ id: "no", title: "No" },
|
|
83
|
+
],
|
|
84
|
+
footer: "Powered by WazzAPI",
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Send an interactive list
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
await client.messages.sendList({
|
|
92
|
+
phone_number: "+6281234567890",
|
|
93
|
+
whatsapp_account_id: "your-whatsapp-account-id",
|
|
94
|
+
body: "Select a plan:",
|
|
95
|
+
button_text: "View plans",
|
|
96
|
+
sections: [
|
|
97
|
+
{
|
|
98
|
+
title: "Plans",
|
|
99
|
+
rows: [
|
|
100
|
+
{ id: "basic", title: "Basic", description: "$9/mo" },
|
|
101
|
+
{ id: "pro", title: "Pro", description: "$29/mo" },
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## List messages
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
const response = await client.messages.list({ limit: 50, status: "sent" });
|
|
112
|
+
|
|
113
|
+
for (const message of response.messages) {
|
|
114
|
+
console.log(message.id, message.status, message.phone_number);
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Get a message
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
const message = await client.messages.get("msg-id");
|
|
122
|
+
console.log(message.status, message.content);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Retry a failed message
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
const result = await client.messages.retry("msg-id");
|
|
129
|
+
console.log(result.status);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Cancel a scheduled message
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const result = await client.messages.cancel("msg-id");
|
|
136
|
+
console.log(result.status);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Lookup by WhatsApp message ID
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
const message = await client.messages.lookup("wamid.xxx");
|
|
143
|
+
console.log(message.id);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Message stats
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
const stats = await client.messages.stats();
|
|
150
|
+
console.log(stats.total, stats.by_status);
|
|
151
|
+
```
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Templates
|
|
2
|
+
|
|
3
|
+
Create and manage reusable message templates.
|
|
4
|
+
|
|
5
|
+
## List templates
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { WazzapiClient } from "@wazzapi/wazzapi";
|
|
9
|
+
|
|
10
|
+
const client = new WazzapiClient({ apiKey: process.env.WAZZAPI_API_KEY });
|
|
11
|
+
const response = await client.templates.list({
|
|
12
|
+
limit: 20,
|
|
13
|
+
category: "marketing",
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
for (const template of response.data) {
|
|
17
|
+
console.log(template.name, template.variables);
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Get a template
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
const template = await client.templates.get("template-id");
|
|
25
|
+
console.log(template.content, template.variables);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Create a template
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
const template = await client.templates.create({
|
|
32
|
+
name: "welcome-message",
|
|
33
|
+
category: "marketing",
|
|
34
|
+
content: "Hi {{name}}, welcome to WazzAPI!",
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
console.log(template.id);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Update a template
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
const template = await client.templates.update("template-id", {
|
|
44
|
+
content: "Hi {{name}}, welcome! Your code is {{code}}.",
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
console.log(template.content);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Delete a template
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
await client.templates.delete("template-id");
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Preview a template
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
const preview = await client.templates.preview({
|
|
60
|
+
content: "Hi {{name}}, your code is {{code}}.",
|
|
61
|
+
custom_variables: { name: "Alice", code: "WZ-1234" },
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
console.log(preview.preview);
|
|
65
|
+
console.log(preview.missing_variables);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Built-in variables
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const response = await client.templates.builtinVariables();
|
|
72
|
+
|
|
73
|
+
for (const variable of response.variables) {
|
|
74
|
+
console.log(variable.name, variable.description, variable.example);
|
|
75
|
+
}
|
|
76
|
+
```
|
package/docs/webhooks.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Webhooks
|
|
2
|
+
|
|
3
|
+
WazzAPI sends webhook events to your endpoint for incoming messages, message status updates, and device status changes.
|
|
4
|
+
|
|
5
|
+
## Verify and parse
|
|
6
|
+
|
|
7
|
+
Always verify the signature before parsing the payload:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { WebhookHandler } from "@wazzapi/wazzapi";
|
|
11
|
+
|
|
12
|
+
const handler = new WebhookHandler("your-webhook-secret");
|
|
13
|
+
const webhook = handler.verifyAndParse(rawBody, request.headers);
|
|
14
|
+
|
|
15
|
+
console.log(webhook.event_type);
|
|
16
|
+
console.log(webhook.data);
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Headers
|
|
20
|
+
|
|
21
|
+
WazzAPI sends these headers with every webhook:
|
|
22
|
+
|
|
23
|
+
- `X-Wazzapi-Signature` — HMAC-SHA256 signature of the raw body
|
|
24
|
+
- `X-Wazzapi-Event` — event type such as `message.received`
|
|
25
|
+
- `X-Wazzapi-Event-ID` — unique event ID
|
|
26
|
+
|
|
27
|
+
## Supported events
|
|
28
|
+
|
|
29
|
+
### Message events
|
|
30
|
+
|
|
31
|
+
- `message.received` — incoming message
|
|
32
|
+
- `message.sent` — outbound message accepted by WhatsApp
|
|
33
|
+
- `message.delivered` — outbound message delivered
|
|
34
|
+
- `message.read` — outbound message read by recipient
|
|
35
|
+
- `message.failed` — outbound message failed
|
|
36
|
+
|
|
37
|
+
### Device events
|
|
38
|
+
|
|
39
|
+
- `device.connected` — WhatsApp device connected
|
|
40
|
+
- `device.disconnected` — WhatsApp device disconnected
|
|
41
|
+
|
|
42
|
+
## Working with message webhooks
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { WebhookHandler } from "@wazzapi/wazzapi";
|
|
46
|
+
import type { PublicMessageWebhook } from "@wazzapi/wazzapi";
|
|
47
|
+
|
|
48
|
+
const handler = new WebhookHandler("your-webhook-secret");
|
|
49
|
+
const webhook = handler.verifyAndParse(rawBody, request.headers);
|
|
50
|
+
|
|
51
|
+
if (webhook.event_type.startsWith("message.")) {
|
|
52
|
+
const messageWebhook = webhook as PublicMessageWebhook;
|
|
53
|
+
console.log(messageWebhook.data.phone_number);
|
|
54
|
+
console.log(messageWebhook.data.status);
|
|
55
|
+
console.log(messageWebhook.data.message_type);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Working with device webhooks
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { WebhookHandler } from "@wazzapi/wazzapi";
|
|
63
|
+
import type { PublicDeviceWebhook } from "@wazzapi/wazzapi";
|
|
64
|
+
|
|
65
|
+
const handler = new WebhookHandler("your-webhook-secret");
|
|
66
|
+
const webhook = handler.verifyAndParse(rawBody, request.headers);
|
|
67
|
+
|
|
68
|
+
if (webhook.event_type.startsWith("device.")) {
|
|
69
|
+
const deviceWebhook = webhook as PublicDeviceWebhook;
|
|
70
|
+
console.log(deviceWebhook.data.status);
|
|
71
|
+
console.log(deviceWebhook.data.reason);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Parse only
|
|
76
|
+
|
|
77
|
+
For debugging or if you handle verification separately:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
const handler = new WebhookHandler("your-webhook-secret");
|
|
81
|
+
const webhook = handler.parse(rawBody);
|
|
82
|
+
console.log(webhook.event_type);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Low-level signature verification
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import {
|
|
89
|
+
generateWebhookSignature,
|
|
90
|
+
verifyWebhookSignature,
|
|
91
|
+
} from "@wazzapi/wazzapi";
|
|
92
|
+
|
|
93
|
+
const expected = generateWebhookSignature(rawBody, "your-webhook-secret");
|
|
94
|
+
const isValid = verifyWebhookSignature(
|
|
95
|
+
rawBody,
|
|
96
|
+
request.headers["x-wazzapi-signature"] as string,
|
|
97
|
+
"your-webhook-secret",
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
console.log(expected, isValid);
|
|
101
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { WazzapiClient } from "../src";
|
|
2
|
+
|
|
3
|
+
const client = new WazzapiClient({ apiKey: process.env.WAZZAPI_API_KEY });
|
|
4
|
+
const template = await client.templates.create({
|
|
5
|
+
name: "welcome-message",
|
|
6
|
+
category: "marketing",
|
|
7
|
+
content: "Hi {{name}}, welcome to WazzAPI!",
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
console.log(template);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { WazzapiClient } from "../src";
|
|
2
|
+
|
|
3
|
+
const client = new WazzapiClient({ apiKey: process.env.WAZZAPI_API_KEY });
|
|
4
|
+
const response = await client.contacts.list({ limit: 20, search: "alice" });
|
|
5
|
+
|
|
6
|
+
response.contacts.forEach((contact) => {
|
|
7
|
+
console.log(contact);
|
|
8
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WazzapiClient } from "../src";
|
|
2
|
+
|
|
3
|
+
const client = new WazzapiClient({ apiKey: process.env.WAZZAPI_API_KEY });
|
|
4
|
+
const preview = await client.templates.preview({
|
|
5
|
+
content: "Hi {{name}}, your code is {{code}}.",
|
|
6
|
+
custom_variables: { name: "Alice", code: "WZ-1234" },
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
console.log(preview);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { WazzapiClient } from "../src";
|
|
2
|
+
|
|
3
|
+
const client = new WazzapiClient({ apiKey: process.env.WAZZAPI_API_KEY });
|
|
4
|
+
const response = await client.messages.send({
|
|
5
|
+
phone_number: "+6281234567890",
|
|
6
|
+
whatsapp_account_id: "your-whatsapp-account-id",
|
|
7
|
+
content: "Hello from WazzAPI!",
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
console.log(response);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EVENT_HEADER,
|
|
3
|
+
EVENT_ID_HEADER,
|
|
4
|
+
SIGNATURE_HEADER,
|
|
5
|
+
WebhookHandler,
|
|
6
|
+
} from "../src";
|
|
7
|
+
|
|
8
|
+
const secret = process.env.WAZZAPI_WEBHOOK_SECRET || "your-webhook-secret";
|
|
9
|
+
const handler = new WebhookHandler(secret);
|
|
10
|
+
const payload = JSON.stringify({
|
|
11
|
+
id: "webhook_1",
|
|
12
|
+
event_type: "message.received",
|
|
13
|
+
timestamp: "2026-04-26T09:15:30Z",
|
|
14
|
+
organization_id: "org_1",
|
|
15
|
+
webhook_id: "wh_1",
|
|
16
|
+
data: {
|
|
17
|
+
message_id: "msg_1",
|
|
18
|
+
phone_number: "6281234567890",
|
|
19
|
+
status: "delivered",
|
|
20
|
+
direction: "inbound",
|
|
21
|
+
message_type: "text",
|
|
22
|
+
whatsapp_account_id: "wa_1",
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const headers = {
|
|
27
|
+
[SIGNATURE_HEADER]: handler.generateSignature(payload),
|
|
28
|
+
[EVENT_HEADER]: "message.received",
|
|
29
|
+
[EVENT_ID_HEADER]: "evt_1",
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const webhook = handler.verifyAndParse(payload, headers);
|
|
33
|
+
console.log(webhook);
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wazzapi/wazzapi",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Typed Node.js SDK for WazzAPI",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"advanced-examples",
|
|
20
|
+
"docs",
|
|
21
|
+
"examples",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=20"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"api",
|
|
29
|
+
"sdk",
|
|
30
|
+
"wazzapi",
|
|
31
|
+
"webhook",
|
|
32
|
+
"whatsapp"
|
|
33
|
+
],
|
|
34
|
+
"homepage": "https://github.com/wazzapihq/wazzapi-node",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/wazzapihq/wazzapi-node.git"
|
|
38
|
+
},
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/wazzapihq/wazzapi-node/issues"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"test": "bun test",
|
|
49
|
+
"prepublishOnly": "bun run typecheck && bun run test && bun run build"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@biomejs/biome": "2.4.15",
|
|
53
|
+
"@types/node": "^24.0.0",
|
|
54
|
+
"tsup": "^8.5.0",
|
|
55
|
+
"typescript": "^5.8.3"
|
|
56
|
+
}
|
|
57
|
+
}
|