Example
curl -G 'https://socialtap.dev/v1/linkedin/search_profiles' \
--data-urlencode 'account_type=company' \
--data-urlencode 'query=coffee roaster' \
-H "x-api-key: $SOCIALTAP_API_KEY"import { SocialTap } from "socialtap";
const client = new SocialTap(); // apiKey defaults to process.env.SOCIALTAP_API_KEY
const res = await client.linkedin.searchProfiles.list({ query: "coffee roaster", account_type: "company" });
console.log(res.data);
console.log(res.credits.charged, res.meta.request_id);const params = new URLSearchParams({
account_type: "company",
query: "coffee roaster",
});
const res = await fetch(`https://socialtap.dev/v1/linkedin/search_profiles?${params}`, {
headers: { "x-api-key": process.env.SOCIALTAP_API_KEY ?? "" },
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
const { data, page, meta } = body;
console.log(data, meta.credits_charged);import os
import requests
res = requests.get(
"https://socialtap.dev/v1/linkedin/search_profiles",
params={"account_type": "company", "query": "coffee roaster"},
headers={"x-api-key": os.environ["SOCIALTAP_API_KEY"]},
)
body = res.json()
if not res.ok:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
data, page, meta = body["data"], body["page"], body["meta"]
print(data, meta["credits_charged"])package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"os"
)
func main() {
q := url.Values{}
q.Set("account_type", "company")
q.Set("query", "coffee roaster")
req, err := http.NewRequest("GET", "https://socialtap.dev/v1/linkedin/search_profiles?"+q.Encode(), nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("x-api-key", os.Getenv("SOCIALTAP_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
var body struct {
Data json.RawMessage `json:"data"`
Page json.RawMessage `json:"page"`
Meta map[string]any `json:"meta"`
Error *struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
log.Fatal(err)
}
if body.Error != nil {
log.Fatalf("%s: %s", body.Error.Code, body.Error.Message)
}
fmt.Println(string(body.Data), body.Meta["credits_charged"])
}<?php
$query = http_build_query([
'account_type' => 'company',
'query' => 'coffee roaster',
]);
$ch = curl_init('https://socialtap.dev/v1/linkedin/search_profiles?' . $query);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['x-api-key: ' . getenv('SOCIALTAP_API_KEY')],
]);
$body = json_decode(curl_exec($ch), true);
if (curl_getinfo($ch, CURLINFO_RESPONSE_CODE) >= 400) {
throw new RuntimeException($body['error']['code'] . ': ' . $body['error']['message']);
}
print_r($body['data']);
echo $body['meta']['credits_charged'], PHP_EOL;require "json"
require "net/http"
uri = URI("https://socialtap.dev/v1/linkedin/search_profiles")
uri.query = URI.encode_www_form('account_type' => 'company', 'query' => 'coffee roaster')
req = Net::HTTP::Get.new(uri)
req["x-api-key"] = ENV.fetch("SOCIALTAP_API_KEY")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(req) }
body = JSON.parse(res.body)
raise "#{body["error"]["code"]}: #{body["error"]["message"]}" unless res.is_a?(Net::HTTPSuccess)
pp body["data"]
puts body["meta"]["credits_charged"]import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
public class Main {
public static void main(String[] args) throws Exception {
String query = "account_type=" + encode("company")
+ "&query=" + encode("coffee roaster");
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://socialtap.dev/v1/linkedin/search_profiles?" + query))
.header("x-api-key", System.getenv("SOCIALTAP_API_KEY"))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
// An error is {"error": {"code", "message", ...}}; success is {data, meta}, meta.credits_charged its price.
if (response.statusCode() >= 400) throw new RuntimeException(response.body());
System.out.println(response.body());
}
static String encode(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
}using System.Text.Json;
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("x-api-key", Environment.GetEnvironmentVariable("SOCIALTAP_API_KEY"));
var query = string.Join("&",
"account_type=" + Uri.EscapeDataString("company"),
"query=" + Uri.EscapeDataString("coffee roaster"));
var res = await http.GetAsync("https://socialtap.dev/v1/linkedin/search_profiles?" + query);
using var body = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
if (!res.IsSuccessStatusCode)
{
var error = body.RootElement.GetProperty("error");
throw new Exception($"{error.GetProperty("code")}: {error.GetProperty("message")}");
}
Console.WriteLine(body.RootElement.GetProperty("data"));
Console.WriteLine(body.RootElement.GetProperty("meta").GetProperty("credits_charged"));// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }, serde_json = "1"
use std::env;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let res = reqwest::blocking::Client::new()
.get("https://socialtap.dev/v1/linkedin/search_profiles")
.query(&[("account_type", "company"), ("query", "coffee roaster")])
.header("x-api-key", env::var("SOCIALTAP_API_KEY")?)
.send()?;
let ok = res.status().is_success();
let body: serde_json::Value = res.json()?;
if !ok {
return Err(format!("{}: {}", body["error"]["code"], body["error"]["message"]).into());
}
println!("{} {}", body["data"], body["meta"]["credits_charged"]);
Ok(())
}{
"data": [
{
"approximate_fields": [
"profile.bio",
"profile.display_name",
"profile.metrics.follower_count"
],
"community": null,
"details": null,
"hashtag": null,
"matched_url": "https://www.linkedin.com/company/red-rooster-coffee-roaster",
"place": null,
"platform": "linkedin",
"platform_specific": {
"linkedin": {
"company": null,
"connection_count": null,
"headline": null,
"kind": "company",
"location": null,
"school": null,
"tagline": null
}
},
"position": 0,
"post": null,
"profile": {
"avatar_url": null,
"bio": "Floyd's first fair trade, organic coffee roaster, located in Floyd, VA. Whole bean coffee from around the world, artisan roasted and shipped to your doorstep.",
"display_name": "Red Rooster Coffee Roaster",
"id": null,
"is_verified": null,
"metrics": {
"follower_count": 368,
"following_count": null,
"post_count": null,
"total_like_count": null,
"total_view_count": null
},
"url": "https://www.linkedin.com/company/red-rooster-coffee-roaster",
"username": "red-rooster-coffee-roaster"
},
"snippet": "Red Rooster Coffee Roaster | 368 followers on LinkedIn. Floyd's first fair trade, organic coffee roaster, located in Floyd, VA. Whole bean coffee from around the world, artisan roasted and shipped to your doorstep.",
"sound": null,
"title": "Red Rooster Coffee Roaster | LinkedIn",
"type": "profile",
"unknown_fields": [],
"url": "https://www.linkedin.com/company/red-rooster-coffee-roaster"
},
{
"approximate_fields": [
"platform_specific.linkedin.tagline",
"profile.bio",
"profile.display_name"
],
"community": null,
"details": null,
"hashtag": null,
"matched_url": "https://www.linkedin.com/company/alabaster-coffee-roaster-&-tea-company",
"place": null,
"platform": "linkedin",
"platform_specific": {
"linkedin": {
"company": null,
"connection_count": null,
"headline": null,
"kind": "company",
"location": null,
"school": null,
"tagline": "Cultivating community though the elevation of coffee culture."
}
},
"position": 1,
"post": null,
"profile": {
"avatar_url": null,
"bio": "Alabaster Coffee is a nationally award winning coffee bar & roasterie located in Williamsport, PA.",
"display_name": "Alabaster Coffee Roaster & Tea Company",
"id": null,
"is_verified": null,
"metrics": {
"follower_count": 319,
"following_count": null,
"post_count": null,
"total_like_count": null,
"total_view_count": null
},
"url": "https://www.linkedin.com/company/alabaster-coffee-roaster-&-tea-company",
"username": "alabaster-coffee-roaster-&-tea-company"
},
"snippet": "Alabaster Coffee Roaster & Tea Company | 319 followers on LinkedIn. Cultivating community though the elevation of coffee culture. | Alabaster Coffee is a nationally award winning coffee bar & roasterie located in Williamsport, PA.",
"sound": null,
"title": "Alabaster Coffee Roaster & Tea Company | LinkedIn",
"type": "profile",
"unknown_fields": [],
"url": "https://www.linkedin.com/company/alabaster-coffee-roaster-&-tea-company"
},
{
"approximate_fields": [
"profile.display_name"
],
"community": null,
"details": null,
"hashtag": null,
"matched_url": "https://www.linkedin.com/company/mozart's-coffee-roasters",
"place": null,
"platform": "linkedin",
"platform_specific": {
"linkedin": {
"company": null,
"connection_count": null,
"headline": null,
"kind": "company",
"location": null,
"school": null,
"tagline": null
}
},
"position": 2,
"post": null,
"profile": {
"avatar_url": null,
"bio": null,
"display_name": "Mozart's Coffee Roasters",
"id": null,
"is_verified": null,
"metrics": {
"follower_count": null,
"following_count": null,
"post_count": null,
"total_like_count": null,
"total_view_count": null
},
"url": "https://www.linkedin.com/company/mozart%27s-coffee-roasters",
"username": "mozart's-coffee-roasters"
},
"snippet": "Operating a scratch bakery on-premise and producing European style hand-made, hand-cut freshly baked cakes, bars, cookies, and savory items such as sandwiches, tacos, and empanadas much in the style of a Grand Cafe is our speciality. Our coffees are ethically sourced from around …",
"sound": null,
"title": "Mozart's Coffee Roasters | LinkedIn",
"type": "profile",
"unknown_fields": [],
"url": "https://www.linkedin.com/company/mozart%27s-coffee-roasters"
}
],
"page": {
"has_more": true,
"next_cursor": "c1.EXAMPLE_CURSOR",
"next_cursor_expires_at": "2026-10-26T12:00:00Z",
"end_reason": null
},
"meta": {
"request_id": "req_3f9c2a7d1e8b4c6a9f0e2d4b6a8c0e1f",
"platform": "linkedin",
"source": "web_search",
"is_cached": false,
"credits_charged": 1,
"latency_ms": 1231,
"fetched_at": "2026-10-25T12:00:00Z",
"input": null,
"credits_remaining": 9999,
"client_request_id": null,
"warnings": []
}
}Long arrays and strings are shortened for display; real responses are complete.
Words to find LinkedIn accounts by, as a web search reads them: a company's or a person's name, an industry and a place, a job title and an employer (stripe, coffee roaster seattle, "bill gates", software engineer stripe). Quotes keep a phrase together and a leading - leaves a word out; site: is set by the endpoint, and intitle:, inurl: and intext: count as plain words.
Examplecoffee roaster
account_typestringOnly accounts of this kind: company (a company's Page), school (a school's Page), showcase (a company's page for one brand or product) or member (a person). Every kind when omitted, which finds fewer of each: use it when you know what you are looking for.
One ofcompanyschoolshowcasemember
Examplecompany
fillstringtrue also fetches each result's item from the platform: its full, current record in details (exact counts, its ID), as the platform's own endpoint for that kind returns it. Priced per result filled; a result the platform no longer serves stays unfilled and costs nothing more.
One oftruefalse
Exampletrue
Favor this country's results: the search engine ranks the pages for it, and pages from elsewhere still appear. Without it, the search engine's ranking for the US. One of AR, AT, AU, BE, BR, CA, CH, CL, CN, DE, DK, ES, FI, FR, GB, GR, HK, ID, IN, IT, JP, KR, MX, MY, NL, NO, NZ, PH, PL, PT, RU, SA, SE, SG, TR, TW, US, ZA (case-insensitive): the countries search engines rank for.
ExampleBR
Items per page, 1 to the endpoint's page size (its default and maximum; larger values are reduced to it). Omit it: every page costs the same, so a smaller limit means more pages to pay for.
Example50
cursorstringpage.next_cursor from the previous response. Send the same other parameters; omit to start from the first page.
Unknown parameters are rejected with a suggestion, never ignored (Requests). limit and cursor page through the list: see Pagination.
Parameters every endpoint accepts
Accept a cached response up to this many seconds old. Cache hits cost 0 credits. Omit to always fetch fresh. The Cache-Control: max-age=N request header is equivalent; max_age wins when both are sent.
fieldsstringReturn only these fields of each item: comma-separated paths in the schema's notation (id,text,metrics.view_count,segments[].text; a parent path keeps the whole object). Unknown paths are rejected. Applied after the cache, so it changes neither the price nor cache hits; page and meta are always returned whole.
Response
200
{data, page, meta}. data is an array of up to 50 web result objects, the search engine's ranking (most relevant first); page says how to get the next page; meta describes the request (meta). Fields only LinkedIn has are under platform_specific.linkedin.
platformstringPlatform the item is on.
typestringThe kind of item the result names, as the resource that describes it: profile (an account), post, hashtag, sound, place or community. The item's summary is the field of that name, and a filled result's record is details.<type>. A search that finds several kinds (a platform's top search) mixes them in one list. New values may be added as more kinds are searchable; treat unknown values as other.
One ofprofileposthashtagsoundplacecommunity
positionintegerZero-based rank of the result in the list, across pages: the search engine's order, counting only the results kept.
urlstring uriThe item's canonical link on the platform (the account's page for a profile, the post's for a post).
matched_urlstring uriThe page the index listed: the item's own page, or one of its pages that names it (a video of an account, for a profile found through it).
titlestringnullableThe page's title as the index shows it: often the item's name, but not the item's own field. Null when the index shows none.
snippetstringnullableThe index's excerpt of the page: often the item's description and counts as the page stated them when it was indexed, days or weeks ago. Null when the index shows none.
profileobjectnullableThe account the result names (type profile): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type.
ShowHide 8 child fields
idstringnullablePlatform-native account ID; null until the result is filled (the index shows only the handle).
usernamestringnullableHandle without the @, as the matched link names it; null when the link names the account only by its number.
display_namestringnullableDisplay name, as the index's title shows it; null when it shows none.
urlstring uriCanonical profile URL (equals the result's url).
biostringnullableProfile bio as the index's snippet quotes it (often cut short: see approximate_fields); null when it quotes none.
avatar_urlstring urinullableProfile picture URL; null until the result is filled (an index's thumbnails are its own copies). Platform CDN URLs can expire within hours.
is_verifiedbooleannullablePlatform verification badge; null until the result is filled, or where the platform has no badge.
metricsobjectCounts as the index's snippet states them (rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated.
ShowHide 5 child fields
follower_countintegernullableFollowers or subscribers.
following_countintegernullableAccounts this profile follows.
post_countintegernullablePosts or videos as the platform counts them on the profile (for a private account, posts the caller cannot see).
total_like_countintegernullableLikes received across all of the profile's posts (not likes given).
total_view_countintegernullableLifetime views across all of the profile's posts.
postobjectnullableThe post the result names (type post): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type.
ShowHide 8 child fields
idstringnullablePlatform-native post ID: the one in the link where the platform's links name it (an X post's /status/<id>), else null until the result is filled.
urlstring uriCanonical post URL (equals the result's url).
titlestringnullableHeadline, on platforms whose posts have one (a YouTube or Reddit title), as the index's title shows it; null on caption-only platforms (the page's title is the result's title).
textstringnullableCaption or body as the index's snippet quotes it (often cut short: see approximate_fields); null when it quotes none.
published_atstring date-timenullableWhen the post went public, as the index's text dates it (often to the day: see approximate_fields); null when it does not.
authorobjectThe posting account as the link and the index's text name it (a /@<username>/video/ link's username, the title's display name); its id, avatar_url and is_verified null until the result is filled.
ShowHide 6 child fields
idstringnullablePlatform-native account ID; null when only the handle is known.
usernamestringnullableHandle without the @; null when the account has none.
display_namestringnullableDisplay name shown on the profile.
urlstring urinullableCanonical profile URL.
avatar_urlstring urinullableProfile picture URL. Platform CDN URLs can expire within hours.
is_verifiedbooleannullablePlatform verification badge; null where the platform has no badge.
thumbnail_urlstring urinullableCover or poster image URL; null until the result is filled (an index's thumbnails are its own copies).
metricsobjectCounts as the index's snippet states them ("1,234 likes, 56 comments"; rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated.
ShowHide 7 child fields
view_countintegernullableViews or plays.
like_countintegernullableLikes, hearts, total reactions or upvotes; never negative. Null when hidden by the owner.
comment_countintegernullableComments and replies.
share_countintegernullableShares or sends (not reposts).
repost_countintegernullableReposts, retweets or reshares.
quote_countintegernullableQuote posts.
save_countintegernullableSaves, bookmarks or favorites.
hashtagobjectnullableThe hashtag the result names (type hashtag): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type.
ShowHide 6 child fields
idstringnullableThe hashtag's ID as the platform's hashtag endpoints key it; null until the result is filled.
namestringThe tag without #, as the matched link or the index's title spells it (case kept where the title shows it).
urlstring uriCanonical hashtag page URL (equals the result's url).
descriptionstringnullableThe hashtag's description as the index's snippet quotes it; null when it quotes none (a platform's generic page text is not one).
thumbnail_urlstring urinullableThe hashtag's own picture; null until the result is filled.
metricsobjectCounts as the index's text states them ("36.2M posts"; rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated.
ShowHide 1 child field
post_countintegernullablePosts carrying the tag, as the platform counts them; rounded on YouTube and Threads (see approximate_fields).
soundobjectnullableThe sound the result names (type sound): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type.
ShowHide 7 child fields
idstringnullablePlatform-native sound ID; null until the result is filled.
urlstring urinullableCanonical page of the sound (equals the result's url).
titlestringnullableSound or track title as the index's text shows it, else the words of the sound page's link (see approximate_fields); null when neither names it.
author_namestringnullableWho the platform credits for the sound (a track's artist, an original sound's creator), as the index's text names it; null when it does not.
is_originalbooleannullableAn original sound a creator uploaded, as the index's title says ("original sound"); null when the text does not say, until the result is filled.
cover_urlstring urinullableCover art URL; null until the result is filled. Platform CDN URLs can expire within hours.
metricsobjectCounts as the index's text states them ("80K reels"; rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated.
ShowHide 1 child field
post_countintegernullablePosts using the sound (TikTok videos, Instagram and Facebook reels, YouTube Shorts), as the platform counts them.
placeobjectnullableThe place the result names (type place): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type.
ShowHide 10 child fields
idstringnullablePlatform-native place ID; null until the result is filled.
namestringnullablePlace name as the index's title shows it; null when it shows none.
urlstring uriCanonical place page URL (equals the result's url).
categorystringnullableThe platform's category label, as the index's text shows it; null when it does not.
addressstringnullableAddress as the index's text shows it; null when it does not.
citystringnullableCity or locality, as the index's text shows it.
country_codestringnullableISO 3166-1 alpha-2 country of the place.
latitudenumbernullableWGS 84 latitude in degrees; null unless the index's text states coordinates, until the result is filled (set together with longitude).
longitudenumbernullableWGS 84 longitude in degrees; null unless the index's text states coordinates, until the result is filled (set together with latitude).
metricsobjectCounts as the index's text states them ("12K posts"; rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated.
ShowHide 3 child fields
post_countintegernullablePublic posts tagged with the place, as the platform counts them.
review_countintegernullablePublic reviews or recommendations of the place, as the platform counts them.
image_countintegernullablePictures the platform has of the place; more than the length of images when the source returns only the first ones.
communityobjectnullableThe community the result names (type community: a group, a subreddit): what its link and the index's text say of it, completed from details when the result is filled. Null for every other type.
ShowHide 8 child fields
idstringnullablePlatform-native community ID; null until the result is filled.
namestringnullableThe name its links use, as the matched link names it (golang for r/golang, a Facebook group's vanity name); null when the link names it only by number.
titlestringnullableThe community's title as the index's title shows it; null when it shows none.
descriptionstringnullableIts description as the index's snippet quotes it (often cut short: see approximate_fields); null when it quotes none (a platform's generic page text is not one).
urlstring uriCanonical community URL (equals the result's url).
avatar_urlstring urinullableThe community's icon or picture; null until the result is filled.
privacystringnullableWho can see and post, as the index's text says ("Public group"); null when it does not. New values may be added; treat unknown values as restricted.
One ofpublicrestrictedprivate
metricsobjectCounts as the index's text states them ("762K members"; rounded, as old as the index's copy: see approximate_fields), or the platform's current ones once filled; null = not stated.
ShowHide 1 child field
member_countintegernullableMembers (on Reddit, subscribers) as the platform counts them.
detailsobjectnullableThe item's own record from the platform, fetched when the request asked for it (fill=true): what the platform's endpoint for the kind returns, under the result's type (details.profile). Null when not asked for, when the platform has no endpoint for the kind, or when it did not serve the item (meta.warnings says how many).
ShowHide 6 child fields
platform_specificobjectFields only this platform has, under its ID (platform_specific.<platform>); each null when unknown.
ShowHide 1 child field
linkedinobjectnullableWhat the index shows of a LinkedIn account beyond the summary.
ShowHide 7 child fields
kindstringnullableWhat the account is on LinkedIn, as its link says: a company's Page, a school's, a showcase page, or a member. Null when unknown. New values may be added; treat unknown values as unknown.
One ofcompanyschoolshowcasemember
taglinestringnullableA Page's tagline as the index's snippet quotes it; null when it quotes none, and for a member.
headlinestringnullableWhat the index's title says of a member after their name: their headline, or where LinkedIn hides it their current employer, school or place (often cut short); null when it says none, and for a Page.
locationstringnullableWhere a member is, as the index's snippet or title says it; null when it does not, and for a Page.
companystringnullableA member's current employer, as the index's snippet says it; null when it does not, and for a Page.
schoolstringnullableThe school a member's profile shows first, as the index's snippet says it; null when it does not, and for a Page.
connection_countintegernullableA member's connections as the index's snippet states them (LinkedIn shows any count above 500 as 500+, which is 500 here); null when it does not, and for a Page.
approximate_fieldsstring[]JSON paths of values parsed from the index's display text or rounded there (profile.metrics.follower_count from "13K followers", a profile.bio or post.text the snippet cut short). Filled values are exact and leave the list. [] when all exact.
unknown_fieldsstring[]JSON paths of lists whose [] means unknown rather than none; [] when every list is known (a result has none yet).
400
400 Bad Request: 2 error codes. Free: errors cost nothing.
invalid_inputNo retryA parameter is missing or malformed, or the link is not one this endpoint takes.
Fix the parameter named in param as the message says. For a link of the wrong kind, call an endpoint listed in details.endpoints, when there is one.
invalid_cursorNo retryThe cursor is malformed or expired, belongs to another endpoint, or came with other parameters than the request that returned it.
Repeat the original request without cursor to start the list again.
401
401 Unauthorized: 1 error code. Free: errors cost nothing.
unauthorizedNo retryThe x-api-key header is missing, or its key is unknown or revoked. On the dashboard's routes: the session cookie is missing or expired.
Send a valid API key in the x-api-key header. No key yet? A person gets one at details.signup_url; an AI agent follows details.agent_auth_url.
402
402 Payment Required: 2 error codes. Free: errors cost nothing.
insufficient_creditsNo retryThe account does not have enough credits for this request.
Have a person buy credits at details.purchase_url (or make them a checkout link with details.checkout), then repeat the request. Do not retry automatically.
spend_limit_reachedNo retryThe API key reached its spend limit for this period. The account may still have credits.
Wait until details.resets_at, or raise the key's spend limit (PATCH /v1/api_keys/{id}). Do not retry automatically.
403
403 Forbidden: 1 error code. Free: errors cost nothing.
forbiddenNo retryThe API key is valid but may not make this request, and details.reason says why: the account is suspended, the key lacks the route's scope, waits for its owner to confirm it by email, has expired, or was used from an IP outside its allowlist, or a rotated key's previous secret was used for a call that needs the admin scope. A running job stops with it too when its account is suspended or the key that created it is revoked or expires. It is about the key, never the item: a private item is private_or_unavailable, also 403, so branch on the code.
Act on details.reason. suspended: contact support. scope: use a key with details.required_scope. previous_secret: use the new secret. key_pending: have the owner open the emailed link. key_expired or key_revoked: create a new key. ip_not_allowed: call from an allowed IP.
429
429 Too Many Requests: 1 error code. Free: errors cost nothing.
rate_limitedYes, laterThe account passed its runaway-protection ceiling: a high per-account limit that stops a broken client loop (plans have no rate limit). Requests without an API key (signup, the MCP server's tool listing and find_endpoint) are limited per IP address instead. It also stops an account whose failed requests in the last hour cost far more than its successful ones paid for: failures are free within a limit (the message says so), and successes raise it.
Wait the seconds in the retry-after header, then retry. If your steady traffic needs more, ask support to raise the ceiling; without an API key, send one.
500
500 Internal Error: 1 error code. Free: errors cost nothing.
internalYes, laterAn unexpected error on SocialTap's side.
Retry with backoff. If it keeps happening, contact support with the request_id.
502
502 Bad Gateway: 1 error code. Free: errors cost nothing.
upstream_errorYes, laterThe platform failed, or answered with something we could not read.
Retry with backoff. Failed requests are free.
503
503 Unavailable: 2 error codes. Free: errors cost nothing.
upstream_blockedYes, laterThe platform refused every attempt, our own retries included.
Retry later with backoff. Failed requests are free.
overloadedYes, laterSocialTap was at capacity, or paused by its operators, and did not start the request. Nothing was fetched or charged.
Retry after the seconds in the retry-after header. Failed requests are free.
Items come in pages, the search engine's ranking (most relevant first). To get the next page, send the same request plus cursor set to page.next_cursor from the previous response. Keep every other parameter the same (limit, max_age and fields may change); anything else that differs is rejected. When page.has_more is false the walk is over, and page.end_reason says why: only end means you have every item (the others say the platform or a page cap stopped the walk early).
The page object
has_morebooleanTrue when another page exists; then next_cursor is set. An empty page with has_more true is not the end.
next_cursorstringnullablePass as cursor, with the same other parameters, to get the next page; null at the end.
next_cursor_expires_atstring date-timenullableWhen next_cursor stops working, RFC 3339 UTC; null at the end. Don't store cursors.
end_reasonstringnullableWhy there are no more pages; null while has_more is true. end: the list ended, or reached since/until. platform_limit: the platform stops serving further pages although the list goes on. max_pages: SocialTap's cap on pages in one walk. New values may be added. A short or empty page is not the end: only has_more false is.
One ofendplatform_limitmax_pages
Next page
curl -G 'https://socialtap.dev/v1/linkedin/search_profiles' \
--data-urlencode 'account_type=company' \
--data-urlencode 'query=coffee roaster' \
--data-urlencode 'cursor=c1.EXAMPLE_CURSOR' \
-H "x-api-key: $SOCIALTAP_API_KEY"- The price is per page: each successful page costs the same, whatever
limitis and however many items it has. Empty pages are charged too (an empty page withhas_more: trueis not the end). - A
limitbelow 50 doesn't save credits: the next request serves the rest of the same platform page, which is fetched again and charged as a page each time, and items can shift between those requests if the platform changes the list. Omittinglimitis the cheapest way to walk the list. - Errors are free, including a rejected cursor.
- Pages served from the cache are free.
- An expired or altered cursor, or one sent with different parameters, fails with
invalid_cursor(HTTP 400): Repeat the original request without cursor to start the list again.
From 1 credit per page, up to 51 credits. Charged per successful page, whatever its number of items. Errors are free. The price depends on the source that produced the result, reported as meta.source.
| Source | Price per successful page | Per 1,000 pages |
|---|---|---|
| Any source | 1 credit + 1 per result filled in up to 51 credits (50 results filled in) | $0.75–$1.97 + $0.75–$1.97 per result filled in |
Example: a result from Any source with 3 results filled in costs 1 + 1 × 3 = 4 credits.
Balance, sources and what you were charged
Your balance must be at least 1 credit to start a request; with less, it is refused with insufficient_credits (HTTP 402) and costs nothing. Only that minimum is set aside when the request starts. One request costs at most 51 credits, but that amount is never locked up in advance: right before costlier work, SocialTap sets aside more of your balance, the exact price when the number of results filled in is known beforehand, otherwise as much as your balance allows (and the work is limited to what that pays for). It then charges the actual price and releases the rest. If the result would cost more than your balance covers, the request is refused with insufficient_credits as well, and costs nothing.
| meta.source | Source | What it means |
|---|---|---|
web_search | Web search | A public web search engine's index of the platform's pages, where the platform has no logged-out search of its own: each result is what the index shows of the item, which can be days or weeks old. |
meta.credits_charged and the x-credits-charged header show what you paid. How credits work · Packs
Endpoint ID linkedin.search_profiles · operationId linkedin.search_profiles.list · Product overview