Skip to main content

Track Telegram Catalog Changes with Snapshots

A snapshot saves the set of channels matching catalog filters at one point in time. A diff later reapplies those saved filters and records which channels have entered or left the original set.

Release status

This guide describes the snapshot API prepared for release. The prices below are agreed for release; public activation still depends on deployment and runtime price configuration.

Access and limits

Credits planMatching channelsActive snapshotsActive diffs
Free / ProNo access00
Advanced50,0005200
Team100,00010400

Subscription API keys require snapshots to be enabled separately as well as catalog access. Their size and active-resource limits are configured individually.

The size cap applies both when creating a snapshot and when evaluating the current matching set for a diff. An oversized result is rejected, never silently truncated. Active counts are shared across a user's snapshots; rotating the API key does not reset them.

Credits pricing

OperationCredits per successful request
Create a snapshot0.400
Create a diff, including a diff with no changes0.400
Read snapshot or diff metadata0.001
List snapshots or diffs0.001 per page
Read added or removed channel IDs0.001 per page
Delete a snapshot or diff, including cascade deletionFree
Storage for 30 days from each resource's creationIncluded

Creation prices are inclusive: there is no additional base-request or per-channel charge. Successful paid requests count towards the API request ceiling. Deletion with a Credits key consumes neither credits nor request quota, but still requires an active key and snapshot access. Subscription keys retain their configured request-quota accounting. Requests rejected by the snapshot handler, including invalid filters, size/capacity limits and storage failures, do not incur a credit charge.

Each successful POST creates a new resource and incurs a separate charge, even when its filters or source snapshot are identical to an earlier request. These endpoints do not support an Idempotency-Key header for deduplicating creation requests. A diff with zero added and zero removed channels still performs a fresh catalog evaluation and costs 0.400 credits.

For example, one snapshot, 30 diffs and 60 change-list pages cost 12.460 credits. Fetching channel details afterwards uses the separate channel-info tariff.

1. Save a baseline

curl --fail-with-body "https://api.tlmtr.io/v1/catalog/snapshots" \
-H "x-api-key: $TELEMETRIO_API_KEY" \
-H "content-type: application/json" \
--data '{"filters":{"country":"ukraine","members_min":1000,"privacy":"Public"}}'

A successful call returns 201 with snapshot_id, saved filters, channels_count, created_at and expires_at. Store the ID and expiry. Creation returns metadata; it does not return the full channel-ID set or a file download.

The request uses catalog filters. Sorting and search pagination do not define the snapshot. Use your original request filters if you create a new baseline: saved response filters have a normalized representation and are not a request body to copy verbatim.

2. Compare later

Set SNAPSHOT_ID to the returned identifier:

curl --fail-with-body -X POST \
"https://api.tlmtr.io/v1/catalog/snapshots/$SNAPSHOT_ID/diffs" \
-H "x-api-key: $TELEMETRIO_API_KEY"

The response is 201 with a diff_id, added/removed counts and its own expiry. Each diff compares with the original snapshot. Creating a diff does not replace or update the baseline, and reading a saved diff does not recalculate it.

removed means that a channel no longer belongs to the filtered set. It does not necessarily mean that the channel was deleted from Telegram.

3. Read added and removed IDs

curl --fail-with-body --get \
"https://api.tlmtr.io/v1/catalog/diffs/$DIFF_ID/changes" \
-H "x-api-key: $TELEMETRIO_API_KEY" \
--data-urlencode "change_type=added" \
--data-urlencode "limit=100"

The response includes channel_ids, the total count for the selected change type, and next_cursor. Pass that cursor unchanged to get the next page. Page size is 1–1,000, default 100.

Run a separate traversal with change_type=removed. Returned IDs identify Telemetr.io channels and can be enriched with /v1/channels/info-batch in batches of up to 100. Enrichment follows that endpoint's normal billing rules.

# client is an authenticated httpx.Client with the correct API base URL.
def changes(client, diff_id, change_type):
cursor = None
while True:
params = {"change_type": change_type, "limit": 1000}
if cursor:
params["cursor"] = cursor
response = client.get(f"/v1/catalog/diffs/{diff_id}/changes", params=params)
response.raise_for_status()
page = response.json()
yield from page["channel_ids"]
cursor = page.get("next_cursor")
if not cursor:
break

Manage capacity and retention

ActionEndpoint
List snapshotsGET /v1/catalog/snapshots
Get or delete one snapshotGET / DELETE /v1/catalog/snapshots/{snapshot_id}
List diffs, optionally for a snapshotGET /v1/catalog/diffs
Get or delete one diffGET / DELETE /v1/catalog/diffs/{diff_id}

Management lists return active_count and active_limit. The diff allowance applies across all of your snapshots even if the list is filtered by snapshot_id. Delete unneeded resources or wait for expiry to free capacity.

Each snapshot and each diff expires 30 days after its own creation. A diff requires an active baseline at creation. Deleting a snapshot without cascade=true retains its existing diffs until their own expiry; cascade=true deletes those diffs too.

After loss of snapshot entitlement, all snapshot/diff operations become unavailable, including reads and deletion. Stored resources expire normally. A lower eligible plan's limits apply to subsequent operations; an oversized saved baseline cannot be used to create a new diff under that plan.

Errors and retries

Only one snapshot creation and one diff creation per user can run at a time. Temporary conflicts return 429 with a stable code and Retry-After. Active-resource exhaustion also uses 429 but requires freeing capacity.

A retained expired resource can return 410. Reads of missing or inaccessible resources return 404. Deleting a missing, malformed or foreign snapshot/diff is idempotent: the response is 200 with snapshot_deleted: false or diff_deleted: false. Oversized snapshots/current sets return 422 with the effective size cap.

Settlement currently happens after the handler has completed. An insufficient-balance or quota response can therefore arrive after a snapshot or diff has already been saved; it does not prove that no resource was created.

If a creation request times out, inspect your recent snapshots/diffs before sending another POST. An uncertain network response does not prove that the operation was not completed. For exact response shapes and billing failures, see authentication and errors.