API Reference

Comments

Read comments received across every connected platform, already classified by sentiment and intent — then reply publicly as one of your accounts.

List comments

GET/api/v1/comments

Requires read. Newest first.

Query parameters

platformstringoptional
Restrict to one platform identifier.
sentimentstringoptional
positive, negative or neutral.
unrepliedstringoptional
Set to 1 to return only comments with no reply yet.
limitnumberoptional
Defaults to 20, clamped to 50.
curl
curl "https://app.echoia.io/api/v1/comments?sentiment=negative&unreplied=1&limit=10" \
  -H "Authorization: Bearer $ECHOIA_API_KEY"
200
{
  "comments": [
    {
      "platformCommentId": "17912345678901234",
      "platform": "instagram",
      "author": "marie.creates",
      "text": "Is the blue one back in stock?",
      "sentiment": "neutral",
      "tags": ["question"],
      "replied": false,
      "postTitle": "New collection drop",
      "url": "https://www.instagram.com/p/C…",
      "createdAt": "2026-09-13T08:41:19.000Z"
    }
  ]
}

Comment object

platformCommentIdstringoptional
The platform's own id. This is what you pass to /comments/reply — not an Echoia id.
platformstringoptional
Where the comment was left.
authorstringoptional
The commenter's display name or handle.
textstringoptional
The comment body.
sentimentstringoptional
How the commenter sounds — not whether the comment is a problem for you. A blunt question often reads as negative.
tagsstring[]optional
Intent labels such as question, complaint, praise or spam. May be empty.
repliedbooleanoptional
Whether this workspace has already answered it.
postTitlestring | nulloptional
The post the comment sits under, for context.
urlstring | nulloptional
Permalink to the comment on the platform, when it exposes one.

Sorting by intent is the point

Filtering by tags lets you answer fifteen questions in one frame of mind instead of switching mode on every comment. That is where the time goes — not in the typing.

Reply to a comment

POST/api/v1/comments/reply

Requires engage. This posts publicly on the platform, immediately.

Parameters

platformstringrequired
The comment's platform.
commentIdstringrequired
The platformCommentId from the list above.
messagestringrequired
The reply text. Up to 2,200 characters.
accountIdstringoptional
Which connected account speaks, from /accounts. Defaults to this workspace's account on that platform.
curl
curl -X POST https://app.echoia.io/api/v1/comments/reply \
  -H "Authorization: Bearer $ECHOIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "instagram",
    "commentId": "17912345678901234",
    "message": "It is — restocked this morning."
  }'
200
{
  "success": true,
  "repliedAs": "yourbrand",
  "result": { "id": "17998877665544332" }
}

Only comments this workspace received

commentId must belong to a comment Echoia has stored for this workspace. A raw platform id you found elsewhere is rejected — engage means “answer your own comments”, not “post anywhere the account can reach”.

Limits worth knowing

  • 20 replies per minute per token, tighter than the general limit.
  • Replies on X draw on the X posts & replies pool and are refunded if the platform rejects them.
  • Replying from an account on a different platform than the comment is an error, not a silent fallback.

A triage loop

node
// Unanswered questions, oldest first — the ones where a reply changes something.
const { comments } = await echoia("/comments?unreplied=1&limit=50");
const questions = comments
  .filter((c) => c.tags.includes("question"))
  .reverse();

for (const c of questions) {
  const message = await draftAnswer(c);   // your own logic, or a human
  if (!message) continue;                 // skip rather than guess

  await echoia("/comments/reply", {
    method: "POST",
    body: JSON.stringify({
      platform: c.platform,
      commentId: c.platformCommentId,
      message,
    }),
  });
}
Was this page helpful?