Public Beta: Direct engineering support available. Join Discord →
Docs
Recipes
LinkedIn: Route Organization Webhooks

Route LinkedIn Organization Webhooks

Time: ~10 minutes | Difficulty: Beginner | Prerequisites: A LinkedIn developer application with webhook access approved by LinkedIn, admin access to the organization page, Slashbin account

TL;DR: LinkedIn puts the event type at data.type, one level inside the body — not at the top of it like Stripe and Square, and not in a header like Shopify and GitHub. A routing rule written against a top-level field matches nothing, and matching nothing produces no error at all. Route LinkedIn through Slashbin, point your rules at $.data.type, and the events you are not matching are visible instead of invisible.


The Problem

You wire up LinkedIn organization events — social actions on your company page, lead form submissions, apply-connect notifications — and nothing reaches your CRM.

Nothing is also what you get when you look for the cause:

  • Your routing rule matches nothing. You wrote it against type, because that is where Stripe and Square put it. LinkedIn puts it at data.type. The rule is syntactically fine and semantically empty.
  • An unmatched event is not an error. No exception is thrown, no 4xx is returned, no alert fires. The request was accepted and verified; it simply did not match anything you asked for.
  • Which makes it indistinguishable from "no events arrived." Both look like an empty dashboard. One is a one-character path fix; the other is a LinkedIn-side configuration problem. Without a record of what actually arrived, you cannot tell which you have.
  • And LinkedIn's own tooling won't tell you. There is no delivery panel on LinkedIn's side you can open to compare what it sent against what you matched.

Two failure modes with one symptom, and the symptom is silence.

⚠️

LinkedIn's webhook access is gated by LinkedIn, not by Slashbin. The APIs that emit organization event notifications sit behind LinkedIn's developer partner programs, and you need your application approved for the relevant products before any event is sent to any URL. Slashbin's side works the moment you have credentials — but if your application has not been approved, the silence described above has a third cause, and no amount of routing configuration will fix it. Confirm your access with LinkedIn first.

And a fourth cause shows up only after everything has already been working:

  • It worked, and then it stopped. LinkedIn re-validates registered endpoints with a challenge-response check roughly every 2 hours. An endpoint that stops answering that check is deactivated on LinkedIn's side — the events simply cease, with no error delivered to you. If a working integration goes quiet, confirm the validation is still being answered before you look at anything else.

The Solution

Route LinkedIn through a Slashbin project. Verification happens at the gateway from stored configuration, and every event is recorded end-to-end:

  • The raw payload exactly as LinkedIn sent it — bytes and headers.
  • The resolved topic — what Slashbin read out of $.data.type for that specific event.
  • The transform result — what your Golden Model produced, or the error it threw.
  • Every delivery attempt to your endpoint — response code, response body, and timing.
  • The final disposition — delivered, retrying, or in the Dead Letter Queue.

Outcome: Silence becomes a record. If an event arrived and matched no rule, you can read the topic it actually carried and fix the path. If nothing arrived at all, you know to go back to LinkedIn.


Step 1: Create a LinkedIn Project in Slashbin

  1. Click Create New Project and select LinkedIn.
  2. Type: Choose Transactional — a lead form submission or a social action is a discrete business event, not a metric.

Selecting LinkedIn loads its verification contract into the project:

FieldLinkedIn's value
Auth typeHMAC
Signature headerx-li-signature
Signature encodinghex
Signature prefix(none)
Signed payloadthe raw request body
Event topic$.data.type, read from the body

Slashbin's gateway has no LinkedIn-specific code path. LinkedIn works because that contract is stored and applied on every request — the same mechanism that verifies Stripe, Square, Shopify and GitHub.


Step 2: Paste the HMAC Secret Key

The wizard labels the field HMAC Secret Key. Enter the secret LinkedIn signs its notifications with, from your LinkedIn developer application.

Slashbin computes HMAC-SHA256 over the raw request body with that key, hex-encodes the digest, and compares it to x-li-signature in constant time. Verification runs before your Golden Model and before any destination is contacted, so an unsigned or mis-signed request never reaches your systems.

