---
title: "Set the sender's approval setting from the extension"
method: POST
path: "/linkedin/agent/state/"
tags: ["linkedin"]
---

# Set the sender's approval setting from the extension

`POST /linkedin/agent/state/`

## Request

- Base URL: `https://api.getoneprofile.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.getoneprofile.ai/linkedin/agent/state/`
- Auth: API key in header `X-API-Key`

Writes the sender's LinkedIn approval setting (`run_mode`), the same setting the sender's LinkedIn page writes, so the two surfaces have one source of truth rather than two that drift. An empty body reads the state without changing it. With a lease nonce, the answer also says whether this browser holds the lease, and which browser does when it does not.

## Request body

- AgentSetStateSchema
  - `lease_nonce` string, nullable: This browser's lease identity. When given, lease_granted in the answer says whether this browser holds the lease; when absent it is always true.
  - `run_mode` union: The sender's LinkedIn approval setting, as the side panel sets it: the same setting the sender's LinkedIn page sets. Absent leaves it untouched.
    - 'manual' | 'auto': Whether a person approves a sender's LinkedIn steps before they run, or they run on their own. The sender's own LinkedIn setting, kept on the sender beside their email modes so the approval queue reads one home for both. The absence of one (``SenderProfileDTO.linkedin_approval_mode`` is None) reads as MANUAL: nothing runs on somebody's LinkedIn unattended until they have said so. The approval queue still tells "never set" apart from "chose manual", which is the level its settings surfaces name.
    - unknown

## Response `200`

Successful Response

