DEV Community

Luiz Américo
Luiz Américo

Posted on • Originally published at blikblum.dev on

WhatsApp webhook API types

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";

Enter fullscreen mode Exit fullscreen mode

Top comments (0)