← All posts
Tutorial

Reply to TikTok Comments via API: Verify the Post and Top-Level Target

To reply to a TikTok comment through UnifyPort, select a verified post owned by the connected account, select a confirmed top-level comment, then call POST /v1/accounts/{account_id}/posts/comments/reply with post_id, comment_id, and text. This is not a DM send or an arbitrary-video comment tool. An accepted result confirms acceptance—not public display, delivery, or a guaranteed webhook.

Key takeaways

  • Keep account, post, and comment identifiers together, and preserve provider IDs as strings.
  • Comment listing covers top-level comments on your own posts, not complete nested-reply history.
  • Missing parent_comment_id alone does not establish that a target is top-level.
  • Separate retryable reads from uncertain writes: a reply timeout or unconfirmed receipt must not trigger an automatic resend.

Choose the comment surface, not the inbox surface

TikTok’s official Query Video Comments reference describes a Research API read: video_id selects comments and comment_id selects replies, with the research.data.basic scope. That is a different contract from posting a response through a connected account. Do not copy its numeric IDs, pagination parameters, or authorization headers into UnifyPort requests.

Likewise, the TikTok Business Messaging vs QR inbox comparison answers a private-messaging architecture question. A public comment is not a conversation destination for the generic message-send endpoint.

This tutorial uses UnifyPort’s unofficial interface for the logged-in TikTok account’s own posts. If the account is not connected yet, complete the TikTok QR authorization setup first. Confirm authorization and runtime_status: running before trying account operations. Keep the workspace API key on your backend and enforce operator access to the selected account.

Read the post and comments before enabling Reply

The four documented operations form a narrow workflow:

JobMethod and API pathImportant boundary
Discover owned postsGET /v1/accounts/{account_id}/postsOnly the logged-in account’s posts
Inspect one postPOST /v1/accounts/{account_id}/posts/infoSend post_id in JSON; ownership must be verified
List commentsPOST /v1/accounts/{account_id}/posts/comments/listTop-level comments only; pagination goes in JSON
ReplyPOST /v1/accounts/{account_id}/posts/comments/replyConfirmed top-level target on an owned post

Start with List account posts, then use Get account post for the selected post. Do not accept a pasted video URL as proof of ownership.

For List top-level post comments, send the selected post_id with limit. The default is 20 and the supported range is 1–50. Omit cursor on the first page; an empty string is invalid. When data.has_more is true, pass data.next_cursor unchanged as the next request’s cursor. The cursor is omitted on the last page.

Keep each pagination chain attached to its account and post. Use the returned IDs, not array positions or display names, for selection. A short page is not a reason to ignore has_more, and a failed read is not an empty comment list.

The reference returns optional content and author fields only when available. Treat an omitted text as unknown, not an empty comment. Do not replace an omitted created_at with the time your worker observed it. Preserve post_id as a positive decimal integer string without leading zeros, and never convert post or comment IDs to JavaScript numbers.

Submit one reviewed reply

Before dispatch, show the selected post, comment, account identity, and draft to the operator. A recommended application record binds these targets to the approved text so refreshing the list cannot redirect the write.

The following illustrative helper makes one call to the Reply to a top-level comment endpoint. Supply real identifiers from the verified selection and a server-side API key. It is not a complete approval system; it does not verify ownership locally or add automatic retries.

async function replyToTikTokComment({
  apiKey, accountId, postId, commentId, text
}) {
  if (typeof postId !== 'string' || !/^[1-9][0-9]*$/.test(postId)) {
    throw new Error('Use the returned post ID string');
  }
  if (typeof commentId !== 'string' || !commentId.trim() ||
      typeof text !== 'string' || !text.trim()) {
    throw new Error('Select a comment and provide reply text');
  }
  if (typeof accountId !== 'string' || !accountId.trim()) {
    throw new Error('Select the connected account');
  }
  const response = await fetch(
    `https://api.unifyport.ai/v1/accounts/${encodeURIComponent(accountId)}/posts/comments/reply`,
    {
      method: 'POST',
      headers: {
        'X-Api-Key': apiKey,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        post_id: postId, comment_id: commentId, text
      })
    }
  );
  const result = await response.json();
  return { httpStatus: response.status, result };
}

The whitespace checks reject blank input without changing the approved text. If the network call or response parsing fails after dispatch, retain an unknown outcome. Do not wrap the helper in a generic POST retry loop.

Interpret results without manufacturing certainty

The endpoint reference distinguishes these outcomes:

ResultMeaningRecommended application action
200, data.status: acceptedRequest acceptedSave the result; do not label it “publicly visible”
Optional data.commentReliable receipt available for the created commentPreserve it if present; do not require it for acceptance
403 post_inaccessiblePost inaccessible; cause is not identifiedStop and investigate access, without marking the post deleted
404 post_not_foundVerified post absenceRefresh the selection
404 comment_not_foundTarget not found after verificationReselect; this does not mean all nested replies were searched
501 unsupported_by_providerUnsupported provider or verified nested reply targetStop this operation; do not switch silently to a DM
502 reply_post_comment_failed after an unconfirmed write receiptWrite outcome unknownHold for review; do not resend automatically

Incomplete verification stops the write. Read-side incomplete verification can be retried, but that does not make an uncertain reply safe to repeat. A later read that does not show the reply is not proof it was never created, especially when the list operation only covers top-level comments.

Serialize your application’s writes for the same target, suppress double-clicks, and retain request_id with the HTTP result. These are local safeguards, not an API idempotency guarantee. Avoid putting customer comment text or API keys into general-purpose logs.

Add notifications only as a separate intake layer

The standard event catalogue documents post.comment.created. Subscription alone does not enable comment polling: polling defaults off, and provider_data.enable_comment: true requires start or reconnect; online changes require reconnect. Confirm environment availability and receiver readiness first. Successful start does not itself prove the setting was applied, and disabling polling does not retract queued events.

Treat notifications as best-effort signals that may be delayed, duplicated, reordered, or omitted—not as complete history or guaranteed reply receipts. Verify signatures under the webhook delivery contract and deduplicate by event ID. A notification without parent_comment_id still needs target verification before a reply. Do not infer a replyable target from a missing field.

FAQ

Can I reply to comments on any TikTok video?

Not through this workflow. The documented operations verify ownership by the logged-in account and restrict replies to confirmed top-level comments.

Does accepted mean the reply is visible?

No. Acceptance is not a display or delivery guarantee. A reliable comment receipt is optional, and a webhook is not guaranteed.

Can I paginate every nested reply?

No. The UnifyPort comment-list operation documents top-level comments, not complete reply pagination. TikTok’s Research API is a separate read contract, not an interchangeable endpoint.

What should I test before enabling the feature?

Test an owned post, an inaccessible post, multiple pages, string-ID preservation, a nested target, repeated clicks, and an ambiguous network result. These are proposed acceptance checks, not reported test results.

Next step and sources

Implement read-only selection with List top-level post comments before enabling reply submission.

References checked on 2026-10-26:

UnifyPort API

Turn messaging integration into a stable product pipeline.

Start by sending through one API, then bring every inbound message back into your business system with standard events.