Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ curl -X POST https://api.publora.com/api/v1/create-post \
| `POST` | `/linkedin-reactions` | Add reaction to a LinkedIn post | [View](https://docs.publora.com/endpoints/linkedin-reactions) |
| `DELETE` | `/linkedin-reactions` | Remove a LinkedIn reaction | [View](https://docs.publora.com/endpoints/linkedin-reactions) |
| `POST` | `/linkedin-reshare` | Reshare an existing LinkedIn post | [View](https://docs.publora.com/endpoints/linkedin-reshare) |
| `GET` | `/linkedin-mentionables` | List mentionable LinkedIn people | [View](https://docs.publora.com/endpoints/linkedin-mentionables) |
| `POST` | `/linkedin-followers` | Get LinkedIn follower statistics | [View](https://docs.publora.com/endpoints/linkedin-followers) |
| `POST` | `/linkedin-profile-summary` | Get LinkedIn profile summary | [View](https://docs.publora.com/endpoints/linkedin-profile-summary) |

Expand Down Expand Up @@ -138,6 +139,7 @@ All plans include full API access. Pro/Premium use per-account pricing — add a
- [LinkedIn Statistics](https://docs.publora.com/endpoints/linkedin-statistics) — post and account analytics
- [LinkedIn Reactions](https://docs.publora.com/endpoints/linkedin-reactions) — add/remove reactions
- [LinkedIn Reshare](https://docs.publora.com/endpoints/linkedin-reshare) — repost an existing LinkedIn post
- [LinkedIn Mentionables](https://docs.publora.com/endpoints/linkedin-mentionables) — list the people you can @mention, with ready-to-paste tokens

### Platform Guides
- [X / Twitter](https://docs.publora.com/platforms/x-twitter) · [LinkedIn](https://docs.publora.com/platforms/linkedin) · [Instagram](https://docs.publora.com/platforms/instagram) · [Threads](https://docs.publora.com/platforms/threads) · [TikTok](https://docs.publora.com/platforms/tiktok) · [YouTube](https://docs.publora.com/platforms/youtube) · [Facebook](https://docs.publora.com/platforms/facebook) · [Bluesky](https://docs.publora.com/platforms/bluesky) · [Mastodon](https://docs.publora.com/platforms/mastodon) · [Telegram](https://docs.publora.com/platforms/telegram)
Expand Down
1 change: 1 addition & 0 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ const response = await fetch('https://api.publora.com/api/v1/platform-connection
| `/linkedin-comments` | POST | Post a comment |
| `/linkedin-comments` | DELETE | Delete a comment |
| `/linkedin-reshare` | POST | Reshare an existing post |
| `/linkedin-mentionables` | GET | List mentionable people (paid plans) |

### Webhooks

Expand Down
9 changes: 9 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ This page records externally relevant REST and MCP contract changes. Dates are d
- MCP `update_post` exposes `content` and `platforms`, and instructs clients to call `list_connections` before changing targets.
- **Migration action:** No change is required for existing callers. Integrations that previously deleted and recreated a post to fix its text or targets should switch to `update-post`. Match on the new `code` values rather than message text, send an `Idempotency-Key` with content/platform edits, and re-read the post with `GET /get-post` on a 409 instead of blind-retrying. If you relied on a repeated connection ID in `platforms` being tolerated, de-duplicate the array.

## 2026-07-17

### LinkedIn mentionable-people directory — publora.com #218

- **Affected surface:** REST and MCP.
- **Tag:** Additive.
- **Changes:** Added `GET /linkedin-mentionables` and the `linkedin_list_mentionables` MCP tool (the 15th active tool). Both list the per-user directory of native LinkedIn member ids captured automatically from engagement on connected company pages, with `q`/`limit` filtering and a ready-to-paste `mention` token per person. Paid plans only — free plans receive `403 UPGRADE_REQUIRED`.
- **Migration action:** None. New integrations that build person mentions should prefer this directory over harvesting actor URNs manually.

## 2026-07-15

### API/MCP correctness release — publora.com #198
Expand Down
122 changes: 122 additions & 0 deletions docs/endpoints/linkedin-mentionables.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# LinkedIn Mentionables

List the LinkedIn members you can @mention — a per-user directory of people whose **native member ids** Publora has captured from engagement on your connected company pages. Each entry includes a ready-to-paste `mention` token for [create-post](create-post.md) content, [comment](linkedin-comments.md) messages, or [reshare commentary](linkedin-reshare.md).

Why this exists: person mentions require LinkedIn's native member id (e.g. `Dk968RHxiO`), which cannot be derived from a linkedin.com profile URL. This directory is where Publora surfaces every native id it has seen for you. See the [LinkedIn Mentions Guide](../guides/linkedin-mentions.md) for the full id explanation and name-matching rules.

> **Paid plans only.** Free plans receive a `403 UPGRADE_REQUIRED` error (see [Errors](#errors)).

## List Mentionable People

```
GET https://api.publora.com/api/v1/linkedin-mentionables
```

### Headers

| Header | Required | Description |
|--------|----------|-------------|
| `x-publora-key` | Yes | Your API key |

### Query Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `q` | string | No | Case-insensitive substring filter on the person's name (regex characters are treated literally). Omit to list everyone. |
| `limit` | number | No | Maximum number of entries to return, `1`–`100`. Default `25`. |

Results are sorted by `lastSeenAt` descending — the most recently engaged people first.

### Response (HTTP 200)

```json
{
"success": true,
"people": [
{
"personId": "Dk968RHxiO",
"name": "Daria Bulaeva",
"profileUrl": "",
"profilePicture": "",
"source": "comment",
"lastSeenAt": "2026-07-16T10:00:00.000Z",
"mention": "@{urn:li:person:Dk968RHxiO|Daria Bulaeva}"
}
]
}
```

| Field | Type | Description |
|-------|------|-------------|
| `personId` | string | The person's **native member id** — the only id form that works in mentions. |
| `name` | string | The display name as captured from LinkedIn. |
| `profileUrl` | string | Currently always an empty string (reserved for future use). |
| `profilePicture` | string | Currently always an empty string (reserved for future use). |
| `source` | string | How the person was last captured: `comment` or `reaction`. The most recent engagement wins. |
| `lastSeenAt` | string | ISO 8601 timestamp of the most recent captured engagement. |
| `mention` | string \| null | Ready-to-paste mention token (`@{urn:li:person:ID\|Name}`) for post content or comment messages. `null` when no usable name is stored. Names containing `\|` or `}` are sanitized in the token. |

> **Note:** The `mention` token uses the person's full captured name. LinkedIn matches display names strictly — if you edit the name part, follow the [name matching rules](../guides/linkedin-mentions.md#critical-name-matching-requirements) (first name, last name, or full name; exact case; nothing extra).

### Examples

#### JavaScript (fetch)

```javascript
const params = new URLSearchParams({ q: 'daria', limit: '10' });
const response = await fetch(
`https://api.publora.com/api/v1/linkedin-mentionables?${params}`,
{ headers: { 'x-publora-key': 'YOUR_API_KEY' } }
);
const data = await response.json();

for (const person of data.people) {
if (person.mention) {
console.log(`${person.name}: ${person.mention}`);
}
}
```

#### cURL

```bash
curl "https://api.publora.com/api/v1/linkedin-mentionables?q=daria&limit=10" \
-H "x-publora-key: YOUR_API_KEY"
```

## How the Directory Fills

The directory is populated **automatically** — there is no endpoint to add people manually:

- When comments or reactions are read on posts of your connected **company pages** (via the Publora app's engagement views or the [feed-retrieval API](linkedin-feed-retrieval.md)), LinkedIn returns each engaging member's native app-scoped person id, and Publora persists it in your directory.
- No extra LinkedIn API calls are made — the ids are captured as a side effect of reads you already perform.
- Engagement on **personal-profile posts is not capturable** — LinkedIn restricts the required scope. Only company-page engagement feeds the directory.
- Placeholder/unresolved actors (entries LinkedIn returns without a resolvable member) are skipped.

There is **no way to add an arbitrary person by profile URL** — the `ACoAA…` web-profile ids visible on linkedin.com cannot be converted to native ids. See [Finding LinkedIn URNs](../guides/linkedin-mentions.md#finding-linkedin-urns) for the full explanation of native vs web-profile ids.

## MCP Tool

The same directory is available to MCP clients as the `linkedin_list_mentionables` tool, with the same `q`/`limit` parameters and the same paid-plan requirement. See the [MCP Tools Reference](../mcp/tools-reference.md#linkedin_list_mentionables).

## Errors

| Status | Error | Cause |
|--------|-------|-------|
| 401 | `"API key is required"` | No `x-publora-key` header provided |
| 401 | `"Invalid API key"` | Bad `x-publora-key` |
| 403 | `"API access is not enabled for this account"` | Account does not have API access enabled |
| 403 | `"The mentionable-people directory is available on paid plans — upgrade to access it"` | Free plan — the response also includes `"code": "UPGRADE_REQUIRED"` |

> **Note:** API keys already require a paid plan, so API callers normally hit the `403` API-access error before the `UPGRADE_REQUIRED` one; the latter mainly appears in edge cases (e.g. a plan downgrade with a still-active key).

## Related

- [LinkedIn Mentions Guide](../guides/linkedin-mentions.md) — mention syntax, native vs web-profile ids, name matching
- [LinkedIn Comments](linkedin-comments.md) — mention people in comments
- [LinkedIn Reshare](linkedin-reshare.md) — mention people in reshare commentary
- [Create Post](create-post.md) — mention people in scheduled posts

---

*[Publora](https://publora.com) is built by [Creative Content Crafts, Inc.](https://cccrafts.ai) Need AI-powered content creation for LinkedIn, Threads, and X? Try [Co.Actor](https://co.actor) — the best AI service for authentic thought leadership at scale.*
18 changes: 18 additions & 0 deletions docs/guides/linkedin-mentions.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,22 @@ const response = await fetch('https://api.publora.com/api/v1/create-post', {
});
```

## Who Can I Mention?

In practice, the people you can mention fall into two groups:

1. **Your own connected accounts** — every LinkedIn connection's native id is in its `platformId` (see [Finding LinkedIn URNs](#finding-linkedin-urns) below).
2. **People who engaged with your connected company pages** — when comments or reactions are read on a company-page post (in the Publora app or via the API), Publora automatically captures each engaging member's native id into a per-user **mentionable-people directory**. No manual step is needed, and no extra LinkedIn calls are made. Engagement on personal-profile posts is not capturable (LinkedIn restricts the required scope).

The recommended way to discover mentionable people is the [`GET /linkedin-mentionables`](../endpoints/linkedin-mentionables.md) endpoint (or the `linkedin_list_mentionables` MCP tool — both paid-plan only). It supports name search and returns a ready-to-paste `mention` token for each person:

```bash
curl "https://api.publora.com/api/v1/linkedin-mentionables?q=daria" \
-H "x-publora-key: YOUR_API_KEY"
```

Anyone outside these two groups — e.g. a person you only know from a linkedin.com profile URL — cannot be mentioned, because their native id is not obtainable (see the honest limitation under [Finding LinkedIn URNs](#finding-linkedin-urns)).

## Finding LinkedIn URNs

### Person URN
Expand All @@ -157,6 +173,7 @@ Where to get native member ids:

- **Your own connected accounts:** the [platform-connections](../endpoints/platform-connections.md) endpoint returns each LinkedIn connection's `platformId` (e.g. `linkedin-Dk968RHxiO`). Strip the `linkedin-` prefix — the remainder is that member's native id.
- **Actor ids returned by Publora's LinkedIn APIs:** endpoints such as [comments](../endpoints/linkedin-comments.md), [reactions](../endpoints/linkedin-reactions.md), and [feed retrieval](../endpoints/linkedin-feed-retrieval.md) return `urn:li:person:…` actor URNs in their responses. The id inside those URNs is the native form and can be used directly.
- **The mentionable-people directory:** [`GET /linkedin-mentionables`](../endpoints/linkedin-mentionables.md) lists every native id Publora has captured for you, searchable by name and with a ready-to-paste `mention` token per person (see [Who Can I Mention?](#who-can-i-mention)).

> **Honest limitation:** There is **no public API to look up an arbitrary member's native id.** You can reliably mention people whose ids you obtained through Publora or LinkedIn API surfaces (your connections, actors on posts/comments you retrieved) — **not** people you found via a linkedin.com profile URL. The `ACoAA…` id visible in profile URLs and page source cannot be converted to a native id.

Expand Down Expand Up @@ -228,6 +245,7 @@ After posting, check your LinkedIn post to ensure:

## Related Guides

- [LinkedIn Mentionables](../endpoints/linkedin-mentionables.md) - List the people you can mention
- [LinkedIn Comments](linkedin-comments.md) - Comment on posts
- [LinkedIn Reshare](../endpoints/linkedin-reshare.md) - Reshare posts with mention-capable commentary
- [LinkedIn Reactions](linkedin-reactions.md) - Like and react to posts
Expand Down
1 change: 1 addition & 0 deletions docs/guides/mcp-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ MCP servers don't conflict -- Claude loads all servers and merges their tools. E
| `linkedin_create_comment` | Post a comment on a LinkedIn post |
| `linkedin_delete_comment` | Delete a comment from a LinkedIn post |
| `linkedin_create_reshare` | Reshare a LinkedIn post, optionally with commentary and visibility settings |
| `linkedin_list_mentionables` | List mentionable LinkedIn people with ready-to-paste mention tokens (paid plans) |

> LinkedIn **analytics/followers/profile-summary** and **workspace** management are **not** MCP tools — use the [REST OpenAPI reference](https://docs.publora.com/openapi.yaml). LinkedIn feed-retrieval tools (`linkedin_posts`, `linkedin_post_comments`, `linkedin_post_reactions`) are implemented but disabled pending LinkedIn's `r_member_social` approval.

Expand Down
4 changes: 2 additions & 2 deletions docs/mcp/client-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ Start a new conversation and ask:
"What MCP tools do you have available?"
```

Claude should list the 14 active Publora tools, including `linkedin_create_reshare` (3 additional LinkedIn feed-retrieval tools — `linkedin_posts`, `linkedin_post_comments`, `linkedin_post_reactions` — are pending LinkedIn approval).
Claude should list the 15 active Publora tools, including `linkedin_create_reshare` and `linkedin_list_mentionables` (3 additional LinkedIn feed-retrieval tools — `linkedin_posts`, `linkedin_post_comments`, `linkedin_post_reactions` — are pending LinkedIn approval).

---

Expand Down Expand Up @@ -555,6 +555,6 @@ Some clients support environment variable interpolation:

## Next Steps

- [Tools Reference](./tools-reference.md) — All 14 active tools with parameters
- [Tools Reference](./tools-reference.md) — All 15 active tools with parameters
- [Examples](./examples.md) — Real-world conversation examples
- [Troubleshooting](./troubleshooting.md) — Common issues and solutions
65 changes: 64 additions & 1 deletion docs/mcp/tools-reference.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MCP Tools Reference

Complete reference for the 14 active Publora MCP tools with parameters, examples, and code snippets. Media can be attached two ways: the fast path (pass public **https** URLs via `mediaUrls` on `create_post`/`update_post`) or the upload dance (`get_upload_url` → HTTP PUT → `complete_media`). Three additional LinkedIn feed-retrieval tools (`linkedin_posts`, `linkedin_post_comments`, `linkedin_post_reactions`) are pending LinkedIn approval of the `r_member_social` permission — see [LinkedIn Feed Retrieval Tools](#linkedin-feed-retrieval-tools-coming-soon-requires-linkedin-approval) below. LinkedIn analytics and workspace-management features are available via the [REST OpenAPI reference](https://docs.publora.com/openapi.yaml), not MCP.
Complete reference for the 15 active Publora MCP tools with parameters, examples, and code snippets. Media can be attached two ways: the fast path (pass public **https** URLs via `mediaUrls` on `create_post`/`update_post`) or the upload dance (`get_upload_url` → HTTP PUT → `complete_media`). Three additional LinkedIn feed-retrieval tools (`linkedin_posts`, `linkedin_post_comments`, `linkedin_post_reactions`) are pending LinkedIn approval of the `r_member_social` permission — see [LinkedIn Feed Retrieval Tools](#linkedin-feed-retrieval-tools-coming-soon-requires-linkedin-approval) below. LinkedIn analytics and workspace-management features are available via the [REST OpenAPI reference](https://docs.publora.com/openapi.yaml), not MCP.

> **Note:** Most tools return the backend API object. `list_connections` deliberately wraps the backend list as `{ "connections": [...] }` for MCP structured content. `list_posts` also supports a `concise` mode that truncates content previews and adds response-format metadata.

Expand Down Expand Up @@ -791,6 +791,69 @@ Reshare an existing LinkedIn post to your feed, optionally with commentary.

---

## LinkedIn Mentionables Tool

### linkedin_list_mentionables

List the LinkedIn members you can @mention — Publora's per-user directory of native member ids captured from engagement (comments and reactions) on your connected company pages. Each entry includes a ready-to-paste `mention` token for post content or comment messages. **Paid plans only** — free plans receive a `403 UPGRADE_REQUIRED` error. Backed by [`GET /linkedin-mentionables`](../endpoints/linkedin-mentionables.md); see the [LinkedIn Mentions Guide](../guides/linkedin-mentions.md) for why native ids are required.

**Parameters:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `q` | string | No | Case-insensitive substring filter on the person's name |
| `limit` | number | No | Maximum entries to return, 1–100 (default: 25) |

Results are sorted by `lastSeenAt` descending (most recently engaged first).

**Example prompts:**

```text
"Who can I mention on LinkedIn?"
"Find the mention token for Daria"
"List people who recently engaged with my company page"
```

**Python example:**

```python
async def list_mentionables():
headers = {"Authorization": "Bearer sk_YOUR_API_KEY"}

async with streamablehttp_client("https://mcp.publora.com", headers=headers) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()

result = await session.call_tool("linkedin_list_mentionables", {
"q": "daria",
"limit": 10
})
print(result.content[0].text)
```

**Response example:**

```json
{
"success": true,
"people": [
{
"personId": "Dk968RHxiO",
"name": "Daria Bulaeva",
"profileUrl": "",
"profilePicture": "",
"source": "comment",
"lastSeenAt": "2026-07-16T10:00:00.000Z",
"mention": "@{urn:li:person:Dk968RHxiO|Daria Bulaeva}"
}
]
}
```

`source` is `comment` or `reaction` (the most recent engagement wins). `mention` is `null` when no usable name is stored. The directory fills automatically when company-page engagement is read — there is no way to add a person manually or by profile URL.

---

## LinkedIn Feed Retrieval Tools (Coming Soon — Requires LinkedIn Approval)

> **Status: DISABLED** - These tools are not yet available. They require the `r_member_social` permission, which is **RESTRICTED** and requires LinkedIn approval. The implementation is ready and will be enabled once LinkedIn approves the permission for Publora.
Expand Down
Loading