Skip to main content
POST

Endpoint

Search finds posts across public professional content by words, by author, or both. Use it to discover posts matching a topic, then call GET /api/v1/post/comments or GET /api/v1/post/reactions on the ones whose engagement you want in full.
The request is a JSON body, not query parameters. Send query, or at least one of authorProfiles / authorCompanies — a search with no words and no author is a request for the whole network and is rejected with 400.

Authentication

Include your API key in the request header:

Billing

1 credit per call, flat.
  • 1 credit whether the page comes back with 50 results, 1 result or none at all. The query ran either way, and an empty page is a real answer: it tells you nothing matches.
  • The price does not change with maxResults, so a 50-result page costs the same as a 1-result page. Ask for 50.
  • 400, 401, 402, 429 and 503 are free. Every validation error is decided before the search runs, so a malformed body never costs a credit.
  • Each page of a cursor walk is its own call and its own credit.
  • A post that repeats across two pages (see Pagination) is part of a page you already paid for; there is no per-result charge either way.
This is the “one credit per request” rule from Quotas, applied per page: the page is the request.

Request body

Filters AND together; the values inside one list filter OR. null anywhere means “field omitted”.
Nothing is accepted and then ignored. An unknown key, an unrecognised enum value, a list that is too long and a maxResults above 50 are all 400s that name the field — never a quiet drop.This matters more here than it looks. The underlying search ignores a value it does not recognise and answers normally, so a single typo in contentType would come back as a perfectly healthy page that silently applied no filter at all, and you would have paid for it without any way to notice. Refusing for free is the only honest option.
string
The search terms, up to 500 characters. See Query grammar for operators, phrases and the operator limit.Required unless you send authorProfiles or authorCompanies.
string
relevance or date (newest first). There is no default.Omit it and the underlying search applies its own ordering. We do not label an order we do not control, so the response reports sort: null in that case rather than guessing a name for it.Two measured caveats before you reach for date:
  • it cannot be combined with a hashtag term in query — the two do not compose upstream and return nothing at all, so the combination is refused with 400 instead;
  • on a tight window it narrows hard. "hiring" over 24 hours returned 6 results unsorted and 1 with sortBy: "date". If you want coverage, omit the sort and sort the results yourself on date.
string
24h, week or month. Keeps only posts published inside that window.This is applied by the search itself, so it changes which results exist, not just which ones you see.
string | integer
Keep only posts published at or after this instant — an ISO-8601 timestamp (2026-10-01T00:00:00Z) or an epoch in milliseconds. Must not be in the future and at most 365 days ago.Unlike postedWithin, this one is applied on our side after the search runs. A page trimmed by it comes back short and still costs its 1 credit. Use postedWithin to pick the window and postedAfter to cut inside it.
string[]
Keep only posts carrying one of these kinds of attachment. Values OR together. Accepted: image, video, liveVideo, jobPost, document.
string[]
Keep only posts published by these people. 1 to 10 values, each a profile id (ACoAA…) or any professional profile URL containing one.A slug on its own is not accepted here: resolving one would cost an extra fetch per value. Resolve it once with GET /api/v1/profile and pass the id.Can be sent without query, to page everything a set of people posted.
string[]
Keep only posts published by these organization pages. 1 to 10 values, each a numeric page id, a page urn, or a page URL ending in a numeric id. Can be sent without query.
string[]
Keep only posts that mention these organization pages. 1 to 10 numeric page ids, urns or URLs.
string
Keep only posts whose author’s current title matches this free text, matched as a phrase. 1 to 100 characters.
integer
default:"50"
How many results this page may return, 1 to 50.50 is both the default and a hard ceiling: above it the underlying search returns nothing at all, so a larger value is refused with 400 rather than billed for an empty page. The price is the same at 1 and at 50.This is a ceiling, not a promise. A page can come back with fewer results than you asked for because results are de-duplicated by post id within the page — a 50-result request measured 49 in production — or simply because it is the last page. A short page is not an error.
string
Opaque cursor for the next page — see Pagination.

Not supported

The filters documented above are the ones whose effect we confirmed on live traffic. A filter we could not confirm is rejected with a free 400 instead of offered, because an unrecognised filter is not refused by the underlying search but silently ignored — so it would hand you a perfectly plausible, completely unfiltered page that you paid for and have no way to detect.
group is rejected with 400. Group posts are a separate surface with no equivalent in this search.
Filters whose answer depends on who is looking — a person’s own network, their connections, their follows — are not supported and will not be. Our requests are served from rotating capacity, so such a filter would give a different answer on every call, which is worse than not offering it.
Not a contentType value yet. The supported values are image, video, liveVideo, jobPost and document.

Query grammar

query is a boolean expression over words and phrases. Operators must be uppercase in the canonical form, every AND / OR / NOT needs a term on both sides, and a query that only excludes (NOT intern) is rejected — there would be nothing to search for.

