List Social Signals Leads
GET/signals/leads
Returns a paginated list of Social Signals leads belonging to the authenticated brand.
Data notice: Responses contain PII (names, LinkedIn URLs, profile images). See the Data Handling & Privacy section for required safeguards.
This endpoint follows the same pagination, filtering, and auth conventions as the existing campaign APIs.
Pagination​
Use page and pageSize query parameters to paginate through results. pageSize is capped at 100, or at 25 when includeEngagements=true (see Engagement inclusion). The cap is applied silently — meta.pagination.pageSize always reports the page size that was actually used, and meta.pagination.pageCount is derived from it.
Incremental sync​
Use updatedAfter / updatedBefore with sort=updatedAt:asc for backfills and recurring true-ups. Consumers should keep a small replay window and de-duplicate by lead id because multiple leads can share the same updatedAt timestamp.
The :asc is required — sort=updatedAt on its own is rejected with 400 invalid_parameter, not treated as ascending. Check meta.sort on the response to confirm the ordering you were served; see Sorting.
Timestamp formats​
The four timestamp filters (createdAfter, createdBefore, updatedAfter, updatedBefore) accept RFC 3339 / ISO 8601 values in these shapes:
| Shape | Examples |
|---|---|
| Date only | 2026-04-01 |
| Date and time | 2026-04-01T14:30, 2026-04-01T14:30:00, 2026-04-01T14:30:00.000 |
| Date and time with UTC designator | 2026-04-01T14:30:00Z, 2026-04-01T14:30:00.000Z |
| Date and time with numeric offset | 2026-04-01T14:30:00+02:00, 2026-04-01T14:30:00+0200 |
Per RFC 3339 section 5.6 the T separator and the Z designator may be written in lower case: 2026-04-01t14:30:00z is accepted and is treated as identical to 2026-04-01T14:30:00Z. A single space may be used in place of T (2026-04-01 14:30:00).
Any other value returns 400 invalid_parameter. Formats that are not accepted include epoch seconds or milliseconds (1775001600000), compact ISO without separators (20260401), RFC 1123 / Date.prototype.toUTCString() output (Wed, 01 Apr 2026 00:00:00 GMT), a bare year (2026), and supplying the same parameter more than once in one query string (?createdAfter=...&createdAfter=...).
Timezone handling​
All four timestamp filters are compared against the lead's stored createdAt / updatedAt values, which are recorded in UTC.
Apart from normalising the case of the T / Z characters, the value you send is used as-is in the comparison — the API does not attach a timezone to it. Always send a full ISO 8601 date-time with an explicit UTC offset (e.g. 2026-04-01T00:00:00.000Z) so the bound is unambiguous.
A naked date such as 2026-04-01 is accepted, but it carries no timezone and is therefore not guaranteed to be interpreted as UTC — its meaning depends on the database session and may drift from UTC midnight. Do not rely on naked dates for incremental sync; use explicit ...Z timestamps instead.
Engagement inclusion​
By default this endpoint returns a lean lead list. Pass includeEngagements=true to include up to 20 newest engagements per lead (trackedAt:desc) using the same public engagement shape as GET /signals/leads/{id}. If a lead has more engagements, engagementsMeta.truncated is true.
Because this mode is substantially heavier, pageSize is capped at 25 while it is enabled. A request for a larger page is served at 25 rather than rejected, and meta.pagination.pageSize reflects the applied value — page through the remainder rather than assuming your requested size was honoured. The two caps together bound a single request to at most 25 x 20 engagements, so response size and query cost stay predictable no matter how active the leads on the page are.
Filtering​
| Parameter | Description | Example |
|---|---|---|
signalId | Filter by signal | ?signalId=12 |
qualified | Filter by qualification status | ?qualified=true |
exported | Filter by export status | ?exported=false |
isEmployee | Filter employee leads | ?isEmployee=false |
createdAfter | Filter to leads created at or after an ISO date/time | ?createdAfter=2026-04-01T00:00:00.000Z |
createdBefore | Filter to leads created at or before an ISO date/time | ?createdBefore=2026-04-08T23:59:59.999Z |
updatedAfter | Filter to leads updated at or after an ISO date/time | ?updatedAfter=2026-04-01T00:00:00.000Z |
updatedBefore | Filter to leads updated at or before an ISO date/time | ?updatedBefore=2026-04-08T23:59:59.999Z |
includeEngagements | Include bounded engagement history in list results | ?includeEngagements=true |
search | Partial match on name or headline | ?search=marketing |
Sorting​
The sort parameter takes a field:direction pair — both halves are required.
| Part | Allowed values |
|---|---|
field | createdAt, updatedAt, score1, name — matched case-sensitively |
direction | asc, desc — matched case-insensitively (ASC is accepted) |
Example: ?sort=updatedAt:asc
Omit sort (or send it empty) to get the default createdAt:desc.
Anything else returns 400 invalid_parameter. In particular a bare field name is not accepted: ?sort=updatedAt is an error, not a request for updatedAt:asc. Also rejected: an unknown field (?sort=bogus:asc), an unknown direction (?sort=updatedAt:sideways), extra segments (?sort=updatedAt:asc:extra), and repeating the parameter in one query string (?sort=createdAt:asc&sort=name:desc). The error message lists the fields you may use.
Changed 2026-07-30: a malformed sort previously returned 200 and was served under the default createdAt:desc ordering, with no indication that the requested field had been discarded. See Versioning & Breaking Changes.
Confirming the ordering you got​
Every 200 response reports the ordering that was actually applied as meta.sort, in the same field:direction form:
{
"data": [],
"meta": {
"pagination": { "page": 1, "pageSize": 25, "pageCount": 4, "total": 89 },
"sort": "updatedAt:asc"
}
}
If you depend on the ordering — as incremental sync does — assert meta.sort matches what you sent rather than inferring it from the rows.
Request​
Responses​
- 200
- 400
- 401
- 403
- 429
Social Signals leads retrieved successfully
Response Headers
The maximum number of requests allowed per minute
The number of requests remaining in the current window
Unix timestamp when the rate limit window resets
Invalid query parameter. The response error.code is invalid_parameter and error.message names the offending parameter. Two cases produce it:
Timestamps — createdAfter, createdBefore, updatedAfter, or updatedBefore is supplied but is not one of the shapes listed under Timestamp formats, for example an epoch timestamp, a compact YYYYMMDD date, or the same parameter supplied twice.
Sort — sort is supplied but is not a field:direction pair, for example the bare field updatedAt, an unknown field bogus:asc, or an unknown direction updatedAt:sideways. See Sorting.
In both cases the request is rejected rather than served under a different filter or ordering.
Unauthorized - Invalid or missing API key
Forbidden - Active subscription required
Rate limit exceeded
Response Headers
The maximum number of requests allowed per minute
The number of requests remaining in the current window
Unix timestamp when the rate limit window resets
Seconds until the rate limit resets (only on 429 responses)