# LinkedIn Automation API: REST, Webhooks & SDKs | SalesMix

> Automate LinkedIn outreach from code: create sequences as JSON, enroll leads, reply to conversations and get webhooks for every invite, accept and reply.

URL: https://salesmix.com/api

# LinkedIn automation API: Automate LinkedIn outreach from your own code.

Create sequences as JSON, enroll leads from any tool, and get a webhook for every invite, accept and reply. The SalesMix app runs on this same API, so nothing is held back.

**In short** 

The SalesMix API is a REST API for LinkedIn outreach automation at `https://api.salesmix.com/v1`. It covers accounts, sequences, leads, conversations, approvals, webhooks and analytics, with bearer-token auth, idempotency keys and an [OpenAPI spec](https://salesmix.com/openapi.json).

[Get an API key](https://app.salesmix.com/signup) [Browse endpoints](#endpoints)

**POST/v1/sequences**

```
{
  "name": "Founders · Series A",
  "type": "dynamic",
  "accounts": "rotate:all",
  "steps": [
    { "visit_profile": {} },
    { "connect": { "note": "Hi {{first_name}}" } },
    { "if": "connected",
      "then": ["message", "wait:3d", "like"],
      "else": { "if": "open_profile",
        "then": "inmail",
        "else": "email" } }
  ]
}
```

**Quickstart** 

## Your first LinkedIn reply in three API calls.

01

### Create a key

In **Settings → API keys**. Keys are scoped to a workspace, so agencies can hand each client its own.

02

### Create a sequence

Send the steps as JSON to `POST /v1/sequences`, or build it on the canvas and grab its id.

03

### Enroll leads and listen

Push leads to `/v1/sequences/:id/leads` and register a webhook for `message.replied`.

```
# Enroll leads straight from your Clay table, CRM or script
curl https://api.salesmix.com/v1/sequences/seq_8Fk2/leads \
  -H "Authorization: Bearer $SALESMIX_KEY" \
  -H "Idempotency-Key: clay-row-4471" \
  -d '{
    "leads": [{
      "linkedin_url": "https://linkedin.com/in/juliatan",
      "first_name": "Julia",
      "company": "Brightpath",
      "custom": { "signal": "hiring_sdrs" }
    }],
    "start": "now"
  }'

# → 202 Accepted
{ "enrolled": 1, "skipped_duplicates": 0 }
```

```
import SalesMix from "@salesmix/node";

const sm = new SalesMix(process.env.SALESMIX_KEY);

await sm.sequences.leads.add("seq_8Fk2", {
  leads: [{
    linkedin_url: "https://linkedin.com/in/juliatan",
    first_name: "Julia",
    company: "Brightpath",
  }],
  start: "now",
});

sm.webhooks.on("message.replied", async (e) => {
  if (e.intent === "interested") await pushToCRM(e.lead);
});
```

```
from salesmix import SalesMix

sm = SalesMix(api_key=os.environ["SALESMIX_KEY"])

sm.sequences.leads.add(
    "seq_8Fk2",
    leads=[{
        "linkedin_url": "https://linkedin.com/in/juliatan",
        "first_name": "Julia",
        "company": "Brightpath",
    }],
    start="now",
)

for convo in sm.conversations.list(intent="interested"):
    print(convo.lead.name, convo.last_message.text)
```

```
// claude_desktop_config.json (or Cursor, or any MCP client)
{
  "mcpServers": {
    "salesmix": {
      "url": "https://mcp.salesmix.com",
      "headers": { "Authorization": "Bearer $SALESMIX_KEY" }
    }
  }
}

› "Find everyone who replied 'interested' this week
   and draft a follow-up. Send them to Approvals."

  ✓ conversations.list(intent="interested")  → 23
  ✓ approvals.create × 23                     → queued
```

**Reference** 

## LinkedIn API endpoints

Base URL `https://api.salesmix.com/v1`. JSON in, JSON out. Bearer-token auth. Machine-readable: [openapi.json](https://salesmix.com/openapi.json).

Accounts

GET`/accounts`List connected LinkedIn accounts and their limits

PATCH`/accounts/:id`Update daily limits, working hours, warm-up

Sequences

POST`/sequences`Create a sequence from JSON steps

GET`/sequences/:id`Fetch a sequence, its steps and stats

POST`/sequences/:id/launch`Start or resume sending

POST`/sequences/:id/pause`Pause without losing progress

Leads

POST`/sequences/:id/leads`Enroll up to 1,000 leads per call

GET`/leads`Filter by status, sequence, account or intent

DELETE`/sequences/:id/leads/:lead_id`Remove a lead from a sequence

Conversations

GET`/conversations`Unified inbox across every account

POST`/conversations/:id/reply`Reply as the original account

Approvals

POST`/approvals`Queue a draft for human review

POST`/approvals/:id/approve`Approve, optionally with edits

Webhooks & analytics

POST`/webhooks`Subscribe a URL to events

GET`/analytics/funnel`Funnel by sequence, account or step

**Webhooks** 

## Your code hears about it instantly.

Every event is a signed POST with the lead, the account, the sequence and the step attached. Failed deliveries retry with backoff.

`lead.enrolled`A lead joined a sequence

`connection.sent`An invite went out

`connection.accepted`The lead accepted

`message.sent`A LinkedIn message or InMail was sent

`message.replied`The lead replied, with an intent label

`lead.intent_changed`Intent moved, e.g. to interested

`email.handoff`Lead handed to your email sequencer

`approval.requested`A draft is waiting for review

`sequence.completed`A lead reached an End step

`account.limit_reached`An account hit its daily cap

**POST → https://hooks.yourapp.com/salesmixlive**

-   09:41:07**message.replied** · Julia Tan · intent=interested200
-   09:40:52**connection.accepted** · Marcus Lee200
-   09:40:31**connection.sent** · Priya Raman · sender=dana200
-   09:40:12**approval.requested** · draft\_5Hq · step 3200
-   09:39:58**email.handoff** · Tom Becker → sequencer200
-   09:39:40**lead.enrolled** · 48 leads · seq\_8Fk2200

**verify.js**

```
import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(raw, header, secret) {
  const [t, sig] = header.split(",");
  const mac = createHmac("sha256", secret)
    .update(`.`).digest("hex");
  return timingSafeEqual(Buffer.from(mac), Buffer.from(sig));
}
```

**MCP server** 

## Give your agent the keys. Keep a human on the lock.

The SalesMix MCP server exposes sequences, leads, conversations and approvals as tools. Connect Claude, Cursor or your own agent and ask for outcomes in plain language. [Read the MCP server guide →](https://salesmix.com/mcp)

-   “Enroll everyone from this Clay view into the Series A sequence.”
-   “Which step in Agency Q4 loses the most people?”
-   “Draft replies to this week's interested leads and queue them for approval.”

**agent session**

```
you › Which sequence has the best reply rate this month,
      and move its stalled leads into a new follow-up?

  ⏺ salesmix.analytics_funnel(period="30d")
  ⏺ salesmix.leads_list(status="connected", replied=false)
  ⏺ salesmix.sequences_create(from="seq_8Fk2", name="Nudge")
  ⏺ salesmix.approvals_create × 41

agent › Founders · Series A leads with 18% replies.
        I built "Nudge" from it and queued 41 drafts
        in Approvals. Nothing sends until you approve.
```

**Conventions** 

## Built so your integration just works.

**Auth** 

### Bearer keys per workspace

Create, scope and revoke keys in Settings. Keys never cross workspaces.

**Idempotency** 

### Retries are safe

Send an `Idempotency-Key` header and repeated requests return the original result.

**Pagination** 

### Cursor-based lists

Every list returns `next_cursor`. No page drift while new replies arrive.

**Rate limits** 

### Headers tell you where you stand

`X-RateLimit-Remaining` on every response, and a clear `429` with `Retry-After`.

**Errors** 

### Errors you can act on

A stable `code`, a human `message` and the field that caused it.

**Pacing** 

### LinkedIn limits are enforced for you

The API queues actions; accounts still send at a human pace inside their own caps.

**FAQ** 

## API questions

### ### Is there an official LinkedIn API for outreach?

LinkedIn’s official APIs are limited to approved partners and don’t cover sending connection requests or messages for most companies. The SalesMix API runs outreach through the LinkedIn accounts you connect to SalesMix, with each account paced inside its own limits.

### ### What can I do with the SalesMix API?

Everything the app does: list and configure LinkedIn accounts, create sequences from JSON, launch and pause them, enroll and remove leads, read and reply to conversations, queue drafts for approval, subscribe to webhooks and query funnel analytics.

### ### Is the API included in every plan?

Yes. The REST API, webhooks and the [MCP server](https://salesmix.com/mcp) are on every plan. There are no per-call fees, and the 7-day free trial includes full API access. See [pricing](https://salesmix.com/pricing).

### ### Will API calls make my LinkedIn accounts send too fast?

No. The API queues work; it doesn’t bypass pacing. Every action still goes out at a human pace inside the account’s daily limits and working hours, however many leads you enroll at once.

### ### What if I retry a request from Clay, n8n or Zapier?

Send an `Idempotency-Key` header and a retried request returns the original result instead of enrolling the same lead twice. Leads are also deduplicated by LinkedIn profile URL.

### ### Do you have an OpenAPI spec or SDKs?

Yes. The spec is at [/openapi.json](https://salesmix.com/openapi.json), and there are SDKs for Node.js and Python. You can generate a client in any other language from the spec.

## Keep exploring

[LinkedIn MCP server Tools, setup and safety for AI agents.](https://salesmix.com/mcp)[Integrations Clay, n8n, Zapier, Make, HubSpot and more.](https://salesmix.com/integrations)[Sequence builder Prefer a canvas? Build the same sequence visually.](https://salesmix.com/product#builder)[LinkedIn limits guide How pacing works behind the API.](https://salesmix.com/guides/linkedin-automation-limits)

## Unlimited LinkedIn accounts, one API, $1,000/mo.

API, webhooks and the MCP server come with every plan. No per-call fees. 7-day free trial, cancel anytime.

[Get an API key](https://app.salesmix.com/signup)[OpenAPI spec](https://salesmix.com/openapi.json)
