Contacts

GET
/v1/contacts/research

Retrieve a contact research request by external ID and external source. This endpoint allows you to look up contact research requests using identifiers from external systems (e.g., HubSpot contact ID).

Authorization

ApiKeyAuth
AuthorizationBearer <token>

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

In: header

Query Parameters

externalId*string

The external identifier of the contact research request (e.g., HubSpot contact ID)

Length1 <= length <= 100
externalSource*string

The source system that provided the external ID (e.g., "hubspot")

Length1 <= length <= 50

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v1/contacts/research?externalId=hubspot_12345&externalSource=hubspot"

{  "id": "cr_abc123def456",  "status": "processing",  "firstName": "John",  "lastName": "Doe",  "companyName": "Acme Corp",  "companyDomain": "acme.com",  "createdAt": "2024-01-15T10:30:00Z"}

POST
/v1/contacts/research

Submit contact details to create a new contact research request. The AI will gather information from LinkedIn, email services, and other data sources to provide comprehensive contact insights.

The research will be processed asynchronously. Use the returned contact research ID to check status via the GET endpoint, or configure a webhook to receive completion notifications.

Credits

Each research request charges 2 credits. Credits are deducted on success and released if the research fails.

Authorization

ApiKeyAuth
AuthorizationBearer <token>

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

firstName*string

First name of the contact

Length1 <= length <= 100
lastName*string

Last name of the contact

Length1 <= length <= 100
companyName*string

Name of the contact's company

Length1 <= length <= 200
companyDomain*string

Company domain (e.g., "acme.com")

Match^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$
Length1 <= length <= 253
contactProfileUrl?string

Contact profile URL of the contact (e.g., LinkedIn or other professional profile, optional)

Formaturi
Lengthlength <= 500
linkedInSalesNavigatorUrl?string

LinkedIn Sales Navigator profile URL of the contact (optional)

Formaturi
Lengthlength <= 500
jobTitle?string

Job title of the contact (optional)

Length1 <= length <= 200
webhookUrl?string

Optional webhook URL to receive notifications when processing completes

Formaturi
Lengthlength <= 2048

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/contacts/research" \  -H "Content-Type: application/json" \  -d '{    "firstName": "John",    "lastName": "Doe",    "companyName": "Acme Corp",    "companyDomain": "acme.com",    "jobTitle": "VP of Sales"  }'
{  "id": "cr_abc123def456",  "status": "processing",  "createdAt": "2024-01-15T10:30:00Z"}
GET
/v1/contacts/research/{id}

Retrieve a contact research request by ID, including its status and results if completed. This endpoint returns the current state of the research request.

Authorization

ApiKeyAuth
AuthorizationBearer <token>

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

In: header

Path Parameters

id*string

The unique identifier of the contact research request

Response Body

application/json

application/json

application/json

curl -X GET "https://example.com/v1/contacts/research/cr_abc123def456"

{  "id": "cr_abc123def456",  "status": "processing",  "firstName": "John",  "lastName": "Doe",  "companyName": "Acme Corp",  "companyDomain": "acme.com",  "createdAt": "2024-01-15T10:30:00Z"}

POST
/v1/contacts/search

Search for contacts using LinkedIn Sales Navigator. Optionally scoped to one or more companies via companyLinkedInUrls. When multiple URLs are provided, each company is searched separately and results are merged and deduplicated.

Pagination: each request returns exactly one page (default size 25, max 100 via limit); there is no server-side auto-fetch. Pass the previous response's nextCursor as cursor to fetch the next page, together with the same filters and limit. The cursor keeps every page in one pagination session on the same Sales Navigator connector. If that connector becomes unavailable, the request returns 422 PAGINATION_SOURCE_UNAVAILABLE; restart the search without a cursor. A 429 is temporary: retry the same cursor later. offset remains accepted for existing callers, but it does not keep connector continuity; provide cursor or offset, not both. An invalid, expired, or older cursor returns 422 INVALID_CURSOR; restart without a cursor. Paging is capped at a 1000-result-per-search ceiling: a page STARTING at or past it is rejected with 422, a page that merely runs past it is clamped to the remaining rows, and nextCursor is omitted once the next page would start at the ceiling; narrow the search filters instead of paging deeper.

Requirements:

  • At least one search parameter must be provided: companyLinkedInUrls, firstName, lastName, jobTitles, keywords, countries, departments, seniorityLevels, recentlyChangedJobs, yearsInCurrentPosition, yearsAtCurrentCompany, industries, companyHeadcounts, or companyTypes.
  • LinkedIn Sales Navigator connection is required for the API key owner

Response:

  • If Sales Navigator is not connected, returns salesNavConnected: false with empty contacts
  • If connected, returns matching contacts with profile information and pagination metadata

Credits

Each page request charges 0.5 credits when a connected search serves a page (SEL-3685). Not-connected responses (salesNavConnected: false) and failed requests are free.

