Engagement API
Read comments and mentions, reply to people, and hide comments across six platforms with a single, unified shape. Each endpoint wraps the exact same platform services Schedulala uses internally, so the data you get back matches what the dashboard shows.
Permission: Endpoints require the engagement permission on your API key. Keys created before this permission existed default to allowed, so existing integrations keep working without any change.
/api/v1/engagement/commentsList recent or per-post comments/api/v1/engagement/replyReply to a comment or post/api/v1/engagement/hideHide or unhide a comment/api/v1/engagement/mentionsList mentions and tags/api/v1/engagement/transcriptYouTube video transcriptsPlatform capabilities
Not every platform supports every action. The table below shows exactly what each platform supports. Calling an unsupported action returns a validation_error (400) that lists the platforms where the action is available.
| Platform | comments | reply | hide | mentions |
|---|---|---|---|---|
facebook | Yes | Yes | Yes | -- |
instagram | Yes | Yes | Yes | Yes |
youtube | Yes | Yes | Yes | -- |
linkedin | Yes | Yes | -- | -- |
threads | Yes | Yes | Yes | Yes |
bluesky | Yes | Yes | -- | Yes |
The unified comment shape
Comments and mentions are normalized into the same shape regardless of platform. Fields with no platform equivalent return null. Every platform-specific field that has no unified slot is preserved under platformData, so you never lose information. The platformData key is omitted entirely when there is nothing extra to carry.
Comment fields
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Optional | The comment ID, as a string. May be null. |
text | string | Optional | The comment text. May be null (for example, a media-only mention). |
author | object | Optional | The author. Contains username, displayName, and profilePicture, each of which may be null. |
createdAt | string | Optional | When the comment was created, as returned by the platform. May be null. |
likeCount | number | Optional | Number of likes on the comment, when the platform reports it. May be null. |
post | object | Optional | The post the comment is on, when known. Contains id, caption, permalink, mediaUrl, thumbnailUrl, createdAt, commentCount, and likeCount. May be null. |
platform | string | Optional | The platform this comment came from. |
platformData | object | Optional | Raw platform-specific fields that have no unified slot. Omitted when empty. |
idstringOptionalThe comment ID, as a string. May be null.
textstringOptionalThe comment text. May be null (for example, a media-only mention).
authorobjectOptionalThe author. Contains username, displayName, and profilePicture, each of which may be null.
createdAtstringOptionalWhen the comment was created, as returned by the platform. May be null.
likeCountnumberOptionalNumber of likes on the comment, when the platform reports it. May be null.
postobjectOptionalThe post the comment is on, when known. Contains id, caption, permalink, mediaUrl, thumbnailUrl, createdAt, commentCount, and likeCount. May be null.
platformstringOptionalThe platform this comment came from.
platformDataobjectOptionalRaw platform-specific fields that have no unified slot. Omitted when empty.
{"id": "17912345678901234","text": "Love this! Where can I get one?","author": {"username": "jane_doe","displayName": "Jane Doe","profilePicture": null},"createdAt": "2026-06-09T18:22:00+0000","likeCount": 4,"post": {"id": "17895695668004550","caption": "Our new summer drop is here.","permalink": "https://www.instagram.com/p/ABC123/","mediaUrl": "https://scontent.cdninstagram.com/v/abc.jpg","thumbnailUrl": null,"createdAt": "2026-06-08T14:00:00+0000","commentCount": 12,"likeCount": 340},"platform": "instagram","platformData": {"mediaType": "IMAGE"}}
List comments
/api/v1/engagement/commentsList recent or per-post commentsOmit postId to get recent comments across the account. Include postId to get comments on a single post. Supported on facebook, instagram, youtube, linkedin, threads, and bluesky.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
platform | string | Required | The platform to query.facebookinstagramyoutubelinkedinthreadsbluesky |
accountId | string | Optional | Which connected account to use. If omitted, the first connected account for that platform is used. |
postId | string | Optional | Return comments on this specific post. See the postId reference below for what this value is per platform. |
limit | integer | Optional | Number of comments to return. Capped at 50.Default: 25 |
cursor | string | Optional | Pagination cursor from a previous response (per-post listing only, where the platform supports it). |
platformstringRequiredThe platform to query.
facebookinstagramyoutubelinkedinthreadsblueskyaccountIdstringOptionalWhich connected account to use. If omitted, the first connected account for that platform is used.
postIdstringOptionalReturn comments on this specific post. See the postId reference below for what this value is per platform.
limitintegerOptionalNumber of comments to return. Capped at 50.
Default: 25
cursorstringOptionalPagination cursor from a previous response (per-post listing only, where the platform supports it).
What is postId, per platform? The native post identifier: media id (instagram, facebook), video id (youtube), post URN (linkedin), thread id (threads), and post URI (bluesky).
# Recent comments across the accountcurl "https://schedulala.com/api/v1/engagement/comments?platform=instagram" \-H "Authorization: Bearer sk_live_abc123..."# Comments on a single postcurl "https://schedulala.com/api/v1/engagement/comments?platform=instagram&postId=17895695668004550&limit=25" \-H "Authorization: Bearer sk_live_abc123..."
{"success": true,"platform": "instagram","account": {"id": "17841400000000000","username": "yourbrand"},"postId": "17895695668004550","comments": [{"id": "17912345678901234","text": "Love this! Where can I get one?","author": {"username": "jane_doe","displayName": null,"profilePicture": null},"createdAt": "2026-06-09T18:22:00+0000","likeCount": 4,"post": null,"platform": "instagram","platformData": {"mediaType": null}}],"hasMore": true,"nextCursor": "QVFIUm..."}
When listing recent comments (no postId), the post field on each comment is populated with the post it belongs to, and hasMore / nextCursor are not returned.
Reply
/api/v1/engagement/replyReply to a comment or postPost a text reply. The reply target differs by platform, so include the fields listed in the reply targets table below. A non-empty message is always required.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
platform | string | Required | The platform to reply on.facebookinstagramyoutubelinkedinthreadsbluesky |
accountId | string | Optional | Which connected account to use. Defaults to the first connected account for that platform. |
message | string | Required | The reply text. Must be non-empty. |
commentId | string | Optional | Reply target for facebook, instagram, youtube, linkedin, and threads. See the reply targets table. |
postId | string | Optional | Reply target for a top-level comment on facebook and linkedin, or the thread being replied to on threads. See the reply targets table. |
parentUri | string | Optional | Bluesky only. The AT-Protocol URI of the post being replied to. |
parentCid | string | Optional | Bluesky only. The CID of the post being replied to. |
rootUri | string | Optional | Bluesky only. The URI of the thread root. |
rootCid | string | Optional | Bluesky only. The CID of the thread root. |
platformstringRequiredThe platform to reply on.
facebookinstagramyoutubelinkedinthreadsblueskyaccountIdstringOptionalWhich connected account to use. Defaults to the first connected account for that platform.
messagestringRequiredThe reply text. Must be non-empty.
commentIdstringOptionalReply target for facebook, instagram, youtube, linkedin, and threads. See the reply targets table.
postIdstringOptionalReply target for a top-level comment on facebook and linkedin, or the thread being replied to on threads. See the reply targets table.
parentUristringOptionalBluesky only. The AT-Protocol URI of the post being replied to.
parentCidstringOptionalBluesky only. The CID of the post being replied to.
rootUristringOptionalBluesky only. The URI of the thread root.
rootCidstringOptionalBluesky only. The CID of the thread root.
Reply targets by platform
| Platform | Required target fields |
|---|---|
instagram | commentId (reply to a comment) |
youtube | commentId (reply to a comment) |
facebook | commentId (reply to a comment) or postId (add a top-level comment) |
linkedin | commentId (nested reply; must be a composite comment URN) or postId (top-level comment) |
threads | commentId or postId (the thread or reply being responded to) |
bluesky | parentUri + parentCid + rootUri + rootCid (all four required) |
Bluesky reply refs: The four AT-Protocol refs come straight off a normalized item's platformData.replyRefs returned by the comments and mentions endpoints. Pass them back to reply to that item.
# Reply to an Instagram commentcurl -X POST https://schedulala.com/api/v1/engagement/reply \-H "Authorization: Bearer sk_live_abc123..." \-H "Content-Type: application/json" \-d '{"platform": "instagram","commentId": "17912345678901234","message": "Thanks! Link is in our bio."}'# Reply on Bluesky (all four refs required)curl -X POST https://schedulala.com/api/v1/engagement/reply \-H "Authorization: Bearer sk_live_abc123..." \-H "Content-Type: application/json" \-d '{"platform": "bluesky","parentUri": "at://did:plc:abc/app.bsky.feed.post/3k...","parentCid": "bafyrei...","rootUri": "at://did:plc:abc/app.bsky.feed.post/3j...","rootCid": "bafyrei...","message": "Appreciate it!"}'
{"success": true,"platform": "instagram","account": {"id": "17841400000000000","username": "yourbrand"},"reply": {"id": "17987654321098765"}}
The reply object varies by platform. Bluesky also returns permalink and cid; threads returns a best-effort permalink when available.
Hide a comment
/api/v1/engagement/hideHide or unhide a commentHide or unhide a comment. Supported on facebook, instagram, youtube, and threads. Set hide to false to unhide; it defaults to true.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
platform | string | Required | The platform.facebookinstagramyoutubethreads |
accountId | string | Optional | Which connected account to use. Defaults to the first connected account for that platform. |
commentId | string | Required | The comment to hide or unhide. |
hide | boolean | Optional | Whether to hide (true) or unhide (false) the comment.Default: true |
platformstringRequiredThe platform.
facebookinstagramyoutubethreadsaccountIdstringOptionalWhich connected account to use. Defaults to the first connected account for that platform.
commentIdstringRequiredThe comment to hide or unhide.
hidebooleanOptionalWhether to hide (true) or unhide (false) the comment.
Default: true
# Hide a commentcurl -X POST https://schedulala.com/api/v1/engagement/hide \-H "Authorization: Bearer sk_live_abc123..." \-H "Content-Type: application/json" \-d '{"platform": "facebook","commentId": "1234567890_9876543210","hide": true}'
{"success": true,"platform": "facebook","account": {"id": "1234567890","username": "Your Page"},"commentId": "1234567890_9876543210","hidden": true}
List mentions
/api/v1/engagement/mentionsList mentions and tagsPosts and comments where the account is mentioned or tagged. Supported on instagram (tags and mentions), threads, and bluesky (mentions and quotes). Each mention uses the same unified comment shape.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
platform | string | Required | The platform to query.instagramthreadsbluesky |
accountId | string | Optional | Which connected account to use. Defaults to the first connected account for that platform. |
limit | integer | Optional | Number of mentions to return. Capped at 50.Default: 25 |
cursor | string | Optional | Pagination cursor from a previous response, where the platform supports it. |
platformstringRequiredThe platform to query.
instagramthreadsblueskyaccountIdstringOptionalWhich connected account to use. Defaults to the first connected account for that platform.
limitintegerOptionalNumber of mentions to return. Capped at 50.
Default: 25
cursorstringOptionalPagination cursor from a previous response, where the platform supports it.
curl "https://schedulala.com/api/v1/engagement/mentions?platform=instagram&limit=25" \-H "Authorization: Bearer sk_live_abc123..."
{"success": true,"platform": "instagram","account": {"id": "17841400000000000","username": "yourbrand"},"mentions": [{"id": "17900000000000000","text": "Just picked these up @yourbrand, obsessed!","author": {"username": "happy_customer","displayName": null,"profilePicture": null},"createdAt": "2026-06-09T12:05:00+0000","likeCount": 21,"post": null,"platform": "instagram","platformData": {"mentionType": "tag","permalink": "https://www.instagram.com/p/XYZ789/","mediaUrl": "https://scontent.cdninstagram.com/v/xyz.jpg","commentCount": 3}}]}
YouTube video transcripts
/api/v1/engagement/transcriptYouTube video transcriptsFetch the caption tracks and a parsed transcript for a YouTube video on a connected channel. Supported on youtube only. The transcript is built from the best available caption track: manually created tracks are preferred over auto-generated (asr) ones, and English is preferred when both options exist at the same level.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
platform | string | Optional | The platform. Only youtube is supported.Default: youtubeyoutube |
accountId | string | Optional | Which connected channel to use. Defaults to the first connected YouTube channel. |
videoId | string | Required | The YouTube video ID to fetch the transcript for. |
platformstringOptionalThe platform. Only youtube is supported.
Default: youtube
youtubeaccountIdstringOptionalWhich connected channel to use. Defaults to the first connected YouTube channel.
videoIdstringRequiredThe YouTube video ID to fetch the transcript for.
curl "https://schedulala.com/api/v1/engagement/transcript?platform=youtube&videoId=dQw4w9WgXcQ" \-H "Authorization: Bearer sk_live_abc123..."
{"success": true,"platform": "youtube","account": {"id": "UCabc123def456","username": "Your Channel"},"videoId": "dQw4w9WgXcQ","tracks": [{"id": "AUieDaZ0Y2FwdGlvbnRyYWNr","language": "en","name": "","trackKind": "asr","isDraft": false}],"transcript": {"trackId": "AUieDaZ0Y2FwdGlvbnRyYWNr","language": "en","trackKind": "asr","segments": [{"index": 1,"start": "00:00:00,080","end": "00:00:02,639","text": "hey everyone and welcome back to the"},{"index": 2,"start": "00:00:02,639","end": "00:00:05,120","text": "channel today we are breaking down"}],"plainText": "hey everyone and welcome back to the channel today we are breaking down"}}
tracks lists every caption track on the video. transcript contains the parsed best track, with segments carrying SRT-style timestamps (HH:MM:SS,mmm, for example 00:00:00,080) and plainText joining all segment text into one string. When the video has no caption tracks, transcript is null.
Errors
Validation problems return 400. When the platform itself denies the request (for example, an account that needs to be reconnected with engagement permissions), you get a 403. Any other upstream failure surfaces as a 502, since the problem is with the platform, not your request.
| Status | Code | When it happens |
|---|---|---|
| 400 | validation_error | Missing or unsupported platform, an unsupported action for the platform, a missing reply target, or no connected account for the platform. |
| 403 | platform_permission_error | The platform denied the request. The account may need to be reconnected with engagement permissions. |
| 502 | platform_error | The platform's API returned an unexpected error. |