> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oneshotagent.com/llms.txt
> Use this file to discover all available pages before exploring further.

# LinkedIn Messaging

> Manage a human's LinkedIn conversations through their own connected account: connect, sync history, read, reply, view profiles, react.

<img src="https://mintcdn.com/freebutter/jPFJoUgC4P5j3KGx/images/objects/linkedin.webp?fit=max&auto=format&n=jPFJoUgC4P5j3KGx&q=85&s=c7181baefb35f354148f288a111dc0ee" alt="" className="docs-object" noZoom width="1200" height="600" data-path="images/objects/linkedin.webp" />

These tools let an agent run a human's LinkedIn conversations through that human's own account. An agent cannot have a LinkedIn account, so it works through a human's. The human connects *their own* account to an agent and grants it specific actions. The agent can then read the inbox, keep it in sync, and send authorized replies through it. The agent wallet is still the caller and payer. The connected account supplies the identity and the delegated authority.

Unlike every other tool on this site, **wallet ownership and payment never authorize acting through a human's account.** The human grants actions when they connect. OneShot re-checks that grant, under a row lock, immediately before every write. The human (or the agent, on their behalf) can revoke it at any time.

## How it works

Five steps take an account from login link to paid write.

1. **Connect.** Call `POST /v1/tools/linkedin/connect` with the actions you want. You get a hosted LinkedIn login link. Show it to the human, who signs in (including any 2FA) on the hosted page. The link expires in 30 minutes and must open in a top-level window, never an iframe.
2. **Bind.** When the login completes, OneShot verifies the account server-side before binding it to your agent. A browser redirect alone never binds ownership. Poll `GET /v1/tools/linkedin/connect/{intent_id}` until `completed`.
3. **Sync.** `POST /v1/tools/linkedin/sync` buys one bounded run of history ingestion. Runs resume from a durable cursor, so a 10,000-message inbox takes a handful of runs, not one long task.
4. **Read.** Conversations and messages are free, keyset-paginated reads. Every response carries `coverage` and `sync_state`, so an unsynced inbox is never mistaken for an empty one.
5. **Act.** `reply`, `profile-view` and `react` are paid, idempotent writes with per-account daily caps and randomized pacing.

Incremental updates arrive through the provider's webhooks and a scheduled reconciliation sweep. You do not need to poll `sync`.

## Grants

Each action the human grants unlocks a fixed set of calls.

| Action | Grants |
| - | - |
| `read` | sync history, list conversations and messages |
| `reply` | send a message in an existing conversation |
| `view_profile` | view a profile (optionally notifying its owner) |
| `react` | react to a post |
| `invite` | Send and withdraw connection invitations |
| `comment` | reserved: accepted by the grant, no route yet |

Reconnect keeps the same account and history. After fresh hosted authentication it can keep, narrow, or widen the grant. To add an action, reconnect the existing account with the complete action list you want. Adding actions preserves queued writes. Removing any action invalidates older queued writes. Revoke ends the grant, cancels every queued write, fails its job (refunded by the failed-job sweep), and deletes the upstream connection so it stops billing.

## Coverage is not completeness

A short inbox can still be mid-sync. The upstream provider back-fills history in the background, and its API cursor can run out before the back-fill ends. In the live test behind this feature, the cursor ran out at 174 messages and the same account had 393 minutes later. OneShot tracks the two separately and reports `coverage.complete: true` only when **the provider finished its back-fill AND a full enumeration started after that AND no paused cursor remains**. Treat `sync_state` as the source of truth: `never_synced`, `syncing`, `partial`, `complete`, or `reconnect_required`.

## Economics and limitations

<Warning>
  Read this before building on the LinkedIn tools. These constraints are structural and cannot be tuned away.
</Warning>

* **Per-account upstream cost.** The connection provider bills OneShot per connected account per month (about \$5.50 at low volume), used or not. Per-action prices are provisional until there is measured utilization. An idle account is revoked automatically after 30 days without an owner-authorized call (`idle_revoke_at` is on every account read, and a warning arrives at 23 days).
* **Unofficial LinkedIn access.** The provider integrates with LinkedIn without an official partner API. LinkedIn's terms restrict automation, and the connected human carries the risk of account restriction. Keep volume at human levels. OneShot enforces per-account daily caps (replies 50, profile views 100, reactions 50, all tunable per environment) with randomized spacing, shared across every caller of that account.
* **No recall.** A message LinkedIn accepted cannot be taken back. Every write requires an `Idempotency-Key`. The SDKs generate one if you omit it.
* **Ambiguous sends.** If the upstream times out after a reply may have gone out, OneShot parks the request as `ambiguous` and reconciles it against the chat for up to 24 hours. With no evidence of delivery it re-attempts at most once. It never auto-refunds an unconfirmed send. Profile views and reactions are idempotent upstream and are retried.
* **Charge semantics.** Sync: an empty run is charged (the enumeration ran). A run rejected before payment (ownership, grant, status, run already active) is free. A run that could not be dispatched is not settled. Internal reconciliation runs are never charged. Writes: every rejection (cap, grant, status, content safety, budget) happens before settlement.
* **Not in v1.** Comments, attachment downloads or uploads, InMail, messages to people who are not connections, marking read, removing reactions, edit history (only the latest text and an `edited` flag are kept).
* **Isolation from the browser tool.** The connected LinkedIn session lives at the provider, not in a browser profile. A read-only grant cannot be bypassed through `POST /v1/tools/browser`, which has no access to that session.

## Where things live

| | |
| - | - |
| Connect / status / reconnect / revoke | [Connect](/api-reference/linkedin/connect), [Accounts](/api-reference/linkedin/accounts) |
| History sync + coverage | [Sync](/api-reference/linkedin/sync) |
| Reads | [Conversations](/api-reference/linkedin/conversations), [Messages](/api-reference/linkedin/messages) |
| Writes | [Reply](/api-reference/linkedin/reply), [Message a connection](/api-reference/linkedin/message), [Engagement](/api-reference/linkedin/engagement), [Invite](/api-reference/linkedin/invite), [Withdraw](/api-reference/linkedin/withdraw), [Invitation status](/api-reference/linkedin/invitations) |
| Prices | [Pricing](/pricing) |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.