---
title: "Activity on a legacy LinkedIn campaign"
method: POST
path: "linkedinCampaignActivity"
tags: ["Webhooks"]
---

# Activity on a legacy LinkedIn campaign

`POST linkedinCampaignActivity` (webhook)

Sent to URLs registered with `type: linkedin` or `linkedin: true`.

- `VISITED`: profile visited.
- `INVITED`: invitation sent. When the contact was already a connection, `INVITED` and `ACCEPTED` are sent together.
- `ACCEPTED`: acceptance detected (connections polling, inferred from a reply, or real time LinkedIn notification).
- `MESSAGE_SENT`: message sent, text in `content`.
- `INMAIL_SENT`: InMail sent.
- `REPLIED`: first reply detected, with `reply` and `sentiment`.

`LIKED`, `FOLLOWED` and `CAMPAIGN_ENDING` are never sent for these campaigns. Most events come from the LinkedIn worker (contact without `id` nor `email`). Replies and acceptances detected in real time come from the API server and add `campaignId`, `contact.id` and `contact.email`; that path retries once on network errors, the worker never retries.

**Delivery.** One `POST` per event and per registered URL, header `Content-Type: application/json`, JSON body, no signature or secret header, default User-Agent of the HTTP library. No timeout is set. Your response (status and body) is ignored: an HTTP error is never retried. Network errors are retried only for some events (see each list). No event ID, no ordering guarantee, no replay; a URL registered twice receives everything twice. Absent fields are omitted, never null.

## Payload

- WebhookLinkedinActivityPayload
  - `event` 'VISITED' | 'INVITED' | 'ACCEPTED' | 'MESSAGE_SENT' | 'INMAIL_SENT' | 'REPLIED', required: Events delivered for legacy LinkedIn campaigns (`type: linkedin`). `LIKED`, `FOLLOWED` and `CAMPAIGN_ENDING` are never delivered for these campaigns.
  - `campaign` string, required: Campaign name.
  - `campaignId` string: Only on replies and acceptances detected in real time.
  - `contact` WebhookLinkedinContact, required: Contact of a legacy LinkedIn campaign: custom fields first, then the standard fields. `id` (Emelia contact ID) and `email` are only present when the event was detected in real time by the API server (replies and acceptances); events from the LinkedIn worker never have them.
    - `id` string: Real time replies and acceptances only.
    - `firstName` string
    - `lastName` string
    - `email` string: Real time replies and acceptances only.
    - `linkedinUrlProfile` string, uri
    - `linkedinId` string: LinkedIn member ID.
    - `company` string
  - `date` string, date-time, required: ISO 8601 UTC. Action time, or message time for replies.
  - `step` integer, required: 0 based index of the sequence step (-1 when not resolved).
  - `reply` string: REPLIED only.
  - `sentiment` WebhookSentiment: AI classification of a reply. Present only when reply classification is enabled on the account and AI credits remain. Classified by Jev, with Gemini as fallback; only the Gemini fallback can add `additionalData`.
    - `classification` 'INTERESTED' | 'NOT_INTERESTED' | 'NEUTRAL' | 'OUT_OF_OFFICE' | 'HOSTILE' | 'DELEGATION' | 'INCOMPREHENSION' | 'QUESTION_ASK'
    - `score` number: Confidence of the classification.
    - `additionalData` object: Gemini fallback only: `delegationEmail` for DELEGATION, `returnDate` (DD/MM/YYYY) for OUT_OF_OFFICE.
      - `delegationEmail` string
      - `returnDate` string
  - `content` string: MESSAGE_SENT only: text of the message sent.

## Acknowledgement `2XX`

Any response is accepted. Emelia ignores the status and the body.

## Other responses

- `default`: Ignored too: errors are not retried and the webhook stays active.

---

[API](https://skmtc.dev/emelia/apis/emelia-api.md) · [All operations](https://skmtc.dev/emelia/apis/emelia-api/llms.txt) · [OpenAPI document](https://skmtc.dev/emelia/apis/emelia-api/revisions/8c0cb435f2c4?raw)