- AgentStateSchema: The authoritative run state, returned on every heartbeat. ``account_mismatch`` is the hard stop: the browser is signed in as somebody other than the account we are bound to, and acting would send this customer's outreach from the wrong identity. ``run_mode`` is the sender's LinkedIn approval setting in force (manual for a sender who never set one): the side panel shows it and can change it. Approval happens on Oneprofile's Tasks page before a step is queued, so a step handed to the browser runs whichever it says. ``queued_count`` counts steps waiting for a browser, not one running in one.
  - `account_mismatch` boolean, required
  - `approvals_waiting` integer: How many of this sender's LinkedIn steps wait for a person on Oneprofile's Tasks page, less those a paused sequence or paused contact holds; the side panel offers Approve tasks while any do.
  - `attempts_enabled` boolean: Whether a build that reports attempts (attempts:v1) reports a run cut off without an error from LinkedIn to /actions/{id}/attempts/ and runs the step again only on the answer. The same switch as resume_enabled.
  - `checkpoint` boolean, required
  - `config_version` integer, required: The version of the selector and pacing config this server serves. A browser running any other version, older or newer, fetches the config again.
  - `lease_granted` boolean, required
  - `lease_holder_label` string, nullable: When lease_granted is false, what the browser holding the lease calls itself (for example 'Chrome on macOS'); null when that is not known.
  - `poll_after_seconds` integer, required: How long to wait before the next check-in: the account's own time between steps, never more, and never so long the browser stops reading as active. At most 15 seconds while work is about to run (the time between steps is running out, a step may start now, or one is running with more behind it), so a missed wake-up costs seconds rather than a whole interval.
  - `queued_count` integer, required
  - `resume_enabled` boolean: Whether a build that resumes steps (resume:v1) may resume one that stopped without an error from LinkedIn. Off, a stopped step fails for a person to retry, as it did before; the grant and the saved results stay on either way.
  - `run_mode` 'manual' | 'auto', required: Whether a person approves a sender's LinkedIn steps before they run, or they run on their own. The sender's own LinkedIn setting, kept on the sender beside their email modes so the approval queue reads one home for both. The absence of one (``SenderProfileDTO.linkedin_approval_mode`` is None) reads as MANUAL: nothing runs on somebody's LinkedIn unattended until they have said so. The approval queue still tells "never set" apart from "chose manual", which is the level its settings surfaces name.
  - `running_claim` 'renewed' | 'lost', nullable: For a check-in that named a running step: renewed while that claim is still this browser's, lost once it is not (settled, rejected, lapsed while the browser was gone, or taken back from a step whose running_wait outlasted every ceiling), and the browser then stops the step before it changes anything more. Null for a check-in that named none.
  - `unpaced_waiting` boolean: A step that waits for no gap between steps (one the Oneprofile team fired to test the sender) could be handed out now: ask for it alone (unmetered_only) without waiting out this browser's own gap.
  - `usage` LinkedInKindUsageReadSchema[]
    - `daily_limit` integer, required
    - `kind` 'profile_view' | 'connection_request' | 'send_message' | 'inmail' | 'withdraw_connection_request' | 'follow_contact' | 'like_latest_post' | 'check_sent_invitations' | 'check_connections' | 'check_inbox' | 'read_conversation', required: What the browser agent is being asked to do. The four ``CHECK_*``/``READ_*`` kinds are housekeeping: they read our own outbound invitations, our own newest connections and our own conversations to detect what the contact did, so they are free and deliberately excluded from the priced kinds below. ``CHECK_CONNECTIONS`` reads the first batch of the sender's connections list, newest first: a person found there has accepted, whenever the invitation went out. It is how an acceptance is noticed at all once an invitation has fallen out of the ten rows the sent list shows a background tab. ``CHECK_INBOX`` scans the conversation list for threads with new inbound activity; ``READ_CONVERSATION`` opens one of them and reads it in full. The split keeps LinkedIn activity proportional to real replies: the cheap scan runs on every sweep, the expensive read only where the scan saw a change. ``LIKE_LATEST_POST`` targets the contact's most recent post at the moment the browser runs it. A contact with no posts is not a failure: the driver reports the action ``SKIPPED``, and the sequence advances either way. Every profile-targeted outcome carries the facts the browser read off the profile, including the three-state Premium "Open Profile" reading; see the section comment above the outcome models.
    - `remaining_today` integer, required: What may still run today: the daily limit's headroom, held to the weekly limit's when that is nearer.
    - `used_this_week` integer: Spent over today and the six days before it.
    - `used_today` integer, required
    - `weekly_limit` integer, nullable: The ceiling over any seven days; null when there is none.
  - `usage_resets_at` string, date-time, nullable: When today's counts in usage start over: 00:00 in the sender's timezone. Older servers leave it out, and a client then reads the next UTC midnight.
  - `wait` LinkedInWaitReadSchema: What the account's next step is waiting on, and until when.
    - `next_at` string, date-time, nullable, required: When the next step may start: the end of the time between steps for pacing, the reset for daily_cap and weekly_cap, when the hours open for outside_window, and null otherwise.
    - `reason` 'not_connected' | 'checkpoint' | 'lease_held_elsewhere' | 'in_flight' | 'outside_window' | 'idle' | 'daily_cap' | 'weekly_cap' | 'kind_disabled' | 'checking_replies' | 'pacing' | 'ready' | 'insufficient_credits', required: Why an account's next step has not started, as one reason, highest first. ``OUTSIDE_WINDOW`` is work that could run but for its run window, shut now in the sender's timezone (2026-10-01); ``IDLE`` is nothing waiting in line. ``DAILY_CAP``, ``WEEKLY_CAP`` and ``KIND_DISABLED`` are named only when every kind that could be handed out is held by one. ``CHECKING_REPLIES`` is a message waiting for the inbox to be read first (2026-10-05): one is never sent on an inbox last read hours ago, or past a reply nobody has read yet. ``PACING`` is the time between steps, ``READY`` a step that may start now. ``INSUFFICIENT_CREDITS`` is a workspace with no credit left: the governor's own reading never names it (it reserves nothing), and the dashboard's account read puts it over the reasons a balance outranks (2026-10-06), as the side panel does off a refused claim.
    - `resets_at` string, date-time, nullable, required: The moment a daily or weekly limit next frees a slot, midnight in the sender's timezone; null for every other reason. A moment, never 'today' or 'tomorrow'.

## Other responses

- `401`: The agent token is invalid, revoked, or expired.
- `403`: Forbidden
- `422`: Invalid request made to the API.
- `500`: Internal server error.
- `502`: Bad gateway error.
- `503`: Service unavailable.

---

[API](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile.md) · [All operations](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile/llms.txt) · [OpenAPI document](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile/revisions/4a6bd71e3f02?raw)
