---
title: "Send LinkedIn connection requests"
method: POST
path: "/connect/linkedin/profile"
tags: ["actions"]
---

# Send LinkedIn connection requests

`POST /connect/linkedin/profile`

Invite named people only (a name, "the second one", a pronoun just used) from the connected LinkedIn account, with an optional note. A described criterion is not a send: peek then propose with filter_contacts intent:"connect" and let the human click. Pass the exact profile URL from the row. No separate visit is needed first. One call for one person, one call with the array for several. The invitation is queued and goes out on its own: say queued, never drafted or waiting for approval, and never sent until the result shows it left. Report position when it helps; never turn it into a time. Anyone already invited, already connected, or on a do-not-contact list is refused with the reason.

## Request body

- object
  - `profile` union, required — One LinkedIn profile, or many. Accepts full URLs (e.g. https://www.linkedin.com/in/username), vanity names (e.g. john-doe), or profile URNs (e.g. urn:li:fsd_profile:ACoAAA...).
    - string
    - string[]
  - `knownPeople` object[] — Optional identity already known for people in this call, matched by profile URL. Omit when you only have the URL. A new contact must not be named from the URL slug when a real name is already known.
    - `profile` string, required
    - `name` string
    - `headline` string
    - `company` string
    - `location` string
    - `avatarUrl` string
  - `message` string — Optional note to include with the invitation, the same note for everyone in this call. Maximum 300 characters. Leaving it out sends a bare invitation, which is the default and often accepted more often.
  - `now` boolean — Try to send one of them inside this call and return the real result, rather than only reporting where they stand. Anyone named here already goes to the front of the line, with or without this. Either way nothing is sent faster than the account can safely send.
  - `list` string — Name of the list to add them to. Lists are just a way to keep separate pieces of work apart, and each one belongs to a single LinkedIn account. Omit to use this account's default list.
  - `campaignSlug` string — Optional label for grouping. Duplicates are refused automatically, with or without it.
  - `actionSlug` string — Deprecated. Use campaignSlug only.
  - `dryRun` boolean — Report what this call would do without doing any of it: nothing is added to any list, no invitation is attempted, and nothing is sent, ever, no matter what else is set. Use this to see the target list's real size and pause state, and each profile's real eligibility, before committing to a real call.

## Response `200`

Connection request sent successfully

- object
  - `success` true, required
  - `message` string, required
  - `sent` number, required — How many invitations actually reached LinkedIn during this call.
  - `queued` object[], required — Everyone now waiting, in the order they will go out.
    - `profile` string, required
    - `position` number, required — Place in line for this account, 1 being next.
    - `etaDays` number, nullable, required — Rough wait in days, from how fast this account has actually been sending. Null when there is no history to estimate from, and null whenever the account is blocked, because the wait then depends on it recovering rather than on how fast it sends.
  - `skipped` object[], required — Anyone not added, each with the reason in plain words.
    - `profile` string, required
    - `reason` string, required
  - `blocked` object, nullable, required — Set when the account itself cannot send right now. Nothing goes out until this clears, and resumesAt is null when clearing it needs a person.
    - `kind` string, required — Which kind of block, as a stable code: paused, session_dead, challenge, rate_limited, invite_cap, no_credit, outside_window, paced. Read this rather than the message when deciding how to present it.
    - `clearsItself` boolean, required — True when the block expires on its own; false when a person has to do something (open LinkedIn, reconnect the account).
    - `message` string, required
    - `resumesAt` string, nullable, required
  - `duplicate` boolean — True if every profile in the request was already invited from this account.
  - `dryRun` boolean — True when this was a preview: nothing was added, attempted, or sent. Everything else in this response describes what a real call would do right now.
  - `list` object — Only present on a dryRun response: which list this call would actually target, and its real current state.
    - `name` string, required
    - `isNew` boolean, required — True if this exact list does not exist yet and a real call would create it.
    - `totalMembers` number, required — How many people are already in this list, before this call.
    - `paused` boolean, required — A paused list sends nothing, ever, until it's resumed, regardless of anything else in this response.
  - `creditsUsed` integer, required — Credits consumed by this call. 0 for free endpoints, cached results, duplicates, and for every query that does not touch LinkedIn.
  - `retryAfter` integer, required — Seconds to wait before another call of the same type. 0 means no wait is needed.
  - `_meta` object — Credit balance carried on every response so a caller never has to ask for it separately. Absent when the caller has no connected account.
    - `credits` object, required
      - `current` number, required — Credits spent this period.
      - `limit` number, nullable, required — Period allowance, or null when unlimited.
      - `remaining` number, nullable, required — Allowance left, or null when unlimited.
      - `percentage` number, required — Share of the allowance spent, 0 to 100.
      - `isUnlimited` boolean, required
      - `accountPlan` string, required — The credential's plan.

## Other responses

- `400` — The server cannot or will not process the request due to something that is perceived to be a client error.
- `401` — Although HTTP specifies "unauthorized", this response means "unauthenticated". Authenticate to continue. NOTE: 401 is also returned with code "linkedin_not_connected" when the caller IS authenticated but has no connected LinkedIn account — connect LinkedIn (not re-authenticate) to continue.
- `403` — The client does not have access rights to the content.
- `404` — The server cannot find the requested resource.
- `409` — The request conflicts with the current state of the server.
- `410` — The requested content has been permanently deleted from the server.
- `422` — The request was well-formed but was unable to be followed due to semantic errors.
- `429` — Rate limit exceeded. Read error.retryAfter for the wait time in seconds.
- `500` — The server encountered a situation it does not know how to handle.
- `502` — LinkedIn returned a server error or the proxy connection failed. Retry after a few seconds.
- `503` — Proxy capacity temporarily exceeded. Retry after a few seconds.

---

[API](https://skmtc.net/berea/apis/bereach-api.md) · [All operations](https://skmtc.net/berea/apis/bereach-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/berea/bereach-api/revisions/9217eedacbb8/schema)
