---
title: "Read the brief, record sender health, heartbeat, schedules, runs and observed replies, claim, start or report a LinkedIn action"
method: POST
path: "/linkedin/actions"
---

# Read the brief, record sender health, heartbeat, schedules, runs and observed replies, claim, start or report a LinkedIn action

`POST /linkedin/actions`

## Request

- Base URL: `https://www.sagaris.ai/api/v1`
- URL: `https://www.sagaris.ai/api/v1/linkedin/actions`
- Auth: HTTP bearer

Health observations record genuine sender measurements, never contact touches or send permission. Use null for unknown metrics; never invent healthy values. Counts must describe the same completed invitation cohort. Evidence expires after 24 hours; replaying an observation ID does not refresh it. Execute only after a successful start response, only once, using the exact copy it returns. Stop for login or CAPTCHA. Report outcome_unknown after an ambiguous browser result; never blindly retry. The server owns sequence advancement. Engine actions (source engine, planned by the parallel LinkedIn engine for the account named by setup) are claimable only when that account's automation mode and windows allow; a 409 names the reason and the next window. A persistent agent (a ChatGPT Dot or any always-on client) starts every run with command brief: it returns the account, its automation windows, today's remaining limits, how many actions are claimable now, whether a person asked for a reconnect, the event names it can subscribe to, and the current instructions with a version. It reports its recurring schedules with schedule_report (RFC 5545 RRULE lines with a time zone, plus how often it checks in), each run with run_report (idempotent on runId), and replies, received messages and accepted invitations it observed with sync (idempotent on externalKey; a reply is logged like a rep-logged reply and stops the engine's open work for that contact; an unmatched profile is recorded without its excerpt). When a person asks for a reconnect, acknowledge with reconnect_ack, then ask the owner to sign in through your private sign-in form or by taking over your browser, never by typing or receiving their password, and send a ready heartbeat; that heartbeat resolves the request. None of brief, schedule_report, run_report, sync or reconnect_ack sends, approves, creates, edits or completes an action; a result with its lease token is the only way an action completes.

## Request body

- object
  - `command` 'setup' | 'health_observation' | 'connection_accepted' | 'heartbeat' | 'brief' | 'schedule_report' | 'run_report' | 'sync' | 'reconnect_ack' | 'claim' | 'start' | 'result', required
  - `observation` object
    - `observationId` string, uuid, required
    - `profileUrl` string, required
    - `observedAt` string, date-time, required
    - `windowStartedAt` string, date-time, required
    - `windowEndedAt` string, date-time, required
    - `invitationsSent` integer, nullable, required
    - `invitationsAccepted` integer, nullable, required
    - `invitationsWithdrawn` integer, nullable, required
    - `warnings` integer, nullable, required
    - `accountAgeDays` integer, nullable, required
    - `evidence` string, required
  - `session` 'ready' | 'login_required' | 'captcha' | 'restricted'
  - `profileUrl` string: Observed signed-in sender profile URL, required for heartbeat
  - `actionId` string, uuid
  - `leaseToken` string, uuid
  - `outcome` 'connection_sent' | 'message_sent' | 'already_connected' | 'profile_unavailable' | 'login_required' | 'captcha' | 'rate_limited' | 'not_sent' | 'outcome_unknown'
  - `evidence` string
  - `schedules` object[]: schedule_report: the recurring schedules the agent configured for itself.
    - `label` string, required
    - `rrule` string, required: RFC 5545 recurrence rule, with or without the RRULE: prefix
    - `timezone` string, required: IANA time zone the rule is read in
    - `nextRunAt` string, date-time
  - `checkInMinutes` integer: schedule_report: how often the agent checks in inside a window
  - `runId` string, uuid: run_report: the agent's id for this run; a repeat returns the stored report
  - `startedAt` string, date-time
  - `finishedAt` string, date-time
  - `status` 'ok' | 'partial' | 'failed': run_report: how the run ended
  - `claimed` integer
  - `completed` integer
  - `failed` integer
  - `synced` integer
  - `notes` string: run_report: a short note; redacted before it is stored
  - `observations` object[]: sync: replies, received messages and accepted invitations observed in the LinkedIn session.
    - `kind` 'reply' | 'connection_accepted' | 'message_received', required
    - `profileUrl` string, required: The other person's LinkedIn profile URL
    - `observedAt` string, date-time, required
    - `externalKey` string, required: The agent's stable key for this observation; a repeat is answered already_recorded
    - `excerpt` string: A short excerpt of the reply; redacted before it is stored, and never stored for an unmatched profile

## Response `200`

Recorded transition, brief, report or per-observation sync result

## Other responses

- `401`: Missing, malformed, invalid, revoked, or expired API key.
- `403`: The key does not hold the required scope for this operation.
- `409`: Held, stale claim, quota, unbound agent, or conflicting result
- `503`: The database / API-keys table is not provisioned.

---

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