> ## Documentation Index
> Fetch the complete documentation index at: https://www.outx.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# LinkedIn Connection Request API - Send Connection Requests

> Send LinkedIn connection requests programmatically using the OutX LinkedIn Connection Request API.

<script type="application/ld+json">
  {`{
    "@context": "https://schema.org",
    "@type": "WebAPI",
    "name": "OutX LinkedIn Connection Request API",
    "url": "https://api.outx.ai/linkedin-agent/send-connection-request",
    "description": "Send LinkedIn connection requests programmatically via API.",
    "documentation": "https://outx.ai/docs/linkedin-api/send-connection-request",
    "provider": {
      "@type": "Organization",
      "name": "OutX.ai",
      "url": "https://www.outx.ai"
    }
    }`}
</script>

The Send Connection Request endpoint creates an async task to send a LinkedIn connection request from your team's oldest admin member's LinkedIn account. The API itself only creates the task; the browser extension performs the LinkedIn action.

## Endpoint

```
POST https://api.outx.ai/linkedin-agent/send-connection-request
```

## Request Body

<ParamField body="profile_urn" type="string" required>
  LinkedIn profile URN for the invitee (a `urn:li:fsd_profile:...` string).
  You can also pass the URN without the `urn:li:fsd_profile:` prefix, the plugin will normalize it.
</ParamField>

<Note>
  To resolve a LinkedIn profile URL (for example `https://www.linkedin.com/in/williamhgates`) into a `profile_urn`, call the [Fetch Profile](/linkedin-api/fetch-profile) endpoint first and use the URN it returns.
</Note>

<ParamField body="note" type="string">
  Optional personal note to include with the invitation. Maximum 300 characters.
  When omitted, empty, or whitespace-only, the invitation is sent without a note.
  Leading and trailing whitespace is trimmed.
</ParamField>

## Response

The endpoint returns immediately with a task ID:

<ResponseField name="success" type="boolean">
  Whether the task was created successfully
</ResponseField>

<ResponseField name="api_agent_task_id" type="string">
  UUID to poll for results via [Get Task Status](/linkedin-api/get-task-status)
</ResponseField>

<ResponseField name="message" type="string">
  Human-readable confirmation
</ResponseField>

<ResponseExample>
  ```json Response theme={null}
  {
    "success": true,
    "api_agent_task_id": "550e8400-e29b-41d4-a716-446655440000",
    "message": "Send connection request task created successfully"
  }
  ```
</ResponseExample>

## Polling for Results

Poll the [Get Task Status](/linkedin-api/get-task-status) endpoint until the status is `completed`:

```
GET https://api.outx.ai/linkedin-agent/get-task-status?api_agent_task_id=550e8400-e29b-41d4-a716-446655440000
```

### Completed Response

When the task finishes, `task_output` will include:

```json theme={null}
{
  "sent": true
}
```

## Code Examples