Authorization

ApiKeyAuth
AuthorizationBearer <token>

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

companyLinkedInUrls*array<>

LinkedIn company URLs to scope the search (note: plural — pass an array even for a single company). Supports multiple companies; results are merged and deduplicated. Omit to search across all companies.

firstName?string

First name of the contact to search for

Lengthlength <= 100
lastName?string

Last name of the contact to search for

Lengthlength <= 100
jobTitles?array<>

Job titles to search for (plural — pass an array)

keywords?string

Keywords to search for in contact profiles (e.g., skills, technologies)

Lengthlength <= 500
countries?array<>

Countries to filter contacts by location. Must be ISO 3166-1 alpha-2 codes (e.g., "US", "GB", "DE") — full country names are not accepted.

departments?array<>

Department (function) filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported. This filter matches the person. For a person with several current positions, it does not identify which position matched.

seniorityLevels?array<>

Seniority level filter using LinkedIn Sales Navigator taxonomy. Multiple values are OR'd together. Combined with other filters via AND. All values are treated as INCLUDED — exclusion is not currently supported. This filter matches the person. For a person with several current positions, it does not identify which position matched.

recentlyChangedJobs?boolean

When true, uses Sales Navigator's Changed jobs filter. LinkedIn controls this rolling window and has no caller-selected start date. Approximately 90 days is an unverified working assumption.

yearsInCurrentPosition?array<>

Sales Navigator's Years in current position ranges. Multiple values are OR'd together. Combined with other filters via AND. This filter matches the person. For a person with several current positions, it does not identify which position matched.

Items1 <= items <= 5
yearsAtCurrentCompany?array<>

Sales Navigator's Years at current company ranges. Multiple values are OR'd together. Combined with other filters via AND. This filter matches the person. For a person with several current positions, it does not identify which position matched.

Items1 <= items <= 5
industries?array<>

Current LinkedIn Sales Navigator industry display names. Letter case and surrounding whitespace are normalized. Multiple values are OR'd together. Combined with other filters via AND. See https://docs.saber.app/contacts/industry-values for the canonical values.

Items1 <= items <= 20
companyHeadcounts?array<>

Current company headcount ranges. Multiple values are OR'd together. Combined with other filters via AND.

Items1 <= items <= 9
companyTypes?array<>

Current company types. Multiple values are OR'd together. Combined with other filters via AND.

Items1 <= items <= 8
limit?integer

Maximum number of contacts to return per page

Range1 <= value <= 100
Default25
offset?integer

Zero-based offset for pagination. Mutually exclusive with cursor — provide one or the other. Pages starting at or past the 1000-result search ceiling are rejected with 422 and error code PAGE_BEYOND_CEILING (distinct from the connector-required 422); a page that merely runs past it is clamped to the remaining rows. This compatibility field does not keep successive requests on one Sales Navigator connector. Use cursor for safe pagination.

Range0 <= value
Default0
cursor?string

Paging handle from the previous response's nextCursor. The documented way to fetch the next page; mutually exclusive with offset. Never construct one yourself. Pass it back with the same filters and limit. The cursor keeps the pagination session on the connector that served its first page. If that connector becomes unavailable, restart from page 1. Invalid, expired, and older cursor formats return 422 INVALID_CURSOR.

Lengthlength <= 100

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/contacts/search" \  -H "Content-Type: application/json" \  -d '{    "companyLinkedInUrls": [      "https://linkedin.com/company/google"    ],    "jobTitles": [      "Engineering Manager",      "VP Engineering"    ],    "countries": [      "US"    ]  }'

{  "items": [    {      "firstName": "Alex",      "lastName": "Rivera",      "fullName": "Alex Rivera",      "role": "Vice President of Revenue",      "companyName": "Acme Software",      "seniority": [        "VP"      ],      "positions": [        {          "companyName": "Open Technology Foundation",          "title": "Board Advisor",          "startedOn": {            "year": 2022,            "month": 1          },          "tenureAtPosition": {            "years": 4,            "months": 8          },          "tenureAtCompany": {            "years": 4,            "months": 8          },          "moveType": "no_recent_move"        },        {          "companyName": "Acme Software",          "title": "Vice President of Revenue",          "startedOn": {            "year": 2026,            "month": 6          },          "tenureAtPosition": {            "months": 3          },          "tenureAtCompany": {            "years": 4,            "months": 3          },          "moveType": "moved_internally"        }      ],      "linkedInSalesNavigatorProfileUrl": "https://www.linkedin.com/sales/lead/ACwAAABOW1gBQZCU123",      "avatar": "https://media.licdn.com/...",      "location": "San Francisco, California"    }  ],  "total": 150,  "limit": 25,  "offset": 0,  "hasMore": true,  "salesNavConnected": true,  "nextCursor": "djI6MjU6Y29ubmVjdG9yLTEyMw"}

On this page