---
title: "List the author and commenters of a LinkedIn post"
method: POST
path: "/v1/posts/engagers"
tags: ["People"]
---

# List the author and commenters of a LinkedIn post

`POST /v1/posts/engagers`

## Request

- Base URL: `https://api.trayo.ai`
- URL: `https://api.trayo.ai/v1/posts/engagers`
- Auth: HTTP bearer

**Required permissions:** `people:read`.

Send `post`, a LinkedIn post URL or the `postId` from POST /v1/posts/search. Returns the post author, then up to 500 commenters in comment order, each with their current title and company where we know them. A person who commented more than once appears once, with their first comment and `commentCount`. `indexed: false` means we did not find the post; it does not mean nobody commented. `reason` says why: `outside_coverage` when the post predates `coverageFrom`, the first day of the 365 days Trayo keeps, else `not_held`. `commentsChecked: false` means we hold the post but not its comments, so the author comes back without commenters. `commentsLoadedAt` is the latest Trayo load time among returned stored comments, or null if none are stored. Stored comments can be stale or incomplete, and `truncated: false` only means the stored rows fit within the read limit. LinkedIn share URLs are resolved to activity ids when the post is held.

Synchronous and read-only; nothing is added to your workspace. To keep people, send them to POST /v1/people/batch.

## Request body

- PostEngagersBodyDto
  - `post` string, required: A LinkedIn activity or share post URL, or the `postId` from a post search. Share URLs resolve only when Trayo holds the post. For a share or ugcPost URN, send the post's /posts/ URL instead; its number is not an activity ID.

## Response `200`

- PostEngagersResponseDto
  - `postId` string, required
  - `url` string, nullable, required
  - `indexed` boolean, required: Whether Trayo found the post. False is not evidence that the post has no comments.
  - `reason` 'outside_coverage' | 'not_held', nullable, required: Why `indexed` is false, or null when it is true. `outside_coverage`: the post was published before `coverageFrom`, so Trayo cannot hold it. `not_held`: the post is inside coverage, but Trayo does not hold it.
  - `coverageFrom` string, required: The earliest publication date Trayo keeps posts for, YYYY-MM-DD. It moves forward daily.
  - `commentsChecked` boolean, required: True when the engagers come from Trayo's comment store for this post. False when Trayo holds the post but not its comment thread, or does not hold the post: empty commenters then say nothing about how many people commented.
  - `commentsLoadedAt` string, nullable, required: Latest Trayo load time among the returned stored comments, ISO 8601. Null means no stored comment rows. Source data may be older than this time; even with a date, other LinkedIn comments or replies may be missing.
  - `engagers` object[], required: The author first, when we hold the post, then one row per commenter in comment order: a person who commented more than once appears once, with their first comment and `commentCount`. Nothing is saved to your workspace.
    - `role` 'author' | 'commenter', required
    - `name` string, nullable, required
    - `fullName` string, nullable, required: The person's name. The same value as `name`, under the name every person-returning route uses.
    - `linkedinUrl` string, nullable, required: The person's LinkedIn profile URL.
    - `linkedinUsername` string, nullable, required: The handle from that profile URL.
    - `photoUrl` string, nullable, required: The person's profile photo, as a directly loadable image URL. Null when Trayo holds no real photo for them — show initials then. Every route that returns a person carries this field under this name.
    - `headline` string, nullable, required: Their LinkedIn headline as shown on the post, often null for commenters.
    - `title` string, nullable, required: Their current job title, where we know it.
    - `company` object, nullable, required: Their current company, where we know it.
      - `companyId` string, nullable, required: Company dataset ID, where known. Reuse it as `companyId` in POST /v1/accounts/lookalikes. Send it as `company.companyId` to company research, stakeholder search or job-change search to name this exact company. Null when Trayo holds no company record for the employer: `name` is then the free text from the LinkedIn profile, and looking it up by name will usually miss; search for it with a find companies `query` instead.
      - `name` string, nullable, required
      - `website` string, nullable, required
      - `linkedinUrl` string, nullable, required
    - `comment` string, nullable, required: Their first comment on the post. Null for the author.
    - `commentedAt` string, nullable, required: When that comment was made, ISO 8601. Null for the author.
    - `commentCount` integer, required: How many comments this person left on the post. For the author, how many replies they left in the thread.
    - `reactionCount` integer, nullable, required: Reactions on their first comment. Null for the author.
  - `truncated` boolean, required: True when Trayo holds more than 500 comment rows and only the first were read. False does not mean every LinkedIn comment was collected.

## Other responses

- `400`: `validation_failed` (`retry: fix_input`) — The request did not pass input validation: a missing or malformed body field, a bad `limit`, a path parameter that is not a UUID, a `signalKey` that already exists or is reserved. `message` lists every failed constraint; `param` names the first offending field when one can be identified.
- `401`: Missing, malformed, or incorrect bearer token. Every way authentication can fail returns the identical body, so do not try to infer which one it was, and do not repeat the call with the same key. `unauthorized` (`retry: do_not_retry`) — Missing, malformed, or incorrect bearer token. Identical body for every cause.
- `403`: The key grant and its owner's current workspace role must both include every scope required by the operation. `insufficient_scope` (`retry: do_not_retry`) — Scope denial details distinguish missing_key_scope (use a key granting every missing scope), owner_permission_limit (the owner needs the missing workspace permissions), and invalid_key_scope (replace the key with supported scopes). Membership and undeclared-route denials remain generic.
- `429`: Every route is rate limited per workspace across REST, MCP, all keys and OAuth users, `GET /v1/whoami` included, so a balance poll competes with the work it is watching. For `rate_limited`, wait `Retry-After` seconds (also `details.retryAfterSeconds`), then send the same request once; do not retry sooner. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` describe the workspace's bucket, and they come back on successful responses too: read them and slow down BEFORE you are refused. A burst from one network can also be refused before the key is checked; that 429 carries `Retry-After` and no `RateLimit-*` headers. `rate_limited` (`retry: retry_later`) — The workspace or source network exhausted its request budget for one bucket. `details.retryAfterSeconds` (and `Retry-After` on REST) is the wait: wait that long, then retry the same request once. Do not poll or retry sooner; an early retry is refused again. If you cannot wait, stop and tell the user when to retry; do not fill the wait with other calls. `details.limit` and `details.bucket` name the exhausted budget. When present, RateLimit-* headers describe the active budget and reset.
- `500`: Something failed on our side. Nothing about the request needs changing. `internal_error` (`retry: retry_later`) — Something failed on our side. `message` never describes it — quote `requestId` when reporting. Retry with exponential backoff and GIVE UP after a few attempts: `retry_later` here does not mean the failure is known to be transient, only that nothing about your request needs changing. A request that fails this way repeatedly will not start working.
- `503`: `post_search_not_configured` (`retry: do_not_retry`) — Post search is unavailable. Retrying will not help. Contact support. `post_search_failed` (`retry: retry_later`) — The post search or engager read failed or exceeded its time budget. Nothing was saved; retry the same request shortly.

---

[API](https://skmtc.dev/trayo/apis/trayo-api.md) · [All operations](https://skmtc.dev/trayo/apis/trayo-api/llms.txt) · [OpenAPI document](https://skmtc.dev/trayo/apis/trayo-api/revisions/0af452dce6de?raw)
