import type { RequireAtLeastOne } from 'type-fest'; export interface Message { messaging_product: 'whatsapp'; recipient_type: 'individual'; to?: string; recipient?: string; from?: string; from_user_id?: string; from_parent_user_id?: string; context?: { message_id: string; }; } interface ContactName { first_name?: string; last_name?: string; middle_name?: string; suffix?: string; prefix?: string; } export interface WebhookContact { profile: { name: string; username?: string; }; wa_id?: string; user_id?: string; parent_user_id?: string; } export interface Contact { addresses?: { street?: string; city?: string; state?: string; zip?: string; country?: string; country_code?: string; type?: 'HOME' | 'WORK'; }[]; birthday?: string; user_id?: string; username?: string; country_code?: string; emails?: { email?: string; type: 'HOME' | 'WORK'; }[]; name: { formatted_name: string; } & RequireAtLeastOne; org?: { company?: string; department?: string; title?: string; }; phones?: { phone?: string; type?: 'CELL' | 'MAIN' | 'IPHONE' | 'HOME' | 'WORK'; wa_id?: string; }[]; urls?: { url?: string; type?: 'HOME' | 'WORK'; }[]; } interface InteractiveHeaderText { type: 'text'; text: string; } interface InteractiveHeaderVideo { type: 'video'; video: Media; } interface InteractiveHeaderImage { type: 'image'; image: Media; } interface InteractiveHeaderDocument { type: 'document'; document: Media; } export type InteractiveHeader = InteractiveHeaderText | InteractiveHeaderVideo | InteractiveHeaderImage | InteractiveHeaderDocument; export interface InteractiveBase { body: { text: string; }; footer?: { text: string; }; header?: InteractiveHeader; } export interface InteractiveReplyButton { type: 'button'; action: { buttons: { type: 'reply'; reply: { title: string | number; id: string; }; }[]; }; } export interface InteractiveURL { type: 'cta_url'; action: { name: 'cta_url'; parameters: { display_text: string; url: `http://${string}` | `https://${string}`; }; }; } export interface InteractiveRequestContactInfo { type: 'request_contact_info'; action: { name: 'request_contact_info'; }; } export type FlowActionPayload = { screen: string; data?: Record; }; export type FlowMode = 'draft' | 'published'; export type FlowAction = 'navigate' | 'data_exchange'; export interface BaseFlowParameters { flow_message_version: '3'; flow_token?: string; flow_cta: string; mode?: FlowMode; flow_action?: FlowAction; flow_action_payload?: FlowActionPayload; } export type FlowIdentifier = { flow_id: string; flow_name?: never; } | { flow_name: string; flow_id?: never; }; export interface InteractiveFlow { type: 'flow'; action: { name: 'flow'; parameters: BaseFlowParameters & FlowIdentifier; }; } export interface InteractiveListMessage { type: 'list'; action: { button: string; sections: { title: string; rows: { id: string | number; title: string | number; description?: string; }[]; }[]; }; } type Interactive = InteractiveBase & (InteractiveReplyButton | InteractiveListMessage | InteractiveURL | InteractiveRequestContactInfo); type InteractiveWithFlow = InteractiveBase & InteractiveFlow; export interface Location { longitude: number; latitude: number; name?: string; address?: string; } export interface MediaWithId { id: string; } export interface MediaWithLink { link: string; } export interface MediaBase { caption?: string; filename?: string; } export type Media = MediaBase & (MediaWithId | MediaWithLink); interface ParameterText { type: 'text'; text: string; } interface ParameterCurrency { type: 'currency'; fallback_value: string; code: string; amount_1000: number; } interface ParameterDateTime { type: 'date_time'; fallback_value: string; } interface ParameterImage { type: 'image'; image: Media; } interface ParameterDocument { type: 'document'; document: Media; } interface ParameterVideo { type: 'video'; video: Media; } interface TemplateComponentTypeHeader { type: 'header'; } interface TemplateComponentTypeBody { type: 'body'; parameters: (ParameterText | ParameterCurrency | ParameterDateTime | ParameterImage | ParameterDocument | ParameterVideo)[]; } interface TemplateComponentTypeButtonQuickReply { sub_type: 'quick_reply'; parameters: { type: 'payload' | 'text'; payload: any; text: string; }[]; } interface TemplateComponentTypeButtonUrl { sub_type: 'url'; parameters: { type?: 'payload' | 'text'; payload?: any; text: string; }[]; } interface TemplateComponentTypeButtonFlow { sub_type: 'flow'; parameters: { type?: 'payload' | 'text'; action: { flow_token: string; flow_action_data: { [key: string]: string | number | boolean | object; }; }; }[]; } interface TemplateComponentTypeButtonBase { type: 'button'; index: 0 | 1 | 2; } type TemplateComponentTypeButton = TemplateComponentTypeButtonBase & (TemplateComponentTypeButtonQuickReply | TemplateComponentTypeButtonUrl | TemplateComponentTypeButtonFlow); export type TemplateComponent = TemplateComponentTypeHeader | TemplateComponentTypeBody | TemplateComponentTypeButton; export interface Template { name: string; language: { policy?: 'deterministic'; code: string; }; components?: TemplateComponent[]; } export interface Text { body: string; preview_url?: boolean; } export interface AudioMessage extends Message { type: 'audio'; audio: Media; } export interface ContactMessage extends Message { type: 'contacts'; contacts: Contact[]; } export interface DocumentMessage extends Message { type: 'document'; document: Media; } export interface ImageMessage extends Message { type: 'image'; image: Media; } export interface InteractiveMessage extends Message { type: 'interactive'; interactive: Interactive; } export interface FlowMessage extends Message { type: 'interactive'; interactive: InteractiveWithFlow; } export interface LocationMessage extends Message { type: 'location'; location: Location; } export interface StickerMessage extends Message { type: 'sticker'; sticker: Media; } export interface TemplateMessage extends Message { type: 'template'; template: Template; } export interface TextMessage extends Message { type: 'text'; text: Text; } export interface VideoMessage extends Message { type: 'video'; video: Media; } export interface ReactionMessage extends Message { type: 'reaction'; reaction: { message_id: string; emoji: string; }; } export interface MarkAsRead { messaging_product: 'whatsapp'; message_id: string; status: 'read'; typing_indicator?: { type: 'text'; }; } export type MediaMessage = AudioMessage | DocumentMessage | ImageMessage | StickerMessage | VideoMessage; export interface Status { id: string; status: 'delivered' | 'read' | 'sent' | 'failed'; timestamp: string; recipient_id?: string; recipient_user_id?: string; parent_recipient_user_id?: string; conversation?: { id: string; origin?: { type: string; }; expiration_timestamp?: string; }; pricing?: { billable: boolean; pricing_model: string; category: string; }; errors?: { code: number; title: string; message: string; error_data: { details: string; }; }[]; } export interface WebhookBody { object: string; entry?: { id: string; changes?: { value: { messaging_product: 'whatsapp'; metadata: { display_phone_number: string; phone_number_id: string; }; contacts?: WebhookContact[]; messages?: Message[]; statuses?: Status[]; }; field: string; }[]; }[]; } export {};