Getting started
Monitors
Watch the web for a query on a schedule, and get only the results that are new.
Before you begin
Section titled “Before you begin”- A Telem API key. Create one in the Telem console, under API keys in your project. See API keys.
- For the Coding agent tab: Telem set up in Claude Code, Codex, Grok Build, Muse, VS Code, Cursor or Devin Desktop, or any agent connected to the hosted MCP server. The other integrations do not have the monitor tools yet.
- For the Python and JavaScript tabs: the Python SDK or the JavaScript SDK.
- For the Console tab: edit rights in the project: Editor, Maintainer or organization administrator. A Viewer can see the monitors but not change them.
Each run of a monitor is billed to your account. See Pricing.
Start a monitor
Section titled “Start a monitor”Create a monitor and read what is new
-
Ask your agent to create a monitor. Say what to watch for and how often.
Create a Telem monitor for "Nvidia files a new 8-K with the SEC" that runs every hour.The agent uses the
create_monitortool and tells you the monitor’s ID. Your agent can ask you before it runs the tool. -
Ask for the new results later.
Get the new results of my Nvidia monitor.The agent uses
get_new_results. To see all your monitors, ask the agent to list them. -
Ask the agent to delete the monitor when you are done. If you do not, Telem ends it after 7 days. To keep it longer, ask for a longer time when you create it, up to 30 days.
-
Create a monitor.
from telem import Telemclient = Telem()monitor = client.monitors.create("Nvidia files a new 8-K with the SEC",frequency="1h",)print(monitor.id) -
Poll it for new results, as often as you need. Or let Telem send them to you: see Get results by webhook.
response = client.monitors.poll(monitor.id)for result in response.results:print(result.title, result.url) -
Delete it when you are done.
client.monitors.delete(monitor.id)
-
Create a monitor.
import { Telem } from "@telemai/sdk"const telem = new Telem()const monitor = await telem.monitors.create("Nvidia files a new 8-K with the SEC", {frequency: "1h",})console.log(monitor.id) -
Poll it for new results, as often as you need. Or let Telem send them to you: see Get results by webhook.
const response = await telem.monitors.poll(monitor.id)for (const result of response.results) console.log(result.title, result.url) -
Delete it when you are done.
await telem.monitors.delete(monitor.id)
-
Create a monitor. The response gives its
id.Terminal window curl -X POST "https://router.telem.ai/v1/monitors" \-H "Authorization: Bearer $TELEM_API_KEY" \-H "Content-Type: application/json" \-d '{"query": "Nvidia files a new 8-K with the SEC","options": {"frequency": "1h"}}' -
Poll it for new results, as often as you need. Or let Telem send them to you: see Get results by webhook.
Terminal window curl -X POST "https://router.telem.ai/v1/monitors/$MONITOR_ID/poll" \-H "Authorization: Bearer $TELEM_API_KEY" -
Delete it when you are done. The answer is
204.Terminal window curl -X DELETE "https://router.telem.ai/v1/monitors/$MONITOR_ID" \-H "Authorization: Bearer $TELEM_API_KEY"
-
Open Monitors in your project. In the Telem console, open your project, then Monitors, then New monitor.
-
Say what to watch for, and how often. Fill in What to watch for. It cannot change later. Then choose:
- How often: every day if you leave it.
- API key: the key the monitor belongs to. It needs Telem Search. Its project pays for the runs.
- Ends at: when the monitor ends, at most 30 days from now. It is 30 days from now if you leave it.
- Optional: Only these sites.
- Agent, on by default: an agent checks each result against what you wrote, and keeps the ones that match, with their sources.
-
See what is new. A console monitor gathers new results automatically. They show on the monitor after every run. You can turn off Gather results automatically. Then press Check for new results to see what is new.
-
Delete it when you are done. Press Delete this monitor. Its found items stay under Show ended.
Everything you can set when you create a monitor
The SDKs take the same options with their own names, for example include_domains
in Python and includeDomains in JavaScript. Through the agent tools you can set
only the query, the frequency, how long the monitor lives, and whether it has an
agent.
| Field | What it does |
|---|---|
query |
Required. A plain sentence that says what to watch for. You cannot change it later. |
options.frequency |
How often Telem runs the query: 1h, 6h, 12h, 1d or 7d. If you leave it out, the monitor runs once a day. |
options.include_domains |
Only results from these sites and their subdomains, such as ["sec.gov"]. Hostnames only, at most 20. |
options.search |
Also search the web for the query on each run. It takes num_results (10 if you leave it out) and tier. {} uses the default search. The default search options of your SDK client do not apply. |
metadata |
Query lineage keys, as in a search. |
webhook_url |
An https URL that gets the new results. See Get results by webhook. |
ttl |
How long the monitor lives, in hours or days, such as 12h or 7d. At most 30d. |
agent |
The monitor agent checks every result against the query and keeps the ones that match. You read what the agent keeps in the console. It is on by default. Send false to create the monitor without an agent. |
{ "query": "Nvidia files a new 8-K with the SEC", "options": { "frequency": "1h", "include_domains": ["sec.gov", "reuters.com"], "search": {"num_results": 20} }, "ttl": "7d"}If the agent cannot start, Telem still creates the monitor, without an agent, and
the answer has agent_note, which says why.
If the create fails, you get an error, and you can send the same request again. After a network error, list your monitors first: the monitor can exist although you got no reply.
What a poll returns
Section titled “What a poll returns”A poll returns the results that are new since your last poll, in the same shape as
a search response. Through the agent tools,
get_new_results gives your agent the same results as text.
- The first poll returns all the results the monitor has found so far.
- A result comes once. A result that you got before does not come back, so keep the results that you poll.
- The body is optional. It takes
session_idandmetadata, as a search does. Without them, Telem records the poll in the monitor’s own session (session_idon the monitor). Thesession_idof another monitor is refused. - After a network error, a poll can have returned results that you did not get. The next poll does not return them again.
- Results about the same story can come under one result. Their envelope then
has
same_story: each key is the URL of the result that stays, and its value is a list of{url, title}. The SDKs give it assame_story(Python) andsameStory(JavaScript) on each provider run.
A poll response can carry warnings:
| Code | What it means |
|---|---|
run_failed |
A run failed or was cancelled. The message gives the reason. |
monitor_inactive |
The monitor stopped and does not run. Delete it and create a new one. |
more_runs_pending |
More than 100 runs were waiting. You get the oldest 100 now and the rest on the next poll. |
results_truncated |
Some old runs are no longer kept, because you did not poll for a long time. |
dropped_results |
Some results had no URL, so Telem skipped them. |
Specific to monitors
Section titled “Specific to monitors”-
Each page comes once. When a page has come from a monitor, it does not come again, even if the page changes later. A new section of a page you already got, such as
changelog#v3, does not count as a new page. -
The web search option looks for new pages. With
options.search, each run returns the pages published since the run before it. The first run returns the pages dated in the last 24 hours. Pages with no date are skipped, and they do not come later. -
A monitor you do not read stops running. If nobody polls a monitor for 7 days, or for two of its periods when that is longer, Telem stops its runs until the next poll. For a monitor with a webhook, a run counts as a poll, also when it finds nothing new, but not when the run or its webhook request fails. Check for new results in the console also counts as a poll. A console monitor that gathers automatically never stops this way. The status still shows
active, and the monitor can miss results from that time. -
How long a monitor lives depends on how you created it:
Created with It lives The SDKs or HTTP Until you delete it, or for ttlif you set itThe agent tools 7 days, or the time your agent sets, up to 30 days The console Up to 30 days, as you choose; 30 by default A monitor with no end date runs until you delete it, and its runs bill. Turning on Gather results automatically gives a monitor with no end date an end 30 days later. In the console you can set a new end date, at most 30 days from then.
At
expires_at, the monitor ends. Its status becomesendedand it stops running. A poll or a change answers409 monitor_ended, and a new end date cannot start it again: create a new monitor. You can still delete it, and the results that you polled stay in the session. Some hours later Telem removes it: the API then answers404, and the console shows it under Show ended. -
A monitor belongs to its API key. Through the API and the agent tools you see only the monitors of your key, including the ones made in the console for it. The console shows all the monitors of the project. If you revoke or delete a key, or it expires, its monitors end, and Telem removes them some hours later. Their results stay readable in the console.
-
The agent tools see less.
list_monitorsshows the newest 50 monitors.get_new_resultsshows no warnings. A result that reports the same story as an earlier one comes as a line under it, such asSame story as <URL>: …. -
When a program reads a console monitor, for example your agent with
get_new_results, the console stops gathering its results, so they are not read twice.
Get results by webhook
Section titled “Get results by webhook”Set webhook_url when you create or change a monitor with an SDK or the API. The
console cannot set a webhook. When a run finds new results,
Telem sends them in a POST request to that URL. The body is the same as a poll
response. You can still poll as well.
The response that sets webhook_url gives a webhook_secret. Telem shows it only
once, so keep it. To get a new secret, set the URL again.
Each request has these headers:
| Header | Value |
|---|---|
Telem-Monitor-Id |
The monitor ID. |
Telem-Signature |
t=<Unix time in seconds>,v1=<signature> |
Check each request before you use it. Give the body exactly as you received it. The check fails if the signature is wrong or older than 5 minutes.
from telem import verify_webhook
ok = verify_webhook(body, headers["Telem-Signature"], webhook_secret)import { verifyWebhook } from "@telemai/sdk"
const ok = await verifyWebhook(body, headers.get("Telem-Signature") ?? "", webhookSecret)- If your URL does not answer with a
2xxstatus, Telem tries again after 1 minute, 5 minutes, 30 minutes and 2 hours, then stops. A3xx, or a4xxother than429, stops it at once: Telem does not follow redirects. - The URL’s host must have a public IPv4 address.
- The same results can come more than once. Use
interaction_idto find a repeat. - A poll does not return the results of a webhook request that failed.
- If all the requests to your URL fail, the monitor stops running. A request that fails does not count as a poll. If the requests fail for 7 days, or for two of the monitor’s periods when that is longer, Telem stops the runs, as for any monitor that nobody reads. When your URL works again, poll the monitor once. The poll starts its runs again.
- When you change or remove the URL, or delete the monitor, the next requests, retries included, go to the new URL with the new secret, or stop.
Pause, change, delete
Section titled “Pause, change, delete”Through the agent tools you can list and delete monitors. In the console you can pause, resume and delete a monitor, turn Gather results automatically on or off, change how often it runs, and set a new end date. To change the webhook, use an SDK or the API. A monitor that has ended cannot change.
Get one monitor, or list yours, newest first: 50 by default, at most 200 at a time.
Over HTTP, the list has next_cursor. Send it as cursor to get the next page. It
is null on the last page.
monitor = client.monitors.get(monitor_id)monitors = client.monitors.list(limit=50)
client.monitors.update(monitor_id, status="paused")client.monitors.update(monitor_id, status="active", frequency="1d")client.monitors.delete(monitor_id)const monitor = await telem.monitors.get(monitorId)const monitors = await telem.monitors.list({ limit: 50 })
await telem.monitors.update(monitorId, { status: "paused" })await telem.monitors.update(monitorId, { status: "active", frequency: "1d" })await telem.monitors.delete(monitorId)curl "https://router.telem.ai/v1/monitors?limit=50" \ -H "Authorization: Bearer $TELEM_API_KEY"
curl -X PATCH "https://router.telem.ai/v1/monitors/$MONITOR_ID" \ -H "Authorization: Bearer $TELEM_API_KEY" \ -H "Content-Type: application/json" \ -d '{"status": "paused"}'A change takes one or more of these fields:
| Field | What it does |
|---|---|
status |
paused pauses the monitor until you resume it. active resumes it. |
frequency |
A new frequency: 1h, 6h, 12h, 1d or 7d. |
webhook_url |
A new webhook URL, with a new webhook_secret in the response. null removes the webhook. In the SDKs, "" also removes it. |
You cannot change the query: delete the monitor and create a new one. If a change
fails with a 502 error, you can send the same request again. If a delete
fails, send it again to finish it.
The monitor object
Create, get, list and change return this object:
{ "id": "6f1c…", "query": "Nvidia files a new 8-K with the SEC", "frequency": "1h", "status": "active", "session_id": "a2d9…", "created_at": "2026-10-11T09:00:00Z", "last_polled_at": null, "expires_at": "2026-10-18T09:00:00Z"}statusisactive(Telem runs the query on the schedule),paused(you paused it; it stays paused until you resume it) orended(its end date passed, or its API key was revoked or expired; it does not run again).session_idis the session where Telem records your polls.expires_atis when the monitor ends, ornullif it does not end.
If something goes wrong
- A poll returns nothing new: the runs found nothing new since your last poll. For a rare event that is normal. A result you already got does not come back.
- Results stopped coming: check the monitor’s
status.paused: resume it.ended: its end date passed, or its API key was revoked or expired. Create a new monitor.active: nobody polled it for 7 days. A poll, or Check for new results in the console, starts its runs again.
- A changed page did not come again: a monitor sends each page once.
- The webhook gets nothing: the URL must use
https, answer with a2xxstatus, not redirect, and have a host with a public IPv4 address. After the last retry, Telem stops, and a poll does not return those results. - The
monitor_inactivewarning: delete the monitor and create a new one.
| Status | Code | When | What to do |
|---|---|---|---|
400 |
invalid_request |
The frequency is not in the list, a change sent none of status, frequency and webhook_url, a search refuses an option in options.search, or a poll names the session_id of another monitor. param names the field. |
Fix the field. |
400 |
invalid_request |
A search provider refused the request. Sending it unchanged will not help. | Change the request, such as the query or the sites. |
400 |
invalid_request |
A search provider no longer has this monitor, so a poll or a change cannot run. Sending it again will not help. | Delete the monitor and create a new one. |
400 |
query_immutable |
A change sent query. |
Create a new monitor. |
400 |
invalid_session |
The session in metadata is not correct. |
Fix the session. |
402 |
payment_required |
A create: the account cannot pay for the monitor. The message says why. | Check the account’s billing in the console. |
404 |
not_found |
The monitor does not exist, or another API key created it. | Check the ID and the key. |
409 |
poll_in_progress |
Another call uses this monitor now. | Try again. |
409 |
monitor_ended |
The monitor has ended. Its results stay readable. | Create a new monitor. |
409 |
pause_not_supported, update_not_supported |
Telem cannot make this change now. Nothing changed. | Try again later. |
422 |
invalid_request |
Any other field is missing or not correct. For example: the body is not valid JSON or has an unknown field; the query is empty; ttl or webhook_url is not correct; a site in options.include_domains is not a hostname; or options.search has an option that the monitor sets itself. param names the field. A monitor ID that is not a UUID also gets 422, not 404. |
Fix the request. |
429 |
rate_limited |
Telem is busy. | Wait for the seconds in Retry-After, then try again. |
500 |
internal_error |
Telem could not create the monitor. No monitor exists. | Try again. |
502 |
unavailable |
The monitor call failed. | Send the same request again. |
503 |
unavailable |
Telem cannot run monitors now. | Try again later. |
Monitor errors have this body: {"error": {"code": "...", "message": "..."}}. The
SDKs keep code on the error. See Errors.
Learn more
Section titled “Learn more”Every field of the monitor calls and their responses.
The monitor tools your agent gets, with the search and page-reading tools.
Monitors, search, fetch and sessions from Python.
Monitors, search, fetch and sessions from TypeScript.
Every error the API returns, and what to do.
What each run of a monitor costs.