Engagement
Like YouTube videos and manage comments through Onepostly.
YouTube engagement is likes on a published video. Likes are rated as the connected account. Pass post as described in Analytics. Use the internal id for Onepostly uploads. Use the native video id plus accountId for outside videos.
Likes
import { Configuration, EngagementApi } from "@onepostly/sdk";
const engagementApi = new EngagementApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await engagementApi.like({
engagementTargetBody: {
"post": "1699f415-7fb6-43f4-9d2a-c447491f32a8"
},
});
console.log(response);{
"postId": "1699f415-7fb6-43f4-9d2a-c447491f32a8",
"destinationId": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"platform": "youtube",
"kind": "like",
"active": true
}import { Configuration, EngagementApi } from "@onepostly/sdk";
const engagementApi = new EngagementApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await engagementApi.unlike({
post: "1699f415-7fb6-43f4-9d2a-c447491f32a8",
});
console.log(response);{
"postId": "1699f415-7fb6-43f4-9d2a-c447491f32a8",
"destinationId": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"platform": "youtube",
"kind": "like",
"active": false
}Unliking returns the same shape with active: false.
Successful calls emit the engagement.liked and engagement.unliked webhooks.
Bookmarks and reposts do not exist on YouTube.
Comments
Manage comments on a published YouTube video. Comments are posted as the connected account.
List
Returns the video top level comment threads. Each thread includes its replies.
import { Configuration, CommentsApi } from "@onepostly/sdk";
const commentsApi = new CommentsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await commentsApi.listComments({
post: "1699f415-7fb6-43f4-9d2a-c447491f32a8",
limit: 25,
});
console.log(response);{
"comments": {
"post": "1699f415-7fb6-43f4-9d2a-c447491f32a8",
"subjects": [
{
"scope": "destination",
"subjectId": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
"platform": "youtube",
"externalPostId": "17895695668004550",
"status": "ready",
"comments": [
{
"id": "c1",
"text": "Love this!",
"username": "jane_doe",
"likeCount": 12,
"timestamp": "2026-08-25T10:05:00.000Z",
"parentId": null
}
],
"nextCursor": null,
"error": null,
"externalUrl": "https://www.youtube.com/watch?v=17895695668004550"
}
]
}
}| Query | Required | Notes |
|---|---|---|
post | Yes | Internal post id or native video id. Native ids require accountId |
accountId | For native ids | Disambiguates the target account. Also narrows internal posts with several destinations |
destinationId | No | Globally unique. Resolves on its own or narrows one destination inside an internal post |
limit | No | 1-50, default 25 |
cursor | No | Pagination cursor from the previous response nextCursor. Requires a single resolved target |
Create
Creates a top level comment, or a reply when parentCommentId is set.
import { Configuration, CommentsApi } from "@onepostly/sdk";
const commentsApi = new CommentsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await commentsApi.createComment({
createCommentBody: {
"post": "1699f415-7fb6-43f4-9d2a-c447491f32a8",
"text": "Love this!",
"parentCommentId": "c0"
},
});
console.log(response);{
"comment": {
"id": "c1",
"text": "Love this!",
"username": "jane_doe",
"likeCount": 12,
"timestamp": "2026-08-25T10:05:00.000Z"
}
}| Body | Required | Notes |
|---|---|---|
post | Yes | Internal post id or native video id. Native ids require accountId |
text | Yes | Comment text |
accountId | For native ids | Target account for native ids. Also disambiguates internal posts |
destinationId | No | Globally unique. Resolves on its own or targets one destination inside an internal post |
parentCommentId | No | Reply to a comment. Omit to comment on the video itself |
Delete
Deletes a comment owned by the connected account. commentId is the comment id on YouTube. Deleting an already removed comment succeeds without error.
import { Configuration, CommentsApi } from "@onepostly/sdk";
const commentsApi = new CommentsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await commentsApi.deleteComment({
post: "1699f415-7fb6-43f4-9d2a-c447491f32a8",
commentId: "c0",
});
console.log(response);{
"deleted": {
"postId": "1699f415-7fb6-43f4-9d2a-c447491f32a8",
"destinationId": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"platform": "youtube",
"commentId": "c0",
"deleted": true
}
}If you get a permission error on any of these, reconnect the YouTube connection once.
Outside Posts
Videos uploaded outside Onepostly work the same way once they are synced. Sync by URL then use the native id plus accountId in every comments call. Omit url and postId to refresh the recent posts of the account in bulk.
import { Configuration, PostsApi } from "@onepostly/sdk";
const postsApi = new PostsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await postsApi.syncExternal({
syncExternalBody: {
"accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
},
});
console.log(response);{
"synced": {
"postsFound": 1,
"postsSynced": 1,
"skipped": false
},
"found": true,
"post": {
"id": "e8f9a0b1-c2d3-4e5f-8a6b-c7d8e9f0a1b2",
"accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
"platform": "youtube",
"externalPostId": "dQw4w9WgXcQ",
"externalUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"mediaKind": "text",
"publishedAt": "2026-08-25T10:00:00.000Z",
"syncedAt": "2026-08-25T10:00:00.000Z",
"analyticsStatus": "ready"
}
}import { Configuration, CommentsApi } from "@onepostly/sdk";
const commentsApi = new CommentsApi(
new Configuration({ apiKey: process.env.ONEPOSTLY_API_KEY })
);
const response = await commentsApi.listComments({
post: "1699f415-7fb6-43f4-9d2a-c447491f32a8",
limit: 25,
});
console.log(response);{
"comments": {
"post": "1699f415-7fb6-43f4-9d2a-c447491f32a8",
"subjects": [
{
"scope": "destination",
"subjectId": "d4e5f6a7-8b9c-4d0e-8f1a-2b3c4d5e6f7a",
"accountId": "a1b2c3d4-e5f6-4a7b-8c9d-e0f1a2b3c4d5",
"platform": "youtube",
"externalPostId": "17895695668004550",
"status": "ready",
"comments": [
{
"id": "c1",
"text": "Love this!",
"username": "jane_doe",
"likeCount": 12,
"timestamp": "2026-08-25T10:05:00.000Z",
"parentId": null
}
],
"nextCursor": null,
"error": null,
"externalUrl": "https://www.youtube.com/watch?v=17895695668004550"
}
]
}
}Errors
| Code | Cause | Fix |
|---|---|---|
MISSING_EXTERNAL_ID | Destination not published yet | Wait for publish |
ENGAGEMENT_PERMISSION | Connection lacks the rating permission | Reconnect the account |
LIKE_FAILED or UNLIKE_FAILED | YouTube rejected the rating. The video owner may have disabled likes | Check the error message for the YouTube reason |
COMMENTS_PERMISSION | Connection lacks comment permissions | Reconnect the account |
TEXT_REQUIRED | Empty comment text | Add message text |
COMMENT_CREATE_FAILED | YouTube rejected the comment. Comments may be disabled on the video | Check the error message for the YouTube reason |
VALIDATION_ERROR | Missing or invalid parameter | Check post, commentId and accountId |