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

# Send Message or Email

> Send a LinkedIn message or InMail, or an email — from a connected account.

## Overview

Sends a message from a connected account. For a **LinkedIn** account it's a direct message — or a [Sales Nav InMail](#inmail) with `inmail: true` / a `recipient_urn`. For an **email** account (see [Connect a mailbox](https://docs.linkupapi.com/api-reference/v2/accounts/login.md#email-mailbox)) it sends an email. For a **WhatsApp** account it sends a WhatsApp message to `phone_number`. For an **iMessage** line it sends an iMessage to `phone_number` (SMS when the contact has no iMessage). The `params` depend on the account's platform — each field below is tagged **(LinkedIn)**, **(Email)**, **(WhatsApp)**, **(iMessage)**, or several.

> [!NOTE]
>
> This endpoint consumes **1 credit** for a text message or email (**2 credits** with LinkedIn media). An InMail consumes **1 InMail credit** from the account's premium seat (separate from your API credits — see [Balance](https://docs.linkupapi.com/api-reference/v2/messages/balance.md)). Ignore this if you're on per-seat pricing: usage is unlimited.

> [!NOTE]
>
> `media_link`, `media_file` and `media_path` attach **one** file (priority: `media_link` > `media_file` > `media_path`). To send **several attachments in the same message**, use `media_links` and/or `media_files` (up to 10 files per message, combinable with the single-file params).

> [!NOTE]
>
> An audio file (`.m4a`, `.mp3`, `.wav`, `.aac`) is delivered as a **native voice note**, not a file to download. LinkedIn caps them at 1 minute.

## Request

**x-api-key** `string` *required*

Your API key for authentication.

**account\_id** `string` *required*

The unique identifier of the account to use.

**action** `string` *required*

Must be `"send"`.

**params** `object` *required*

**params properties**

**message\_text** `string` *required*

