The (Missing) WhatsApp webhook API types
I am working on a project that involves integrating with the WhatsApp Business API, and I noticed that there are no official TypeScript types for the webhook API. The documentation while detailed, lacks (or i could not find) the type definitions that would make it easier to work with the API in a type-safe manner.
So, I decided to create my own minimal set of types to help me with the integration.
Reverse engineering the webhook payload
The process was pretty simple: 1 - In my app webhook endpoint, i saved the received payloads to a database 2 - From this sample i created the types using a JSON to TypeScript converter 3 - I then refined the types to make them more readable and easier to work with.
Some notes:
- The types are not exhaustive, they only cover the message types that I needed for my project i.e, ‘messages’ and ‘message_template_status_update’.
- My go to JSON to Typescript converter was from Transform.Tools which is based on json_typegen. But is lacking creation of enum / union types from fields with repeatable values. Fortunately i found quicktype that supports this feature.
The types
export interface NotificationPayload { object: "whatsapp_business_account"; entry: Entry[];}
export interface Entry { id: string; changes: Change[];}
export type Change = MessagesChange | MessageTemplateStatusUpdateChange;
export interface MessagesChange { field: "messages"; value: MessagesValue;}
export interface MessageTemplateStatusUpdateChange { field: "message_template_status_update"; value: MessageTemplateStatusUpdateValue;}
export interface MessageTemplateStatusUpdateValue { reason: string; message_template_name: string; event: string; message_template_language: string; message_template_id: number;}
export interface MessagesValue { metadata: Metadata; messaging_product: MessagingProduct; statuses?: StatusElement[]; messages?: Message[]; contacts?: Contact[];}
export interface Contact { profile: Profile; wa_id: string;}
export interface Profile { name: string;}
export interface Message { from: string; id: string; text?: Text; type: string; timestamp: string; sticker?: Sticker;}
export interface Sticker { sha256: string; mime_type: string; animated: boolean; id: string;}
export interface Text { body: string;}
export type MessagingProduct = "whatsapp";
export interface Metadata { phone_number_id: string; display_phone_number: string;}
export interface StatusElement { biz_opaque_callback_data?: string; id: string; conversation?: Conversation; pricing?: Pricing; status: StatusEnum; timestamp: string; recipient_id: string; errors?: Error[];}
export interface Conversation { origin: Origin; id: string; expiration_timestamp?: string;}
export interface Origin { type: Category;}
export type Category = "marketing" | "utility";
export interface Error { code: number; title: string; message: string; error_data: ErrorData;}
export interface ErrorData { details: string;}
export interface Pricing { pricing_model: PricingModel; category: Category; billable: boolean;}
export type PricingModel = "CBP";
export type StatusEnum = "delivered" | "failed" | "read" | "sent";