The 5-operator limit

A query may use at most 5 boolean operators. This is a limit of the underlying search, not a quota: from the sixth operator it stops answering and returns an empty result set that is indistinguishable from “nothing matched”.Rather than hand you that empty page and charge for it, we refuse the query outright:
The refusal is decided before anything runs — measured at ~2 ms, 0 credits. To search a wider expression, split it into several searches and merge the results, de-duplicating on id. Splitting on the top-level OR branches is usually the cheapest cut.
Each AND, OR and NOT counts as one. Parentheses, phrases and bare terms count as none, so ("head of growth" OR "vp growth") AND (saas OR fintech) uses 3 operators and #hiring uses 0. There is also a cap of 20 quoted phrases and 5 levels of nesting, both well above normal use.

What we normalise for you

These rewrites are applied silently, because each of them is something the underlying search would otherwise handle worse than you expect: Nothing is rewritten inside a quoted phrase, and an apostrophe in the middle of a word (we'll be raising soon) is left alone — only a matched pair of single quotes at word boundaries becomes a phrase. Every rewrite is auditable: the response echoes the query it actually ran as query. Compare it to what you sent whenever a result set surprises you.

Pagination

Send the first page without cursor, then pass the cursor from each response back into the next request, unchanged, with the same query and filters. Stop when cursor is null.
Rules:
  • cursor is opaque. Pass it back byte for byte; do not parse or build one. A cursor issued for a different query or different filters is a 400 ('cursor' belongs to a different search.), and so is anything this API did not issue.
  • maxResults may change between pages, the query and filters may not.
  • cursor is null in every way a walk ends — a last page with results, an empty page past the end, and a query that matched nothing — so one condition closes your loop.
  • De-duplicate on id. The result set is live and re-orders between calls; across a measured 4-page walk, 40 results held 37 distinct posts.
Depth. One query is exhausted after a few hundred results: cursor comes back null while posts matching your words certainly still exist. To go further, split the query — by date window (postedWithin, postedAfter) or by author — and combine the pages.

Response

string | null
The query as it was interpreted, after normalisation. null on an author-only search.
string | null
The ordering that was applied: relevance, date, or null when sortBy was omitted and the underlying search used its own.
string | null
Opaque cursor for the next page, or null when the result set is exhausted.
object
Present only when at least one card on this page could not be read and was dropped, so a short page is never silently short: droppedResults and a reasons breakdown. Diagnostic and additive — log it, do not branch on the keys of reasons.
array
Matching posts, de-duplicated within the page. Can hold fewer items than maxResults, and can be empty.

Example Request

Everything a set of authors posted this month, with no keywords at all:

Example Response

Errors

See Error Handling for the shared envelope and recommended handling. This endpoint has no 404: a search that matches nothing is a 200 with an empty results.
Concurrency, not just rate. Your per-second limit counts request starts; this endpoint also caps how many of your searches may be running at the same moment. That allowance follows your plan’s rate limit and is set generously above it, precisely so that sending the rate you pay for never hits it — a 429 from this cap means you have far more searches open at once than your rate implies, not that your plan is too small. Lower your concurrency and honour Retry-After.
A 503 here is never a partial page. If a page cannot be read in full we refuse it and charge nothing, rather than return a short page you would have to distrust. Retry it.

Performance

Observed, not guaranteed: roughly 1–2 s for a small page (up to a handful of results) and 4.5–7 s for a full 50-result page, measured across local and production runs on 2026-10-07. Treat that as a range to size a timeout against rather than a service level — plan a per-request timeout of at least 30 seconds. Because a page is held open for seconds, parallel searches add up fast: see the concurrency note above.

Limitations

Stated plainly, because you will hit every one of them in an afternoon of real use.
reactionCount, commentCount, sharesCount, reactionTypeCounts and reactionsByType are read at the moment of the fetch. A post found an hour ago has moved since. Re-read the post when the number matters, and do not treat two pages of the same walk as counted at the same instant.
An edited post reports when it was originally published, not when it was edited, and isEdited: true is the only signal that the two differ. There is no edit timestamp.
Image, video, document and avatar URLs are signed by the source’s CDN and stop working after an expiry date we do not control. Download what you want to keep; do not store the URL as if it were permanent. Read image sizes from width / height, not from the path.
The result set behind a query is live and re-orders between requests, so the same post can appear on two consecutive pages — measured at 8% over a 4-page walk (40 results, 37 distinct). There is no snapshot to page against. De-duplicate on id.
#hiring on its own works. #hiring with sortBy: "date" returns nothing at all upstream, so the combination is refused with 400 instead of billing you for an empty page. Drop the #, or drop the sort.
sortBy: "date" with postedWithin: "24h" returns markedly fewer results than the same query unsorted — measured 1 against 6 on "hiring". When you want coverage of a narrow window, omit sortBy and order the results yourself on date.
cursor goes null well before you have everything that matches your words. Split by date window or by author, as in Pagination.
Stemming, synonyms and relevance are the underlying search’s, not ours. Use quoted phrases when you need the words in that order, and verify against the echoed query when a result set surprises you.

Notes

Ask for maxResults: 50. The call costs 1 credit at any page size, so a smaller page is strictly worse value.
Nothing you search for is written back anywhere, and the posts returned are not re-fetched as a side effect of a search.

Authorizations

X-API-Key
string
header
required

Body

application/json

Send query, or at least one of authorProfiles / authorCompanies. Every other field is optional. null reads as "field omitted" everywhere. The body is validated strictly: an unknown key, an unrecognised enum value or a list that is too long is rejected with 400 and costs nothing, rather than being accepted and ignored.

query
string

The search terms. Supports quoted phrases, AND / OR / NOT, parentheses with nesting up to 5 levels, and hashtag terms. At most 5 boolean operators - this is a limit of the underlying search, and a 6th is refused with 400 rather than silently matching nothing, so split the query into several searches and combine the results. At most 20 quoted phrases. Curly quotes, lowercase operators, single-quote delimiters and a bare & are normalised silently, and the interpreted query is echoed back as the response's query. Required unless authorProfiles or authorCompanies is set.

Maximum string length: 500
Example:

"\"head of growth\" AND (saas OR fintech) NOT intern"

sortBy
enum<string>

How to order the results. No default: omit it and the underlying search applies its own ordering, which the response reports as sort: null. date is newest first. date cannot be combined with a hashtag term in query (400), and on a tight postedWithin window it returns markedly fewer results than no sort at all.

Available options:
relevance,
date
postedWithin
enum<string>

Keep only posts published within this window. Applied by the search itself, so it also changes which results exist.

Available options:
24h,
week,
month
postedAfter

Keep only posts published at or after this instant, as an ISO-8601 timestamp or an epoch in milliseconds. Must not be in the future and at most 365 days ago. Applied by us after the search runs, so a page filtered this way comes back short and still costs its 1 credit. Combine it with postedWithin to narrow inside a window.

Example:

"2026-10-01T00:00:00Z"

contentType
enum<string>[]

Keep only posts carrying one of these kinds of attachment. Values OR together.

Required array length: 1 - 5 elements
Available options:
image,
video,
liveVideo,
jobPost,
document
Example:
authorProfiles
string[]

Keep only posts published by these people. 1 to 10 values, each a profile id or any profile URL containing one. A slug on its own is not accepted here - resolve it with GET /api/v1/profile first. Can be sent without query to page a set of authors.

Required array length: 1 - 10 elements
Example:
authorCompanies
string[]

Keep only posts published by these organization pages. 1 to 10 values, each a numeric page id, a page urn, or a page URL ending in a numeric id. Can be sent without query.

Required array length: 1 - 10 elements
Example:
mentionsCompanies
string[]

Keep only posts that mention these organization pages. 1 to 10 numeric page ids, urns or URLs.

Required array length: 1 - 10 elements
Example:
authorJobTitle
string

Keep only posts whose author's current title matches this free text. Matched as a phrase.

Required string length: 1 - 100
Example:

"Head of Growth"

maxResults
integer
default:50

How many results this page may return. 50 is both the default and the hard ceiling; a larger value is refused with 400 because the underlying search answers nothing at all above it. A page can return fewer results than this: results are de-duplicated by post id within the page (a 50-result request measured 49), and the last page of a walk is short by nature.

Required range: 1 <= x <= 50
cursor
string

Opaque cursor for the next page. Pass back the cursor from the previous response, byte for byte, with the same query and filters; omit it to start a new search. A cursor issued for a different query, or any value this API did not issue, is refused with 400. Keep paging while cursor is not null.

Maximum string length: 1024

Response

A page of matching posts. Billed 1 credit, including when results is empty. Observed latency, not a guarantee: ~1-2 s for a small page and 4.5-7 s for a full 50-result page.

query
string | null
required

The query as it was interpreted, after normalisation - so every silent rewrite is auditable. null on an author-only search.

sort
enum<string> | null
required

The ordering that was applied, echoed from the request. null when sortBy was omitted, meaning the underlying search used its own ordering, which we do not name.

Available options:
relevance,
date,
null
results
object[]
required

Matching posts, de-duplicated within the page. Can hold fewer items than maxResults, and can be empty - which still costs 1 credit.

cursor
string | null
required

Opaque cursor for the next page, or null when this result set is exhausted. Pass it back unchanged with the same query and filters. One query is exhausted after a few hundred results.

partial
object

Present only when at least one card on the page could not be read and was dropped, so a short page is never silently short. Diagnostic and additive: log it, do not branch on the keys of reasons.