⚠️

Hex does not imply a prefix. LinkedIn sends a bare hex digest in x-li-signature. GitHub sends the same encoding — hex — in x-hub-signature-256, but prefixed with the literal string sha256=. If you already implemented GitHub's check and reused it for LinkedIn, you will be comparing sha256=<digest> against <digest> and every event will fail verification with an error indistinguishable from a wrong key. See Debug and Route GitHub Webhooks for the prefixed side of the same encoding.


Step 3: Register the Slashbin Ingestion URL With LinkedIn

  1. Copy the Ingestion URL from the Slashbin project dashboard.
  2. In your LinkedIn developer application, register it as the notification URL for the organization events your application has been approved for.
  3. Confirm on LinkedIn's side that the organization whose events you want is authorized for your application.
⚠️

Registration is not a one-time handshake. LinkedIn requires a challenge-response validation endpoint and re-sends that challenge to the URL you registered roughly every 2 hours, for as long as the registration is live. An endpoint that stops answering the check is deactivated on LinkedIn's side: delivery stops and no error is sent to you. Confirm in the LinkedIn Developer Portal that your webhook registration is still active — and check it first if a working integration goes quiet.

Then open the Slashbin Delivery Log and wait for the first real event. A verified delivery in that log is the proof that the secret matches on both sides — and, just as usefully, an empty log after a known action on the page tells you the problem is upstream of Slashbin.


Step 4: Route on data.type and Deliver

The topic is nested

This is the fact worth the page. A LinkedIn organization event arrives shaped like this:

{
  "id": "urn:li:event:8462013975",
  "time": 1785196982000,
  "data": {
    "type": "ORGANIZATION_SOCIAL_ACTION_NOTIFICATIONS",
    "organization": "urn:li:organization:2414183",
    "actor": "urn:li:person:AbC1dEfGh2"
  }
}

The routing key is ORGANIZATION_SOCIAL_ACTION_NOTIFICATIONS, and it lives at $.data.type — inside the data object, not at the top of the body.

Compare that with the sources already documented:

SourceWhere the topic lives
GitHubx-github-event — a header
Shopifya header
Stripetypetop level in the body
Squaretypetop level in the body
Typeformevent_typetop level in the body
LinkedIn$.data.type — nested one level down

A rule written against top-level type on a LinkedIn project does not error. It reads a field that is not there, resolves to nothing, and matches nothing — which is why this specific mistake costs an afternoon rather than a minute. Write the full path.

Then deliver

On the Outbound tab, click + Add Destination and point each topic at the system that should own it — your CRM for lead events, an internal service for social actions, or both at once. One event can fan out to several destinations, each with its own retry policy.

From there the guarantees are Slashbin's:

  • Transient failure → retry with backoff. Your CRM returning 502 for ninety seconds costs you nothing.
  • Exhausted attempts → the Dead Letter Queue, holding the original raw payload rather than a summary of it.
  • Fixed the handler → Replay. Slashbin re-delivers from its own storage; LinkedIn is not involved and does not need to be.
  • Unmatched events surface instead of vanishing. An event whose data.type matched no rule is recorded, so the routing mistake in this section is one you can see and correct.

Why Slashbin vs a Raw Handler

  • The bare-hex-versus-prefixed-hex trap disappears. x-li-signature, hex, no prefix, raw body — applied at the gateway as configuration. You never write the check, so you never write it wrong, and adding LinkedIn next to GitHub does not mean maintaining two nearly-identical verification functions.
  • Nested-path routing without body-parsing code. $.data.type becomes a routing rule instead of an if-else chain reaching into body.data.
  • Silence becomes evidence. The stored payload and resolved topic tell you whether an event arrived and missed your rules, or never arrived at all — the one distinction LinkedIn's own tooling will not make for you.
  • Delivery is retried and replayable from Slashbin's storage, on your schedule.

Next Steps