UNPKG

@great-detail/whatsapp

Version:

SDK for interfacing with WhatsApp Business Platform in Typescript or Node.js using the Cloud API, hosted by Meta.

1,459 lines (1,407 loc) 45.1 kB
import * as ky from 'ky'; import { Options as Options$1 } from 'ky'; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ /** * A Phone Number. **Not** a Phone Number ID. */ type PhoneNumberString = `+${string}` | (string & NonNullable<unknown>); /** * WhatsApp Phone Number ID. * * @since 7.0.0 */ type PhoneNumberID = string; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type GetBusinessProfileFields = { about?: boolean; address?: boolean; description?: boolean; email?: boolean; profile_picture_url?: boolean; websites?: boolean; vertical?: boolean; }; type GetBusinessProfileOptions<Fields extends GetBusinessProfileFields = object> = { phoneNumberID: PhoneNumberID; fields?: Fields; }; type GetBusinessProfilePayload<Fields extends GetBusinessProfileFields = object> = { data: [ { about: Fields extends { about: true; } ? string : undefined; address: Fields extends { address: true; } ? string : undefined; description: Fields extends { description: true; } ? string : undefined; email: Fields extends { email: true; } ? string : undefined; messaging_product: "whatsapp"; profile_picture_url: Fields extends { profile_picture_url: true; } ? string : undefined; vertical: Fields extends { vertical: true; } ? "" | (string & NonNullable<unknown>) : undefined; websites: Fields extends { websites: true; } ? [string] | [string, string] | (string[] & NonNullable<unknown>) : undefined; } ]; }; type UpdateBusinessProfileOptions = { phoneNumberID: PhoneNumberID; about?: string; address?: string; description?: string; email?: string; profile_picture_handle?: string; vertical?: "" | (string & NonNullable<unknown>); websites?: [string] | [string, string] | (string[] & NonNullable<unknown>); }; type UpdateBusinessProfilePayload = { success: boolean; }; interface MethodOptions$4 { request?: Options$1; } declare class BusinessProfile { protected _request: Options$1; constructor(_request: Options$1); protected getEndpoint(phoneNumberID: PhoneNumberID): string; getBusinessProfile<Fields extends GetBusinessProfileFields = object>({ phoneNumberID, fields, request, }: MethodOptions$4 & GetBusinessProfileOptions<Fields>): ky.ResponsePromise<GetBusinessProfilePayload<Fields>>; updateBusinessProfile({ phoneNumberID, request, ...json }: MethodOptions$4 & UpdateBusinessProfileOptions): ky.ResponsePromise<UpdateBusinessProfilePayload>; } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type MediaID = string; interface MediaUploadOptions { file: Blob; phoneNumberID: PhoneNumberID; filename?: string; mimeType: string; } type MediaUploadPayload = { id: MediaID; }; type MediaGetURLOptions = { phoneNumberID?: PhoneNumberID; mediaID: MediaID; }; type MediaGetURLPayload = { messaging_product: "whatsapp"; url: string; mime_type: string; sha256: string; file_size: string | number; id: MediaID; }; type MediaDeleteOptions = { phoneNumberID?: PhoneNumberID; mediaID: MediaID; }; type MediaDeletePayload = { success: boolean; }; interface MethodOptions$3 { request?: Options$1; } interface DownloadOptions { mediaURL: string; } declare class Media { protected _request: Options$1; constructor(_request: Options$1); protected getEndpoint(phoneNumberID: PhoneNumberID): string; /** * Upload Media. * All media files sent through this endpoint are encrypted and persist for * 30 days, unless they are deleted earlier. */ upload({ phoneNumberID, file, filename, mimeType, request, }: MethodOptions$3 & MediaUploadOptions): ky.ResponsePromise<MediaUploadPayload>; /** * Retrieve Media URL. * Use the returned URL to download the media file. Note that clicking this * URL (i.e. performing a generic GET) will not return the media; you must * include an access token. * * A successful response includes an object with a media url. The URL is only * valid for 5 minutes. */ getURL({ mediaID, phoneNumberID, request, }: MethodOptions$3 & MediaGetURLOptions): ky.ResponsePromise<MediaGetURLPayload>; delete({ mediaID, phoneNumberID, request, }: MethodOptions$3 & MediaDeleteOptions): ky.ResponsePromise<MediaDeletePayload>; /** * Download Media. * All media URLs expire after 5 minutes —you need to retrieve the media URL * again if it expires. If you directly click on the URL you get from a * `/MEDIA_ID` GET call, you get an access error. * * If successful, you will receive the binary data of media saved in * media_file, response headers contain a content-type header to indicate the * mime type of returned data. * * If media fails to download, you will receive a `404 Not Found` response * code. In that case, we recommend you try to retrieve a new media URL and * download it again. If doing so doesn't resolve the issue, please try to * renew the `ACCESS_TOKEN` then retry downloading the media. * * @see {@link https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#supported-media-types} * @example * // Download Media and Write to a File * const download = await sdk.media.download({ mediaURL }); * const file = await download.arrayBuffer(); * fs.writeFile("filename.ext", Buffer.from(file)); */ download({ mediaURL, request }: MethodOptions$3 & DownloadOptions): ky.ResponsePromise<unknown>; } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ /** * A WhatsApp End-User Account ID. */ type AccountID = string; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type WhatsappError = { code: number; message?: string; type: string; title?: string; error_data?: { messaging_product: "whatsapp"; /** * Error description and a description of the most likely reason for the * error. May also contain information on how to address the error, such as * which parameter is invalid or what values are acceptable. */ details: string; }; /** * Trace ID you can include when contacting Direct Support. The ID may help * support to debug the error. */ fbtrace_id: string; /** * @deprecated Since Graph API v16.0. */ error_subcode?: number; }; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type CreateMessageContact = { /** * Full contact address(es) formatted as an addresses object. */ addresses: { type: "HOME" | "WORK" | (string & NonNullable<unknown>); /** * Street number and name. * * @since 4.2.0 */ street?: string; /** * City name. * * @since 4.2.0 */ city?: string; /** * State abbreviation. * * @since 4.2.0 */ state?: string; /** * ZIP code. * * @since 4.2.0 */ zip?: string; /** * Full country name. * * @since 4.2.0 */ country?: string; /** * Two-letter country abbreviation. * * @since 4.2.0 */ country_code?: string; }[]; /** * YYYY-MM-DD formatted string. */ birthday?: `${number}${number}${number}${number}-${number}${number}-${number}${number}` | (string & NonNullable<unknown>); /** * Contact email address(es) formatted as an emails object. */ emails: { type: "HOME" | "WORK" | (string & NonNullable<unknown>); /** * Email address. */ email?: string; }[]; /** * Full contact name formatted as a name object. * This appears to fit the required fields pattern for VCF4 contact files. */ name: { /** * Full name, as it normally appears. */ formatted_name: string; /** * First name. */ first_name?: string; /** * Last name. * * @since 4.2.0 */ last_name?: string; /** * Middle name. * * @since 4.2.0 */ middle_name?: string; /** * Name suffix. * * @since 4.2.0 */ suffix?: string; /** * Name prefix. * * @since 4.2.0 */ prefix?: string; }; org?: { /** * Name of the contact's company. */ company?: string; /** * Name of the contact's department. */ department?: string; /** * Contact's business title. */ title?: string; }; phones?: { type?: "CELL" | "MAIN" | "IPHONE" | "HOME" | "WORK" | (string & NonNullable<unknown>); /** * Automatically populated with the `wa_id` value as a formatted phone * number. */ phone?: PhoneNumberString; /** * WhatsApp ID. */ wa_id?: AccountID; }[]; urls: { type?: "HOME" | "WORK" | (string & NonNullable<unknown>); /** * URL. * * @since 4.2.0 */ url?: string; }[]; }; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type CreateMessageLocation = { /** * Longitude of the location. */ longitude: number; /** * Latitude of the location. */ latitude: number; /** * Name of the location. */ name: string; /** * Address of the location. */ address: string; }; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type CreateMessageMedia = { /** * ID for the media file. */ id?: string; /** * Required when type is audio, document, image, sticker, or video and you * are not using an uploaded media ID (i.e. you are hosting the media asset * on your public server). * * The protocol and URL of the media to be sent. Use only with HTTP/HTTPS URLs. * * Do not use this field when message type is set to text. * * Cloud API users only: * * - See {@link https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-messages#media-http-caching} * if you would like us to cache the media asset for future messages. * - When we request the media asset from your server you must indicate the * media's MIME type by including the `Content-Type` HTTP header. For * example: `Content-Type: video/mp4`. See * {@link https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#supported-media-types} * for a list of supported media and their MIME types. */ link?: string; /** * Media asset caption. Do not use with audio or sticker media. * * On-Premises API users: * * - For v2.41.2 or newer, this field is limited to 1024 characters. * - Captions are currently not supported for `document` media. */ caption?: string; /** * Describes the filename for the specific document. Use only with document * media. * * The extension of the filename will specify what format the document is * displayed as in WhatsApp. */ filename?: string; }; type EventNotificationMessageMedia = { /** * ID for the media file. * * @since 5.0.0 */ id?: string; /** * Mime type of the media file. * * @since 5.0.0 */ mime_type: string; /** * Media asset caption. Do not use with audio or sticker media. * * On-Premises API users: * * - For v2.41.2 or newer, this field is limited to 1024 characters. * - Captions are currently not supported for `document` media. */ caption?: string; /** * Describes the filename for the specific document. Use only with document * media. * * The extension of the filename will specify what format the document is * displayed as in WhatsApp. */ filename?: string; /** * Image hash. */ sha256: string; }; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type CreateMessageText = { body: string; preview_url?: boolean; }; type EventNotificationMessageText = { body: string; }; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ declare enum MessageType { Audio = "audio",// for audio messages. Contacts = "contacts",// for contact messages. Document = "document",// for document messages. Image = "image",// for image messages. Interactive = "interactive",// for list and reply button messages. Location = "location",// for location messages. Reaction = "sticker",// for reaction messages. Sticker = "sticker",// for sticker messages. /** * Not supported for Outgoing Messages. */ System = "system", /** * Not supported for Outgoing Messages. */ Button = "button", /** * Not supported for Outgoing Messages. */ Order = "order", Template = "template",// for template messages. Text and media (images and documents) message templates are supported. Text = "text",// for text messages. Video = "video" } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ /** * WhatsApp Message ID. * This ID likely starts with `wamid.`. */ type MessageID = `wamid.${string}` | (string & NonNullable<unknown>); type MessageStatusType = "read" | (string & NonNullable<unknown>); type MessageRecipientType = "individual" | "group" | (string & NonNullable<unknown>); type CreateMessageOptions = { phoneNumberID: PhoneNumberID; /** * WhatsApp ID or phone number of the customer you want to send a message to. */ to: PhoneNumberID | PhoneNumberString; /** * Currently, you can only send messages to individuals. * * @default "individual" * @see {@link https://developers.facebook.com/docs/graph-api/reference/whats-app-business-account-to-number-current-status/messages/#parameters} */ recipientType?: MessageRecipientType; /** * Required if replying to any message in the conversation. */ context?: { inReplyTo: MessageID; }; /** * An arbitrary 256B string, useful for tracking. For example, you could pass * the message template ID in this field to track your customer's journey * starting from the first message you send. You could then track the ROI of * different message template types to determine the most effective one. * * Any app subscribed to the messages webhook field on the WhatsApp Business * Account can get this string, as it is included in statuses object within * webhook payloads. * * Cloud API does not process this field, it just returns it as part of * sent/delivered/read message webhooks. * * @since November 14, 2023 */ biz_opaque_callback_data?: string; [key: string]: unknown | undefined; } & ({ type: MessageType.Audio; [MessageType.Audio]: Omit<CreateMessageMedia, "caption">; } | { type: MessageType.Contacts; [MessageType.Contacts]: CreateMessageContact[]; } | { type: MessageType.Document; [MessageType.Document]: CreateMessageMedia; } | { type: MessageType.Image; [MessageType.Image]: CreateMessageMedia; } | { type: MessageType.Interactive; [MessageType.Interactive]: unknown; } | { type: MessageType.Location; [MessageType.Location]: CreateMessageLocation; } | { type: MessageType.Reaction; [MessageType.Reaction]: Omit<CreateMessageMedia, "caption">; } | { type: MessageType.Sticker; [MessageType.Sticker]: Omit<CreateMessageMedia, "caption">; } | { type: MessageType.Template; [MessageType.Template]: unknown; } | { type: MessageType.Text; [MessageType.Text]: CreateMessageText; } | { type: MessageType.Video; [MessageType.Video]: CreateMessageMedia; } | { type: string & NonNullable<unknown>; }); type CreateMessagePayload = { messaging_product: "whatsapp"; contacts: { input: PhoneNumberString; wa_id: AccountID; }[]; messages: { id: MessageID; message_status: "accepted" | "held_for_quality_assessment"; }[]; error: WhatsappError; }; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type CreateStatusOptions = { phoneNumberID: PhoneNumberID; message_id: MessageID; status: MessageStatusType; typing_indicator?: { type: "text"; }; [key: string]: unknown | undefined; }; type CreateStatusPayload = { success?: boolean; error: WhatsappError; }; interface MethodOptions$2 { request?: Options$1; } declare class Message { protected _request: Options$1; constructor(_request: Options$1); protected getEndpoint(phoneNumberID: PhoneNumberID): string; createStatus({ phoneNumberID, request, ...status }: MethodOptions$2 & CreateStatusOptions): ky.ResponsePromise<CreateStatusPayload>; createMessage({ to, phoneNumberID, context, recipientType, request, ...message }: MethodOptions$2 & CreateMessageOptions): ky.ResponsePromise<CreateMessagePayload>; } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type BusinessAccountID = string; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type ListPhoneNumbersOptions = { businessAccountID: BusinessAccountID; sort?: string; filtering?: string; }; type ListPhoneNumbersPaylod = { data: { id: PhoneNumberID; verified_name: string; code_verification_status: "VERIFIED" | (string & NonNullable<unknown>); display_phone_number: string; quality_rating: string; platform_type: string; throughput: { level: string; }; last_onboarded_time?: string; webhook_configuration: { application?: string; }; }[]; }; type GetPhoneNumberFields = { name_status?: boolean; }; type GetPhoneNumberOptions<Fields extends GetPhoneNumberFields = object> = { phoneNumberID: PhoneNumberID; fields?: Fields; }; type GetPhoneNumberPayload<Fields extends GetPhoneNumberFields = object> = { id: PhoneNumberID; verified_name: string; name_status: Fields extends { name_status: true; } ? "APPROVED" | "AVAILABLE_WITHOUT_REVIEW" | "DECLINED" | "EXPIRED" | "PENDING_REVIEW" | "NONE" | (string & NonNullable<unknown>) : undefined; code_verification_status: "VERIFIED" | (string & NonNullable<unknown>); display_phone_number: string; quality_rating: string; platform_type: string; throughput: { level: string; }; last_onboarded_time?: string; webhook_configuration: { application?: string; }; }; interface MethodOptions$1 { request?: Options$1; } declare class PhoneNumbers { protected _request: Options$1; constructor(_request: Options$1); getEndpoint(businessAccountID: BusinessAccountID): string; getPhoneNumber<Fields extends GetPhoneNumberFields = object>({ phoneNumberID, fields, request, }: MethodOptions$1 & GetPhoneNumberOptions): ky.ResponsePromise<GetPhoneNumberPayload<Fields>>; listPhoneNumbers({ businessAccountID, sort, filtering, request, }: MethodOptions$1 & ListPhoneNumbersOptions): ky.ResponsePromise<ListPhoneNumbersPaylod>; } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type CreateSubscriptionOptions = { businessAccountID: BusinessAccountID; }; type CreateSubscriptionPayload = { success: boolean; }; type ListSubscriptionsOptions = { businessAccountID: BusinessAccountID; }; type ListSubscriptionsPayload = { data: { whatsapp_business_api_data: { id: string; link?: string | null; name: string; }; }[]; }; interface MethodOptions { request?: Options$1; } declare class SubscribedApps { protected _request: Options$1; constructor(_request: Options$1); protected getEndpoint(businessAccountID: BusinessAccountID): string; createSubscription({ businessAccountID, request, }: MethodOptions & CreateSubscriptionOptions): ky.ResponsePromise<CreateSubscriptionPayload>; listSubscriptions({ businessAccountID, request, }: MethodOptions & ListSubscriptionsOptions): ky.ResponsePromise<ListSubscriptionsPayload>; } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type EventNotificationMessageIdentity = { /** * State of acknowledgment for the messages system customer_identity_changed. */ acknowledged: string; /** * The time when the WhatsApp Business Management API detected the customer * may have changed their profile information. */ created_timestamp: string; /** * The ID for the messages system customer_identity_changed. */ hash: string; }; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type EventNotificationMessageReferral = { /** * The Meta URL that leads to the ad or post clicked by the customer. Opening * this URL takes you to the ad viewed by your customer. */ source_url: string; /** * The type of the ad's source. */ source_type: "ad" | "post" | (string & NonNullable<unknown>); /** * Meta ID for an ad or a post. */ source_id: string; /** * Headline used in the ad or post. */ headline: string; /** * Body for the ad or post. */ body: string; /** * Media present in the ad or post. */ media_type: "image" | "video" | (string & NonNullable<unknown>); /** * URL of the image, when media_type is an image. */ image_url: URL; /** * URL of the video, when media_type is a video. */ video_url: URL; /** * URL for the thumbnail, when media_type is a video. */ thumbnail_url: URL; /** * Click ID generated by Meta for ads that click to WhatsApp. * * @since September 27, 2023 */ ctwa_clid?: string; }; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type EventNotificationMessageSystem = { /** * Describes the change to the customer's identity or phone number. */ body: string; /** * Hash for the identity fetched from server. */ identity: string; /** * The WhatsApp ID for the customer prior to the update. */ customer: AccountID; /** * Type of system update. */ type: "customer_changed_number" | "customer_identity_changed.js"; /** * New WhatsApp ID for the customer when their phone number is updated. * * @deprecated since Webhook v11.0 */ new_wa_id: AccountID; /** * New WhatsApp ID for the customer when their phone number is updated. */ wa_id: AccountID; }; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ type ConversationType = "authentication" | "marketing" | "utility" | "service" | "referral_conversation" | (string & NonNullable<unknown>); type WebhookEventNotificationMessagesChanges = { /** * Notification type. Value will be messages. */ field: "messages"; /** * A value object. */ value: { /** * Array of contact objects with information for the customer who sent a * message to the business. */ contacts: { /** * The customer's WhatsApp ID. A business can respond to a customer using * this ID. This ID may not match the customer's phone number, which is * returned by the API as input when sending a message to the customer. */ wa_id: AccountID; /** * Additional unique, alphanumeric identifier for a WhatsApp user. */ user_id?: string; /** * A customer profile object. */ profile: { /** * The customer's name. */ name: string; }; }[]; /** * An array of error objects describing the error. */ errors: WhatsappError[]; /** * Product used to send the message. Value is always whatsapp. * * @default 'whatsapp' */ messaging_product: "whatsapp"; /** * Information about a message received by the business that is subscribed to * the webhook. */ messages?: ({ /** * The ID for the message that was received by the business. You could use * messages endpoint to mark this specific message as read. */ id: MessageID; /** * Unix timestamp indicating when the WhatsApp server received the message * from the customer. */ timestamp: string; /** * The customer's WhatsApp ID. A business can respond to a customer using * this ID. This ID may not match the customer's phone number, which is * returned by the API as input when sending a message to the customer. */ from: AccountID; /** * Context object. Only included when a user replies or interacts with one of * your messages. */ context?: { /** * Set to true if the message received by the business has been forwarded. */ forwarded: boolean; /** * Set to true if the message received by the business has been forwarded * more than 5 times. */ frequently_forwarded: boolean; /** * The WhatsApp ID for the customer who replied to an inbound message. */ from: AccountID; /** * The message ID for the sent message for an inbound reply. */ id: MessageID; /** * Referred product object describing the product the user is requesting * information about. You must parse this value if you support Product * Enquiry Messages. */ referred_product: { /** * Unique identifier of the Meta catalog linked to the WhatsApp Business * Account. */ catalog_id: string; /** * Unique identifier of the product in a catalog. */ product_retailer_id: string; }; }; /** * An array of error objects describing the error. * * @since 4.2.0 */ errors?: WhatsappError[]; /** * An identity object. Webhook is triggered when a customer's phone number or * profile information has been updated. */ identity: EventNotificationMessageIdentity; /** * Referral object. When a customer clicks an ad that redirects to WhatsApp, * this object is included in the messages object. */ referral?: EventNotificationMessageReferral; } & ({ type: MessageType.Audio; [MessageType.Audio]: Omit<EventNotificationMessageMedia, "caption" | "filename" | "sha256">; } | { type: MessageType.Button; [MessageType.Button]: { payload: string; text: string; }; } | { type: MessageType.Contacts; [MessageType.Contacts]: unknown; } | { type: MessageType.Document; [MessageType.Document]: EventNotificationMessageMedia; } | { type: MessageType.Image; [MessageType.Image]: EventNotificationMessageMedia; } | { type: MessageType.Interactive; [MessageType.Interactive]: unknown; } | { type: MessageType.Order; [MessageType.Order]: unknown; } | { type: MessageType.Location; [MessageType.Location]: unknown; } | { type: MessageType.Reaction | MessageType.Sticker; [MessageType.Sticker]: Omit<EventNotificationMessageMedia, "caption" | "filename"> & { animated: boolean; }; } | { type: MessageType.Text; [MessageType.Text]: EventNotificationMessageText; } | { type: MessageType.Video; [MessageType.Video]: Omit<EventNotificationMessageMedia, "filename">; } | { type: MessageType.System; /** * When messages type is set to system, a customer has updated their phone * number or profile information, this object is included in the messages * object. */ [MessageType.System]: EventNotificationMessageSystem; }))[]; /** * A metadata object describing the business subscribed to the webhook. */ metadata: { /** * The phone number that is displayed for a business. */ display_phone_number: PhoneNumberString; /** * ID for the phone number. A business can respond to a message using this * ID. */ phone_number_id: PhoneNumberID; }; /** * Status object for a message that was sent by the business that is * subscribed to the webhook. */ statuses?: { /** * The ID for the message that the business that is subscribed to the * webhooks sent to a customer. */ id: MessageID; /** * The customer's WhatsApp ID. A business can respond to a customer using * this ID. This ID may not match the customer's phone number, which is * returned by the API as input when sending a message to the customer. */ recipient_id: AccountID; /** * For a status to be read, it must have been delivered. In some scenarios, * such as when a user is in the chat screen and a message arrives, the * message is delivered and read almost simultaneously. In this or other * similar scenarios, the delivered notification will not be sent back, as it * is implied that a message has been delivered if it has been read. The * reason for this behavior is internal optimization. */ status: "delivered" | "read" | "sent" | "failed"; /** * Date for the status message. */ timestamp: number; /** * An object containing pricing information. */ pricing: { /** * Indicates the conversation category. * * @since 4.2.0 */ category: ConversationType; /** * Type of pricing model used by the business. */ pricing_model: "CBP" | (string & NonNullable<unknown>); /** * Indicates if the given message or conversation is billable. Default is * true for all conversations, including those inside your free tier limit, * except those initiated from free entry points. Free entry point * conversation are not billable, false. You will not be charged for free * tier limit conversations, but they are considered billable and will be * reflected on your invoice. * * @deprecated */ billable: boolean; }; /** * Information about the conversation. */ conversation: { /** * Represents the ID of the conversation the given status notification * belongs to. */ id: string; /** * Date when the conversation expires. This field is only present for * messages with a `status` set to `sent`. */ expiration_timestamp?: number; /** * Describes conversation category */ origin: { /** * Indicates conversation category. This can also be referred to as a * conversation entry point. */ type: ConversationType; }; }; /** * Arbitrary string included in sent message. */ biz_opaque_callback_data?: string; }[]; }; }; type WebhookEventNotificationAccountUpdateChanges = { field: "account_update"; value: { event: "PARTNER_APP_INSTALLED" | (string & NonNullable<unknown>); waba_info: { waba_id: AccountID; owner_business_id: BusinessAccountID; partner_app_id: string; }; }; }; type WebhookEventNotification = { /** * The specific webhook a business is subscribed to. The webhook is * whatsapp_business_account. */ object: string; /** * An array of entry objects. */ entry: { /** * The WhatsApp Business Account ID for the business that is subscribed to * the webhook. */ id: BusinessAccountID; /** * An array of change objects. */ changes: (WebhookEventNotificationMessagesChanges | WebhookEventNotificationAccountUpdateChanges)[]; }[]; }; /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ declare class WebhookError extends Error { } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ declare class IncorrectMethodWebhookError extends WebhookError { } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ declare class InvalidHubChallengeWebhookError extends WebhookError { } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ declare class InvalidHubModeWebhookError extends WebhookError { } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ declare class InvalidHubSignatureWebhookError extends WebhookError { } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ declare class InvalidHubVerifyTokenWebhookError extends WebhookError { } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ declare class MissingBodyWebhookError extends WebhookError { } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ interface IncomingRequest { method: string; query: Record<string, string>; body?: string; headers: Record<string, string>; } declare class Webhook { errors: { WebhookError: typeof WebhookError; IncorrectMethodWebhookError: typeof IncorrectMethodWebhookError; InvalidHubChallengeWebhookError: typeof InvalidHubChallengeWebhookError; InvalidHubModeWebhookError: typeof InvalidHubModeWebhookError; InvalidHubSignatureWebhookError: typeof InvalidHubSignatureWebhookError; InvalidHubVerifyTokenWebhookError: typeof InvalidHubVerifyTokenWebhookError; MissingBodyWebhookError: typeof MissingBodyWebhookError; }; /** * Handle a Registration Webhook Request. * The handler for `GET` requests to your webhook endpoint. A registration * request is when WhatsApp sends a GET request to your webhook endpoint to * verify that it is valid. The challenge should be returned if valid. * * **ExpressJS**: * * ```ts * app.get( * "/path/to/webhook", * async (req, res) => { * const reg = await sdk.webhook.register({ * method: request.method, * query: req.query, * body: req.body, * headers: req.headers, * }); * // DIY: Check the reg.verifyToken value * if (reg.verifyToken !== "abcd") { * return res.end(reg.reject()); * } * return res.end(reg.accept()); * } * ); * ``` * * **Fastify**: * * ```ts * // See: https://github.com/fastify/fastify/issues/707#issuecomment-817224931 * fastify.addContentTypeParser("application/json", { parseAs: "buffer" }, (_req, body, done) => { * done(null, body); * }); * * fastify.route({ * method: "GET", * url: "/path/to/webhook", * handler: (request, reply) => { * assert(Buffer.isBuffer(request.body) || typeof request.body === "string"); * const body = request.body.toString(); * * const reg = await sdk.webhook.register({ * method: request.method, * query: request.query, * body, * headers: request.headers, * }); * // DIY: Check the reg.verifyToken value * if (reg.verifyToken !== "abcd") { * return reply.send(reg.reject()); * } * return reply.send(reg.accept()); * } * }); * ``` * * @throws {WebhookError} */ register(request: IncomingRequest): Promise<{ verifyToken: string; challenge: string; accept: () => string; reject: () => void; }>; /** * Handle an Event Notification Webhook Request. * The handler for `POST` requests to your webhook endpoint. * * **ExpressJS**: * * ```ts * app.use(express.raw()); // Important <- * app.post( * "/path/to/webhook", * async (req, res) => { * const event = sdk.webhook.eventNotification({ * method: request.method, * query: req.query, * body: req.body.toString(), * headers: req.headers, * }); * // DIY: Load the Meta App Secret * event.verifySignature("abcd-app-secret"); * if (someFailedCondition) { * return res.end(event.reject()); * } * return res.end(event.accept()); * } * ); * ``` * * **Fastify**: * * ```ts * fastify.route({ * method: "POST", * url: "/path/to/webhook", * handler: (request, reply) => { * const event = sdk.webhook.eventNotification({ * method: request.method, * query: request.query, * body: JSON.stringify(req.body), * headers: request.headers, * }); * // DIY: Load the Meta App Secret * event.verifySignature("abcd-app-secret"); * if (someFailedCondition) { * return reply.code(400).send(); * } * return reply.send(event.accept()); * } * }); * ``` */ eventNotification(request: IncomingRequest): Promise<{ eventNotification: WebhookEventNotification; signature: { sha1: { value: string; getCalculatedSignature: (appSecret: string) => string; check: (appSecret: string) => boolean; }; sha256: { value: string; getCalculatedSignature: (appSecret: string) => string; check: (appSecret: string) => boolean; }; }; checkSignature: (appSecret: string) => boolean; verifySignature(appSecret: string): void; accept: () => void; }>; } /** * WhatsApp NodeJS SDK. * * @author Great Detail Ltd <info@greatdetail.com> * @author Dom Webber <dom.webber@hotmail.com> * @see https://greatdetail.com */ interface Options { prefixUrl?: string; graphVersion?: `v${string}` | (string & NonNullable<unknown>); } declare class Client { protected _request: Options$1; businessProfile: BusinessProfile; message: Message; phoneNumbers: PhoneNumbers; subscribedApps: SubscribedApps; media: Media; webhook: Webhook; constructor({ prefixUrl, graphVersion, }?: Options); } export { type AccountID, type BusinessAccountID, Client, Client as CloudAPI, type ConversationType, type CreateMessageContact, type CreateMessageLocation, type CreateMessageMedia, type CreateMessageOptions, type CreateMessagePayload, type CreateMessageText, type CreateStatusOptions, type CreateStatusPayload, type CreateSubscriptionOptions, type CreateSubscriptionPayload, type EventNotificationMessageIdentity, type EventNotificationMessageMedia, type EventNotificationMessageReferral, type EventNotificationMessageSystem, type EventNotificationMessageText, type ListSubscriptionsOptions, type ListSubscriptionsPayload, type MediaDeleteOptions, type MediaDeletePayload, type MediaGetURLOptions, type MediaGetURLPayload, type MediaID, type MediaUploadOptions, type MediaUploadPayload, type MessageID, type MessageRecipientType, type MessageStatusType, MessageType, type PhoneNumberID, type PhoneNumberString, type WebhookEventNotification, type WebhookEventNotificationAccountUpdateChanges, type WebhookEventNotificationMessagesChanges, type WhatsappError, Client as default };