Tracker
Watch companies and people for the changes that matter — 52 rule types, refresh cadences from daily to quarterly, signals delivered by webhook and API.
Tracker
We built Tracker to watch companies and people on LinkedIn so you don't have to. Add entities to a list, pick rules — "headcount grew 20%", "person changed company", "new funding round" — and we re-check everything on your schedule. When a rule matches, you get a signal: pushed by webhook and stored for the API. You declare what matters; the watching, comparing, and noise-filtering happen for you.
Core concepts
| Concept | What it is |
|---|---|
| List | A named set of entities sharing rules and a refresh cadence — company list or person list, never mixed |
| Dynamic list | A list backed by a saved search: membership refreshes itself, and a member that stops matching emits a departure signal |
| Entity | One company or person, tracked with its own history |
| Rule | A condition checked on every refresh ("headcount crossed 100"). Up to 25 per list |
| Signal | A detected change that matched a rule — delivered by webhook and stored for the API |
| Refresh interval | How often a list's entities are re-checked: 1–90 days (default 7) |
| Lookback | Optional per-rule window (1–90 days) — compare against ~N days ago instead of the last check |
A rule fires only when tracked data actually changes in a way that matches — a refresh that finds nothing produces nothing.
How monitoring behaves
- The first check is a baseline. When you add an entity, its first check snapshots the current state and fires nothing — there's nothing to compare against yet. Signals start from the second check onward, about one refresh interval after the baseline: a daily list added today can fire its first signals tomorrow, a weekly list about a week in. A fresh list with no immediate signals is behaving correctly. (Want history on day one? See day-one signals.)
- The list sets the cadence. Every entity in a list is re-checked on the
list's refresh interval, and scheduled runs land overnight US-Pacific time —
mornings show fresh data. New entities — and a brand-new list's first run —
are picked up by an hourly scheduler, so baselines land within about an
hour of adding; they never delay the entities already tracked.
getTrackerCompanyList/getTrackerPersonListreturnnextRefreshAt, so you always know when the next scheduled run is. - You can refresh on demand.
refreshTrackerCompanyList/refreshTrackerPersonListre-checks a list immediately, at most once every 12 hours per list. UsegetTrackerOverviewfirst to see what the run will cost. - We tell you before and after scheduled runs. Subscribe to
tracker.list_run_upcoming(about a day ahead) andtracker.list_run_completedat Webhooks.
| When | What happens |
|---|---|
| Entity first added | Baseline captured within about an hour. No signal. |
| Second refresh onward | Compared against the previous state; matches fire signals. |
| Entity paused / removed | No further checks or charges; signal history is kept. |
Day-one signals (initial look-back)
A brand-new list doesn't have to start silent. Pass initialSignals when
you add entities (or save rules) and we look backward — up to 30 days
— and fire signals for recent events that would have matched: funding rounds,
matching job postings, news, posts, acquisitions, new investors, layoffs.
Set lookbackPeriodDays explicitly: the default is your refresh interval, so
a daily list only looks back one day unless you say otherwise.
Look-back only works for rules anchored to dated events — 15 of the 52 types:
new_funding_round, funding_stage_changed, job_posting_with_keyword,
job_posting_in_function, news_with_keyword, company_news,
company_posted, company_posted_with_keyword, acquired_company,
new_investor, recent_layoffs, person_posted,
person_posted_with_keyword, person_reacted_to_post,
person_commented_on_post
Diff-based rules (headcount thresholds, title changes, profile edits) need a
before and an after, so they start from the second check as usual —
unsupported rules come back listed in skippedRules, nothing fails.
listAvailableTrackerRules marks every rule with supportsInitialSignals so
you can check programmatically.
Day-one signals are billed per entity, only on success, and they seed the baseline — the first scheduled refresh won't re-fire the same events.
Limits
| Limit | Value |
|---|---|
| Companies per list | 100,000 |
| People per list | 100,000 |
| Tracked entities per organization | 100,000 |
| Members per dynamic list | 10,000 |
| Rules per list | 25 |
| Entities per add/remove call | 10,000 |
| Refresh interval | 1–90 days |
| Lookback period | 1–90 days |
Billing
-
2 credits per entity per refresh at the standard rate. 500 companies checked weekly ≈ 1,000 credits/week. See Billing & credits.
-
Volume and frequency earn automatic discounts:
Rate Credits / entity / refresh When it applies Standard 2 default Scale 1 10,000+ tracked entities or a daily interval Bulk 0.5 10,000+ tracked entities and a daily interval Tiers apply on their own — no plan change needed. On-demand refreshes bill at the Standard or Scale rate.
-
Premium rules set a floor. Eight premium rules watch news coverage and LinkedIn activity on every refresh, so a list containing at least one bills at minimum the Scale rate (1 credit / entity / refresh) — the Bulk discount never drops below it. Standard-rate lists are unaffected, and the floor applies once per list no matter how many premium rules it carries.
-
Free: adding entities, reading signals, managing lists, dummy signals, payload previews. (Opting into day-one signals is the exception: those bill per entity, on success.)
-
Charged per refresh, never per signal — a refresh firing five signals costs the same as one firing none.
-
Out of credits? Nothing breaks. If your balance can't cover a run, we skip it before charging anything — no partial runs, no backlog of surprise charges. The list retries daily instead of waiting out its full interval, and tracking resumes on its own once you top up.
-
Forecast spend with
getTrackerOverview(GET /v1/tracker/overview): every list, its rules, an upcoming-refresh timeline, and estimated daily/monthly credit burn. -
Pause a list (
isActive: false) to stop charges without losing anything.
Rule mechanics
- Per-item rules emit one signal per detected item (posts, news, job postings, funding rounds) — webhook volume can fan out. Aggregated rules (headcount, title changes) emit one signal per entity per refresh.
- Updating rules — two modes, never mixed: pass
trackingRulesto replace the whole set, oraddRules/removeRuleIdsfor granular edits. Combining them in one request returns a400— the guard exists so a small edit can't accidentally wipe your rule set. - Rule identity survives edits. Saving a list keeps the same
ruleIdfor rules you didn't change, so signal history and integrations keyed onruleIdstay intact.
Company rules
| Group | Rules | Tune with… |
|---|---|---|
| Headcount & growth | headcount_crossed_threshold, headcount_growth_percent, employee_count_milestone, department_size_threshold, recently_hired_with_title, follower_count_growth | thresholds, % change, direction, departments, title keywords |
| Funding & financials | new_funding_round, funding_stage_changed, acquired_company, new_investor | min amount, round/stage types, investor types |
| Hiring & postings | job_posting_with_keyword, job_posting_in_function | keywords, seniority, work modality, min postings, functions |
| News & content | company_news, news_with_keyword, company_posted, company_posted_with_keyword | keywords, min articles/reactions |
| Profile changes | hq_location_changed, company_status_changed, technology_added, company_name_changed, company_description_changed, company_logo_changed, company_went_inactive, new_office_location, recent_layoffs | countries/cities, target statuses, technologies, keywords |
Example:
{
"type": "new_funding_round",
"entityType": "company",
"minAmountUsd": 10000000,
"roundTypes": ["series_b", "series_c"]
}Person rules
| Group | Rules |
|---|---|
| Career changes | person_changed_company, person_title_changed, person_got_promoted, person_got_demoted, person_started_company, person_employment_type_changed, person_stuck_in_role, person_tenure_milestone |
| Status signals | person_stealth_changed, person_open_to_work, person_is_hiring, person_became_verified, person_became_premium, person_became_influencer, person_became_top_voice |
| Profile changes | person_headline_changed, person_summary_changed, person_location_changed |
| Skills & activity | person_skills_added, person_new_certification, person_tag_gained, person_posted, person_posted_with_keyword, person_reacted_to_post, person_commented_on_post |
| Growth | person_connections_milestone, person_follower_milestone |
That's the full catalog: 25 company rules and 27 person rules. Direction
rules take direction (entered/exited, started/stopped, or
either); keyword rules take match lists. The full field schema for every
rule is in the API reference — listAvailableTrackerRules
(GET /v1/tracker/rules) returns it programmatically.
Stealth moves are trackable. person_stealth_changed fires when a
watched person enters or exits stealth mode — see
Stealth Tracking for why that signal matters.
Premium rules
Eight rules watch more than the base profile — on every refresh we also monitor news coverage and LinkedIn activity for each tracked entity:
| Watches | Rules |
|---|---|
| News coverage (company) | company_news, news_with_keyword |
| LinkedIn posts (company) | company_posted, company_posted_with_keyword |
| LinkedIn activity (person) | person_posted, person_posted_with_keyword, person_reacted_to_post, person_commented_on_post |
- A list containing at least one premium rule bills at minimum the Scale rate — see Billing. The floor applies once per list: one premium rule or eight, same per-entity rate.
- Mix premium and standard rules freely within the 25-rules-per-list limit.
- Spot them programmatically:
listAvailableTrackerRules(GET /v1/tracker/rules) returnsisPremiumfor every rule type, and thegetTrackerOverviewestimates already reflect the floor — you see the true per-refresh cost before a premium rule ever runs.
Recipes
- Buying intent (companies):
job_posting_with_keyword("data engineer")headcount_growth_percent(15%+) +new_funding_round($5M+) — any one means spending; all three together is a very strong signal.
- Champion tracking (people):
person_changed_company+person_got_promoted+person_open_to_work— a champion who moves companies is a warm intro to their new org. - Fundraise timing (companies):
headcount_growth_percent(30% over 90 days vialookbackDays) +job_posting_in_function(Finance, Legal) +recently_hired_with_title(CFO, VP Finance).
Signals & noise
Tracker is conservative by design — it alerts on real changes and stays quiet otherwise:
- Small fluctuations don't fire. A one-person headcount wobble won't trigger a growth rule.
- The same signal doesn't fire twice. Within a rule's lookback window we suppress repeats, and flip-flop states ("open to work" toggling on and off) are debounced for a week.
- Missing data isn't a change. A temporarily unavailable field is treated as unknown, never as "went to zero" — no false "person left their company" alerts.
- Promotions and demotions are verified before firing, so cosmetic title edits don't get mislabeled.
- Every signal carries a
confidencescore (0–1). Deterministic rules report1.0; interpretive ones report model confidence so you can weight them in your automations.
Consuming signals
Webhooks (real-time). A firing rule delivers a tracker.signal_detected
webhook — a self-contained envelope with the entity, the matched rule, a
human-readable summary, structured changeData, source URLs (sources),
a methodology note, the real-world eventDate where one exists, and
confidence:
{
"eventId": "evt_...",
"occurredAt": "2026-06-02T12:00:00.000Z",
"entity": { "type": "company", "identifiers": { "linkedinSlug": "example-co", "domain": "example.com" } },
"subscription": { "type": "headcount_crossed_threshold", "listName": "Target Accounts" },
"signal": { "summary": "Headcount crossed 100 (now 104)", "confidence": 1.0, "isDummy": false }
}eventId is stable across retries — dedupe on it. Configure the endpoint at
fiber.ai/app/webhooks; see
Webhooks for signatures and retries.
API polling (the reliable fallback). Every signal is stored whether or not
a webhook exists — read them with listTrackerSignals
(GET /v1/tracker/signals/{listId}) or listTrackerChanges
(GET /v1/tracker/changes/{listId}), using since (ISO timestamp), cursor,
limit (1–100), and includeDummy. Reading signals is free. A robust
integration does both: webhooks to react now, polling with since to backfill
anything missed.
Testing tools (both free):
fireTrackerDummy(POST /v1/tracker/fire-dummy/{listId}) — mark rulesisDummy: trueand fire synthetic signals through your real webhook, flaggedisDummy: true, as often as you like.previewTrackerSignal(POST /v1/tracker/rules/preview-signal) — send a rule, get an example payload. Nothing is created, nothing is delivered.
Managing lists
- Pause/resume:
isActive: falsestops refreshes and charges; rules, interval, and history are preserved. Flip back to resume. - Remove an entity: stops its future checks and charges; signal history is preserved. Re-adding the same entity later does not reset its baseline — a genuinely new entity starts fresh.
- Delete a list: deactivates the list and everything in it; signal history is retained.
API quick reference
All operations are under /v1/; each links to its focused reference page in
the operation index.
| Operation | Method & path |
|---|---|
createTrackerCompanyList | POST /v1/tracker/company-lists |
listTrackerCompanyLists | GET /v1/tracker/company-lists |
getTrackerCompanyList | GET /v1/tracker/company-lists/{listId} |
updateTrackerCompanyList | PATCH /v1/tracker/company-lists/{listId} |
deleteTrackerCompanyList | DELETE /v1/tracker/company-lists/{listId} |
addTrackerCompanies | PUT /v1/tracker/company-lists/{listId}/companies |
removeTrackerCompanies | DELETE /v1/tracker/company-lists/{listId}/companies |
refreshTrackerCompanyList | POST /v1/tracker/company-lists/{listId}/refresh |
| Person-list operations | Same shape under /v1/tracker/person-lists… (…People) |
listTrackerSignals | GET /v1/tracker/signals/{listId} |
listTrackerChanges | GET /v1/tracker/changes/{listId} |
getTrackerOverview | GET /v1/tracker/overview |
listAvailableTrackerRules | GET /v1/tracker/rules |
fireTrackerDummy | POST /v1/tracker/fire-dummy/{listId} |
previewTrackerSignal | POST /v1/tracker/rules/preview-signal |