14 day free trial

Recipes

Poll for new and updated companies

Pulling newly identified companies — and catching updates to ones you already have — keeps your records in lockstep with FirmTrace. The simple case is easy. But once traffic grows or you start managing multiple accounts, you'll want a sturdier approach. Here are the patterns we use.

Whether companies are first identified or updated with new data, every change ticks the cursor forward. You poll on your own cadence — each call returns everything that changed since you last asked, in one batch.

Scope

A company's changed_time ticks forward on a lot more than visits. Anything that modifies the record bumps it.

Trigger Bumps changed_time?
Website visit yes
Profile data refresh yes
Label / target audience change yes
Tag added or removed yes
No activity no

That broad scope is the point — changed_time is what makes syncing work in the strict sense: keep your copy in lockstep with FirmTrace, no matter how the source record changed.

Visits only?

If you only care about new visit activity (no profile updates, no tag changes), swap from_changed_time for last_visit=<cursor>: with sort_by=last_visit. Same cursor pattern, narrower scope.

Basics

One endpoint, four parameters, one timestamp to remember. Each cycle, fetch the changes since your last cursor and save the latest changed_time from the response as the cursor for next time.

GET /v1.3/companies
Parameter Value Why
sort_by changed_date Walk in change order.
sort_order asc Oldest first — advance the cursor in step.
from_changed_time your stored cursor Catches anything that ticked changed_time forward. Empty on first run.
limit 50 Default. Raise it for higher volume — see Pagination.

Cycles

Match the cadence to your traffic.

Traffic Cadence
20–50 sessions / day (≤ ~100) every 30–120 minutes
Higher volume every 5–15 minutes
Near-real-time use cases every 1–5 minutes
Heads-up

Matching doesn't wait for the visit to end. A visitor may still be on your site at the moment their company match is recorded — and shows up in your next poll while the session is live. Workflows that act on a match should handle currently here as well as was here earlier.

Loops

If your downstream sync writes back to FirmTrace — adding a tag, setting a label, anything via PATCH — that write itself ticks changed_time forward. The next cycle re-fetches the same company because its updated changed_time is past your cursor. Loop.

Track the latest changed_time per company in your own store. When a poll returns a company, compare its changed_time against the value you have stored — only act if the response is newer. Your own PATCH still ticks changed_time forward and the next cycle re-fetches the company, but downstream you've already stored that newer value, so the re-fetch is recognised as "nothing actually new" and skipped.

Pagination

When response.found exceeds limit, paginate. Walk page=1, 2, 3 … until a response comes back empty before you save the cursor.

Parameter Value
limit 50 (or higher if you process larger batches)
page 1, 2, 3 … until the response is empty

Save the cursor only after the last page returns empty — otherwise a crash mid-pagination leaves you with a half-claimed batch.

Throttling

For a single account on a sensible cadence, throttling won't bite you. The question gets real once you're polling many accounts in parallel: the per-account fair-use limit is one request per endpoint per second, but if you manage 100+ accounts and fire them all at the same moment, you'll feel it on the receiving infrastructure long before any single account does. Stagger the cycles, or batch them across a window.

Errors & retry

Sort responses into three buckets and handle each on its own terms.

Bucket Examples What to do
Transient network, 5xx, 429 Retry with exponential backoff (1s → 2s → 4s, capped). On 429, respect Retry-After if present.
Permanent 4xx (other than 429) Log and stop the cycle. Usually a config or auth issue — retrying won't help.
Success 200 Process the batch — see Where to advance the cursor below.
Where to advance the cursor

Treat the cursor as your commit point: only persist it after downstream finishes the batch. If you save it earlier and downstream then fails, those records are gone for good. Make your handler idempotent on company.id so a retried fetch — which re-delivers the same batch — doesn't double-write.

See also Poll for new companies