<RequestExample>
  ```bash cURL theme={null}
  # Send a connection request without a note
  curl -X POST \
    "https://api.outx.ai/linkedin-agent/send-connection-request" \
    -H "Content-Type: application/json" \
    -H "x-api-key: YOUR_API_KEY" \
    -d '{
      "profile_urn": "urn:li:fsd_profile:ACoAABCDEF123"
    }'

  # Send a connection request with an optional personal note
  curl -X POST \
    "https://api.outx.ai/linkedin-agent/send-connection-request" \
    -H "Content-Type: application/json" \
    -H "x-api-key: YOUR_API_KEY" \
    -d '{
      "profile_urn": "urn:li:fsd_profile:ACoAABCDEF123",
      "note": "Hi, I came across your work and would love to connect."
    }'

  # Check the result
  curl -X GET \
    "https://api.outx.ai/linkedin-agent/get-task-status?api_agent_task_id=TASK_ID" \
    -H "x-api-key: YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  async function sendConnectionRequest(profileUrn, note) {
    const body = { profile_urn: profileUrn };
    if (note) body.note = note;

    const response = await fetch(
      "https://api.outx.ai/linkedin-agent/send-connection-request",
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "x-api-key": "YOUR_API_KEY",
        },
        body: JSON.stringify(body),
      }
    );

    const { api_agent_task_id } = await response.json();

    // Poll for completion
    while (true) {
      const statusRes = await fetch(
        `https://api.outx.ai/linkedin-agent/get-task-status?api_agent_task_id=${api_agent_task_id}`,
        { headers: { "x-api-key": "YOUR_API_KEY" } }
      );

      const result = await statusRes.json();
      if (result.data.status === "completed") {
        return result.data.task_output; // { sent: true }
      }

      await new Promise((r) => setTimeout(r, 5000));
    }
  }

  // Without a note
  const result = await sendConnectionRequest("urn:li:fsd_profile:ACoAABCDEF123");
  console.log(result); // { sent: true }

  // With an optional personal note
  const resultWithNote = await sendConnectionRequest(
    "urn:li:fsd_profile:ACoAABCDEF123",
    "Hi, I came across your work and would love to connect."
  );
  console.log(resultWithNote); // { sent: true }
  ```

  ```python Python theme={null}
  import requests
  import time

  def send_connection_request(profile_urn, note=None):
      headers = {
          "Content-Type": "application/json",
          "x-api-key": "YOUR_API_KEY",
      }

      payload = {"profile_urn": profile_urn}
      if note:
          payload["note"] = note

      response = requests.post(
          "https://api.outx.ai/linkedin-agent/send-connection-request",
          headers=headers,
          json=payload,
      )
      task_id = response.json()["api_agent_task_id"]

      while True:
          result = requests.get(
              "https://api.outx.ai/linkedin-agent/get-task-status",
              headers={"x-api-key": "YOUR_API_KEY"},
              params={"api_agent_task_id": task_id},
          ).json()

          if result["data"]["status"] == "completed":
              return result["data"]["task_output"]  # {"sent": True}

          time.sleep(5)

  # Without a note
  print(send_connection_request("urn:li:fsd_profile:ACoAABCDEF123"))

  # With an optional personal note
  print(send_connection_request(
      "urn:li:fsd_profile:ACoAABCDEF123",
      note="Hi, I came across your work and would love to connect.",
  ))
  ```
</RequestExample>

## Error Responses

| Status | Error                                             | Description                                                                                                                                                                       |
| ------ | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | `Missing or invalid 'profile_urn'`                | The `profile_urn` field is missing or not a string                                                                                                                                |
| `400`  | `Invalid 'note': must be a string`                | The `note` field was provided but is not a string                                                                                                                                 |
| `400`  | `Invalid 'note': must be 300 characters or fewer` | The `note` exceeds LinkedIn's 300 character limit (measured after trimming whitespace)                                                                                            |
| `401`  | `Missing API Key` / `Invalid API Key`             | API key is missing or invalid                                                                                                                                                     |
| `403`  | `Plugin installation required...`                 | No team member has an active Chrome extension. See [Authentication](/api-reference/authentication)                                                                                |
| `404`  | `No admin user found in the team`                 | Your team has no admin members                                                                                                                                                    |
| `429`  | `LinkedIn invitation limit reached`               | LinkedIn has temporarily blocked further invitations from the sending account because its custom (weekly) invite limit has been hit. Wait for the limit to reset before retrying. |

## FAQ

<AccordionGroup>
  <Accordion title="Who sends the connection request?">
    The connection request is executed from your team's **oldest admin member's** LinkedIn account (sorted by when they joined the team).
  </Accordion>

  <Accordion title="Can I include a custom message with the request?">
    Yes. Pass an optional `note` field (up to 300 characters) in the request body to include a personal message with the invitation. Omit `note` (or leave it empty) to send the invitation without a message.
  </Accordion>

  <Accordion title="What is the correct profile URN format?">
    Use a LinkedIn `fsd_profile` URN (for example: `urn:li:fsd_profile:ACoA...`).
    If you omit the `urn:li:fsd_profile:` prefix, the plugin will normalize it automatically.
  </Accordion>
</AccordionGroup>

## Related

* [Get Task Status](/linkedin-api/get-task-status) - Poll for task results
* [Fetch Profile](/linkedin-api/fetch-profile) - Get a profile URN for use as `profile_urn`

***

## Learn More

* [LinkedIn Automation Safety Guide](https://www.outx.ai/blog/linkedin-automation-safety-guide-best-practices-2026)
