whatsapp-cloud 0.0.4 → 0.0.5

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/agent_docs/INCOMING_MESSAGES_BRAINSTORM.md +500 -0
  3. package/cloud-api-docs/webhooks/endpoint.md +112 -0
  4. package/cloud-api-docs/webhooks/overview.md +154 -0
  5. package/package.json +6 -2
  6. package/src/client/HttpClient.ts +43 -6
  7. package/src/client/WhatsAppClient.ts +3 -0
  8. package/src/examples/main.ts +9 -0
  9. package/src/examples/template.ts +134 -0
  10. package/src/schemas/client.ts +2 -2
  11. package/src/schemas/index.ts +1 -0
  12. package/src/schemas/templates/component.ts +145 -0
  13. package/src/schemas/templates/index.ts +4 -0
  14. package/src/schemas/templates/request.ts +78 -0
  15. package/src/schemas/templates/response.ts +64 -0
  16. package/src/services/accounts/AccountsClient.ts +6 -14
  17. package/src/services/accounts/AccountsService.ts +19 -21
  18. package/src/services/accounts/methods/list-phone-numbers.ts +1 -2
  19. package/src/services/business/BusinessClient.ts +1 -9
  20. package/src/services/business/BusinessService.ts +19 -21
  21. package/src/services/business/methods/list-accounts.ts +1 -2
  22. package/src/services/messages/MessagesClient.ts +2 -6
  23. package/src/services/messages/MessagesService.ts +42 -22
  24. package/src/services/templates/TemplatesClient.ts +35 -0
  25. package/src/services/templates/TemplatesService.ts +117 -0
  26. package/src/services/templates/index.ts +3 -0
  27. package/src/services/templates/methods/create.ts +27 -0
  28. package/src/services/templates/methods/delete.ts +38 -0
  29. package/src/services/templates/methods/get.ts +23 -0
  30. package/src/services/templates/methods/list.ts +36 -0
  31. package/src/services/templates/methods/update.ts +35 -0
  32. package/src/types/index.ts +1 -0
  33. package/src/types/templates/component.ts +33 -0
  34. package/src/types/templates/index.ts +4 -0
  35. package/src/types/templates/request.ts +28 -0
  36. package/src/types/templates/response.ts +34 -0
  37. package/tsconfig.json +2 -3
@@ -0,0 +1,64 @@
1
+ import { z } from "zod";
2
+ import { componentSchema } from "./component";
3
+
4
+ /**
5
+ * Schema for template response (single template)
6
+ */
7
+ export const templateResponseSchema = z.object({
8
+ id: z.string(),
9
+ name: z.string(),
10
+ language: z.string(),
11
+ status: z.string(),
12
+ category: z.string(),
13
+ components: z.array(componentSchema),
14
+ });
15
+
16
+ /**
17
+ * Schema for create template response
18
+ */
19
+ export const createTemplateResponseSchema = z.object({
20
+ id: z.string(),
21
+ status: z.string(),
22
+ category: z.string(),
23
+ });
24
+
25
+ /**
26
+ * Schema for list templates response
27
+ */
28
+ export const templateListItemSchema = z.object({
29
+ id: z.string(),
30
+ name: z.string(),
31
+ language: z.string(),
32
+ status: z.string(),
33
+ category: z.string(),
34
+ components: z.array(componentSchema),
35
+ });
36
+
37
+ export const listTemplatesResponseSchema = z.object({
38
+ data: z.array(templateListItemSchema),
39
+ paging: z
40
+ .object({
41
+ cursors: z
42
+ .object({
43
+ before: z.string().optional(),
44
+ after: z.string().optional(),
45
+ })
46
+ .optional(),
47
+ })
48
+ .optional(),
49
+ });
50
+
51
+ /**
52
+ * Schema for update template response
53
+ */
54
+ export const updateTemplateResponseSchema = z.object({
55
+ success: z.boolean(),
56
+ });
57
+
58
+ /**
59
+ * Schema for delete template response
60
+ */
61
+ export const deleteTemplateResponseSchema = z.object({
62
+ success: z.boolean(),
63
+ });
64
+
@@ -1,42 +1,34 @@
1
1
  import type { HttpClient } from "../../client/HttpClient";
2
2
 
