Skip to content

SwarmForensics API

Stop bot swarms before they hit your comments.

One API call per comment. SwarmForensics compares each new comment against your last 24 hours of activity and flags coordinated copy-paste waves, brigading bursts, and spam floods with a clear allow, review, or hold verdict.

500 free checks every month. No credit card required.

Pricing

Monthly plans, cancel any time. Usage resets on the 1st of each month (UTC). Checks stop at your plan limit, so there are no surprise overage bills.

  • Sandbox

    Free

    • 500 checks / month
    • 30 requests / minute
    • 2 active API keys
    • Dashboard flags only
    Start free
  • StarterPOPULAR

    $19/mo

    • 10,000 checks / month
    • 120 requests / minute
    • 5 active API keys
    • Signed swarm-alert webhooks
    Start Starter
  • Growth

    $49/mo

    • 50,000 checks / month
    • 300 requests / minute
    • 10 active API keys
    • Signed swarm-alert webhooks
    Start Growth
  • Scale

    $149/mo

    • 250,000 checks / month
    • 600 requests / minute
    • 25 active API keys
    • Signed swarm-alert webhooks
    Start Scale

Quickstart

  1. 1. Sign in and open Account → SwarmForensics API.
  2. 2. Create a key and store it as a server-side secret, for example SEEDENV_SWARM_KEY.
  3. 3. Call the API from your backend when a comment is submitted. Publish on allow, queue on review, and hide pending review on hold.

Never call the API from browser or mobile code. Anyone could read the key and spend your quota.

// Fail open: never block real users if the check is slow or unavailable.
export async function screenComment(comment) {
  try {
    const response = await fetch("https://seedenv.com/api/v1/moderate", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.SEEDENV_SWARM_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        text: comment.body,
        authorId: comment.userId,
        threadId: comment.postId,
        commentId: comment.id,
      }),
      signal: AbortSignal.timeout(1500),
    });
    const verdict = await response.json();
    return verdict.action; // "allow" | "review" | "hold"
  } catch {
    return "allow";
  }
}

Signals

Each signal adds weight to a 0–100 score. Defaults: 40+ is review, 70+ is hold.

Copy-paste clustercopy_paste_cluster
Identical text arrived from other accounts in the last 24 hours.
Coordinated phrasingcoordinated_phrasing
Near-identical wording shared across several distinct accounts.
Burst windowburst_window
Matching comments from multiple accounts landed within 10 minutes.
Same-thread brigadesame_thread_brigade
Matching accounts converged on one thread at the same time.
Author floodauthor_flood
One author posted an unusual number of comments in 10 minutes.
Self repeatself_repeat
One author pasted the same text into several different threads.
Link heavylink_heavy
Several links, or links from a brand-new account.
New accountnew_account
Amplifier only: the author is under 2 days old and other signals fired.

Signals are statistical indicators, not proof of automation. Organic viral moments can look bursty, so pair holds with human review.

API reference

POST https://seedenv.com/api/v1/moderate

Authenticate with Authorization: Bearer sfk_live_… (or X-API-Key). JSON body up to 20 KB.

Request fields
FieldTypeDescription
textstring, requiredThe comment body, up to 5,000 characters. Used to compute a fingerprint and never stored.
authorIdstring, requiredYour stable ID for the commenter. Hashed with a per-account salt.
threadIdstringThe post, video, or thread the comment belongs to. Enables brigade detection.
commentIdstringYour comment ID. Echoed back and shown in the dashboard so you can match flags.
postedAtISO 8601When the comment was posted. Defaults to now; values outside the last 24 hours are clamped.
authorAccountAgeDaysnumberAge of the commenter's account. Amplifies other signals for brand-new accounts.
thresholds{ review, hold }Override the default scores (40 / 70) that map to review and hold.

Request

curl -X POST https://seedenv.com/api/v1/moderate \
  -H "Authorization: Bearer $SEEDENV_SWARM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "This update is a scam, everyone cancel now",
    "authorId": "user_8812",
    "threadId": "post_311",
    "commentId": "c_90211",
    "authorAccountAgeDays": 0.4
  }'

Response

{
  "id": "mod_cm3x…",
  "commentId": "c_90211",
  "action": "hold",
  "score": 82,
  "signals": [
    { "code": "copy_paste_cluster", "weight": 30, "detail": "Identical text posted by 4 other accounts in the last 24h." },
    { "code": "coordinated_phrasing", "weight": 30, "detail": "Near-identical phrasing shared with 4 other accounts." },
    { "code": "burst_window", "weight": 20, "detail": "4 matching accounts posted within 10 minutes." }
  ],
  "cluster": { "size": 4, "sameThread": 4, "inBurstWindow": 4 },
  "thresholds": { "review": 40, "hold": 70 },
  "plan": "STARTER",
  "usage": { "used": 1288, "limit": 10000, "remaining": 8712, "resetsAt": "2026-12-01T00:00:00.000Z" }
}

Errors

Errors use { error: { code, message }, action: "allow" } so fail-open handling is one line.

Error codes
StatusCodeMeaning
400invalid_json / invalid_requestBody is not JSON or a field failed validation.
401unauthorizedMissing, invalid, or revoked API key.
413payload_too_largeBody is larger than 20 KB.
429rate_limitedPer-minute limit hit. Honor the Retry-After header.
429quota_exceededMonthly allowance spent. Checks resume on the 1st (UTC) or after upgrading.
500internal_errorTemporary failure. Fail open and retry later.

Webhooks

On paid plans, add an HTTPS endpoint in your dashboard. When a comment is held we POST a comment.held event with the moderation ID, your comment, thread, and author IDs, the score, signals, and cluster size. Each request carries a SeedEnv-Signature header. Verify it and reject anything older than 5 minutes.

import { createHmac, timingSafeEqual } from "node:crypto";

// Header: SeedEnv-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "t.rawBody">
export function verifySeedEnvSignature(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const expected = createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest();
  const received = Buffer.from(parts.v1 ?? "", "hex");
  return received.length === expected.length && timingSafeEqual(received, expected);
}

Privacy & acceptable use

  • Comment text is used only to compute a fingerprint and is never stored.
  • Fingerprints use a random salt unique to your account, are never shared across customers, and are deleted after 24 hours.
  • You are responsible for disclosing automated moderation in your own privacy policy where required.
  • The API may not be used to suppress lawful speech based on viewpoint, or to target individuals.

FAQ

Does it filter political opinions?

No. SwarmForensics never scores what a comment says or which side it takes. It looks only for coordination patterns, such as many accounts posting the same text in a short burst, which works the same for spam, astroturfing, and brigades of any viewpoint.

Will it delete comments automatically?

No. The API returns a recommendation. We suggest holding high scores for human review rather than deleting them, because heuristics can produce false positives during genuinely viral moments.

What data do you store?

We never store comment text. Each check keeps a short-lived fingerprint (salted hashes of the author, thread, text, and words) for 24 hours so we can spot coordination across comments, then it is deleted automatically.

What happens when I hit my limit?

Requests return 429 quota_exceeded with action "allow" so your app keeps working. Upgrade any time, or wait for the monthly reset on the 1st (UTC).

Is the free paste tool still free?

Yes. The SwarmForensics paste tool stays free, runs in your browser, and needs no account. The API is for apps that want continuous, automatic screening.

Start screening comments today

Free sandbox key in under a minute. Upgrade when your traffic does.

Get a free sandbox key