Skip to main content

Espelho · Sincronização

Syncs the conversation history and the contact list from the WhatsApp Business App (coexistence mode) into the Cloud API.

The sync is triggered manually after the customer connects the number through Embedded Signup — and it has to happen within 24 hours.

Prerequisites​

  1. The customer approved sharing on their phone. During Embedded Signup, the WhatsApp Business App asks permission to share history and contacts. If they declined, nothing will be sent.
  2. The webhook fields are subscribed. Enable history and smb_app_state_sync on the number's webhook endpoint.

24-hour window, one shot​

You have exactly 24 hours from Embedded Signup. Miss it and there is no recovery — the customer has to redo onboarding.

Each sync type (history and smb_app_state_sync) can be triggered once per integration.

How history arrives​

Through multiple asynchronous webhooks, split into phases and chunks:

phaseNominal period
0day 0 → day 1
1day 1 → day 90
2day 90 → day 180

In practice the phases overlap — messages from any date can show up in any phase. Don't use the phase to infer a period; sort everything by timestamp.

Each phase can arrive in several chunks (chunk_order), not necessarily in order. The progress field (0–100) tracks the overall advance: progress: 100 on the last phase means the history is complete.

A single webhook can carry thousands of messages:

webhook (1 POST)
└── value.history[]
└── threads[] ← 1 thread = 1 conversation with 1 contact
└── messages[] ← messages in that conversation

Duplicates — a hard requirement​

The same thread.id shows up across several webhooks, and the same message can arrive more than once. When processing:

  1. Collect every message with the same thread.id from all webhooks.
  2. Deduplicate by wamid (message.id).
  3. Sort by timestamp (Unix seconds, 10 digits).

Use history_context.from_me for direction: true means the business sent it, false or absent means it was received.

Media inside history​

Media does not travel inside the threads — it shows up as type: "media_placeholder", with no content. The real file arrives in separate webhooks (value.messages or value.message_echoes), matched by wamid. Only media from roughly the last 14 days still has a file available.

Contacts​

Usually a single webhook, with every contact in the state_sync array. Large accounts may produce several, with no guaranteed ordering.

  • action: "add" → add or update a contact
  • action: "remove" → remove a contact
  • Timestamps are in milliseconds (13 digits) — unlike history, which uses seconds.

After the initial sync, later contact changes keep arriving automatically through smb_app_state_sync, with no need to call this endpoint again.