Engagement
Comments
List, write, reply to, delete, hide and like comments on your posts, and answer a comment with a private reply.
Read and answer the comments on your posts, as the account that published them. This also works for posts made outside Onepostly.
Support by Platform
| Platform | List, comment and reply | Delete | Hide | Like a comment | Private reply |
|---|---|---|---|---|---|
| X (Twitter) | No | No | No | ||
| No | |||||
| Threads | No | No | |||
| No | No | No | No | No | |
| YouTube | No | No | No | ||
| TikTok | No | No | No | No | No |
| No | No | No | No | No | |
| Bluesky | No | No | No |
An unsupported action returns 400 UNSUPPORTED_PLATFORM. Each platform page lists its rules, such as Instagram.
On X, comment reads and writes are paid from your wallet. A low balance returns 402 INSUFFICIENT_WALLET.
Comment Ids
Every comment has a cmt_ id for replying, deleting, hiding, liking and private replies. It works only in the workspace that received it.
| Field | Contains |
|---|---|
id | The cmt_ id |
postId | The post's pst_ id |
accountId | The post's account, which also writes your comments |
platformCommentId | The comment's platform id |
parentId | The cmt_ id it replies to, or null |
text | The comment text |
username | The author's username without @, or null |
likeCount | Likes, or null when not reported |
createdAt | When it was posted, or null when not reported |
replies | Replies, on platforms that return them |
List Comments
GET /v1/posts/{id}/comments reads comments live from the platform, 50 per page at most. Pass nextCursor as cursor until hasMore is false.
import { Configuration, CommentsApi } from "@onepostly/sdk";
const commentsApi = new CommentsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await commentsApi.listComments({
id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
limit: 25,
});
console.log(response);{
"data": [
{
"id": "cmt_amtpCkVartn0nqaE1Je0v2VkSEm03WARoWPFRyRgiFzkP3uEcxR4W9LztUdBGz2YWD5AFw9KMvsNTqsnW544OSHrpC1iYD3cgpan0HmOMKINUmnERALRze",
"postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"accountId": "acc_1699f4157fb643f49d2ac447491f32a8",
"platform": "instagram",
"platformCommentId": "17988123456789012",
"parentId": null,
"text": "Great results, congrats!",
"username": "mark.builds",
"likeCount": 0,
"createdAt": "2027-03-15T09:42:19.000Z",
"replies": []
},
{
"id": "cmt_cDQEpthzkh9NCjzItFNd19ItnVdYlB4tB4t92XY6Edv1B72jDW9DvSpwIgqi6O75UgGzjUt3zONixH1SGrdIkBYuTm34IsLyxwSJLHBgdYz5DYn31g4zQ0",
"postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"accountId": "acc_1699f4157fb643f49d2ac447491f32a8",
"platform": "instagram",
"platformCommentId": "18050512345678901",
"parentId": null,
"text": "Love this! Where can I get one?",
"username": "jane_doe",
"likeCount": 3,
"createdAt": "2027-03-15T09:20:11.000Z",
"replies": [
{
"id": "cmt_8c86vC3o0CyUONgnTCe2CNWfzeYcEfSNcRGHQeDTlVL6dsCpsa0OptpfZ9BoWxAPeFYf82BGoYyBMqDIOfv3NcCyj5R6TP7RcXGj8OcZEOBnRYy4q42spq",
"postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"accountId": "acc_1699f4157fb643f49d2ac447491f32a8",
"platform": "instagram",
"platformCommentId": "18050598765432109",
"parentId": "cmt_cDQEpthzkh9NCjzItFNd19ItnVdYlB4tB4t92XY6Edv1B72jDW9DvSpwIgqi6O75UgGzjUt3zONixH1SGrdIkBYuTm34IsLyxwSJLHBgdYz5DYn31g4zQ0",
"text": "The link is in our bio!",
"username": "yourbrand",
"likeCount": 1,
"createdAt": "2027-03-15T09:24:37.000Z",
"replies": []
}
]
}
],
"nextCursor": "QVFIUjRtc2N5ZAWZAkV3ZA0bHBpTlJXNWdVaU5GUEI3c1BtX0VnSzFnYWZAkdC1QWFZAiR0Q5ZAVNfNlBhTHVoa2RnMEtsSVlyTkhz",
"hasMore": true
}A post that is not live yet returns 409 NOT_PUBLISHED, so wait for post.published. Stories have no comments.
Comment on a Post
POST /v1/posts/{id}/comments with text comments as the post's account and returns 201. Text over the platform's limit returns 400 TEXT_TOO_LONG.
import { Configuration, CommentsApi } from "@onepostly/sdk";
const commentsApi = new CommentsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await commentsApi.createComment({
id: "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
commentTextBody: {
"text": "Thanks for watching!"
},
});
console.log(response);{
"id": "cmt_jDn7AR68Du8FrawkvedZhy5qdVdXf8RMwWvtDCyDlOrDKhCBUKiix6E0T0FqW3UCGizpXZkVbUZ5b3uBVb8DDqwU0wRr4eoefhlGX0uQc6y2iCPDboTCpG",
"postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"accountId": "acc_1699f4157fb643f49d2ac447491f32a8",
"platform": "instagram",
"platformCommentId": "18063456789012345",
"parentId": null,
"text": "Thanks for watching!",
"username": null,
"likeCount": 0,
"createdAt": "2027-03-15T10:00:00.000Z",
"replies": []
}Reply to a Comment
POST /v1/comments/{id}/replies with text returns 201 with the reply. Its parentId is the comment you answered.
import { Configuration, CommentsApi } from "@onepostly/sdk";
const commentsApi = new CommentsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await commentsApi.replyToComment({
id: "cmt_YOUR_COMMENT_ID",
commentTextBody: {
"text": "Glad you liked it."
},
});
console.log(response);{
"id": "cmt_ztfnHfaU0iNb9UBUuNnnxN8waYgVvu3Y12mVBDR6dweXoMSb4tn0DeDwvC0IeIW2SQEWLo9bNYoYFOPhESI4pxuKjN5txdk2pDjSaIaePIKjvOpsFJ26lA",
"postId": "pst_3c8a2d6e91b44f7a8e250d6b4c1f9a73",
"accountId": "acc_1699f4157fb643f49d2ac447491f32a8",
"platform": "instagram",
"platformCommentId": "18063456789012399",
"parentId": "cmt_YOUR_COMMENT_ID",
"text": "Glad you liked it.",
"username": null,
"likeCount": 0,
"createdAt": "2027-03-15T10:00:00.000Z",
"replies": []
}Delete a Comment
DELETE /v1/comments/{id} deletes a comment and returns 204.
On X, Instagram, Facebook and Threads, the id of one of your own posts returns 400 NOT_A_COMMENT. Use Delete a Post instead.
Hide or Unhide a Comment
PUT /v1/comments/{id}/hidden hides a comment from everyone but its author. DELETE on the same path shows it again. Both return id and hidden. It works on Instagram, Facebook and Threads only.
Like a Comment
PUT /v1/comments/{id}/like likes a comment as the Page. DELETE on the same path removes the like. Both return id and liked. Facebook only.
Send a Private Reply
POST /v1/comments/{id}/private-reply sends the author a direct message. It returns 201 with the message id, commentId, text and createdAt.
import { Configuration, CommentsApi } from "@onepostly/sdk";
const commentsApi = new CommentsApi(
new Configuration({ accessToken: process.env.ONEPOSTLY_API_KEY })
);
const response = await commentsApi.sendPrivateReply({
id: "cmt_YOUR_COMMENT_ID",
privateReplyBody: {
"text": "Thanks! Check your DMs."
},
});
console.log(response);{
"id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDAxMjM0NTY3ODk6MzQwMjgyMzY2ODQxNzEwMzAwOTQ5MTI4MTM3NjE5NzM2Mzg3MTI4",
"commentId": "cmt_YOUR_COMMENT_ID",
"text": "Thanks! Check your DMs.",
"createdAt": "2027-03-15T10:00:00.000Z"
}| Rule | ||
|---|---|---|
text length | 1,000 characters | 2,000 characters |
| Replies per comment | 1 | 1 |
| Time limit | 7 days | 7 days |
A second reply, or one after 7 days, fails with 502 PRIVATE_REPLY_FAILED. After the private reply, the conversation continues in the Inbox. To answer keywords without writing any code, set up an automation.
Webhooks
| Event | Fires when |
|---|---|
comment.created | You comment or reply through the API |
comment.deleted | You delete a comment, or it is removed on Facebook |
comment.received | Anyone comments on an Instagram or Facebook post |
Hides, likes and private replies send no event. See Comment Webhooks.
Errors
| Code | HTTP | Cause | Fix |
|---|---|---|---|
NOT_FOUND | 404 | No post or comment has this id | Check the id |
UNSUPPORTED_PLATFORM | 400 | The platform lacks this action | See Support by Platform |
TEXT_TOO_LONG | 400 | text is over the limit | Shorten it |
NOT_A_COMMENT | 400 | The id is one of your posts | Use Delete a Post |
NOT_PUBLISHED | 409 | The post is not live yet | Wait for post.published |
TOKEN_EXPIRED, TOKEN_INVALID | 409 | The account's access ended | Reconnect it |
INSUFFICIENT_WALLET | 402 | The wallet is too low for an X action | Top up, then retry |
COMMENTS_PERMISSION | 422 | A permission is missing, the delete is refused, or comments are off | Reconnect and approve every permission |
COMMENT_*_FAILED, PRIVATE_REPLY_FAILED | 502 | The platform did not complete it | Read error, then retry later |
Comments, replies, deletes and private replies count toward action limits. Over one, you get 429 QUOTA_EXCEEDED, and error says when to retry. 429 RATE_LIMITED is the request limit. Other codes are in Error Codes.