@whatsapi.sh/sdk 0.1.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.
@@ -0,0 +1,285 @@
1
+ // GENERATED FILE — do not edit. Run `bun run sdk:gen`.
2
+ // Source: apps/api/src/routes/v1 (the mounted operations)
3
+ //
4
+ // One method per capability, named the way its MCP tool is named, returning
5
+ // the DTO the operation declares. `Whatsapi` in ../client.ts supplies request().
6
+ /** The version this client reports in `x-whatsapi-client`. */
7
+ export const SDK_VERSION = "0.1.0";
8
+ /** The hosted API. */
9
+ export const DEFAULT_BASE_URL = "https://api.whatsapi.sh/v1";
10
+ export class GeneratedOperations {
11
+ /**
12
+ * Send a WhatsApp message
13
+ *
14
+ * Send a text message to a phone number over WhatsApp. Counts as one message against the
15
+ * account's monthly quota. The reply carries WhatsApp's message id — delivery and read
16
+ * receipts arrive later on the account's webhook, not here.
17
+ *
18
+ * `POST /messages`
19
+ */
20
+ sendMessage(params) {
21
+ return this.request({ method: "POST", path: "/messages" }, params);
22
+ }
23
+ /**
24
+ * Send a photo, video, voice note or file
25
+ *
26
+ * Send media over WhatsApp from a public URL or base64 data. `type` picks the bubble the
27
+ * recipient sees: `image` and `video` support a caption, `document` is a file attachment named
28
+ * by `fileName`, and `audio` becomes a voice note when the file is ogg/opus — any other audio
29
+ * format is sent as a playable attachment instead, because WhatsApp will not render a voice
30
+ * note that is not opus. Files are capped at 16MB, and `url` beats `base64` for anything
31
+ * sizeable. Counts as one message.
32
+ *
33
+ * `POST /messages/media`
34
+ */
35
+ sendMedia(params) {
36
+ return this.request({ method: "POST", path: "/messages/media" }, params);
37
+ }
38
+ /**
39
+ * Send one text to many recipients
40
+ *
41
+ * Send the same text to up to 25 recipients in one call — one message, and one message's worth
42
+ * of quota, per recipient. The answer reports each recipient separately: a batch where some
43
+ * land and some do not is the normal case, not an error. If something systemic stops the run
44
+ * (the number drops its session, the quota or rate limit refuses) the remaining recipients
45
+ * come back as `skipped` rather than being attempted, so they can be sent again once that is
46
+ * cleared. Sends inside a batch leave back-to-back, so keep lists small and space calls
47
+ * minutes apart — pacing keeps your number off WhatsApp's spam radar (see the avoiding-bans
48
+ * guide). Paid plans only.
49
+ *
50
+ * `POST /messages/batch`
51
+ */
52
+ sendBatch(params) {
53
+ return this.request({ method: "POST", path: "/messages/batch" }, params);
54
+ }
55
+ /**
56
+ * Send a location pin
57
+ *
58
+ * Send a map pin over WhatsApp. Counts as one message.
59
+ *
60
+ * `POST /messages/location`
61
+ */
62
+ sendLocation(params) {
63
+ return this.request({ method: "POST", path: "/messages/location" }, params);
64
+ }
65
+ /**
66
+ * Send a contact card
67
+ *
68
+ * Send a contact card (vCard) over WhatsApp, so the recipient can save the number with one
69
+ * tap. Counts as one message.
70
+ *
71
+ * `POST /messages/contact`
72
+ */
73
+ sendContact(params) {
74
+ return this.request({ method: "POST", path: "/messages/contact" }, params);
75
+ }
76
+ /**
77
+ * Send a verification code
78
+ *
79
+ * Generate a 6-digit code, send it over WhatsApp and return it. Returning the code is
80
+ * deliberate: verify it yourself, or hand it back to check_otp and keep nothing. Codes expire
81
+ * in 5 minutes by default and one number can only be sent a new code once a minute. Counts as
82
+ * one message.
83
+ *
84
+ * `POST /otp`
85
+ */
86
+ sendOtp(params) {
87
+ return this.request({ method: "POST", path: "/otp" }, params);
88
+ }
89
+ /**
90
+ * Check a verification code
91
+ *
92
+ * Verify a code sent with send_otp and consume it, so it can never be used twice. A wrong or
93
+ * expired code answers 400 OTP_INVALID — deliberately an error, not a `verified: false`, so a
94
+ * missing check at the caller can never read as success. Five wrong guesses kill the code.
95
+ * Free.
96
+ *
97
+ * `POST /otp/check`
98
+ */
99
+ checkOtp(params) {
100
+ return this.request({ method: "POST", path: "/otp/check" }, params);
101
+ }
102
+ /**
103
+ * List your WhatsApp numbers
104
+ *
105
+ * Every WhatsApp number on the account with its connection status. Start here when you do not
106
+ * know which number to send from, or to check whether one needs re-pairing. Free.
107
+ *
108
+ * `GET /numbers`
109
+ */
110
+ listNumbers() {
111
+ return this.request({ method: "GET", path: "/numbers" });
112
+ }
113
+ /**
114
+ * Add a WhatsApp number
115
+ *
116
+ * Create a new WhatsApp number slot on the account and return it. This is step one of two: the
117
+ * slot starts `disconnected` and cannot send until pair_number links a real WhatsApp account
118
+ * to it. How many can exist at once is what the plan sells. Free.
119
+ *
120
+ * `POST /numbers`
121
+ */
122
+ createNumber(params) {
123
+ return this.request({ method: "POST", path: "/numbers" }, params);
124
+ }
125
+ /**
126
+ * Check whether a phone is on WhatsApp
127
+ *
128
+ * Ask WhatsApp whether a phone number has an account, and get its profile picture when it
129
+ * does. Brazilian mobiles are checked with and without the extra 9 and the answer reports the
130
+ * form that actually matched. If WhatsApp cannot be reached the answer assumes yes and sets
131
+ * `verified: false` — an outage must not block sends to real people. Free.
132
+ *
133
+ * `GET /numbers/check/:phone`
134
+ */
135
+ checkNumber(params) {
136
+ return this.request({ method: "GET", path: "/numbers/check/:phone", pathParams: ["phone"] }, params);
137
+ }
138
+ /**
139
+ * Get one number's status
140
+ *
141
+ * One number's current state: `connected` (ready to send), `pairing` (waiting for a scan),
142
+ * `disconnected` (session dropped — pair it again) or `banned` (WhatsApp restricted it; wait
143
+ * out the 24h window before reconnecting). Free.
144
+ *
145
+ * `GET /numbers/:id`
146
+ */
147
+ numberStatus(params) {
148
+ return this.request({ method: "GET", path: "/numbers/:numberId", pathParams: ["numberId"] }, params);
149
+ }
150
+ /**
151
+ * Pair a number with WhatsApp
152
+ *
153
+ * Start (or resume) linking a WhatsApp account to one of your numbers. `qr` returns a QR code
154
+ * to scan from WhatsApp → Linked devices; `code` returns an 8-character linking code to type
155
+ * there instead, and needs the phone number being linked. A QR lives ~90 seconds and a new one
156
+ * can only be minted every few minutes, so call again to poll: `state: "pairing"` with no code
157
+ * yet simply means it is still being minted. Free.
158
+ *
159
+ * `POST /numbers/:id/pair`
160
+ */
161
+ pairNumber(params) {
162
+ return this.request({ method: "POST", path: "/numbers/:numberId/pair", pathParams: ["numberId"] }, params);
163
+ }
164
+ /**
165
+ * Disconnect a number from WhatsApp
166
+ *
167
+ * Log the linked WhatsApp account out of this number, keeping the number itself. Use it to
168
+ * link a different phone: a connected number cannot be re-paired until it is unpaired. Free.
169
+ *
170
+ * `POST /numbers/:id/unpair`
171
+ */
172
+ unpairNumber(params) {
173
+ return this.request({ method: "POST", path: "/numbers/:numberId/unpair", pathParams: ["numberId"] }, params);
174
+ }
175
+ /**
176
+ * Delete a number
177
+ *
178
+ * Remove a number from the account for good, logging its WhatsApp session out on the way. This
179
+ * frees a slot against the plan's limit. Messages already sent are unaffected, and the usage
180
+ * they cost stays on the bill. Free, and not reversible.
181
+ *
182
+ * `DELETE /numbers/:id`
183
+ */
184
+ deleteNumber(params) {
185
+ return this.request({ method: "DELETE", path: "/numbers/:numberId", pathParams: ["numberId"] }, params);
186
+ }
187
+ /**
188
+ * Show the typing indicator
189
+ *
190
+ * Show (or clear) the “typing…” indicator in a chat. Free — it is not a message. WhatsApp
191
+ * clears it on its own after a few seconds, so call it again for a long reply.
192
+ *
193
+ * `POST /chats/:phone/typing`
194
+ */
195
+ typing(params) {
196
+ return this.request({ method: "POST", path: "/chats/:to/typing", pathParams: ["to"] }, params);
197
+ }
198
+ /**
199
+ * Mark messages as read
200
+ *
201
+ * Put blue ticks on messages your number received in a chat. Free. Message ids come from the
202
+ * inbound webhook.
203
+ *
204
+ * `POST /chats/:phone/read`
205
+ */
206
+ markRead(params) {
207
+ return this.request({ method: "POST", path: "/chats/:to/read", pathParams: ["to"] }, params);
208
+ }
209
+ /**
210
+ * Get your webhook endpoint
211
+ *
212
+ * The endpoint events are being POSTed to, which ones it is subscribed to, and whether it is
213
+ * still healthy. `null` when none is registered. `disabledReason: "failures"` means we stopped
214
+ * delivering after a long run of dead attempts — fix the endpoint and set it again (or fire a
215
+ * test) to switch it back on. Free.
216
+ *
217
+ * `GET /webhooks`
218
+ */
219
+ getWebhook() {
220
+ return this.request({ method: "GET", path: "/webhooks" });
221
+ }
222
+ /**
223
+ * Register your webhook endpoint
224
+ *
225
+ * Point whatsapi.sh at an https URL and start receiving events there. The answer carries the
226
+ * signing secret ONCE, on first registration: keep it — every delivery is signed with it in
227
+ * the `x-whatsapi-signature` header (`t=<unix>,v1=<hmac-sha256 of "<t>.<body>">`), and that
228
+ * signature is how you know a request is really from us. Calling this again updates the URL or
229
+ * the subscription and keeps the same secret unless you ask to rotate it. Saving also
230
+ * re-enables an endpoint we had disabled. Free.
231
+ *
232
+ * `PUT /webhooks`
233
+ */
234
+ setWebhook(params) {
235
+ return this.request({ method: "PUT", path: "/webhooks" }, params);
236
+ }
237
+ /**
238
+ * Fire a test event at your endpoint
239
+ *
240
+ * Send a `ping` event to your registered endpoint right now and wait for the answer, so you
241
+ * can verify the URL and your signature check without waiting for a real message. The result
242
+ * is the actual outcome: `ok: false` carries the HTTP status your server answered, or why we
243
+ * could not reach it. A successful ping also revives an endpoint we had auto-disabled. Free.
244
+ *
245
+ * `POST /webhooks/test`
246
+ */
247
+ testWebhook() {
248
+ return this.request({ method: "POST", path: "/webhooks/test" });
249
+ }
250
+ /**
251
+ * Recent webhook deliveries
252
+ *
253
+ * The last deliveries we attempted, newest first — what we sent, what your endpoint answered,
254
+ * and how many attempts it took. This is the answer to “the event never arrived”. Deliveries
255
+ * are kept for a week. Free.
256
+ *
257
+ * `GET /webhooks/deliveries`
258
+ */
259
+ listWebhookDeliveries(params) {
260
+ return this.request({ method: "GET", path: "/webhooks/deliveries" }, params);
261
+ }
262
+ /**
263
+ * Remove your webhook endpoint
264
+ *
265
+ * Stop sending events and forget the endpoint, its secret and its delivery history.
266
+ * Registering again mints a new secret. Free.
267
+ *
268
+ * `DELETE /webhooks`
269
+ */
270
+ deleteWebhook() {
271
+ return this.request({ method: "DELETE", path: "/webhooks" });
272
+ }
273
+ /**
274
+ * Check quota and usage
275
+ *
276
+ * Messages sent this month against the plan quota, today against the daily fair-use cap, the
277
+ * leftover credit balance, and the per-key breakdown. Read this before a bulk send. Free.
278
+ *
279
+ * `GET /usage`
280
+ */
281
+ getUsage() {
282
+ return this.request({ method: "GET", path: "/usage" });
283
+ }
284
+ }
285
+ //# sourceMappingURL=operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/generated/operations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,177 @@
1
+ /** Arguments for `sendMessage()`. */
2
+ export interface SendMessageParams {
3
+ /** Recipient — a phone number in international format (+5511988887777) or a WhatsApp address
4
+ * (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group). */
5
+ to: string;
6
+ /** Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a
7
+ * single connected number it is resolved for you. */
8
+ from?: string;
9
+ /** The message body. */
10
+ text: string;
11
+ /** Render a preview card for the first link in the text. Default: on. */
12
+ linkPreview?: boolean;
13
+ }
14
+ /** Arguments for `sendMedia()`. */
15
+ export interface SendMediaParams {
16
+ /** Recipient — a phone number in international format (+5511988887777) or a WhatsApp address
17
+ * (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group). */
18
+ to: string;
19
+ /** Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a
20
+ * single connected number it is resolved for you. */
21
+ from?: string;
22
+ /** Which kind of media bubble to send. */
23
+ type: "image" | "video" | "audio" | "document";
24
+ /** Public https URL of the file — the better option. We stream the download and forward the
25
+ * bytes, so the size of the file never rides in your request. */
26
+ url?: string;
27
+ /** The file as base64, bare or as a `data:<mime>;base64,…` URI. Base64 inflates a request by a
28
+ * third, so prefer `url` for anything but small files. */
29
+ base64?: string;
30
+ /** Overrides the detected content type, e.g. `image/webp`. */
31
+ mimeType?: string;
32
+ /** Text shown under the media. Images and videos only — WhatsApp has no caption field for
33
+ * documents or audio. */
34
+ caption?: string;
35
+ /** Documents: the filename WhatsApp shows on the bubble. */
36
+ fileName?: string;
37
+ /** Voice notes: duration, so the bubble shows the right length. */
38
+ seconds?: number;
39
+ }
40
+ /** Arguments for `sendBatch()`. */
41
+ export interface SendBatchParams {
42
+ /** Recipients, up to 25. Each gets its own message; no duplicates. */
43
+ to: string[];
44
+ /** Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a
45
+ * single connected number it is resolved for you. */
46
+ from?: string;
47
+ /** The message body — the same for everyone. */
48
+ text: string;
49
+ }
50
+ /** Arguments for `sendLocation()`. */
51
+ export interface SendLocationParams {
52
+ /** Recipient — a phone number in international format (+5511988887777) or a WhatsApp address
53
+ * (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group). */
54
+ to: string;
55
+ /** Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a
56
+ * single connected number it is resolved for you. */
57
+ from?: string;
58
+ latitude: number;
59
+ longitude: number;
60
+ /** Label shown on the pin. */
61
+ name?: string;
62
+ }
63
+ /** Arguments for `sendContact()`. */
64
+ export interface SendContactParams {
65
+ /** Recipient — a phone number in international format (+5511988887777) or a WhatsApp address
66
+ * (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group). */
67
+ to: string;
68
+ /** Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a
69
+ * single connected number it is resolved for you. */
70
+ from?: string;
71
+ /** Display name on the card. */
72
+ name: string;
73
+ /** The vCard payload, e.g. `BEGIN:VCARD\nVERSION:3.0\n…\nEND:VCARD`. */
74
+ vcard: string;
75
+ }
76
+ /** Arguments for `sendOtp()`. */
77
+ export interface SendOtpParams {
78
+ /** Recipient — a phone number in international format (+5511988887777) or a WhatsApp address
79
+ * (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group). */
80
+ to: string;
81
+ /** Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a
82
+ * single connected number it is resolved for you. */
83
+ from?: string;
84
+ /** Message body. Must contain `{code}`; `{minutes}` expands to the expiry. Default: “{code} is
85
+ * your verification code. It expires in {minutes} minutes.” */
86
+ template?: string;
87
+ /** How long the code stays valid. Default 300 (5 minutes). */
88
+ expiresInSeconds?: number;
89
+ }
90
+ /** Arguments for `checkOtp()`. */
91
+ export interface CheckOtpParams {
92
+ /** Recipient — a phone number in international format (+5511988887777) or a WhatsApp address
93
+ * (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group). */
94
+ to: string;
95
+ /** The code the user typed. */
96
+ code: string;
97
+ }
98
+ /** Arguments for `createNumber()`. */
99
+ export interface CreateNumberParams {
100
+ /** A label you choose, e.g. “Support” — only you ever see it. */
101
+ name: string;
102
+ /** Pull the phone's existing chat history on pairing. Off by default: it copies conversations
103
+ * we otherwise never see. */
104
+ historySync?: boolean;
105
+ }
106
+ /** Arguments for `checkNumber()`. */
107
+ export interface CheckNumberParams {
108
+ /** The phone number to look up, e.g. +5511988887777. */
109
+ phone: string;
110
+ /** Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a
111
+ * single connected number it is resolved for you. */
112
+ from?: string;
113
+ }
114
+ /** Arguments for `numberStatus()`. */
115
+ export interface NumberStatusParams {
116
+ /** Id of the number, from list_numbers. */
117
+ numberId: string;
118
+ }
119
+ /** Arguments for `pairNumber()`. */
120
+ export interface PairNumberParams {
121
+ /** Id of the number to pair, from list_numbers. */
122
+ numberId: string;
123
+ /** `qr` (default) or `code` for the type-in linking code. */
124
+ mode?: "qr" | "code";
125
+ /** Required with `mode: "code"` — the phone number being linked. */
126
+ phone?: string;
127
+ }
128
+ /** Arguments for `unpairNumber()`. */
129
+ export interface UnpairNumberParams {
130
+ /** Id of the number, from list_numbers. */
131
+ numberId: string;
132
+ }
133
+ /** Arguments for `deleteNumber()`. */
134
+ export interface DeleteNumberParams {
135
+ /** Id of the number to delete, from list_numbers. */
136
+ numberId: string;
137
+ }
138
+ /** Arguments for `typing()`. */
139
+ export interface TypingParams {
140
+ /** Recipient — a phone number in international format (+5511988887777) or a WhatsApp address
141
+ * (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group). */
142
+ to: string;
143
+ /** Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a
144
+ * single connected number it is resolved for you. */
145
+ from?: string;
146
+ /** `composing` shows the indicator, `paused` clears it. Default: composing. */
147
+ state?: "composing" | "paused";
148
+ /** Show “recording audio…” instead of “typing…”. */
149
+ recording?: boolean;
150
+ }
151
+ /** Arguments for `markRead()`. */
152
+ export interface MarkReadParams {
153
+ /** Recipient — a phone number in international format (+5511988887777) or a WhatsApp address
154
+ * (5511988887777@s.whatsapp.net, an @lid contact, or a @g.us group). */
155
+ to: string;
156
+ /** Which of your WhatsApp numbers sends this — its id or its phone number. Optional: with a
157
+ * single connected number it is resolved for you. */
158
+ from?: string;
159
+ /** Ids of the received messages to acknowledge. */
160
+ messageIds: string[];
161
+ }
162
+ /** Arguments for `setWebhook()`. */
163
+ export interface SetWebhookParams {
164
+ /** Where to POST events, e.g. https://api.yourapp.com/webhooks/whatsapp. */
165
+ url: string;
166
+ /** Which events to receive: message.created, message.status, number.connected,
167
+ * number.disconnected, number.logged_out. Defaults to all of them. */
168
+ events?: "message.created" | "message.status" | "number.connected" | "number.disconnected" | "number.logged_out"[];
169
+ /** Mint a new signing secret and return it — the old one stops working. */
170
+ rotateSecret?: boolean;
171
+ }
172
+ /** Arguments for `listWebhookDeliveries()`. */
173
+ export interface ListWebhookDeliveriesParams {
174
+ /** How many to return, newest first. Up to 50 (the default). */
175
+ limit?: number;
176
+ }
177
+ //# sourceMappingURL=params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../src/generated/params.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ // GENERATED FILE — do not edit. Run `bun run sdk:gen`.
2
+ // Source: apps/api/src/operations/*.ts (zod input schemas)
3
+ //
4
+ // What each call takes. These are the same schemas the API validates with,
5
+ // so a value TypeScript accepts here is a value the server accepts too.
6
+ export {};
7
+ //# sourceMappingURL=params.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"params.js","sourceRoot":"","sources":["../../src/generated/params.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,2DAA2D;AAC3D,EAAE;AACF,2EAA2E;AAC3E,wEAAwE"}
@@ -0,0 +1,10 @@
1
+ export { Whatsapi } from "./client.ts";
2
+ export type { RequestSpec, WhatsapiOptions } from "./client.ts";
3
+ export { WebhookSignatureError, WhatsapiError } from "./errors.ts";
4
+ export type { ClientErrorCode, WhatsapiErrorInit } from "./errors.ts";
5
+ export { verifyWebhook } from "./webhooks.ts";
6
+ export type { VerifyWebhookInput } from "./webhooks.ts";
7
+ export { DEFAULT_BASE_URL, SDK_VERSION } from "./generated/operations.ts";
8
+ export * from "./generated/contract.ts";
9
+ export type * from "./generated/params.ts";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE1E,cAAc,yBAAyB,CAAC;AACxC,mBAAmB,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ // The published surface of `whatsapi`.
2
+ export { Whatsapi } from "./client.js";
3
+ export { WebhookSignatureError, WhatsapiError } from "./errors.js";
4
+ export { verifyWebhook } from "./webhooks.js";
5
+ export { DEFAULT_BASE_URL, SDK_VERSION } from "./generated/operations.js";
6
+ // Every DTO, error code and event shape the API speaks.
7
+ export * from "./generated/contract.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC1E,wDAAwD;AACxD,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { WebhookEvent } from "./generated/contract.ts";
2
+ export interface VerifyWebhookInput {
3
+ /** The RAW request body — the exact bytes we signed. A body that has been
4
+ * parsed and re-serialized will not match, even when it looks identical. */
5
+ payload: string | Uint8Array;
6
+ /** The `x-whatsapi-signature` header. */
7
+ signature: string | null | undefined;
8
+ /** The `whsec_` secret, shown once when the endpoint was registered. */
9
+ secret: string;
10
+ /** How old a delivery may be, in seconds. Default 300. */
11
+ toleranceSeconds?: number;
12
+ }
13
+ /**
14
+ * Verify a delivery and parse it.
15
+ *
16
+ * Throws `WebhookSignatureError` for anything that does not check out — answer
17
+ * 400 and log it. On success you get the event, discriminated on `type`:
18
+ *
19
+ * ```ts
20
+ * const event = await verifyWebhook({ payload: rawBody, signature: req.headers["x-whatsapi-signature"], secret });
21
+ * if (event.type === "message.created") reply(event.data.message.text);
22
+ * ```
23
+ *
24
+ * Deliveries retry, so the same `event.id` (also the `x-whatsapi-delivery`
25
+ * header) can arrive twice: record it and drop repeats.
26
+ */
27
+ export declare function verifyWebhook(input: VerifyWebhookInput): Promise<WebhookEvent>;
28
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D,MAAM,WAAW,kBAAkB;IAC/B;iFAC6E;IAC7E,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,yCAAyC;IACzC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AA6BD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAiCpF"}
@@ -0,0 +1,73 @@
1
+ // Receiving events: check the signature, then hand back a typed event.
2
+ //
3
+ // Verifying is not optional. The URL is public, so anything can POST to it —
4
+ // the `x-whatsapi-signature` header is the only thing that separates our
5
+ // delivery from someone else's forgery, and it signs the TIMESTAMP alongside
6
+ // the body so a captured payload cannot be replayed at you later.
7
+ import { WebhookSignatureError } from "./errors.js";
8
+ const encoder = new TextEncoder();
9
+ function hex(buffer) {
10
+ return Array.from(new Uint8Array(buffer), (b) => b.toString(16).padStart(2, "0")).join("");
11
+ }
12
+ /** Constant time in the length that matters: comparing hex digit by digit with
13
+ * `===` leaks how much of a guess was right through timing. */
14
+ function timingSafeEqual(a, b) {
15
+ if (a.length !== b.length)
16
+ return false;
17
+ let diff = 0;
18
+ for (let i = 0; i < a.length; i++)
19
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
20
+ return diff === 0;
21
+ }
22
+ /** `t=<unix seconds>,v1=<hex>` — tolerant of spacing and of future `vN=` parts. */
23
+ function parseHeader(header) {
24
+ let timestamp = NaN;
25
+ let v1 = "";
26
+ for (const part of header.split(",")) {
27
+ const [key, value = ""] = part.trim().split("=", 2);
28
+ if (key === "t")
29
+ timestamp = Number(value);
30
+ if (key === "v1")
31
+ v1 = value;
32
+ }
33
+ return Number.isFinite(timestamp) && v1 ? { timestamp, v1 } : null;
34
+ }
35
+ /**
36
+ * Verify a delivery and parse it.
37
+ *
38
+ * Throws `WebhookSignatureError` for anything that does not check out — answer
39
+ * 400 and log it. On success you get the event, discriminated on `type`:
40
+ *
41
+ * ```ts
42
+ * const event = await verifyWebhook({ payload: rawBody, signature: req.headers["x-whatsapi-signature"], secret });
43
+ * if (event.type === "message.created") reply(event.data.message.text);
44
+ * ```
45
+ *
46
+ * Deliveries retry, so the same `event.id` (also the `x-whatsapi-delivery`
47
+ * header) can arrive twice: record it and drop repeats.
48
+ */
49
+ export async function verifyWebhook(input) {
50
+ const { payload, signature, secret, toleranceSeconds = 300 } = input;
51
+ if (!signature)
52
+ throw new WebhookSignatureError("Missing x-whatsapi-signature header.");
53
+ if (!secret)
54
+ throw new WebhookSignatureError("Missing webhook secret.");
55
+ const parsed = parseHeader(signature);
56
+ if (!parsed)
57
+ throw new WebhookSignatureError("Malformed x-whatsapi-signature header.");
58
+ const age = Math.abs(Date.now() / 1000 - parsed.timestamp);
59
+ if (age > toleranceSeconds)
60
+ throw new WebhookSignatureError(`Delivery is ${Math.round(age)}s old, outside the ${toleranceSeconds}s tolerance.`);
61
+ const body = typeof payload === "string" ? payload : new TextDecoder().decode(payload);
62
+ const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
63
+ const expected = hex(await crypto.subtle.sign("HMAC", key, encoder.encode(`${parsed.timestamp}.${body}`)));
64
+ if (!timingSafeEqual(expected, parsed.v1))
65
+ throw new WebhookSignatureError("Signature does not match — the body is not from us.");
66
+ try {
67
+ return JSON.parse(body);
68
+ }
69
+ catch {
70
+ throw new WebhookSignatureError("Delivery body is not JSON.");
71
+ }
72
+ }
73
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"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"}