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"
      }
    ]
  }
}
QueryRequiredNotes
postYesInternal post id or native video id. Native ids require accountId
accountIdFor native idsDisambiguates the target account. Also narrows internal posts with several destinations
destinationIdNoGlobally unique. Resolves on its own or narrows one destination inside an internal post
limitNo1-50, default 25
cursorNoPagination 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"
  }
}
BodyRequiredNotes
postYesInternal post id or native video id. Native ids require accountId
textYesComment text
accountIdFor native idsTarget account for native ids. Also disambiguates internal posts
destinationIdNoGlobally unique. Resolves on its own or targets one destination inside an internal post
parentCommentIdNoReply 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

CodeCauseFix
MISSING_EXTERNAL_IDDestination not published yetWait for publish
ENGAGEMENT_PERMISSIONConnection lacks the rating permissionReconnect the account
LIKE_FAILED or UNLIKE_FAILEDYouTube rejected the rating. The video owner may have disabled likesCheck the error message for the YouTube reason
COMMENTS_PERMISSIONConnection lacks comment permissionsReconnect the account
TEXT_REQUIREDEmpty comment textAdd message text
COMMENT_CREATE_FAILEDYouTube rejected the comment. Comments may be disabled on the videoCheck the error message for the YouTube reason
VALIDATION_ERRORMissing or invalid parameterCheck post, commentId and accountId

See Also