Developer Docs

ZenMode REST API

Push LinkedIn automation tasks programmatically. Available on all plans.

Authentication

All API requests require a Bearer token. Generate an API key from your dashboard.

bash
curl -H "Authorization: Bearer zm_your_api_key_here" \
  https://www.zen-mode.io/api/v1/tasks

Keep your API key secret. It is shown only once when created. If compromised, revoke it from the dashboard and generate a new one.

Rate Limits

API Requests

100 per minute

Task Creation

500 per day per LinkedIn account

Exceeding limits returns 429 Too Many Requests.

Endpoints

POST/api/v1/tasksCreate a task

Queue a LinkedIn action. The desktop app picks it up automatically.

Request Body

json
{
  "action_type": "connect",
  "linkedin_account_id": "acc_abc123",
  "payload": {
    "profile_url": "https://linkedin.com/in/jane-doe",
    "message": "Hi Jane, I'd love to connect!"
  },
  "priority": 0,
  "max_retries": 3
}

Action Types

connect — Send a connection request (with optional message)

message — Send a direct message to an existing connection

follow — Follow a profile

view_profile — View a profile (warm-up action)

withdraw_connection — Withdraw a pending connection request

Response (201)

json
{
  "task": {
    "id": "task_m1abc_x7k2p9qr",
    "action_type": "connect",
    "status": "pending",
    "linkedin_account_id": "acc_abc123",
    "payload": { ... },
    "priority": 0,
    "created_at": "2026-04-02T10:30:00.000Z"
  }
}
GET/api/v1/tasksList tasks

Retrieve your tasks with optional filters.

Query Parameters

status — Filter by status: pending, processing, completed, failed, cancelled

linkedin_account_id — Filter by LinkedIn account

limit — Results per page (default 50, max 100)

offset — Pagination offset

bash
curl -H "Authorization: Bearer zm_..." \
  "https://www.zen-mode.io/api/v1/tasks?status=completed&limit=10"
GET/api/v1/tasks/:idGet task status
bash
curl -H "Authorization: Bearer zm_..." \
  https://www.zen-mode.io/api/v1/tasks/task_m1abc_x7k2p9qr
DELETE/api/v1/tasks/:idCancel a pending task

Only tasks in pending or queued status can be cancelled.

bash
curl -X DELETE -H "Authorization: Bearer zm_..." \
  https://www.zen-mode.io/api/v1/tasks/task_m1abc_x7k2p9qr

Webhooks

Register a webhook URL to receive POST callbacks when tasks complete or fail.

POST/api/v1/webhooksRegister a webhook
json
{
  "url": "https://your-server.com/zenmode-webhook",
  "events": ["task.completed", "task.failed"]
}

URL must use HTTPS. Valid events: task.completed, task.failed.

GET/api/v1/webhooksList webhooks
DELETE/api/v1/webhooks?id=123Delete a webhook

Webhook Payload

When a task completes or fails, ZenMode sends a signed POST to your webhook URL.

Headers

X-ZenMode-Signature — HMAC-SHA256 hex digest of the request body, signed with your webhook secret

X-ZenMode-Event — Event type (e.g. task.completed)

Body

json
{
  "event": "task.completed",
  "data": {
    "task_id": "task_m1abc_x7k2p9qr",
    "action_type": "connect",
    "status": "completed",
    "result": { "success": true },
    "linkedin_account_id": "acc_abc123"
  },
  "timestamp": "2026-04-02T10:35:00.000Z"
}

Verifying Signatures

javascript
const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Code Examples

cURL

bash
# Create a connection request task
curl -X POST https://www.zen-mode.io/api/v1/tasks \
  -H "Authorization: Bearer zm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "action_type": "connect",
    "linkedin_account_id": "acc_abc123",
    "payload": {
      "profile_url": "https://linkedin.com/in/jane-doe",
      "message": "Hi Jane, would love to connect!"
    }
  }'

# Check task status
curl https://www.zen-mode.io/api/v1/tasks/task_m1abc_x7k2p9qr \
  -H "Authorization: Bearer zm_your_api_key"

# List completed tasks
curl "https://www.zen-mode.io/api/v1/tasks?status=completed&limit=20" \
  -H "Authorization: Bearer zm_your_api_key"

Python

python
import requests

API_KEY = "zm_your_api_key"
BASE_URL = "https://www.zen-mode.io/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}

# Create a task
task = requests.post(f"{BASE_URL}/tasks", headers=headers, json={
    "action_type": "connect",
    "linkedin_account_id": "acc_abc123",
    "payload": {
        "profile_url": "https://linkedin.com/in/jane-doe",
        "message": "Hi Jane, would love to connect!"
    }
}).json()

print(f"Task created: {task['task']['id']}")

# Poll for completion
import time
while True:
    status = requests.get(
        f"{BASE_URL}/tasks/{task['task']['id']}", headers=headers
    ).json()
    if status["task"]["status"] in ("completed", "failed"):
        print(f"Task {status['task']['status']}: {status['task'].get('result')}")
        break
    time.sleep(10)

JavaScript / Node.js

javascript
const API_KEY = "zm_your_api_key";
const BASE_URL = "https://www.zen-mode.io/api/v1";

async function createTask(actionType, profileUrl, message) {
  const res = await fetch(`${BASE_URL}/tasks`, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      action_type: actionType,
      payload: { profile_url: profileUrl, message },
    }),
  });
  return res.json();
}

// Send a connection request
const { task } = await createTask(
  "connect",
  "https://linkedin.com/in/jane-doe",
  "Hi Jane, would love to connect!"
);
console.log("Task ID:", task.id);

// Register a webhook to get notified
await fetch(`${BASE_URL}/webhooks`, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://your-server.com/webhook",
    events: ["task.completed", "task.failed"],
  }),
});

Task Lifecycle

pendingprocessingcompleted
orprocessingfailed

pending — Task queued, waiting for desktop app to pick up

processing — Desktop app is executing the task

completed — Action performed successfully on LinkedIn

failed — Action failed (check result for details)

cancelled — Task was cancelled before processing

Error Codes

StatusMeaning
400Bad request — missing or invalid fields
401Unauthorized — missing or invalid API key
403Forbidden — no active subscription
404Not found — task or webhook doesn't exist
429Rate limit exceeded — wait 60 seconds
500Server error

Need help?

Generate your API key and start sending tasks in minutes.