technographics.technologies.name is a company field and job_details.title is a job field, so the watch delivers companies running Snowflake that are hiring a data engineer. Neither condition could be expressed in a single-dataset watch: technology stack is not carried on job records, and open roles are not carried on company records.
Why this exists
A job record already carries some of its company’s attributes, so a job watch can filter on funding stage, headcount, industry, and head office without leaving the job dataset. Nothing marks those fields as special from the outside, which made the boundary invisible: filtering a job watch on funding stage worked, and filtering the same watch on technology stack failed. Cross-dataset filters put every filter field on all three search endpoints within reach of any discovery watch.What you can combine
Every pairing works, and a single watch can pull from all three datasets at once.
People join through their current employer only. A filter on a past employer
still selects the right people, but the company it points at is where they
work now. “Companies that hired away from Acme” means companies that
currently employ someone whose earlier experience was at Acme.
How a run works
1
Field names decide the dataset
Field names are unique across the three datasets, so the name alone
identifies where a condition belongs.
headcount.total is a company field,
job_details.title a job field, experience.employment_details.current.title
a person field. Every name is listed in the
Company Search,
Person Search, and
Job Search references.A handful of names appear in more than one vocabulary. technographics.technologies.name,
technographics.technologies.category, and technographics.technologies.super_category
are on both company and job records, and indexed_at and updated_at are on all three.
Your watch’s own dataset always wins those, so a job watch filtering on
technographics.technologies.name reads the job record’s own copy rather than
querying the company dataset.2
We query the other dataset first
Conditions from another dataset run against that dataset and come back as a
set of company IDs. We fetch the IDs and nothing else.
3
Those IDs narrow your watch
The IDs go back into the filter tree in the position the conditions occupied,
as a membership condition. Your watch then runs as normal.
Grouping
Conditions from the same dataset sitting side by side in a group are answered together, as one question. In this company watch:job_details.title and location.country are both job fields, so the watch asks for one posting that is an engineering role and is in the United States. It does not return a company with an engineering role in India and a separate sales role in the United States. Writing the two job conditions inside their own and group means the same thing, so you can group them for readability without changing the result.
Under or the two forms also agree: a posting matching A, or a posting matching B, is a posting matching A or B.
When a cross-dataset condition matches nothing
An empty result counts as false and travels up through your groups. Underand, the whole branch is false and the run delivers nothing. Under or, that branch drops out and the rest of the watch still runs.
Recipes
Every one of these is verified against the live API. Swap the notification channel for your own./watch/company/search and /watch/person/search. The second is a job watch and goes to /watch/job/search.
Three datasets in one watch
A company watch running Snowflake, hiring data engineers, and employing someone who used to work at Databricks:“First time” watches
Set up a watch for companies that employ a machine learning engineer. Its free baseline run records every company that already has one and delivers almost nothing. After that, a company can only appear by joining the set for the first time. That gives you “hired their first machine learning engineer” with no extra configuration, and the same shape gives you first hire in a country, first sales hire, or first posting of any kind. Two caveats. It means first as far as our data reaches, so a coverage gap or an edited job title will both set it off. And it fires once: a company that hires an ML engineer, loses them, and hires another stays quiet the second time.Records from the other dataset
The payload carries your watch’s own records and nothing else. A company watch tells you Acme matched. It does not tell you which posting or which person put Acme there, because only IDs cross between datasets, never records. That is also why you are not charged for the dataset you filtered on. To get those records, call that dataset’s own search or enrich API with the ID from the delivered record and the same conditions you filtered on.
A company watch on Snowflake and
job_details.title contains data engineer delivers company 8294878. This gets the posting that put it in the feed:
company.basic_info.crustdata_company_id, and a delivered person record carries it as crustdata_company_id on each current employer.
These are ordinary search and enrich calls, billed at their normal rate. See Pricing.
What is not supported
Negation across datasets
We reject the operators that negate a single record when they sit on a cross-dataset condition:!=, not_in, (!), not_contains, and geo_exclude.
400:
basic_info.year_founded != 2020 on a company watch is accepted, because there it means what it says.
Counting
You can ask whether at least one matching record exists. You cannot ask for a number. “Five or more open engineering roles”, “doubled their postings this quarter”, and “three or more people left” are all out of reach.Growth on the other dataset
“Companies whose engineering headcount grew” works, because that figure sits on the company record. “Companies whose engineering postings grew” does not, because job records carry no growth figures.Limits
We check both when you create the watch, so you find out immediately rather than on the first run.
The first is the baseline limit. The baseline run delivers a sample of 5, but it reads the whole match set to record what already exists, and that read is what the 500,000 bounds. It is not a ceiling on the watch’s lifetime: later runs deliver whatever newly matches, bounded by
config.max_results_per_run.
A cross-dataset condition under and narrows the set before the baseline limit is measured, so a watch can pair a very broad condition on its own dataset with a narrow one from another. This is accepted even though headcount.total > 10 alone matches over four million companies:
or there is no narrowing, so the same pair is rejected:
basic_info.year_founded > 2020 reaches roughly four million companies, and the 400 opens Your company filters cover more than 1,000,000 companies. before suggesting you add a location, a date, or a more specific title. The full envelope is in the Watch API reference, under Create a discovery watch.
If we cannot reach the other dataset at creation time, the watch is not created and you can retry:
Timing and deduplication
A single-dataset watch narrows each run to records reindexed since the previous run. That shortcut does not hold once another dataset is involved: a company posts a job on Tuesday, the job record is new, and the company record is untouched. A cross-dataset watch re-evaluates the full current match set on every run instead. What stops a record arriving twice is the record of what has already been sent, not the time window. Each match is delivered once, ever, for a given watch. If it drops out of the set and comes back later, the watch stays quiet.Credits
Credits work exactly as they do on a single-dataset watch. You pay for records delivered to you, at your watch’s own rate: 2 credits per company, 0.5 per person, 0.5 per job. Reading another dataset to narrow your filters is free, and the baseline run is free. See Pricing for the full table.Related
Company discovery watcher
Deliver companies that newly match a filter.
Person discovery watcher
Deliver people that newly match a filter.
Job watcher
Deliver jobs that newly match a filter.
Pricing
Credit costs across all Crustdata endpoints.

