# comment.received

A new comment arrived on a tracked post.

### Platform notes

Delivered for Instagram, Facebook, Threads, YouTube, LinkedIn, Bluesky, Reddit and TikTok. X/Twitter does not fire it. TikTok needs an account connected through the TikTok for Business app.

### Delivery timing

Instagram, Facebook, Threads and TikTok arrive in real time from the platform's webhook. The rest are poll-driven, so delivery is not instant.

### Live comments

On Instagram, `comment.isLive: true` marks a comment made during a live broadcast. The key is absent on every other comment.

### Ads

`comment.ad` is present only on comments made on paid content, so `if (comment.ad)` filters ad-driven comments.

### Ad fields

Instagram carries `ad.id` and `ad.title`. Facebook carries `ad.promotionStatus`: `active` for boosted organic posts, `ineligible` for dark post creatives.

### Instagram author profile

Comments may carry `comment.author.instagramProfile` (`isFollower`, `isFollowing`, `followerCount`, `isVerified`). An absent object means unknown, never "not a follower".

### Why the profile is often absent

Meta reveals the follow relationship only for people who have messaged the account, and commenting does not grant that consent. The object is absent for most first-time commenters.




**Payload for `comment.received`:**

- **id** (required) `string`: Stable webhook event ID: the dedupe key, also sent as the X-Zernio-Event-Id header and identical on every retry and redelivery. It identifies the event only, never an account or other resource.
- **profiles**: `WebhookProfiles` - See schema definition
- **test** `boolean`: Always true when present: only a sample sent by POST /v1/webhooks/test with an event carries it. Real deliveries never do.
- **event** (required) `string`: No description - one of: comment.received
- **comment** (required) `object`: 
  - **id** (required) `string`: Platform comment ID
  - **postId** (required) `string,null`: Internal post ID (null for posts not published through Zernio)
  - **platformPostId** (required) `string`: Platform's post ID
  - **platform** (required) `string`: No description - one of: instagram, facebook, threads, youtube, linkedin, bluesky, reddit, tiktok
  - **text** (required) `string`: Comment text content
  - **author** (required) `object`: 
    - **id** (required) `string`: Author's platform ID
    - **username** `string`: No description
    - **name** `string`: No description
    - **picture** `string,null`: No description
    - **isOwnAccount** `boolean`: True when this comment was authored by the connected account itself. Absent means not evaluated, never "not the account".

- Instagram and Facebook realtime webhooks: populated (Meta re-delivers the account's own replies as comments events).
- TikTok: inferred. Comments created through this API are always flagged, and once the account's own author identifier is known (from one of those or from a comments listing), every author is compared against it.

    - **instagramProfile** `object`: Instagram only, best-effort. Present ONLY for commenters who have
messaged the account before: Meta gates the follow relationship behind
messaging consent, and commenting does not grant it. Absent otherwise -
treat a missing object as "unknown", never as "not a follower". To check
on demand, call GET /v1/accounts/{accountId}/follow-status/{userId}.

      - **isFollower** `boolean,null`: The commenter follows this account.
      - **isFollowing** `boolean,null`: This account follows the commenter.
      - **followerCount** `integer,null`: No description
      - **isVerified** `boolean,null`: No description
  - **createdAt** (required) `string` (date-time): No description
  - **isReply** (required) `boolean`: Whether this is a reply to another comment
  - **parentCommentId** (required) `string,null`: Parent comment ID if this is a reply
  - **isLive** `boolean`: Instagram only: true when the comment was made on a live broadcast (the live_comments webhook field). Absent on every other comment.
  - **ad** `object`: Ad context. Present only when the comment was made on paid content; absent for comments on organic posts that are not promoted.

**Instagram**: populated from the webhook payload's value.media.ad_id, value.media.ad_title and value.media.original_media_id, each only when Meta includes it.

**Facebook**: populated from a Graph API lookup of the parent post. Present when the post is an ad dark post (isDarkPost true, whatever its promotionStatus) or an organic post that is or was boosted (promotionStatus "active", "extendable" or "finished").

Meta does not link a dark post to its ad, so on Facebook id is set only when a Meta Ads account is connected and exactly one of its ads has the same text as the post. title is never set on Facebook.

    - **id** `string`: Meta ad ID. Instagram: from the webhook. Facebook: only when a connected Meta Ads account has one ad with the same text.
    - **title** `string`: Ad creative title (Instagram only).
    - **originalMediaId** `string`: Original media ID that Meta reports for the ad (Instagram only).
    - **promotionStatus** `string`: Facebook only. The parent post's promotion_status as the Graph API returns it, for example
"active" (organic post currently boosted). Ad dark posts usually report "inactive" and
sometimes "ineligible", so use isDarkPost, not this value, to tell an ad comment apart.

    - **isDarkPost** `boolean`: Facebook only: true when the post is an unpublished ad creative (dark post), false for a boosted organic post.
  - **attachment**: Facebook only. Present on graphic-only comments (sticker, GIF, photo) that carry no text:
the webhook only includes it when the comment has no text. The REST comments API returns it
whenever Facebook returns one, text or not.

- **post** (required) `object`: 
  - **id** (required) `string,null`: Internal post ID (null for posts not published through Zernio)
  - **platformPostId** (required) `string`: Platform's post ID
  - **content** (required) `string,null`: Post text, from our synced copy. No platform call is made on the comment path, so null when the post was never synced.
  - **imageUrl** (required) `string,null`: Post thumbnail or first media item URL. Platform CDN URLs expire, fetch promptly.
  - **permalink** (required) `string,null`: Public URL of the post. Null when no URL was ever stored for it, for example a platform draft or a post recovered without one.
- **account** (required) `object`: 
  - **id** (required) `string`: Account ID
  - **accountId** `string`: Account ID (same as id); canonical field for account filtering.
  - **platform** (required) `string`: No description
  - **username** (required) `string`: No description
- **timestamp** (required) `string` (date-time): UTC time at which Zernio generated this event (set once when the event payload is built, before delivery is queued). Retries and redeliveries keep the original value, so it reflects the event, not the delivery attempt.