NewSales Navigator search on our seats — no licence needed

The LinkedIn API, built for builders.

The complete LinkedIn record, fetched live. Other APIs resell a database crawled months ago with half the fields missing — Edges unmasks every data point at the moment you ask. Full work history, exact employee counts, funding rounds, Sales Navigator IDs, this morning’s posts. Two entities: People and Companies. One API key.

Edges is not related to LinkedIn and is not an official LinkedIn product.

curl -X POST \ https://api.edges.run/v1/actions/linkedin-extract-people/run/live \ -H "X-API-Key: $EDGES_API_KEY" \ -H "Content-Type: application/json" \ -d '{"input":{"linkedin_profile_url":"linkedin.com/in/jane-doe"}}'
Almost there. Grab a key at app.edges.run, then rerun this.
Freshness
100%

read at request time

Coverage
38

fields per person · 41 per company

Reachable
750M

people · 54M companies · any URL

Actions
70+

read and write, same key

“We used to keep a fleet of LinkedIn accounts alive just to read public data — cookies expiring, profiles getting flagged, someone on-call for it every week. With Edges we pull profiles without connecting a single account, and when we do need to send an invite or a message, it’s the same API key. That deleted an entire class of problems for us.”
AurélienCEO, CargoCargo

// used by

// Two ways in

Use our access, or use yours.

Both modes hit the same actions, the same schema, the same key. The only difference is whose access the call runs on.

ManagedSales Navigator included

We bring the access.

No cookies, no LinkedIn account, no warmup, no seats to babysit. You send a URL, you get the complete record back. Most teams never build anything else.

Sales Navigator search on our seats — no Sales Nav licence of your own
Zero credentials in your codebase
Scales well past a single account’s ceiling
// nothing to configure
const { data: profile } = await edges.linkedin.extractPeople({
  input: { linkedin_profile_url: url }
})

// Sales Navigator search — our seats, not yours
const { data: leads } = await edges.salesnavigator.searchPeople({
  input: { title: "VP Product", headcount: "51-200" }
})
Connected

You bring the account.

Attach your own LinkedIn or Sales Navigator seats when the call has to come from a specific identity — messages, invites, your saved searches, your lead lists.

Connect a seat with a cookie or email + password
Write actions from a real, named identity
Your Sales Nav searches, lists and smart links
// 1 · register the identity once
await edges.core.createIdentity({
  input: {
    email: "alex@yourco.com",
    password: "••••••••"
  }
})

// 2 · same call, your identity
const { data } = await edges.linkedin.messageProfile({
  input: { linkedin_profile_url: url, text },
  identity: "alex@yourco.com"
})

Managed Sales Navigator access is rare — almost every other LinkedIn API makes you supply your own seat.

// The difference

The same profile, from a database and from the source.

Resold datasets return what was true when they crawled it, minus every field their crawler couldn't see. Ours goes and gets it.

Resold datasetscached crawl
job_titleheadline string, unparsed
experiences[ ]truncated · 2–3 roles
number_employeesbucketed range only
sales_navigator_*_idnot available
last_funding_*not available
post activitynot available
freshnesscrawled weeks ago
Edgeslive, unmasked
job_titleparsed, with company + dates
experiences[ ]full history, every role
number_employeesexact count, not a bucket
sales_navigator_*_idresolved on every record
last_funding_*date, type, amount, investors
post activityposts, reactions, commenters
freshnessfetched at call time

No stock of data to go stale. Highest freshness because it’s read now; highest coverage because nothing is masked.

See it on a profile you know.

100 free credits, no card. Paste any LinkedIn URL and compare the response to whatever you’re using today.

// Infrastructure

Getting this data is the hard part. That's our problem.

Access, pacing, anti-bot posture, breakage response — the work that makes unmasked live data possible, already done.

Managed access

Access health, rotation and pacing are handled on our side. You never touch a cookie or a credential.

Idempotent retries

Pass an idempotency key, retry safely on 429 / 5xx. SDK does exponential backoff with jitter.

Cursors + pagination

Stable cursors on list Actions; async runs can auto-paginate and deliver batches to your callback.

Action callbacks

Async and schedule modes POST results to your URL. Missed deliveries replay from callback history.

p50 1.2s · p99 2.4s

A live read against the source, every time. Even a cold profile lands inside 3 seconds.

SOC 2 Type II

Audited annually. 99%+ uptime. Region-pinned residency on enterprise plans.

// Developer ergonomics

TypeScript SDK on top. Plain REST underneath.

The TS SDK is the fastest path on Node. Every other runtime talks to the same REST surface with whatever HTTP client you already use.

TypeScript SDKv2.4.1 · recommended

Typed, retried, paginated, traced. Drop it into any Node service.

// npm i @edgesrun/sdk
import { Edges } from "@edgesrun/sdk"
const edges = new Edges({ apiKey })
const { data } = await edges.linkedin.extractPeople({ input })
liveNode 18+ · ESM + CJS
cURLREST · v1

No dependency. Copy-paste from any docs page, run it in your shell.

# standard REST, JSON, X-API-Key auth
curl -X POST https://api.edges.run/v1/actions/linkedin-extract-people/run/live \
  -H "X-API-Key: $EDGES_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"input":{"linkedin_profile_url":"linkedin.com/in/jane-doe"}}'
liveWorks everywhere
HTTP / any languageOpenAPI 3.1

No SDK to install, no version to keep up with. It's plain HTTP, so it already works in whatever you write. Ask us for the OpenAPI spec if you want a typed client.

# plain HTTP — no client library,
# no version to keep up with
POST /v1/actions/{action}/run/live
liveNo SDK required

// Beyond requests

Async jobs, cron schedules, full workflows.

Live REST is one mode. The same API runs jobs asynchronously, on a schedule, or as multi-step workflows that trigger, enrich and engage on their own — one key, one schema, four execution modes.

sync

Live REST

Request in, response out. The mode you start with.

// blocking call
const { data } = await edges.linkedin
  .extractPeople({
    input: { linkedin_profile_url: url }
  })
p501.2 s
async

Async jobs

Run any action async — poll outputs or receive callbacks.

// fire-and-forget
const { data: job } = await edges.linkedin
  .extractPeople({
    input,
    mode: "async",
    callback: { url: "https://…/done" }
  })
// → run_uid · poll /runs/{uid}/outputs
up to1 M / job
cron

Cron schedules

Schedule mode is set on the action run itself.

// every Mon 09:00 UTC
await edges.linkedin.extractCompany({
  input: { company_url },
  schedule: { cron: "0 9 * * 1" }
})
granularity1 min
pipeline

Workflows

Compose trigger → enrich → filter → engage.

// trigger → … → engage
const { data } = await edges
  .linkedin.extractPostCommenters(input)
for (const c of data.commenters) {
  await edges.linkedin.connectProfile(…)
}
composemulti-step
workflow · inbound-vp-productactive · last run 38 s ago
cron · */15 * * * *Open workflow
Trigger
Post commenters
linkedin-extract-post-commenters
events / 24h1,248
Enrich
Profile + company
linkedin-extract-people
p501.2 s
Filter
VP Product · US/UK
if role.title ~ …
passes528 · 42%
Engage
Send invite + note
linkedin-connect-profile
reply rate21.4%
ModeWorkflow · cron
Sent / 24h498
Replies107
Credits used1,776
Identityalex@yourco.com

Get the full record in an afternoon.

100 free credits. No card, no cookies, no LinkedIn account required.