3
3
  /**
4
- * Accounts client - wraps HttpClient with WABA ID (WhatsApp Business Account ID) as base endpoint
4
+ * Accounts client - wraps HttpClient with WABA ID as base endpoint
5
5
  *
6
- * This client automatically prepends `/${wabaId}` to all request paths,
7
- * so methods can use relative paths like `/phone_numbers` instead of `/${wabaId}/phone_numbers`.
8
- *
9
- * Note: The wabaId is the WhatsApp Business Account ID (not the Business Portfolio ID).
10
- * This is used in endpoints like GET /<WABA_ID>/phone_numbers.
11
- *
12
- * This treats wabaId as a "client" for the accounts namespace - different
13
- * wabaIds represent different WhatsApp Business Account endpoints.
6
+ * This client automatically prepends `/${businessAccountId}` to all request paths.
14
7
  */
15
8
  export class AccountsClient {
16
9
  constructor(
17
10
  private readonly httpClient: HttpClient,
18
- private readonly wabaId: string
11
+ private readonly businessAccountId: string
19
12
  ) {}
20
13
 
21
14
  /**
22
15
  * Make a GET request with WABA ID prefix
23
16
  */
24
17
  async get<T>(path: string): Promise<T> {
25
- return this.httpClient.get<T>(`/${this.wabaId}${path}`);
18
+ return this.httpClient.get<T>(`/${this.businessAccountId}${path}`);
26
19
  }
27
20
 
28
21
  /**
29
22
  * Make a POST request with WABA ID prefix
30
23
  */
31
24
  async post<T>(path: string, body: unknown): Promise<T> {
32
- return this.httpClient.post<T>(`/${this.wabaId}${path}`, body);
25
+ return this.httpClient.post<T>(`/${this.businessAccountId}${path}`, body);
33
26
  }
34
27
 
35
28
  /**
36
29
  * Make a PATCH request with WABA ID prefix
37
30
  */
38
31
  async patch<T>(path: string, body: unknown): Promise<T> {
39
- return this.httpClient.patch<T>(`/${this.wabaId}${path}`, body);
32
+ return this.httpClient.patch<T>(`/${this.businessAccountId}${path}`, body);
40
33
  }
41
34
  }
42
-
@@ -7,41 +7,39 @@ import type { PhoneNumberListResponse } from "../../types/accounts/phone-number"
7
7
  /**
8
8
  * Accounts service for managing WhatsApp Business Accounts
9
9
  *
10
- * The service validates that businessAccountId (WABA ID - WhatsApp Business Account ID) is set
11
- * at the client level and creates an AccountsClient instance.
12
- *
13
- * Note: businessAccountId in the client config represents the WABA ID, not the Business Portfolio ID.
14
- * The WABA ID is used in endpoints like GET /<WABA_ID>/phone_numbers.
15
- *
16
- * AccountsClient treats wabaId as a "client" for the accounts namespace - different
17
- * wabaIds represent different WhatsApp Business Account endpoints.
10
+ * This service handles WABA operations like listing phone numbers.
11
+ * It supports both a globally configured businessAccountId (in WhatsAppClient)
12
+ * and per-request businessAccountId overrides.
18
13
  */