**(LinkedIn + Email + WhatsApp + iMessage)** The text content. Required for LinkedIn and iMessage; for email, provide `message_text` and/or `html`; for WhatsApp, `message_text` and/or an attachment. iMessage sending rules: see [iMessage limits](https://docs.linkupapi.com/api-reference/v2/best-practices.md#imessage-limits).
To tag someone in a LinkedIn message, use `mention_user(public_id, display_text)` (`public_id` = the slug of `linkedin.com/in/<public_id>`, or the profile URL) — e.g. `"Hi, meet mention_user(williamhgates, Bill Gates)!"` is sent as `Hi, meet @Bill Gates!` with Bill Gates tagged. An unknown profile returns an error and nothing is sent.

**subject** `string`

**(InMail + Email + iMessage)** Subject line. On LinkedIn it applies to InMails only (ignored for standard messages, and alone it does **not** trigger an InMail); on email it's the email subject; on iMessage, a bold title above the text.

**profile\_url** `string`

**(LinkedIn)** URL of the recipient's profile. Used for a standard message and an InMail (with `inmail: true`). Required unless you pass `recipient_urn` or `conversation_id`.

**conversation\_id** `string`

**(LinkedIn)** Reply into an existing thread, 1:1 or group, instead of addressing a person: pass the `conversation_id` from [List Inbox](https://docs.linkupapi.com/api-reference/v2/messages/list-inbox.md) or a webhook event, without `profile_url`. With `sales_nav: true` it is the Sales Navigator thread id (reply inside an InMail thread, no subject needed); with `recruiter: true`, the Recruiter thread id.

**inmail** `boolean` (default: false)

**(LinkedIn)** Set to `true` to send an **InMail** (to a non-connection, via the premium seat) instead of a standard message. Consumes 1 InMail credit. Not needed when `recipient_urn` is a Sales Nav URN.

**recipient\_urn** `string`

**(LinkedIn InMail)** The lead's `urn:li:fs_salesProfile:(...)` from the [lead search](https://docs.linkupapi.com/api-reference/v2/profiles/search-people-nav.md). Passing it sends an InMail. Use this **or** `profile_url` + `inmail: true`.

**recruiter** `boolean` (default: false)

**(LinkedIn Recruiter)** Send from the account's **Recruiter seat**. See [Recruiter InMail](#recruiter-inmail) below.

**phone\_number** `string`

**(WhatsApp + iMessage)** Recipient number in international format, e.g. `+33612345678`. Required for a WhatsApp account. On iMessage, pass `phone_number`, an Apple ID `email`, or a group `conversation_id`.

**effect** `string`

**(iMessage)** Message effect: `slam`, `loud`, `gentle`, `invisibleInk`, `echo`, `spotlight`, `balloons`, `confetti`, `love`, `lasers`, `fireworks`, `shootingStar` or `celebration`.

**to** `string`

**(Email)** Recipient email address. Required for an email account.

**html** `string`

**(Email)** HTML body. Provide `html` and/or `message_text`.

**reply\_to** `string`

**(Email)** Optional `Reply-To` address.

**thread\_ref** `string`

**(Email)** Message-ID to reply into an existing thread.

**cc** `string | string[]`

**(Email)** CC recipients (a comma-separated string or an array).

**bcc** `string | string[]`

**(Email)** BCC recipients — hidden from the other recipients (e.g. to log a copy into a CRM).

**custom\_headers** `object`

**(Email)** Extra `X-…` headers as a `{ name: value }` map — e.g. `{ "X-Campaign-Id": "camp-42" }` — to correlate replies/bounces back to your system.

**account\_ids** `string[]`

**(Email)** Optional pool of your own mailbox ids to route the send across (home-court + daily limits). `sent_from` in the response tells you which was used.

**media\_link** `string`

**(LinkedIn + Email + WhatsApp)** A publicly accessible URL to a file to attach.

**media\_file** `object`

**(LinkedIn + Email + WhatsApp)** A base64-encoded file to attach.

**media\_file properties**

**data** `string` *required*

The base64-encoded file content.

**filename** `string` *required*

The filename including extension (e.g. `"document.pdf"`).

**media\_path** `string`

**(LinkedIn + Email)** A server-side file path to a file to attach.

**media\_links** `string[]`

**(LinkedIn + Email + WhatsApp + iMessage)** Publicly accessible URLs of files to attach — all delivered in the same message. iMessage takes `https://` URLs only, up to 10.

**media\_files** `object[]`

**(LinkedIn + Email + WhatsApp)** Base64-encoded files to attach — same shape as `media_file` (`data`, `filename`).

**voice\_message** `boolean` (default: false)

**(LinkedIn + WhatsApp + iMessage)** Force the attached media to be sent as a **voice note**. Only needed when the filename carries no usable extension. On iMessage, a voice note is one audio link (mp3, wav, m4a, caf, aac) with no `message_text`.

**quoted\_message\_id** `string`

Reply to a specific message (quoted above yours, like the Reply action of the app). **LinkedIn:** the message's `entity_urn` from [Get Conversation](https://docs.linkupapi.com/api-reference/v2/messages/get-conversation.md) or `metadata.entity_urn` of a webhook event; the thread is resolved from `conversation_id` or `profile_url`, and the quoted message must be among the last 100 of the thread. **WhatsApp:** its `id` from Get Conversation. **iMessage:** its `message_id`.

## Response

**success** `boolean`

Indicates whether the request was successful.

**data** `object`

Details of the sent message. The shape differs between a LinkedIn standard message, an InMail, and an email.

**standard message**

**status** `string`

`"success"` when the message was sent.

**data** `object`

**properties**

**entityUrn** `string`

The unique URN of the sent message entity.

**conversation\_id** `string`

The URN of the conversation the message was sent in.

**deliveredAt** `integer`

Unix epoch timestamp in **milliseconds**.

**InMail**

**status** `string`

`"success"` when the InMail was sent.

**message** `string`

Human-readable result, e.g. `"InMail sent"`.

**recipient\_urn** `string`

The Sales Nav URN the InMail was sent to.

**data** `object`

Raw send result: `{ "value": { "threadId": "...", "messageId": "..." } }`.

**email**

**status** `string`

`"success"` when the email was sent.

**data** `object`

**properties**

**message\_id** `string`

The sent email's Message-ID.

**sent\_from** `string`

The mailbox address the email was sent from.

**esp** `string`

Sending mailbox provider bucket (`google` / `outlook` / `other`).

**recipient\_esp** `string`

Recipient's detected provider bucket.

**home\_court** `boolean`

`true` when sender and recipient are on the same provider.

**over\_cap** `boolean`

`true` when the mailbox is over its daily limit (the send still went out).

**mailbox\_health** `object`

`sends_today`, `daily_limit`, `bounce_rate` for the sending mailbox.

**metadata** `object`

**metadata properties**

**action** `string`

The action that was performed (`"send"`).

**account\_id** `string`

The account ID used for the request.

**credits\_consumed** `integer`

Number of credits consumed (1 for text, 2 with media).

**timestamp** `string`

ISO 8601 timestamp of the response.

```json 200 (message) theme={null}
{
  "success": true,
  "data": {
    "status": "success",
    "data": {
      "entityUrn": "urn:li:msg_message:(urn:li:fsd_profile:ACoAA...,2-MTc4NTI3...)",
      "conversation_id": "urn:li:msg_conversation:(urn:li:fsd_profile:ACoAA...,2-M2RkYWQ4...)",
      "deliveredAt": 1785272227840
    }
  },
  "metadata": {
    "action": "send",
    "account_id": "your-account-id",
    "credits_consumed": 1,
    "timestamp": "2026-03-24T12:00:00Z"
  }
}
```

```json 200 (InMail) theme={null}
{
  "success": true,
  "data": {
    "status": "success",
    "message": "InMail sent",
    "recipient_urn": "urn:li:fs_salesProfile:(ACwAAA...,name, )",
    "data": {
      "value": {
        "threadId": "2-OTQwMTJlODEt...",
        "messageId": "2-MTc4NTIyODc1..."
      }
    }
  },
  "metadata": {
    "action": "send",
    "account_id": "your-account-id",
    "credits_consumed": 1,
    "timestamp": "2026-03-24T12:00:00Z"
  }
}
```

```json 200 (email) theme={null}
{
  "success": true,
  "data": {
    "status": "success",
    "data": {
      "message_id": "<...@gmail.com>",
      "sent_from": "you@company.com",
      "esp": "google",
      "recipient_esp": "other",
      "home_court": false,
      "over_cap": false,
      "mailbox_health": { "sends_today": 1, "daily_limit": 40, "bounce_rate": 0.0 }
    }
  },
  "metadata": { "action": "send", "account_id": "your-email-account-id", "credits_consumed": 1, "timestamp": "2026-09-14T12:00:00Z" }
}
```

```json 200 (WhatsApp) theme={null}
{
  "success": true,
  "data": {
    "status": "success",
    "data": {
      "entityUrn": "3EB05338283099EC87F1F8",
      "conversation_id": "33612345678@s.whatsapp.net",
      "deliveredAt": 1790436783000,
      "phone_number": "33612345678"
    }
  },
  "metadata": { "action": "send", "account_id": "your-whatsapp-account-id", "credits_consumed": 1, "timestamp": "2026-09-26T15:33:03Z" }
}
```

```json 400 theme={null}
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "message_text is required"
  },
  "metadata": {
    "action": "send",
    "account_id": "your-account-id",
    "credits_consumed": 0,
    "timestamp": "2026-03-24T12:00:00Z"
  }
}
```

## React, edit or delete a message

Same endpoint, classic LinkedIn messages only, 1 credit each. `message_id` is the message URN: `entity_urn` from [Get Conversation](https://docs.linkupapi.com/api-reference/v2/messages/get-conversation.md) or from a webhook event (a bare `2-…` id works with `conversation_id`). Only the account's own messages can be edited or deleted, within 60 minutes of sending them.

| `action` | `params` |
| - | - |
| `react_message` | `message_id`, `emoji`, `remove?` (`true` removes the reaction) |
| `edit_message` | `message_id`, `message_text` |
| `delete_message` | `message_id` (unsends it for everyone) |

**iMessage:** `react_message` works too, with the `message_id` of the message: `emoji` is a tapback (`love`, `like`, `dislike`, `laugh`, `emphasize`, `question`) or any emoji. Not in group chats. `action: "typing"` with `conversation_id` (and `seconds`, 60 max) shows the typing indicator, in a conversation active in the last 5 minutes.

```json theme={null}
{
  "account_id": "your-account-id",
  "action": "react_message",
  "params": { "message_id": "urn:li:msg_message:(urn:li:fsd_profile:ACoAAD...,2-MTc5...)", "emoji": "👍" }
}
```

## InMail

Reaches someone you are not connected to, through the account's premium seat. Triggered by `inmail: true` or a `recipient_urn` — a `subject` alone never turns a message into an InMail. Prefer `recipient_urn` from the [lead search](https://docs.linkupapi.com/api-reference/v2/profiles/search-people-nav.md) when you have it.

```json theme={null}
{
  "account_id": "your-account-id",
  "action": "send",
  "params": {
    "recipient_urn": "urn:li:fs_salesProfile:(...)",
    "subject": "Quick question",
    "message_text": "Hi ..."
  }
}
```

A profile that cannot be InMailed is rejected before any credit is spent. Credits come from the seat — see [Balance](https://docs.linkupapi.com/api-reference/v2/messages/balance.md).

## Recruiter InMail

Set `recruiter: true`.

**New InMail** — `recipient_urn` (the candidate's `profile_urn` from [Search People Recruiter](https://docs.linkupapi.com/api-reference/v2/profiles/search-people-recruiter.md)), `subject` and `message_text`. Optional:

* `project_urn` — the thread is also filed in that [project](https://docs.linkupapi.com/api-reference/v2/recruiter/projects.md)
* `signature` — replaces the seat's own signature, appended by default

**Reply** — `conversation_id` (from [List Inbox](https://docs.linkupapi.com/api-reference/v2/messages/list-inbox.md#recruiter-inbox)) and `message_text`. No subject. The candidate is read off the thread; pass `recipient_urn` to save that lookup.

```json theme={null}
{
  "account_id": "your-account-id",
  "action": "send",
  "params": {
    "recruiter": true,
    "recipient_urn": "urn:li:ts_profile:AEMAA…",
    "subject": "Growth role in Paris",
    "message_text": "Hi Jane, ..."
  }
}
```

Returns the `conversation_id` of the thread. Consumes **1 credit** plus **1 Recruiter InMail credit** when the candidate is not free to InMail (see [Check InMail](https://docs.linkupapi.com/api-reference/v2/profiles/check-inmail.md#recruiter)).

## Email

Sending from an [email mailbox](https://docs.linkupapi.com/api-reference/v2/accounts/login.md#email-mailbox) uses the same `params` above — `to` + `subject` + `message_text` (and/or `html`):

```json theme={null}
{
  "account_id": "your-email-account-id",
  "action": "send",
  "params": { "to": "prospect@example.com", "subject": "Quick question", "message_text": "Hi there, ..." }
}
```

## WhatsApp

Sending from a [WhatsApp account](https://docs.linkupapi.com/api-reference/v2/accounts/login.md#whatsapp) uses `phone_number` + `message_text`:

```json theme={null}
{
  "account_id": "your-whatsapp-account-id",
  "action": "send",
  "params": { "phone_number": "+33612345678", "message_text": "Hi there, ..." }
}
```

A number without WhatsApp returns `CHANNEL_ERROR` (422). Check numbers first with [Check Numbers](https://docs.linkupapi.com/api-reference/v2/messages/check-numbers.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.