Skip to main content
POST
Sync History
Imports a connected account’s message history, one bounded run at a time, and returns a request_id to poll. Paid: one flat price per run (see Pricing). Requires the read grant. Runs are resumable. A run enumerates messages newest-first, up to max_pages pages of 250, and commits each page together with its next cursor in one transaction. If the run hits its page bound, it is paused with a durable cursor. The next call with mode: "continue" resumes right after the last committed page. A crash between pages loses nothing, and replaying a page inserts nothing twice (messages are unique per account + provider id). The call is async. GET /v1/requests/{request_id} shows live progress (pages, messages seen/inserted) while the run executes.

Request

string
required
Connected LinkedIn account id.
string
default:"continue"
continue resumes the newest paused cursor (or enumerates from the top when nothing is paused). restart discards paused cursors and starts from the top. history also re-requests the provider’s own history back-fill (see below).
number
default:"10"
Pages of 250 messages this run may fetch, 1–10 (the flat price covers up to 10). A 10,000-message inbox is four runs.

Before payment

A rejected sync is never charged, because these checks run on the unpaid request. The account must be yours (404 account_not_found), connected (409 reconnect_required), have the read grant (403 grant_denied), and have no run already queued or running (409 sync_in_progress with run_id).

Response

The job result (from GET /v1/requests/{request_id}) reports outcome ∈ exhausted (cursor ran out) · bounded (page limit hit, needs_continuation: true) · partial (data landed, then a hard error, cursor preserved), plus counters: pages, requests, messages_seen, messages_inserted, messages_updated, conversations_inserted, earliest_seen_at, latest_seen_at, upstream_ms, duration_ms, and provider_history.

Coverage

GET /v1/tools/linkedin/accounts/{id}/sync (free) returns:
Why two notions. Cursor exhaustion does not mean the history is complete. The connection provider back-fills an account’s history in the background after login. Its listing cursor can run out while the back-fill is still running. The live test behind this feature saw 174 messages at cursor exhaustion and 393 on the same account a few minutes later. OneShot therefore requests the provider back-fill on the first run, polls it on later runs, and reports complete only when:
  1. provider_history is done (the provider finished, or its SYNC_SUCCESS webhook arrived), and
  2. a windowless enumeration started after that and reached cursor exhaustion, and
  3. no paused cursor remains.
Until then sync_state is partial (or syncing while a run is active). mode: "history" forces a new provider back-fill request when a previous one ended in error. If your paid run exhausted the available messages while provider history is still requested or running, you do not need another paid sync. Reconciliation checks pending history every ten minutes and runs free internal imports, including a full enumeration after the provider finishes, even if the provider’s completion webhook never arrives. A paid run paused at its page limit still requires an explicit continue.

Incremental updates

You do not need to keep calling sync. New, edited, deleted and read messages arrive through the provider’s messaging webhook, and a scheduled reconciliation sweep enqueues small internal runs (an overlap window behind the last incremental) every few hours, plus a nightly conversation-metadata refresh. Internal runs are never charged and never continue a paid paused cursor. Only the owner can continue one. Cursors are opaque and never returned. has_next_cursor / pending_cursor tell you one exists.

Charge semantics

Example