For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
DashboardGet API Key
GuidesAPI ReferenceCommon Patterns
  • Getting Started
    • Welcome
    • Introduction
    • Quickstart
    • Authentication
  • Core Concepts
    • Sessions & Cookies
    • Profiles
    • Messaging
    • Posts & Engagement
    • Connections
    • Search
    • SalesNav
    • SalesNav Filters
  • Playbooks
    • Multi-Step Workflows
    • Query Patterns
  • Workflow Guides
    • Lead Discovery
    • Warm Outreach
    • Content Intelligence
    • Company Research
    • Job Market Intelligence
    • Webhooks
  • Integration
    • MCP Server
    • WebSocket Relay
DashboardGet API Key
On this page
  • How Voyager Works
  • Architecture
  • Key Concepts
  • Sessions
  • Tenants
  • Users
  • API Keys
  • Async Jobs
  • Webhooks
  • API Design Principles
  • Consistent Response Envelope
  • Rate Limiting as Metering
  • Multi-Strategy Fallbacks
  • Retry and Auto-Pause Discipline
Getting Started

Introduction

Was this page helpful?
Previous

Quickstart

Next
Built with

How Voyager Works

Voyager is a multi-tenant server that proxies calls to LinkedIn’s internal Voyager API and Sales Navigator API on behalf of AI agents. Your agent calls Voyager over REST (or MCP); Voyager forwards the call to LinkedIn using either your real Chrome session (via a WebSocket relay) or a direct server-side HTTP call through a residential proxy.

Your Agent ──▶ Voyager REST API ──▶ LinkedIn
│
┌─────────────┴──────────────┐
│ │
Chrome extension relay Direct HTTP
(real browser IP + cookies) (+ residential proxy)

Architecture

  • Multi-tenant. Each tenant has one or more users; each user maps 1:1 to a LinkedIn account. Tenants are isolated — separate sessions, rate meters, and data directories. One Voyager instance handles dozens of tenants with hundreds of users.
  • Pure HTTP. Every endpoint — Voyager, Sales Navigator, search, messaging, connections, engagement — is direct HTTP, no headless browser and no DOM scraping. Requests are either forwarded through the user’s extension relay or issued from the server with synced cookies. The entire Puppeteer stack (Chromium launch, stealth patches, DOM-only phantoms) was removed 2026-04-22.
  • 2-tier fetch. Tier 1 is the extension relay — the request leaves your user’s real Chrome with real cookies and a real residential IP. Tier 2 is a direct server-side call that uses the synced cookies plus an IPRoyal residential proxy. If Tier 1 is unreachable, Tier 2 kicks in automatically; callers don’t see the difference.
  • Self-healing. Each operation tries REST first, falls back to GraphQL with a captured query ID, and retries transient failures (429, 5xx, relay disconnects) with 2s/4s backoff. When LinkedIn rotates a query ID or shape, the nightly stress harness detects it within the hour and files a GitHub issue.
  • Discoverable. GET /api/agent/capabilities returns a structured catalogue of every endpoint, parameter, and response shape. GET /api/llms.txt is the plain-text equivalent for LLMs. GET /api/openapi.json is the OpenAPI 3.x spec.

Key Concepts

Sessions

A session is an authenticated LinkedIn connection. You provide cookies from your LinkedIn browser session (easiest: install the Chrome extension, which auto-syncs them). Voyager stores them server-side and forwards them on every call — either via the extension relay or directly. Background session health checks only pause a user on genuine auth signals (HTTP 401/403); transient 5xx or network blips never cause an auto-pause.

Tenants

Each organization is a tenant. A tenant can host multiple LinkedIn accounts. Tenants are isolated — separate cookies, rate meters, and data directories. API keys are tenant-scoped.

Users

Within a tenant, each LinkedIn account is a user identified by a userId string (e.g. "charis", "harry"). The X-User-Id header routes a request to the correct LinkedIn session. Single-user tenants can omit the header — Voyager defaults to the only user.

API Keys

Tenant-scoped API keys (voy_ prefix) authenticate requests. Each key is bound to a specific tenant; the X-User-Id header picks which user within the tenant. Keys are created, rotated, and revoked via the dashboard or POST /api/keys.

Async Jobs

A few long-running operations (bulk employee export, deep company dossier, batch reads) return 202 Accepted with a jobId. Poll GET /api/jobs/:jobId until the job completes. See Async Jobs.

Webhooks

Instead of polling for new messages or connection requests, configure webhooks to receive real-time events (message_received, message_seen, connection_received, session_expired, etc.). Voyager signs payloads with HMAC-SHA256 and can auto-format messages for Slack. See Webhooks.

API Design Principles

Consistent Response Envelope

Every JSON endpoint returns the same top-level shape:

1{
2 "success": true,
3 "statusCode": 200,
4 "message": null,
5 "data": { "profile": { "fullName": "Jane Smith", "...": "..." } },
6 "errors": null
7}

On failure, success is false, statusCode reflects the HTTP status, and errors is an array of structured error objects — each with message, code, statusCode, retryable, and action:

1{
2 "success": false,
3 "statusCode": 401,
4 "message": "Invalid API key",
5 "data": null,
6 "errors": [
7 {
8 "message": "Invalid API key",
9 "code": "UNAUTHORIZED",
10 "statusCode": 401,
11 "retryable": false,
12 "action": "check_api_key",
13 "request_id": "req_3990045c65fb4efd9270"
14 }
15 ]
16}

Every endpoint’s data lives under data. If you’re migrating from an older client that accessed res.profile directly, change it to res.data.profile.

Rate Limiting as Metering

Voyager does not enforce rate limits on outbound LinkedIn calls. It records and reports usage — messages sent, connections requested, profiles viewed, account age, seconds since last action — so your orchestrating agent has the full context (campaign strategy, account trust score, test vs. production) to decide policy. If you genuinely want a throttle, impose it in the agent. See Rate Limiting.

Multi-Strategy Fallbacks

LinkedIn deprecates internal APIs without notice. Voyager tries multiple strategies per operation:

  1. REST (fastest, most reliable)
  2. GraphQL with a live-captured query ID (fallback)
  3. Voyager normalized+json (application/vnd.linkedin.normalized+json+2.1) for shape-sensitive endpoints

If strategy 1 fails, Voyager automatically tries strategy 2. Query IDs are pinned in tests against live captures so rotation fails loudly instead of silently serving stale data.

Retry and Auto-Pause Discipline

Transient transport failures — HTTP 429, any 5xx, "Relay connection closed", network errors — get retried with 2s then 4s backoff. Sustained auth-expiry signals (401/403 with authwall / checkpoint markers) auto-pause the user via the RiskMonitor. Nothing else does. A Railway redeploy that momentarily drops the WebSocket will not flip a user to paused.