How to Build a Unified Social Media Inbox via API

One chat and message schema across Facebook Messenger, Instagram DMs, Telegram, and Bluesky — list conversations, receive webhooks, and reply from a single inbox API.

One schema, four platforms

The Direct Messages API normalizes Facebook Messenger, Instagram, Telegram, and Bluesky into two resources:

  • Chat — a conversation with one participant: participant_name, participant_avatar_url, last_message_at, platform-specific metadata.
  • Messagedirection (inbound/outbound), body, attachments, status, timestamps.

Your inbox renders these two objects. The platform differences — Meta webhooks vs Telegram Bot API vs AT Protocol polling — stay on Postproxy’s side of the line.

The conversation list

Pull chats per connected profile, ordered by latest activity:

Terminal window
curl "https://api.postproxy.dev/api/profiles/PROFILE_ID/chats?per_page=20" \
-H "Authorization: Bearer YOUR_API_KEY"

Merge the lists from all profiles, sort by last_message_at, and that’s the left pane. Each chat already has the participant’s display name and a stable avatar URL — no platform lookups to render a row. before / after timestamp filters handle incremental refresh.

The thread view

Terminal window
curl "https://api.postproxy.dev/api/chats/CHAT_ID/messages?per_page=50" \
-H "Authorization: Bearer YOUR_API_KEY"

Messages come newest-first with everything a thread UI needs:

  • direction decides bubble alignment.
  • attachments carry stable storage URLs — inbound media is mirrored off platform CDNs, so images don’t break when Meta’s tokens expire.
  • external_read_at / external_delivered_at give read receipts (Facebook and Instagram).
  • reactions is the live reaction state per message.
  • external_edited_at and external_deleted_at let you render “edited” and tombstones.

Real-time updates

Subscribe one webhook endpoint to the message events and fan out to your UI over your own websocket/SSE:

  • message.received — new inbound message (the event that bumps a chat to the top)
  • message.sent, message.delivered, message.read — outbound lifecycle
  • message.edited, message.deleted — thread mutations
  • reaction.received — reactions, including removals

One caveat: Bluesky has no webhooks upstream, so inbound Bluesky messages arrive via a ~5-minute poller. The message.received event still fires — just with up to 5 minutes of latency.

Replying

Same send call regardless of platform:

Terminal window
curl -X POST "https://api.postproxy.dev/api/chats/CHAT_ID/messages" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "body": "On it — refund issued, you should see it in 3-5 days." }'

Track the returned message’s status (pendingpublished, or failed with error_details) to show send state in the composer, or let message.sent / message.failed webhooks drive it.

Capability differences to surface in the UI

The schema is uniform; platform abilities aren’t. Disable composer features per chat’s platform:

CapabilityFacebookInstagramTelegramBluesky
AttachmentsYes (1/send)Yes (1/send)YesNo
ReactionsYesYesNoNo
Edit sent messageNoNoYesNo
Read receiptsYesYesNoNo
Free-form send window24h after last inbound24h after last inboundAny time after first user DMAny time

The 24-hour rule is the one to design around. Past that point on a Meta chat, an ordinary send fails — but a human agent can still reply for up to 7 days from last_inbound_at by sending with tag: "HUMAN_AGENT", so the right UI is a labelled state rather than a dead composer: normal inside 24 hours, “outside 24h window · human agent” between 24 hours and 7 days, disabled after that. (Private replies are the comment-triggered exception, and the tag is for humans only — see the HUMAN_AGENT tag.)

Beyond DMs

The same inbox pattern extends to public interactions: comments on Instagram, Facebook, and Threads, and Google Business reviews — all webhook-driven, all replied to with one POST. Per-platform send guides: Instagram DMs, Facebook Messenger. For the scope of the messaging API itself — chats, private replies, ig.me referrals — see Direct messages via API. To pull published posts back into the same interface rather than just conversations, see the social media aggregator API guide.

Ready to get started?

Start with our free plan and scale as your needs grow. No credit card required.