Guides

Daily new-jobs check for agents

Run the same search once a day and get only the jobs that are new since the last run, with postedSince and nextSince.

The most common thing an agent does with Trawle is a scheduled check: "tell me about new frontend jobs in Copenhagen every morning." The API is built for this.

How it works

Every search response includes nextSince, the time of that search. Store it. On the next run, send it back as postedSince, and you get only jobs that Trawle first saw after your previous run.

JSON
{
  "query": { "roles": ["frontend-engineer"], "places": [2618425] },
  "postedSince": "2026-10-30T07:00:00.000Z"
}

No overlap and no gaps: a job first seen between two runs shows up in exactly one of them.

Run once a day

Trawle scans every employer board once a day, starting early in the morning (UTC). dataDate in each response says when the data last changed. Running more often than daily just returns empty results; running less often is fine, because postedSince catches up on everything since the stored time.

A complete run

TypeScript
type State = { since?: string };

async function dailyCheck(state: State) {
  const jobs = [];
  let cursor: string | null = null;
  let nextSince: string | undefined;
  do {
    const response = await fetch("https://trawle.com/v1/jobs/search", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        query: { roles: ["frontend-engineer"], places: [2618425] },
        postedSince: state.since,
        cursor,
        limit: 100,
      }),
    });
    const page = await response.json();
    jobs.push(...page.jobs);
    cursor = page.nextCursor;
    nextSince ??= page.nextSince; // keep the first page's value
  } while (cursor);
  state.since = nextSince; // store only after the run succeeded
  return jobs;
}

On the first run there is no stored time. Leave out postedSince and you get every matching open job, or use query.posted: "1d" (or "7d") to start with a short window.

Tips

  • Store nextSince from the first page, and only after the whole run succeeds. If a run fails, the next one picks up from the older time and nothing is lost.
  • Keep the query identical between runs. A changed query with an old postedSince only returns jobs new since then, not every match for the new query.
  • postedSince counts from when Trawle first saw the job (firstSeenAt), not the employer's "date posted", which is often unreliable.
  • Reposts count as new: a job taken down and posted again under a new id has a new firstSeenAt. Add query.reposts: "hide" to skip them, or check repostCount.
  • The MCP server offers the same pattern as a daily_job_search prompt. See MCP for agents.