← All posts
Integrations6 min read

[INTEGRATIONS] · Jun 5, 2026 · 09:40

Sync live chat conversations and contacts to your CRM

Keep your CRM current with every chat: who wrote in, what they asked, and how it ended. Two ways to do it, real-time and batch, both on the muro API.

Tm

The muro team

muro.chat

#crm#integrations#api#sync#contacts#webhooks

Your CRM is only as good as what reaches it. Every chat is a signal: a question, an objection, a lead handing over their email. The muro API gives you two clean ways to keep your CRM in sync, and most teams use both.

Two ways to sync

Real-time uses webhooks: muro pushes an event the moment it happens, so your CRM updates within seconds. Batch uses the REST API: you pull contacts and conversations on a schedule, which is simpler to operate and great for backfills. Real-time keeps things fresh; batch keeps things complete. Run real-time for live updates and a nightly batch as a safety net.

Real-time: push on identification

Subscribe to visitor.identified. It fires when a visitor hands over their email, which is exactly the moment they become a CRM-worthy lead. In your receiver, verify the signature, then upsert the contact and attach the conversation as a note. Our webhooks guide has a copy-paste receiver with signature verification.

Batch: pull with the API

On a schedule, page through contacts, then fetch each conversation's transcript. Contacts are keyset-paginated by last activity, so you can sync only what changed since your last run by stopping once you reach contacts you have already seen.

typescriptconst BASE = 'https://muro.chat/api/v1';
const headers = { Authorization: 'Bearer ' + process.env.MURO_KEY };

// 1. Page through contacts (most recently seen first)
let cursor: string | null = null;
do {
  const url = BASE + '/contacts?limit=100' + (cursor ? '&cursor=' + cursor : '');
  const page = await fetch(url, { headers }).then((r) => r.json());
  for (const contact of page.data) {
    if (contact.email) await upsertCrmContact(contact);
  }
  cursor = page.has_more ? page.next_cursor : null;
} while (cursor);

// 2. Pull a conversation transcript for a contact record
const convs = await fetch(BASE + '/conversations?limit=100', { headers }).then((r) => r.json());
const msgs = await fetch(BASE + '/conversations/' + convs.data[0].id + '/messages', { headers })
  .then((r) => r.json());
const transcript = msgs.data.map((m) => m.sender_type + ': ' + m.content).join('\n');

Mapping the fields

  • Contact email and name map straight to your CRM contact or lead.
  • Contact conversation_count is a quick engagement score.
  • A conversation becomes an activity, a deal note, or a ticket.
  • The joined messages become the transcript attached to that record.
✦ ✦ ✦

Webhooks for the moment it matters, the REST API for everything else. Wire both and your CRM stops missing the conversations that turn into customers.

Tm

✎ Written by

The muro team

muro.chat