Observations and evidence
How to read freshness, scope, install states, and absence without drawing conclusions the data does not support.
The API never reports what a site is doing right now. It reports what a completed observation saw, and when. Every store object carries the evidence for its own claims, and the rules below are the ones the API itself follows when it derives a fact.
Completed observations only
An observation is a scan that finished with a known scope. A fetch that timed out, was blocked by a bot challenge, returned an error, or was never attempted produces no observation at all. It cannot lower a count, remove a technology, or change a status. This is the single most important property of the data: incomplete observations are not negative evidence.
observation on each store tells you what you are looking at:
| Field | Meaning |
|---|---|
last_completed_scan_at | When the most recent completed scan finished. null means the store is known but never fully observed; treat other fields as unknown. |
scope | full, partial, or homepage_only. What that scan covered. |
coverage_note | Plain-language caveat, for example "product pages returned a bot challenge". |
Unknown is not "not a store"
GET /v1/stores/{domain} returns 404 not_found, and enrich returns match: no_match, when no store profile was returned. That is not one situation but four, and the reason field is what tells them apart. Read it before drawing any conclusion:
| Reason | Meaning |
|---|---|
not_in_corpus | We have never observed this domain. Ask for an observation with refresh: true. |
invalid_domain | The input did not canonicalize to a public registrable domain. |
not_ecommerce | We observed it and classified it as not a store. |
blocked | The domain is on a policy denylist. |
Only not_ecommerce is a statement about the site: we observed it and classified it. The other three are statements about us, and not_in_corpus in particular means missing coverage, not a verdict.
Absence is not removal
technologies lists what the last completed observation saw. A technology missing from the list was not seen in that scope; it was not necessarily removed. Before you conclude that a store dropped a vendor:
- Check
observation.scope. Afullobservation supports "not detected within what that scan covered". It does not by itself establish a removal; the confirmation rule below does. - Check
last_completed_scan_at. An old observation says less than a recent one. - Use confirmed events.
recent_signals(and, in a later release,/v1/stores/{domain}/history) carriestechnology_removedevents, which require the technology to be missing from three consecutive comparable completed observations and to be absent from every other page we observe for that store.
Install states
Each technology carries an install_state:
| State | Meaning |
|---|---|
active | Loading on the storefront in the last completed observation. |
configured | Referenced but not loading, for example a disabled app block. Counts as installed, not as in use. |
inactive | Seen active before, then missing from three consecutive comparable completed observations, with no other observed page still showing it. This is a confirmed removal. One missed scan never produces it. |
first_observed_at and last_confirmed_at bracket the evidence. A technology with last_confirmed_at equal to observation.last_completed_scan_at was seen in the latest scan.
Confidence
confidence is high, medium, or low on platforms, technologies, and signals. high means more than one independent signal corroborates the fact. low rests on a single weak signal and is a hint to verify, not a fact to act on. Filter on it when precision matters more than recall, which for outreach it usually does.
Freshness and stale
Each plan has a freshness window (plan.limits.freshness_days). A profile whose last_completed_scan_at is older than that window is returned as match: stale on enrich. Stale profiles are complete, billed, and usable; the flag exists so you can decide whether to spend a lookup_live unit on refresh: true.
Signals
A signal is a confirmed change with provenance. The six types:
| Type | Definition |
|---|---|
store_first_observed | First completed observation of a storefront. |
technology_added | Present in a completed scan and absent in the latest comparable prior scan. |
technology_removed | Missing from three consecutive comparable completed observations where it was previously present, and not live on any other observed page. effective_at is the first of those misses; confirmed_at is the scan that met the threshold. |
platform_migrated | Platform changed between two completed scans, confirmed. |
store_became_active | Storefront entered the active_storefront state. |
store_became_inactive | Storefront left active_storefront, confirmed. |
Each carries effective_at (best estimate of when it happened: the first completed observation showing the new state) and confirmed_at (when the confirmation rule was satisfied). Signal ids are deterministic: the same fact has the same id on every delivery and replay, so consumers dedupe on id.
Counts state their population
Any count the API returns says which population it measures: candidate, reachable, verified_ecommerce, active_storefront, or monitored. The corpus is much larger than the set of confirmed active storefronts, and the two are not comparable. Public copy quotes only active_storefront and monitored counts with their date; do the same.