Part 2 of 7 · Social inbox unifier series ~4 min read

How a DM reaches the unified inbox

The inbox can only unify what reaches it. So the first job is getting every platform’s messages into one place, in one shape, the moment they arrive. Each platform does the pushing itself: you give it a web address, and from then on it calls that address every time a new DM comes in. A small connector per platform catches the call, checks it’s genuine, and turns whatever odd format that platform uses into one common message everyone downstream understands. Three platforms in, one queue out.

Key takeaways

  • Each platform pushes new messages to a webhook — a URL it calls within seconds of a DM arriving.
  • One small connector per platform verifies the call’s signature so fake messages can’t get in.
  • Every connector turns its platform’s format into one common shape: sender, platform, text, time, thread.
  • Each normalized message lands on a single work queue (SQS) for the labeler to pick up.
  • Adding a new channel later is just one more connector that writes the same common shape.

Three connectors into one queue

Three platform connectors funnel into one queue A diagram with three vertical lane columns at the top and a single unified row at the bottom. Lane one, Instagram: the Instagram account pushes a new direct message to the connector's webhook; a connector Lambda verifies the call's signature, reads the Instagram-specific payload, and turns it into the common shape. Lane two, Facebook: the Facebook Page pushes a new Page message to its webhook; the connector verifies the signature, reads the Facebook payload, and emits the same common shape. Lane three, WhatsApp: the WhatsApp business number pushes a new message to its webhook; the connector verifies the signature, reads the WhatsApp payload, and emits the same common shape. All three lanes converge on the same work queue, an SQS queue, where each message waits as one common record: sender, platform, text, timestamp, and conversation id. A note at the bottom: every platform speaks its own format at the door — past the connector, the rest of the system only ever sees the one common shape. Lane 1 · webhook Instagram • Account pushes a new DM to webhook • Connector verifies the signature • Reads the IG payload format • Emits the common message shape Lane 2 · webhook Facebook • Page pushes a new message to webhook • Connector verifies the signature • Reads the FB payload format • Emits the common message shape Lane 3 · webhook WhatsApp • Number pushes a new message in • Connector verifies the signature • Reads the WhatsApp payload format • Emits the common message shape Work queue — SQS (one common message shape) sender · platform · text · timestamp · conversation id · attachments every connector writes this exact record — the rest of the system reads only this to labeler, next Every platform speaks its own format at the door — past the connector, the system sees one shape.
Fig 2. Three connectors converge on one work queue. Each platform pushes its own format to its own webhook; each connector verifies and normalizes, then writes the same common record. Past the queue, no piece of the system needs to know which app a message came from.

What a webhook is, in one paragraph

A webhook is just a phone number you give a platform so it can call you when something happens, instead of you calling it over and over to ask. You register a web address with Instagram, Facebook, and WhatsApp once. From then on, the moment a customer sends a DM, that platform makes a small web request to your address with the message attached. There’s no polling, no app left open, no delay — the message shows up at your door within a second or two of being sent. In this system, each platform’s web address is a Lambda Function URL — a direct, no-frills address for a small piece of code, with no API Gateway in front of it.

The connector’s first job: make sure the call is genuine

An address that anything on the internet can call is an address anything on the internet can lie to. So every platform signs its calls — it attaches a short code, computed from a shared secret only you and the platform know, that proves the call really came from them. The connector’s first move is to recompute that code and compare. If it doesn’t match, the call is dropped on the spot and nothing enters the queue. The shared secret for each platform lives in Secrets Manager, never in the code. This one check is what stops a stranger from injecting fake DMs into your team’s queue.

The connector’s second job: turn five formats into one

Every platform describes a message a little differently. Instagram nests the text one way, Facebook another, WhatsApp a third; one calls the customer a “sender id,” another a “from,” another a phone number. If the rest of the system had to know all of those quirks, every downstream piece would carry three sets of special cases forever. Instead, each connector flattens its platform’s payload into one common record: sender, platform, text, timestamp, conversation_id, and any attachments. From the queue onward, the labeler, the router, and the inbox all read that one shape. Adding a fourth channel — a website chat, say — means writing one more connector that emits the same record, and nothing downstream changes.

Why a queue sits in the middle

The connector doesn’t label or route the message itself. It just drops the normalized record on a work queue — an SQS queue — and replies to the platform right away so the platform knows the message was received. This matters for two reasons. First, the platform wants a fast answer; if the connector tried to do the labeling and routing before replying, a slow moment could make the platform think the call failed and re-send it. Second, the queue smooths out bursts: if forty messages arrive in one minute during a sale, they line up in the queue and get worked through steadily instead of overwhelming anything. If a message ever fails to process, it lands in a dead-letter queue — a side queue for messages that need a second look — so nothing is silently lost.

Next post: how the labeler picks each message off the queue, reads it once with a model to get its topic and urgency, and drops the duplicates before they ever open a second thread.

All posts