Telegram moderation, programmable
Check any message against the same anti-spam engine that protects thousands of Telegram groups, manage protection settings, read moderation history and receive real-time webhooks. Full API access is included in Pro ($29/mo) and Business plans; the spam-check endpoint works on every plan.
Quickstart — check a message in 30 seconds
Create a key in Dashboard → Settings → API & Webhooks, then:
curl -X POST https://api.telm.com/api/public/v1/spam/check \
-H "Authorization: Bearer tk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "Earn $5000 a week! DM me now @fast_money"}'{
"verdict": "spam",
"score": 87,
"confidence": 0.92,
"recommended_action": "delete",
"categories": ["contact_flow"],
"matched_rules": ["earnings_promise", "dm_invite"],
"signals": {"earnings_promise": 40, "dm_invite": 35},
"quota": {"used": 1, "limit": 100, "reset_at": "2026-07-08T00:00:00Z"}
}Python and Node are just as short — the API is plain JSON over HTTPS, no SDK required:
# Python
import requests
r = requests.post(
"https://api.telm.com/api/public/v1/spam/check",
headers={"Authorization": "Bearer tk_live_YOUR_KEY"},
json={"text": "gm! how is everyone today?"},
)
print(r.json()["verdict"]) # "clean"// Node.js
const res = await fetch("https://api.telm.com/api/public/v1/spam/check", {
method: "POST",
headers: {
Authorization: "Bearer tk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ text: "gm! how is everyone today?" }),
});
const { verdict, score } = await res.json();Authentication
Pass your key in the Authorization header (or X-API-Key):
Authorization: Bearer tk_live_...
- Keys are shown once at creation — store them like passwords.
- Read-only keys (scope
read) can only perform GET requests. - Revoking a key takes effect immediately.
Plans, quotas and rate limits
Quotas reset at midnight UTC. Every response carries X-Quota-Used / X-Quota-Limit headers.
| Plan | API calls / day | Rate limit | AI checks / day | Access |
|---|---|---|---|---|
| Free | 100 | 60/min | — | Spam check only |
| Basic ($9/mo) | 1,000 | 60/min | — | Spam check only |
| Pro ($29/mo) | 10,000 | 600/min | 1,000 | Full API + webhooks |
| Business ($99/mo) | 50,000 | 1,800/min | 10,000 | Full API + webhooks |
Hitting the quota returns 429 daily_quota_exceeded with reset_at and a Retry-After header. Group-scoped endpoints additionally require the target group to be on Pro or higher (otherwise 403 plan_required).
Endpoints
Base URL: https://api.telm.com/api/public/v1 — full request/response schemas in the OpenAPI spec.
Spam checking
/spam/checkCheck a text against the production engine. Optional group context applies the group's custom rules; include_ai adds the AI verdict (Pro+).
/spam/check-batchUp to 20 texts per call, one quota unit each.
/users/checkScreen a Telegram user: CAS verdict + Telm dataset (spam decisions in 90 days, reputation) + aggregated risk level.
Groups & settings
/groupsYour groups with plan and API availability.
/groups/{id}Group details.
/groups/{id}/settingsCurrent protection settings.
/groups/{id}/settingsPartial update (merge). Only catalog keys are writable; values are validated.
/settings-catalogMachine-readable catalog of writable settings (types, ranges, defaults).
/groups/{id}/rulesCustom moderation rules — also POST, PUT /{ruleId}, DELETE /{ruleId}.
/groups/{id}/whitelistUser whitelist — also POST, DELETE /{userId}.
History & analytics
/groups/{id}/journalEvery engine decision (verdict, score, matched rules, action) with cursor pagination and filters.
/groups/{id}/analyticsMessages, active users, joins/leaves, spam blocked, daily series.
Webhooks
/webhooksRegister an HTTPS endpoint — also GET (list), GET/PATCH/DELETE /{id}, POST /{id}/test, GET /{id}/deliveries.
Account
/usagePlan, limits, today's usage. Free of quota.
/meCurrent key info (health check). Free of quota.
Webhooks
Real-time events: spam.detected, message.suspicious, user.banned, user.kicked, user.muted, user.joined, user.left.
Each delivery is an HTTPS POST with a JSON envelope:
{
"id": "0d4f7a3e-...", // unique event id — deduplicate by it
"type": "spam.detected",
"created_at": "2026-07-07T10:00:00Z",
"group_id": -1001234567890,
"data": {
"message_id": 456,
"user_id": 789,
"text": "DM me for a deal!",
"action": "deleted",
"category": "contact_flow",
"confidence": 0.92
}
}Deliveries are signed. Verify the X-Telm-Signature header (v1=hex(hmac_sha256(secret, timestamp + "." + body))) and reject stale timestamps:
# Python
import hmac, hashlib, time
def verify(secret: str, headers, body: bytes) -> bool:
ts = int(headers["X-Telm-Timestamp"])
if abs(time.time() - ts) > 300: # 5 min anti-replay window
return False
expected = "v1=" + hmac.new(
secret.encode(), f"{ts}.".encode() + body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, headers["X-Telm-Signature"])// Node.js
import crypto from "node:crypto";
function verify(secret, headers, rawBody) {
const ts = Number(headers["x-telm-timestamp"]);
if (Math.abs(Date.now() / 1000 - ts) > 300) return false;
const expected =
"v1=" +
crypto.createHmac("sha256", secret).update(`${ts}.`).update(rawBody).digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(headers["x-telm-signature"])
);
}- Respond with any 2xx within 10 seconds; redirects are not followed.
- Failed deliveries retry: +1m, +5m, +30m, +2h, +6h (6 attempts total).
- Delivery is at-least-once: deduplicate by the envelope
id(also sent asX-Telm-Delivery). Event capture is best-effort — events emitted during brief maintenance windows on our side may be skipped, so treat webhooks as a real-time signal and use the journal API as the source of truth. - The signature covers the timestamp and body only. Always read the event type from the signed
typefield in the body, not from theX-Telm-Eventheader. - Endpoints failing for 3 days straight are disabled automatically — the owner gets a Telegram DM and can re-enable after fixing the receiver.
Errors
Errors are JSON with a machine-readable error code and a human message:
| Status | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | Key missing, malformed or revoked |
| 403 | insufficient_scope | Read-only key used for a mutation |
| 403 | plan_required | Endpoint needs Pro+ (on the group or your account) |
| 404 | group_not_found | Group doesn't exist or you are not its admin |
| 413 | body_too_large | Request body exceeds the size limit (64 KiB, batch 256 KiB) |
| 422 | unknown_setting | Setting key is not writable via the API |
| 429 | rate_limit_exceeded | Per-account per-minute limit (shared across your keys) — honor Retry-After |
| 429 | daily_quota_exceeded | Daily quota spent — resets at midnight UTC |
Start building
Create a free key and try the spam-check endpoint right now — 100 calls a day cost nothing. Upgrade to Pro when you are ready for the full API.