# Comment schema (/docs/schema/comment) {/* AUTO-GENERATED. Do not hand-edit. Source: packages/social-api/src/docs/generate-schema-pages.ts Regenerate with: pnpm -F @repo/social-api generate:docs Field tables derive from the canonical Zod schemas (packages/social-api/src/schemas/canonical.ts); availability + equivalence derive from the registry fieldMaps. */} Comment schema [#comment-schema] Every SocialCrawl endpoint that returns a comment gives you this exact shape, whatever the source platform. Write your parser once and the same code reads comment data from every platform below. That is the unified schema: one contract instead of a dozen raw upstream formats. Field reference [#field-reference] | Field | Type | Nullable | Description | | --------------------- | ------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | No | Platform-specific comment ID (always a string) | | `url` | `string` | Yes | Direct URL to the comment on the source platform | | `parent_id` | `string` | Yes | Parent comment ID for nested replies, or null for top-level comments | | `post_id` | `string` | Yes | ID of the post this comment belongs to | | `text` | `string` | Yes | Comment body. Tombstone sentinels (\[deleted] / \[removed]) are collapsed to null upstream — customers never see them. | | `author.username` | `string` | Yes | Comment author username (null when tombstoned) | | `author.display_name` | `string` | Yes | Comment author display name | | `author.avatar_url` | `string` | Yes | URL to comment author profile picture | | `author.verified` | `boolean` | Yes | Whether the comment author is verified | | `engagement.likes` | `integer` | Yes | Like / upvote count | | `engagement.replies` | `integer` | Yes | Reply / child-comment count. `0` when the upstream structurally reports the count and the comment has no replies; `null` only when the upstream does not surface a reply count at all. | | `flags.pinned` | `boolean` | Yes | Pinned flag (null when platform does not surface) | | `flags.deleted` | `boolean` | No | Whether the comment is tombstoned (always present, even when false) | | `published_at` | `string or integer` | Yes | Comment creation timestamp as an ISO 8601 UTC string. When the upstream sent a Unix epoch it is converted here and the raw epoch is preserved under `comment.ext.published_at_epoch` for one deprecation cycle. | | `replies` | `object[]` | Yes | Nested reply tree — array of child comments, each itself a full Comment object with its own `replies`. Populated on threaded platforms (Reddit); absent on flat-comment platforms, which thread only via `parent_id`. | Extension fields (`ext`) [#extension-fields-ext] Platform-specific passthrough. Each field is present only on the platforms that expose it and is absent everywhere else, so treat every `ext.*` field as optional. These carry the richer, per-platform signals the unified leaves cannot hold, and the join keys that chain endpoints together. | Field | Type | Nullable | Description | | ---------------------------- | ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `ext.replies_token` | `string` | Yes | YouTube reply continuation token — pass to `/v1/youtube/video/comment/replies?continuationToken=` | | `ext.replies_cursor` | `string` | Yes | Reddit reply-branch continuation cursor. Present when this comment's reply tree is truncated upstream — pass it back as `?cursor=` on `/v1/reddit/post/comments` to load the rest of the branch. | | `ext.published_at_epoch` | `integer` | Yes | Raw Unix epoch for `published_at` (present only when the upstream sent a numeric epoch that was normalised to the ISO 8601 string). | | `ext.feedback_id` | `string` | Yes | Facebook comment feedback id — feeds `/v1/facebook/post/comment/replies` | | `ext.expansion_token` | `string` | Yes | Facebook comment expansion/paginator token — feeds `/v1/facebook/post/comment/replies` | | `ext.author_id` | `string` | Yes | The commenter's platform-native numeric user id, where the upstream exposes one. | | `ext.urn` | `string` | Yes | | | `ext.reaction_counts` | `string[]` | Yes | | | `ext.is_edited` | `boolean` | Yes | | | `ext.previous_replies_token` | `string` | Yes | | | `ext.updated_at` | `string` | Yes | | | `ext.author_channel_id` | `string` | Yes | | | `ext.author_url` | `string` | Yes | | | `ext.viewer_rating` | `string` | Yes | | | `ext.text_original` | `string` | Yes | | | `ext.preview_replies` | `string[]` | Yes | | | `ext.lookup` | `string` | Yes | | Platform availability [#platform-availability] 12 platforms return the `Comment` shape. `id`, `flags.deleted` are never null on any platform. The fields below vary: **yes** means the platform populates it (the value may still be null); a blank means the platform never provides it, so it is always null.
| Platform | `flags.pinned` | `parent_id` | `author.verified` | `post_id` | `url` | `author.avatar_url` | `author.display_name` | `author.username` | `engagement.likes` | `engagement.replies` | | ----------- | -------------- | ----------- | ----------------- | --------- | ----- | ------------------- | --------------------- | ----------------- | ------------------ | -------------------- | | Facebook | | | | | | yes | yes | yes | yes | yes | | GitHub | | | | yes | yes | yes | | yes | yes | | | Google | | yes | | yes | | yes | yes | yes | | yes | | Hacker News | | yes | | yes | | | | yes | yes | | | Instagram | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | | LinkedIn | yes | | | | | | yes | | | yes | | Reddit | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | | Rumble | | | | | | yes | yes | yes | yes | yes | | Snapchat | | | | yes | | | yes | | yes | yes | | Threads | yes | | yes | | | yes | yes | yes | yes | yes | | TikTok | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes | | YouTube | | | | yes | | yes | | yes | yes | yes |
Machine-readable schema [#machine-readable-schema] Validate responses programmatically against the JSON Schema (2020-12): [`/schemas/comment.json`](/schemas/comment.json) Point a validator (Ajv, `jsonschema`, or your framework's) at that URL, or hand it to an agent so it can check the shape without a live call. Returned by [#returned-by] Endpoints with the `Comment` / `CommentList` archetype return this shape: [Facebook](/platforms/facebook) · [GitHub](/platforms/github) · [Google](/platforms/google) · [Hacker News](/platforms/hackernews) · [Instagram](/platforms/instagram) · [LinkedIn](/platforms/linkedin) · [Reddit](/platforms/reddit) · [Rumble](/platforms/rumble) · [Snapchat](/platforms/snapchat) · [Threads](/platforms/threads) · [TikTok](/platforms/tiktok) · [YouTube](/platforms/youtube) See how the same fields map to each platform's raw upstream names in the [cross-platform field equivalence table](/docs/schema/field-equivalence.md).