19
14
  export class AccountsService {
20
- private readonly accountsClient: AccountsClient;
15
+ constructor(private readonly httpClient: HttpClient) {}
21
16
 
22
- constructor(httpClient: HttpClient) {
23
- // Validate that businessAccountId (WABA ID) is set at client level
24
- // This is the WhatsApp Business Account ID, not the Business Portfolio ID
25
- if (!httpClient.businessAccountId) {
17
+ /**
18
+ * Helper to create a Scoped Client (prefer override, fallback to config)
19
+ */
20
+ private getClient(overrideId?: string): AccountsClient {
21
+ const id = overrideId || this.httpClient.businessAccountId;
22
+ if (!id) {
26
23
  throw new WhatsAppValidationError(
27
- "businessAccountId (WABA ID - WhatsApp Business Account ID) is required for AccountsService. Provide it in WhatsAppClient config.",
24
+ "businessAccountId (WABA ID) is required. Provide it in WhatsAppClient config or as a parameter.",
28
25
  "businessAccountId"
29
26
  );
30
27
  }
31
28
 
32
- // Create accounts client with WABA ID baked in
33
- this.accountsClient = new AccountsClient(
34
- httpClient,
35
- httpClient.businessAccountId
36
- );
29
+ // Just wrap the existing httpClient
30
+ return new AccountsClient(this.httpClient, id);
37
31
  }
38
32
 
39
33
  /**
40
34
  * List phone numbers for a WhatsApp Business Account
41
35
  *
36
+ * @param businessAccountId - Optional WABA ID (overrides client config)
42
37
  * @returns List of phone numbers associated with the WABA
43
38
  */
44
- async listPhoneNumbers(): Promise<PhoneNumberListResponse> {
45
- return listPhoneNumbers(this.accountsClient);
39
+ async listPhoneNumbers(
40
+ businessAccountId?: string
41
+ ): Promise<PhoneNumberListResponse> {
42
+ const client = this.getClient(businessAccountId);
43
+ return listPhoneNumbers(client);
46
44
  }
47
45
  }
@@ -4,7 +4,7 @@ import type { PhoneNumberListResponse } from "../../../types/accounts/phone-numb
4
4
  /**
5
5
  * List phone numbers for a WhatsApp Business Account
6
6
  *
7
- * @param accountsClient - Accounts client with WABA ID baked in
7
+ * @param accountsClient - Scoped accounts client
8
8
  * @returns List of phone numbers associated with the WABA
9
9
  */
10
10
  export async function listPhoneNumbers(
@@ -13,4 +13,3 @@ export async function listPhoneNumbers(
13
13
  // Make API request - accountsClient handles the WABA ID prefix automatically
14
14
  return accountsClient.get<PhoneNumberListResponse>("/phone_numbers");
15
15
  }
16
-
@@ -3,14 +3,7 @@ import type { HttpClient } from "../../client/HttpClient";
3
3
  /**
4
4
  * Business client - wraps HttpClient with Business Portfolio ID as base endpoint
5
5
  *
6
- * This client automatically prepends `/${businessId}` to all request paths,
7
- * so methods can use relative paths like `/whatsapp_business_accounts` instead of `/${businessId}/whatsapp_business_accounts`.
8
- *
9
- * Note: The businessId is the Business Portfolio ID (not the WABA ID).
10
- * This is used in endpoints like GET /<Business-ID>/whatsapp_business_accounts.
11
- *
12
- * This treats businessId as a "client" for the business namespace - different
13
- * businessIds represent different Business Portfolio endpoints.
6
+ * This client automatically prepends `/${businessId}` to all request paths.
14
7
  */
15
8
  export class BusinessClient {
16
9
  constructor(
@@ -39,4 +32,3 @@ export class BusinessClient {
39
32
  return this.httpClient.patch<T>(`/${this.businessId}${path}`, body);
40
33
  }
41
34
  }
42
-
@@ -7,41 +7,39 @@ import type { BusinessAccountsListResponse } from "../../types/business/account"
7
7
  /**
8
8
  * Business service for managing Business Portfolios
9
9
  *
10
- * The service validates that businessId (Business Portfolio ID) is set at the client level
11
- * and creates a BusinessClient instance.
12
- *
13
- * Note: businessId in the client config represents the Business Portfolio ID.
14
- * The Business Portfolio ID is used in endpoints like GET /<Business-ID>/whatsapp_business_accounts.
15
- *
16
- * BusinessClient treats businessId as a "client" for the business namespace - different
17
- * businessIds represent different Business Portfolio endpoints.
10
+ * This service handles Business Portfolio operations like listing WABAs.
11
+ * It supports both a globally configured businessId (in WhatsAppClient)
12
+ * and per-request businessId overrides.
18
13
  */
19
14
  export class BusinessService {
20
- private readonly businessClient: BusinessClient;
15
+ constructor(private readonly httpClient: HttpClient) {}
21
16
 
22
- constructor(httpClient: HttpClient) {
23
- // Validate that businessId (Business Portfolio ID) is set at client level
24
- if (!httpClient.businessId) {
17
+ /**
18
+ * Helper to create a Scoped Client (prefer override, fallback to config)
19
+ */
20
+ private getClient(overrideId?: string): BusinessClient {
21
+ const id = overrideId || this.httpClient.businessId;
22
+ if (!id) {
25
23
  throw new WhatsAppValidationError(
26
- "businessId (Business Portfolio ID) is required for BusinessService. Provide it in WhatsAppClient config.",
24
+ "businessId (Business Portfolio ID) is required. Provide it in WhatsAppClient config or as a parameter.",
27
25
  "businessId"
28
26
  );
29
27
  }
30
28
 
31
- // Create business client with Business Portfolio ID baked in
32
- this.businessClient = new BusinessClient(
33
- httpClient,
34
- httpClient.businessId
35
- );
29
+ // Just wrap the existing httpClient
30
+ return new BusinessClient(this.httpClient, id);
36
31
  }
37
32
 
38
33
  /**
39
34
  * List WhatsApp Business Accounts (WABAs) for a Business Portfolio
40
35
  *
36
+ * @param businessId - Optional Business Portfolio ID (overrides client config)
41
37
  * @returns List of WABAs associated with the Business Portfolio
42
38
  */
43
- async listAccounts(): Promise<BusinessAccountsListResponse> {
44
- return listAccounts(this.businessClient);
39
+ async listAccounts(
40
+ businessId?: string
41
+ ): Promise<BusinessAccountsListResponse> {
42
+ const client = this.getClient(businessId);
43
+ return listAccounts(client);
45
44
  }
46
45
  }
47
-
@@ -4,7 +4,7 @@ import type { BusinessAccountsListResponse } from "../../../types/business/accou
4
4
  /**
5
5
  * List WhatsApp Business Accounts (WABAs) for a Business Portfolio
6
6
  *
7
- * @param businessClient - Business client with Business Portfolio ID baked in
7
+ * @param businessClient - Scoped business client
8
8
  * @returns List of WABAs associated with the Business Portfolio
9
9
  */
10
10
  export async function listAccounts(
@@ -15,4 +15,3 @@ export async function listAccounts(
15
15
  "/whatsapp_business_accounts"
16
16
  );
17
17
  }
18
-
@@ -2,12 +2,8 @@ import type { HttpClient } from "../../client/HttpClient";
2
2
 
3
3
  /**
4
4
  * Messages client - wraps HttpClient with phone number ID as base endpoint
5
- *
6
- * This client automatically prepends `/${phoneNumberId}` to all request paths,
7
- * so methods can use relative paths like `/messages` instead of `/${phoneNumberId}/messages`.
8
- *
9
- * This treats phoneNumberId as a "client" for the messaging namespace - different
10
- * phoneNumberIds represent different messaging endpoints.
5
+ *
6
+ * This client automatically prepends `/${phoneNumberId}` to all request paths.
11
7
  */
12
8
  export class MessagesClient {
13
9
  constructor(
@@ -1,4 +1,4 @@
1
- import type { HttpClient } from "../../client/HttpClient";
1
+ import { HttpClient } from "../../client/HttpClient";
2
2
  import { sendText } from "./methods/send-text";
3
3
  import { sendImage } from "./methods/send-image";
4
4
  import { sendLocation } from "./methods/send-location";
@@ -16,62 +16,82 @@ import type { MessageResponse } from "../../types/messages/response";
16
16
  /**
17
17
  * Messages service for sending WhatsApp messages
18
18
  *
19
- * The service validates that phoneNumberId is set at the client level and creates
20
- * a MessagesClient instance. MessagesClient treats phoneNumberId as a "client" for
21
- * the messaging namespace - different phoneNumberIds represent different endpoints.
19
+ * This service handles message operations.
20
+ * It supports both a globally configured phoneNumberId (in WhatsAppClient)
21
+ * and per-request phoneNumberId overrides.
22
22
  */
23
23
  export class MessagesService {
24
- private readonly messagesClient: MessagesClient;
24
+ constructor(private readonly httpClient: HttpClient) {}
25
25
 
26
- constructor(httpClient: HttpClient) {
27
- // Validate that phoneNumberId is set at client level
28
- if (!httpClient.phoneNumberId) {
26
+ /**
27
+ * Helper to create a Scoped Client (prefer override, fallback to config)
28
+ */
29
+ private getClient(overrideId?: string): MessagesClient {
30
+ const id = overrideId || this.httpClient.phoneNumberId;
31
+ if (!id) {
29
32
  throw new WhatsAppValidationError(
30
- "phoneNumberId is required for MessagesService. Provide it in WhatsAppClient config.",
33
+ "phoneNumberId is required. Provide it in WhatsAppClient config or as a parameter.",
31
34
  "phoneNumberId"
32
35
  );
33
36
  }
34
37
 
35
- // Create messages client with phone number ID baked in
36
- this.messagesClient = new MessagesClient(
37
- httpClient,
38
- httpClient.phoneNumberId
39
- );
38
+ // Just wrap the existing httpClient
39
+ return new MessagesClient(this.httpClient, id);
40
40
  }
41
41
 
42
42
  /**
43
43
  * Send a text message
44
44
  *
45
45
  * @param request - Text message request (to, text)
46
+ * @param phoneNumberId - Optional phone number ID (overrides client config)
46
47
  */
47
- async sendText(request: SendTextRequest): Promise<MessageResponse> {
48
- return sendText(this.messagesClient, request);
48
+ async sendText(
49
+ request: SendTextRequest,
50
+ phoneNumberId?: string
51
+ ): Promise<MessageResponse> {
52
+ const client = this.getClient(phoneNumberId);
53
+ return sendText(client, request);
49
54
  }
50
55
 
51
56
  /**
52
57
  * Send an image message
53
58
  *
54
59
  * @param request - Image message request (to, image)
60
+ * @param phoneNumberId - Optional phone number ID (overrides client config)
55
61
  */
56
- async sendImage(request: SendImageRequest): Promise<MessageResponse> {
57
- return sendImage(this.messagesClient, request);
62
+ async sendImage(
63
+ request: SendImageRequest,
64
+ phoneNumberId?: string
65
+ ): Promise<MessageResponse> {
66
+ const client = this.getClient(phoneNumberId);
67
+ return sendImage(client, request);
58
68
  }
59
69
 
60
70
  /**
61
71
  * Send a location message
62
72
  *
63
73
  * @param request - Location message request (to, location)
74
+ * @param phoneNumberId - Optional phone number ID (overrides client config)
64
75
  */
65
- async sendLocation(request: SendLocationRequest): Promise<MessageResponse> {
66
- return sendLocation(this.messagesClient, request);
76
+ async sendLocation(
77
+ request: SendLocationRequest,
78
+ phoneNumberId?: string
79
+ ): Promise<MessageResponse> {
80
+ const client = this.getClient(phoneNumberId);
81
+ return sendLocation(client, request);
67
82
  }
68
83
 
69
84
  /**
70
85
  * Send a reaction message
71
86
  *
72
87
  * @param request - Reaction message request (to, reaction)
88
+ * @param phoneNumberId - Optional phone number ID (overrides client config)
73
89
  */
74
- async sendReaction(request: SendReactionRequest): Promise<MessageResponse> {
75
- return sendReaction(this.messagesClient, request);
90
+ async sendReaction(
91
+ request: SendReactionRequest,
92
+ phoneNumberId?: string
93
+ ): Promise<MessageResponse> {
94
+ const client = this.getClient(phoneNumberId);
95
+ return sendReaction(client, request);
76
96
  }
77
97
  }
@@ -0,0 +1,35 @@
1
+ import type { HttpClient } from "../../client/HttpClient";
2
+
3
+ /**
4
+ * Templates client - wraps HttpClient with WABA ID as base endpoint
5
+ *
6
+ * This client automatically prepends `/${businessAccountId}` to all request paths.
7
+ * Similar to AccountsClient, since templates are scoped to WABA.
8
+ */
9
+ export class TemplatesClient {
10
+ constructor(
11
+ private readonly httpClient: HttpClient,
12
+ private readonly businessAccountId: string
13
+ ) {}
14
+
15
+ /**
16
+ * Make a GET request with WABA ID prefix
17
+ */
18
+ async get<T>(path: string): Promise<T> {
19
+ return this.httpClient.get<T>(`/${this.businessAccountId}${path}`);
20
+ }
21
+
22
+ /**
23
+ * Make a POST request with WABA ID prefix
24
+ */
25
+ async post<T>(path: string, body: unknown): Promise<T> {
26
+ return this.httpClient.post<T>(`/${this.businessAccountId}${path}`, body);
27
+ }
28
+
29
+ /**
30
+ * Make a DELETE request with WABA ID prefix
31
+ */
32
+ async delete<T>(path: string): Promise<T> {
33
+ return this.httpClient.delete<T>(`/${this.businessAccountId}${path}`);
34
+ }
35
+ }
@@ -0,0 +1,117 @@
1
+ import type { HttpClient } from "../../client/HttpClient";
2
+ import { TemplatesClient } from "./TemplatesClient";
3
+ import { createTemplate } from "./methods/create";
4
+ import { listTemplates } from "./methods/list";
5
+ import { getTemplate } from "./methods/get";
6
+ import { updateTemplate } from "./methods/update";
7
+ import { deleteTemplate } from "./methods/delete";
8
+ import { WhatsAppValidationError } from "../../errors";
9
+ import type {
10
+ CreateTemplateRequest,
11
+ UpdateTemplateRequest,
12
+ ListTemplatesRequest,
13
+ DeleteTemplateRequest,
14
+ } from "../../types/templates/request";
15
+ import type {
16
+ CreateTemplateResponse,
17
+ ListTemplatesResponse,
18
+ TemplateResponse,
19
+ UpdateTemplateResponse,
20
+ DeleteTemplateResponse,
21
+ } from "../../types/templates/response";
22
+
23
+ /**
24
+ * Templates service for managing message templates
25
+ *
26
+ * This service handles template operations like creating, listing, and deleting templates.
27
+ * It supports both a globally configured businessAccountId (in WhatsAppClient)
28
+ * and per-request businessAccountId overrides.
29
+ *
30
+ * Note: Get and Update operations use template ID directly (no WABA prefix needed).
31
+ */
32
+ export class TemplatesService {
33
+ constructor(private readonly httpClient: HttpClient) {}
34
+
35
+ /**
36
+ * Helper to create a Scoped Client (prefer override, fallback to config)
37
+ */
38
+ private getClient(overrideId?: string): TemplatesClient {
39
+ const id = overrideId || this.httpClient.businessAccountId;
40
+ if (!id) {
41
+ throw new WhatsAppValidationError(
42
+ "businessAccountId (WABA ID) is required for templates. Provide it in WhatsAppClient config or as a parameter.",
43
+ "businessAccountId"
44
+ );
45
+ }
46
+
47
+ return new TemplatesClient(this.httpClient, id);
48
+ }
49
+
50
+ /**
51
+ * Create a message template
52
+ *
53
+ * @param request - Template creation request
54
+ * @param businessAccountId - Optional WABA ID (overrides client config)
55
+ */
56
+ async create(
57
+ request: CreateTemplateRequest,
58
+ businessAccountId?: string
59
+ ): Promise<CreateTemplateResponse> {
60
+ const client = this.getClient(businessAccountId);
61
+ return createTemplate(client, request);
62
+ }
63
+
64
+ /**
65
+ * List message templates
66
+ *
67
+ * @param options - Optional filter options (name)
68
+ * @param businessAccountId - Optional WABA ID (overrides client config)
69
+ */
70
+ async list(
71
+ options?: ListTemplatesRequest,
72
+ businessAccountId?: string
73
+ ): Promise<ListTemplatesResponse> {
74
+ const client = this.getClient(businessAccountId);
75
+ return listTemplates(client, options);
76
+ }
77
+
78
+ /**
79
+ * Get a template by ID
80
+ *
81
+ * Note: This uses the template ID directly (no WABA prefix needed)
82
+ *
83
+ * @param templateId - Template ID
84
+ */
85
+ async get(templateId: string): Promise<TemplateResponse> {
86
+ return getTemplate(this.httpClient, templateId);
87
+ }
88
+
89
+ /**
90
+ * Update a template
91
+ *
92
+ * Note: This uses the template ID directly (no WABA prefix needed)
93
+ *
94
+ * @param templateId - Template ID
95
+ * @param request - Template update request
96
+ */
97
+ async update(
98
+ templateId: string,
99
+ request: UpdateTemplateRequest
100
+ ): Promise<UpdateTemplateResponse> {
101
+ return updateTemplate(this.httpClient, templateId, request);
102
+ }
103
+
104
+ /**
105
+ * Delete a template
106
+ *
107
+ * @param options - Delete options (name or hsm_id)
108
+ * @param businessAccountId - Optional WABA ID (overrides client config)
109
+ */
110
+ async delete(
111
+ options: DeleteTemplateRequest,
112
+ businessAccountId?: string
113
+ ): Promise<DeleteTemplateResponse> {
114
+ const client = this.getClient(businessAccountId);
115
+ return deleteTemplate(client, options);
116
+ }
117
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./TemplatesService";
2
+ export * from "./TemplatesClient";
3
+
@@ -0,0 +1,27 @@
1
+ import type { TemplatesClient } from "../TemplatesClient";
2
+ import { createTemplateRequestSchema } from "../../../schemas/templates/request";
3
+ import type { CreateTemplateRequest } from "../../../types/templates/request";
4
+ import type { CreateTemplateResponse } from "../../../types/templates/response";
5
+ import { transformZodError } from "../../../utils/zod-error";
6
+
7
+ /**
8
+ * Create a message template
9
+ *
10
+ * @param templatesClient - Templates client with WABA ID baked in
11
+ * @param request - Template creation request
12
+ */
13
+ export async function createTemplate(
14
+ templatesClient: TemplatesClient,
15
+ request: CreateTemplateRequest
16
+ ): Promise<CreateTemplateResponse> {
17
+ // Validate request with schema - throws WhatsAppValidationError if invalid
18
+ const result = createTemplateRequestSchema.safeParse(request);
19
+ if (!result.success) {
20
+ throw transformZodError(result.error);
21
+ }
22
+ const data = result.data;
23
+
24
+ // Make API request - templatesClient handles the WABA ID prefix automatically
25
+ return templatesClient.post<CreateTemplateResponse>("/message_templates", data);
26
+ }
27
+
@@ -0,0 +1,38 @@
1
+ import type { TemplatesClient } from "../TemplatesClient";
2
+ import { deleteTemplateRequestSchema } from "../../../schemas/templates/request";
3
+ import type { DeleteTemplateRequest } from "../../../types/templates/request";
4
+ import type { DeleteTemplateResponse } from "../../../types/templates/response";
5
+ import { transformZodError } from "../../../utils/zod-error";
6
+
7
+ /**
8
+ * Delete a template
9
+ *
10
+ * @param templatesClient - Templates client with WABA ID baked in
11
+ * @param options - Delete options (name or hsm_id)
12
+ */
13
+ export async function deleteTemplate(
14
+ templatesClient: TemplatesClient,
15
+ options: DeleteTemplateRequest
16
+ ): Promise<DeleteTemplateResponse> {
17
+ // Validate request with schema - throws WhatsAppValidationError if invalid
18
+ const result = deleteTemplateRequestSchema.safeParse(options);
19
+ if (!result.success) {
20
+ throw transformZodError(result.error);
21
+ }
22
+ const data = result.data;
23
+
24
+ // Build query string
25
+ const params = new URLSearchParams();
26
+ if (data.name) {
27
+ params.append("name", data.name);
28
+ }
29
+ if (data.hsm_id) {
30
+ params.append("hsm_id", data.hsm_id);
31
+ }
32
+ const queryString = params.toString();
33
+ const path = `/message_templates?${queryString}`;
34
+
35
+ // Make API request - templatesClient handles the WABA ID prefix automatically
36
+ return templatesClient.delete<DeleteTemplateResponse>(path);
37
+ }
38
+
@@ -0,0 +1,23 @@
1
+ import type { HttpClient } from "../../../client/HttpClient";
2
+ import type { TemplateResponse } from "../../../types/templates/response";
3
+
4
+ /**
5
+ * Get a template by ID
6
+ *
7
+ * Note: This uses the template ID directly (no WABA prefix needed)
8
+ *
9
+ * @param httpClient - HTTP client
10
+ * @param templateId - Template ID
11
+ */
12
+ export async function getTemplate(
13
+ httpClient: HttpClient,
14
+ templateId: string
15
+ ): Promise<TemplateResponse> {
16
+ if (!templateId || templateId.trim().length === 0) {
17
+ throw new Error("Template ID is required");
18
+ }
19
+
20
+ // Make API request - template ID is used directly, no WABA prefix
21
+ return httpClient.get<TemplateResponse>(`/${templateId}`);
22
+ }
23
+