The LKDN Autopilot API and MCP server
With the LKDN Autopilot API, your software, your CRM, your automations (n8n, Make, Zapier) and your AI assistants (Claude, ChatGPT) use your connected LinkedIn account, through us: they read conversations and connections, search for people, send messages and connection requests, publish posts and comment.
Three things to know first:
- One account, yours. The key is tied to your LKDN Autopilot account and to your LinkedIn account. You do not connect other accounts and you do not choose an account: the key already knows which one it is.
- One budget, shared with the autopilot. Every visit, connection request, message, comment, reaction and post made through the API uses the same daily budget as the autopilot, and so does every read that reaches LinkedIn (profiles, searches, lists, posts, companies), with the same limits and the same pauses between one action and the next. If the API uses 5 connection requests, the autopilot has 5 fewer that day. This is how your account stays safe.
- We do not keep your conversations. When you read a chat through the API, we read it from your account at that moment and pass it to you. We do not save it in our records or in our logs: if you need to keep it, your CRM keeps it.
API access is enabled on request, per account: write to us at info@lkdnautopilot.com.
Contents #
- Getting started in five minutes
- Keys and authentication
- Limits and the shared budget
- Response format
- Idempotency-Key
- Simulated mode
- Endpoints
- Webhooks
- MCP server: Claude, ChatGPT, n8n
- Ready-made prompts
- Errors
- Privacy and responsibility
- What it does not do
Getting started in five minutes #
- In the app, go to API and integrations (at the top of the home page).
- Create a key: a name (for example "my CRM") and what it may do, read only or read and write. The key is shown only once: copy it and keep it somewhere safe.
- Try it:
curl https://ayuhpqrbmizgsjstmcrt.supabase.co/functions/v1/public-api/v1/me \
-H "Authorization: Bearer lkdn_sk_LA_TUA_CHIAVE"
The answer is your profile, the state of the connection and the LinkedIn plan we detected:
{
"data": {
"id": "per_3mQ8...",
"name": "Giulia Demo",
"headline": "Consulente, Demo Consulting Srl",
"public_identifier": "giulia-demo",
"linkedin_status": "connected",
"linkedin_plan": "premium",
"inmail_credits": 5,
"simulated": false
}
}
The base address of every call is:
https://ayuhpqrbmizgsjstmcrt.supabase.co/functions/v1/public-api/v1
The complete OpenAPI specification is in openapi.json: import it into Postman, Insomnia or a client generator.
Keys and authentication #
Every request carries the key in the header:
Authorization: Bearer lkdn_sk_...
- A key has one or two permissions:
read(reading) andwrite(acting: messages, invitations, posts, comments, reactions, visits, webhooks). A read-only key that tries to act gets403 insufficient_scope. - You can have up to 5 active keys. Give each piece of software its own key: if one must be revoked, the others keep working.
- Revoking is immediate: the next request with that key gets
401 invalid_api_key. - We keep only a fingerprint of the key (a hash), never the key itself: if you lose it, create a new one.
- The key lives on a server, never in a web page or in an app running in the browser. The API does not answer calls made directly from a browser.
Limits and the shared budget #
Your LinkedIn account has a daily budget, the same for the autopilot and for the API. We decide it in one single place, with the same rules: the LinkedIn plan we detected, the warm-up period of a new account, the limits you chose yourself and the ones we may lower if the account is at risk. The API cannot exceed it, in any case.
| Action | Default value per day | Endpoint |
|---|---|---|
| Visits with notification | 30 | POST /v1/people/{id}/visits |
| Connection requests | 20 (about 5 on a free LinkedIn account), 100 in 7 days | POST /v1/invitations |
| Messages | 25 | POST /v1/conversations, POST /v1/conversations/{id}/messages |
| InMails | 3 | POST /v1/conversations with inmail: true |
| Comments | 10 | POST /v1/posts/{id}/comments |
| Reactions | 20 | POST /v1/posts/{id}/reactions |
| Posts | 2 | POST /v1/posts |
| Withdrawn requests | 10 | DELETE /v1/invitations/{id} |
| Total of the actions above | 70 | |
| Profiles read (without notification) | 40 | GET /v1/people/{id} |
| Profiles opened in all: visits and profiles read together | 70 | POST /v1/people/{id}/visits, GET /v1/people/{id} |
| Search results | 300 | POST /v1/searches |
| Lists, posts and pages read | 40 | GET /v1/me (up to 2), GET /v1/connections, GET /v1/invitations, GET /v1/people/{id}/posts, GET /v1/posts/{id}, GET /v1/posts/{id}/comments, GET /v1/posts/{id}/reactions, GET /v1/companies/{id} |
Conversations and messages (GET /v1/conversations...) use no budget: they are already synchronised from your account, without a request to LinkedIn for every read. Comments and reactions read the post first: that read is always counted, even if the action then does not go out, but an action is never refused because of the read budget.
These are the default values: the ones of your account may be lower (warm-up, free plan, limits you chose). The real ones, for today, are always in GET /v1/usage, together with how much you have already used and how much the API has used.
No number, not even the ones we can raise on request, goes above 80% of the limits recommended for a LinkedIn account by the infrastructure we use to connect: for example at most 64 connection requests a day and 160 in 7 days, 80 profiles opened a day between visits and reads, 800 search results a day (2000 with Sales Navigator or Recruiter). The database refuses any setting beyond this margin.
Other rules that protect the account:
- Actions are spaced out. Between one action on your profile and the next a few minutes pass, with a random interval, as a person would do; now and then the pause is longer (up to three quarters of an hour). If you ask for an action too soon you get
429 action_pacedwithRetry-Afterin seconds. - Actions towards new people follow your working hours. Visits, connection requests and InMails go out only on the days and at the hours you chose in the app (outside them:
429 outside_activity_window). Messages in conversations, comments, reactions and posts do not. - People who must not be contacted are not contacted. Anyone who asked not to be contacted, anyone you excluded, anyone in the categories we do not contact (for example network marketing) gets
403 person_not_contactable, through the API too. - Whoever you contact through the API is not contacted again by the autopilot. The person becomes yours: from that moment the autopilot skips them.
- A final refusal from LinkedIn stays final. If LinkedIn no longer accepts requests to a person, the API answers
422 invitation_not_allowedand does not try again. - When LinkedIn asks to slow down, the account slows down. If LinkedIn reports too many requests (a
429), all actions and reads stop until midnight in your time zone; if it happens two days in a row, for 7 days connection requests and messages drop to half. If LinkedIn reports the connection request limit, requests stop until the end of the following day. Meanwhile you get429 account_backoffwithRetry-After, andGET /v1/usagesays why inbackoff. It applies to the autopilot and the API together. - Requests to the API: at most 60 a minute per key and 2000 a day per account, reads included (
429 rate_limited,429 daily_request_limit).
Every 429 has the Retry-After header: after how many seconds to try again. When the day's budget is used up, Retry-After points at the opening of your next working hours. An AI agent that gets a 429 must stop and say so, not retry in a loop.
Response format #
Responses are JSON, with English names that never change:
- an object:
{"data": {...}} - a list:
{"data": [...], "page": {"next_cursor": "cur_..." }}; for the next page passcursor=cur_...;next_cursorisnullon the last page. Cursors expire after one hour and are valid only for the list that gave them. - dates are ISO 8601 in UTC (
2026-10-25T09:30:00.000Z) and end in_at. idvalues are opaque and stable, with a prefix that says what they are:per_person,cnv_conversation,msg_message,inv_connection request,pst_post,cmt_comment,cmp_company,flt_search filter,whk_webhook. You can save them in your CRM: the same person always has the sameid. They are valid only for your account.- where useful, LinkedIn's public references are there too:
public_identifier(the part afterlinkedin.com/in/) andprofile_url. degreeis the degree of connection:1,2,3ornull(out of network or unknown).
Every response has the X-Request-Id header: quote it if you write to us about a problem.
Errors follow the RFC 9457 standard (Content-Type: application/problem+json):
{
"type": "https://lkdnautopilot.com/api-doc/#errori-daily_budget_exhausted",
"title": "The daily budget for this action is used up, by the autopilot and the API together.",
"status": 429,
"code": "daily_budget_exhausted",
"request_id": "req_9f2c...",
"retry_after": 52310
}
The field to read in your code is code: it is stable and never changes meaning. The complete list is in Errors.
Idempotency-Key #
Every request that acts (POST and DELETE, except POST /v1/searches, which is a read) requires the Idempotency-Key header: a unique value you choose, from 8 to 200 characters, for example a UUID.
curl -X POST https://ayuhpqrbmizgsjstmcrt.supabase.co/functions/v1/public-api/v1/invitations \
-H "Authorization: Bearer lkdn_sk_..." \
-H "Idempotency-Key: 6b1f0e5e-2f4a-4c39-9a0e-4d8f2f0a1c11" \
-H "Content-Type: application/json" \
-d '{"person_id": "per_3mQ8...", "message": "Ciao Marco, ho letto il tuo post sulla logistica e mi è piaciuto."}'
- If you repeat the same request with the same key (a timeout, a network error), you get the same response and the action is not repeated. The response has
Idempotency-Replayed: true. - The same key with a different request:
422 idempotency_key_reused. - If the first request is still in progress:
409 idempotency_in_progress. - If the request did not act (a 429, a 400, a 409 about the state of the account), the key is freed and you can try again with the same one.
- Keys are remembered for 24 hours.
502 action_outcome_unknown means that LinkedIn did not give us a readable answer and the action may or may not have gone out. Do not retry with a new key: check first (for a message, read the conversation).
Simulated mode #
While your account is getting ready, the API answers with simulated data (made-up people) and no action really goes out: actions still go through the limits and are recorded. Simulated responses have the LKDN-Mode: simulated header and, for actions, "simulated": true. It is the right way to build and test an integration without touching anyone.
Endpoints #
All paths are relative to the base address. Read: read permission. Action: write permission and Idempotency-Key.
Your account #
GET /v1/me (read). Your profile, linkedin_status (connected, reconnect_required, not_connected), linkedin_plan (free, premium, sales_navigator), your InMail credits. Uses up to two list reads (the profile and the InMail credits).
GET /v1/usage (read). Today's budget, shared with the autopilot:
{
"data": {
"date": "2026-10-25",
"timezone": "Europe/Rome",
"linkedin_plan": "premium",
"invitation_note_available": true,
"requests": { "today": 41, "per_day": 2000, "per_minute": 60 },
"budget": {
"invitations": { "used": 7, "limit": 20, "used_by_api": 2, "weekly_limit": 100 },
"messages": { "used": 3, "limit": 25, "used_by_api": 3 },
"list_reads": { "used": 6, "limit": 40, "used_by_api": 6 },
"profile_retrievals": { "used": 21, "limit": 70, "used_by_api": 4 },
"total_actions": { "used": 18, "limit": 70 }
},
"activity_window": { "open_now": true, "start": "09:00", "end": "18:00", "working_day": true },
"backoff": null,
"shared_with_autopilot": true
}
}
backoff is null, or it says why the account is going slower today: {"kind": "all_stop" | "invite_stop" | "halved", "reason": "...", "until": "2026-10-26T23:00:00.000Z"} (everything stopped, connection requests stopped, pace halved) and until when.
People #
GET /v1/people/{id} (read). A profile: id is a per_... or the public_identifier. The person is not notified. Uses one "profile read" (and counts towards the profiles opened in all). It does not return other people's emails or phone numbers.
POST /v1/people/{id}/visits (action). Visits the profile: the person sees that you looked at them. Uses one visit.
GET /v1/people/{id}/posts (read). The person's recent posts. limit up to 50, cursor. Uses one list read per page.
GET /v1/connections (read). Your first-degree connections, most recent first. q filters by name, limit up to 200, cursor. Uses one list read per page.
Search #
GET /v1/search/filters?type=location&q=verona (read). Turns a place (type=location) or an industry (type=industry) into a flt_... filter to use in the search. Always use it: the search refuses a filter that does not come from here (400 invalid_filter), because LinkedIn would silently ignore an unknown filter and give you the results of a search different from the one you wanted.
POST /v1/searches (read). Searches for people:
{
"keywords": "logistica",
"titles": ["CFO", "direttore finanziario"],
"locations": ["flt_..."],
"industries": ["flt_..."],
"degree": [2, 3],
"limit": 10
}
At least one of keywords, titles, locations, industries. limit up to 10 (up to 25 with Sales Navigator); each result uses one "search result". For the next page repeat the same search with cursor. The response also has page.total_estimate.
Conversations #
GET /v1/conversations (read). Your conversations, most recent first: type (direct or group), participant_id, kind (message, inmail, sponsored, offer), inbox, unread_count, last_activity_at. unread=true for unread ones only, limit up to 100, cursor.
GET /v1/conversations/{id} (read). One conversation.
GET /v1/conversations/{id}/messages (read). The messages, most recent first: text, from_me, sender_id, sent_at, kind, seen, attachments (type and name, without a link). We read the text from your account at that moment and do not keep it.
POST /v1/conversations/{id}/messages (action). Reply in a one-to-one conversation: {"text": "..."} (up to 8000 characters). Group conversations are not supported (422 group_conversation_not_supported).
POST /v1/conversations (action). Write to a person: {"person_id": "per_...", "text": "..."}. It works with first-degree connections (otherwise 422 not_first_degree). For an InMail to someone you are not connected with: {"person_id": "per_...", "text": "...", "inmail": true, "subject": "..."}; it uses one InMail from the budget and one InMail credit from your plan.
Connection requests #
GET /v1/invitations?direction=sent (read). The requests you sent that are still pending; direction=received for the ones you received. Uses one list read per page.
POST /v1/invitations (action). {"person_id": "per_...", "message": "..."}. The note (message, up to 300 characters) is not available on a free LinkedIn account (403 invitation_note_not_available): on that plan the request goes out without a note. Already connected: 409 already_connected; request already pending: 409 already_invited.
DELETE /v1/invitations/{id} (action). Withdraws a request you sent that is still pending.
Posts #
GET /v1/posts/{id} (read). A post: id is a pst_..., a LinkedIn URN (urn:li:activity:...) or the activity number. Uses one list read.
GET /v1/posts/{id}/comments, GET /v1/posts/{id}/reactions (read). Comments and reactions. Uses one list read per page.
POST /v1/posts (action). Publishes a post on your profile: {"text": "..."} (up to 3000 characters).
POST /v1/posts/{id}/comments (action). {"text": "...", "reply_to": "cmt_..."}; reply_to to reply to a comment. The author of the post gets a notification.
POST /v1/posts/{id}/reactions (action). {"type": "like"}; type is one of like, celebrate, support, love, insightful, funny.
Companies #
GET /v1/companies/{id} (read). A company page: id is a cmp_... or the public name after linkedin.com/company/. Uses one list read.
Webhooks #
GET /v1/webhooks (read), POST /v1/webhooks (action), DELETE /v1/webhooks/{id} (action). See Webhooks.
Webhooks #
Instead of asking every minute "is there anything new?", we call you. Create a webhook from the app (API and integrations) or with:
curl -X POST https://ayuhpqrbmizgsjstmcrt.supabase.co/functions/v1/public-api/v1/webhooks \
-H "Authorization: Bearer lkdn_sk_..." -H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" \
-d '{"url": "https://crm.example.com/hooks/lkdn", "events": ["message.received", "connection.accepted"]}'
The response contains the signing secret (whsec_...) only once.
| Event | When | data |
|---|---|---|
message.received | a person writes to you | conversation_id, message_id, sender_id, sent_at |
connection.accepted | a connection request is accepted (it can arrive up to 8 hours later) | person_id, public_identifier, accepted_at |
invitation.sent | a connection request goes out, from the autopilot or from the API | invitation_id, person_id, source (autopilot or api), sent_at |
account.status_changed | the connection of your account changes state | status, previous_status, changed_at; states: connected, connecting, reconnect_required, disconnected, error |
The body of the call:
{
"id": "evt_0b6f1f40000040008000000000000001",
"type": "message.received",
"created_at": "2026-10-25T10:00:03.000Z",
"data": {
"conversation_id": "cnv_...",
"message_id": "msg_...",
"sender_id": "per_...",
"sent_at": "2026-10-25T10:00:00.000Z"
}
}
The text of the message does not travel in the webhook: read it with GET /v1/conversations/{conversation_id}/messages. This way no text stays in our delivery queues.
Every call has the headers LKDN-Event-Id, LKDN-Event-Type and LKDN-Signature: t=<secondi unix>,v1=<firma>. The signature is the HMAC-SHA256, in hexadecimal, of the string <t>.<corpo esatto> with your secret. Always verify it, and refuse a call older than 5 minutes:
// Node.js
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(secret, rawBody, header, now = Math.floor(Date.now() / 1000)) {
const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header ?? '');
if (!m || Math.abs(now - Number(m[1])) > 300) return false;
const expected = createHmac('sha256', secret).update(`${m[1]}.${rawBody}`).digest('hex');
return timingSafeEqual(Buffer.from(expected), Buffer.from(m[2]));
}
# Python
import hashlib, hmac, re, time
def verify(secret: str, raw_body: str, header: str) -> bool:
m = re.fullmatch(r"t=(\d+),v1=([0-9a-f]{64})", header or "")
if not m or abs(time.time() - int(m.group(1))) > 300:
return False
expected = hmac.new(secret.encode(), f"{m.group(1)}.{raw_body}".encode(), hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, m.group(2))
Answer with a 2xx code within 10 seconds. Otherwise we try again after 1, 5 and 30 minutes, then 2, 6, 12 and 24 hours; after 8 attempts the event is lost, and after 20 lost events in a row the webhook switches off (you switch it back on from the app). A 410 Gone switches it off at once for that event. The same event can arrive twice: use id to recognise it. We accept only https addresses on port 443, never internal or private addresses, and we do not follow redirects.
MCP server: Claude, ChatGPT, n8n #
The MCP server exposes the same functions as tools for an AI assistant, with the same key and the same limits: there is no path that skips them. The tools that act say so in their description, and ask the assistant to show you the exact text and wait for your yes.
Address:
https://ayuhpqrbmizgsjstmcrt.supabase.co/functions/v1/mcp
Authentication: Authorization: Bearer lkdn_sk_.... For software that does not let you set a header there is a form with the key in the address, .../functions/v1/mcp/lkdn_sk_...: treat it as a password, because whoever has the address has the key. Use a dedicated key for this, and a read-only one if reading is enough for the assistant.
Tools: get_my_profile, get_usage, get_person, visit_profile, list_person_posts, list_connections, find_search_filters, search_people, list_conversations, get_conversation_messages, send_message, start_conversation, list_invitations, send_invitation, withdraw_invitation, get_post, list_post_comments, list_post_reactions, publish_post, comment_on_post, react_to_post, get_company.
Claude Code #
claude mcp add --transport http lkdn-autopilot \
https://ayuhpqrbmizgsjstmcrt.supabase.co/functions/v1/mcp \
--header "Authorization: Bearer lkdn_sk_..."
Claude Desktop #
In Settings, Developer, Edit Config (claude_desktop_config.json), with the mcp-remote bridge (it needs Node.js):
{
"mcpServers": {
"lkdn-autopilot": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://ayuhpqrbmizgsjstmcrt.supabase.co/functions/v1/mcp",
"--header", "Authorization:Bearer ${LKDN_API_KEY}"],
"env": { "LKDN_API_KEY": "lkdn_sk_..." }
}
}
}
Restart Claude Desktop: the tools appear in the tools menu.
Claude.ai (custom connector) #
In Settings, Connectors, Add custom connector: as the URL use the form with the key in the address, https://ayuhpqrbmizgsjstmcrt.supabase.co/functions/v1/mcp/lkdn_sk_..., and leave the OAuth fields empty. The custom connector is available on the Claude plans that include it.
ChatGPT #
In Settings, Apps and connectors, with developer mode on: create a connector with the URL in the form with the key in the address and authentication "none". The tools that act ask for confirmation before going out.
n8n #
In the MCP Client Tool node of an AI Agent: Endpoint https://ayuhpqrbmizgsjstmcrt.supabase.co/functions/v1/mcp, HTTP Streamable transport, Bearer authentication with your key. For a flow without AI use the HTTP Request node on the REST API, with a "Header Auth" credential (Authorization = Bearer lkdn_sk_...), and a Webhook node as the destination of our webhooks.
Ready-made prompts #
To paste into Claude or ChatGPT with the MCP server connected.
Today's replies
Look at my unread LinkedIn conversations. For each one tell me who the person is (name, role, company),
what they wrote to me in one line, and whether you think it needs a reply today. Do not reply to anyone: suggest
a draft reply only for the ones that matter, and wait for my yes on every text.
Preparing for a meeting
Read the LinkedIn profile of <name or link> and their latest posts. Give me five lines: who they are, what they
work on now, what they wrote recently, one thing we have in common and one smart question to ask them.
Do not visit the profile with a notification and do not write to them.
Finding people for a segment
Search LinkedIn for owners and directors of dental practices in Veneto (use find_search_filters for the place).
Show me the first 10 in a table with name, role, city and degree of connection. Before searching, tell me
how many search results I have left today (get_usage). Do not send connection requests.
Connection requests with a real note
For each of these people <list of links>: read the profile, write me a connection note of at most
250 characters, in English, about something real in their profile, without selling anything and without links.
Show me all the notes. Send only the ones I approve, one at a time, and stop if the day's budget runs out.
Replying to comments on my posts
Take my latest post (look for it among the posts on my profile) and read the comments. For the ones I have not
replied to yet, suggest a short, friendly reply. Publish only the replies I approve.
The week's summary
Tell me how many connection requests I have had pending for more than two weeks and who they are. Suggest which
to withdraw. Do not withdraw any of them without my ok.
Rules that apply to every prompt: the assistant must not invent facts about the person, it must show you every text before sending it, and when it gets action_paced, daily_budget_exhausted or outside_activity_window it must stop and tell you.
Errors #
Every error has a stable code: it is a contract, it never changes meaning. Read the code, not the text.
| Status | code | What it means, what to do |
|---|---|---|
| 400 | invalid_request | a field is missing or not valid (field, detail say which) |
| 400 | invalid_cursor | cursor malformed, expired or from another list: start again from the first page |
| 400 | invalid_filter | a search filter does not come from GET /v1/search/filters |
| 400 | idempotency_key_required | Idempotency-Key is missing on a request that acts |
| 401 | invalid_api_key | key missing, unknown or revoked |
| 403 | insufficient_scope | the key does not have the write permission |
| 403 | api_access_not_enabled | the API is not enabled for your account |
| 403 | subscription_inactive | the subscription is not active |
| 403 | person_not_contactable | this person must not be contacted from this account |
| 403 | invitation_note_not_available | on your LinkedIn plan the request cannot have a note |
| 403 | linkedin_feature_missing | it needs a LinkedIn product the account does not have |
| 404 | not_found | the resource does not exist or does not belong to your account |
| 404 | route_not_found | the endpoint does not exist |
| 405 | method_not_allowed | the endpoint exists but not with this method |
| 409 | linkedin_not_connected | no LinkedIn account connected: connect it from the app |
| 409 | linkedin_reconnect_required | the account must be reconnected from the app |
| 409 | linkedin_account_unavailable | the account is suspended for now |
| 409 | account_paused | our team has paused the actions of this account |
| 409 | idempotency_in_progress | the request with this Idempotency-Key is still in progress or has not finished |
| 409 | already_connected | you are already connected |
| 409 | already_invited | there is already a pending request to this person |
| 422 | idempotency_key_reused | the same Idempotency-Key with a different request |
| 422 | invitation_not_allowed | LinkedIn does not allow another request to this person: final |
| 422 | recipient_unreachable | the person cannot be reached |
| 422 | not_first_degree | a message needs a first-degree connection: send a request or an InMail |
| 422 | inmail_not_allowed | this person cannot be sent an InMail |
| 422 | insufficient_inmail_credits | InMail credits used up |
| 422 | comments_disabled | comments are closed on this post |
| 422 | group_conversation_not_supported | group conversations are not supported |
| 422 | action_refused | LinkedIn refused the action |
| 422 | invalid_webhook | the webhook cannot be created (reason says why) |
| 429 | rate_limited | too many requests for this key: wait for Retry-After |
| 429 | daily_request_limit | the day's requests are used up for this account |
| 429 | daily_budget_exhausted | the day's budget for this action is used up, by the autopilot and the API together |
| 429 | weekly_budget_exhausted | the weekly budget of connection requests is used up |
| 429 | action_paced | actions spaced out to protect the account: wait for Retry-After |
| 429 | outside_activity_window | outside your working hours |
| 429 | linkedin_rate_limited | LinkedIn is limiting the account right now: try again later |
| 429 | account_backoff | LinkedIn asked the account to slow down: this action is paused until Retry-After |
| 500 | internal_error | an error on our side |
| 502 | linkedin_error | LinkedIn gave an answer we cannot read |
| 502 | action_outcome_unknown | the action may or may not have gone out: check before trying again |
| 503 | api_unavailable | the API is switched off right now |
| 503 | service_not_configured | the service is not configured yet |
| 503 | linkedin_unavailable | LinkedIn did not answer in time: try again later |
Privacy and responsibility #
- Messages in transit. The conversations and messages read through the API pass through us and reach you; we do not save them in our records or in our logs. The same goes for the texts you send: messages, notes, comments and posts go to LinkedIn and do not stay with us. Of the API traffic we record only what was asked (the type of request, the outcome, the duration), for 90 days, and the actions taken (what type, towards which person, when, without text), for 180 days, because they are needed to enforce the limits.
- You are the controller. For the data of the people you read and contact, you are the data controller, as with the autopilot; we are the data processor under the agreement (DPA) you accepted. If you keep conversations in your CRM, that storage is yours.
- What your software does, your account does. Every action taken with one of your keys, by your software or by an AI assistant you connected, is taken in your name and under your responsibility, towards LinkedIn and towards the people contacted, as set out in the Terms of service. Keep your keys safe and revoke at once any key you think has ended up in the wrong hands.
- LinkedIn's limits are real. LinkedIn does not like automated use: our limits exist to reduce the risk, they do not remove it. The risk of a restriction on the account remains yours.
What it does not do #
- It does not connect other accounts, and it does not create or delete the connection to LinkedIn: connecting is done only from the app.
- It does not give free access to LinkedIn: only the operations on this page, each with its own limits.
- It never exceeds the limits of your account, not even if you ask it to.
- It does not keep your conversations.
- It does not work with platforms other than LinkedIn.