Skip to main content
👤 For humans Give this to your agent and it will set up TAMradar monitoring for you — create radars, check balance, retrieve findings. Give this link to your agent: https://docs.tamradar.com/agentic/tamradar-agent.md

You set up TAMradar monitoring for a user. Read this file top to bottom before starting. Base URL: https://api.tamradar.com Auth header: x-api-key: {TAMRADAR_API_KEY} — required on every request. No Bearer prefix.

Authentication

Check the environment for TAMRADAR_API_KEY. If the variable is unset or empty, ask the user: “I need your TAMradar API key to proceed. You can find it in your account settings at tamradar.com.” Never guess or construct the key. Do not proceed without it. Canonical request format — use this exact pattern for every call:
x-api-key is the auth header. Content-Type: application/json is required on all POST requests.

How this works — overview

Detailed breakdown follows.

Inputs — collect before starting

Webhook URL — default to polling

webhook_url is optional. Default to polling via GET /v1/updates unless the user explicitly provides a webhook URL. If no webhook URL provided: omit webhook_url entirely — the radar will be poll-only. Retrieve findings via GET /v1/updates. No need to ask. If user provides a real webhook URL (Make.com, Clay, Zapier, n8n): include it. Real-time delivery will work automatically. ⚠️ Once set, webhook_url cannot be changed without deactivating and recreating the radar. Avoid ephemeral test URLs like webhook.site for production radars.

Phase 1: Pre-flight — ALWAYS run first

Sample response:
Balance gate — enforce strictly:
  • IF data.balance_remaining_usd == 0STOP. Tell user: “Your TAMradar balance is $0. Add funds at tamradar.com before I can create any radars.”
  • IF data.balance_remaining_usd < 5WARN. Tell user the balance, ask if they want to continue.
  • IF data.balance_remaining_usd >= 5 → Proceed. Report balance to user.

Recommend: balance monitoring cron (to user only — do not auto-install)

Tell the user:
“To avoid radars being deactivated unexpectedly, I recommend setting up a daily job that calls GET /v1/account and alerts you if balance_remaining_usd drops below a threshold (e.g. 10).TAMradarautodeactivatesradarswhenbalancehits10). TAMradar auto-deactivates radars when balance hits 0 and sends a radar_failure webhook — but proactive monitoring is better than reacting after the fact.”
Only suggest this. Do not install cron jobs, crontab entries, or scheduled tasks without explicit instruction.

Phase 2: Create radars

Idempotency — check local store first

Before every POST, look up (domain, radar_type) in ./tamradar-radars.jsonl (your local mapping store). If a matching entry exists, skip the POST and use the stored radar_id. This avoids wasteful requests and eliminates a whole class of 409 errors.

Singles vs bulk

  • ≤10 targets → create one by one (single POSTs). Simple, easy to debug.
  • >10 targets → use POST /v1/radars/bulk (async queue, max 1000 items per request).

Single radar creation

updates_since is optional. Never invent or infer it. Include it only when the user explicitly asks for historical data or supplies an earliest date. Require an RFC 3339 timestamp with timezone; future scheduling is not supported. Omit it to use radar creation time. Do not use the deprecated include_historical field. custom_fields recommendation: always pass your internal IDs here. They echo back in every finding, making it easy to route data back to your CRM, database, or workflow.

Company radar

Contact radar

Industry radar

⚠️ CRITICAL: persist the mapping after every 201

Store immediately to ./tamradar-radars.jsonl (append one JSON object per line):
This file IS your monitoring state. Without it you cannot poll by specific radar, deactivate targets, or check idempotency before creating.

Bulk creation — for >10 targets

Send up to 1000 radars per request. webhook_url is required at the envelope level and applies to all items in the submission.
Bulk submission response — HTTP 202 accepted:
  • Response returns bulk_id and submission summary only.
  • Item-level outcomes are asynchronous and arrive via:
    • webhook events (radar_created / radar_failure / bulk_completed)
    • GET /v1/radars/bulk/{bulk_id} polling

Phase 3: Error handling

MUST handle every error before reporting success.

Phase 4: Retrieve findings (polling)

GET /v1/updates returns the same data as webhooks. The response uses updates[] — not data[]. Note: findings are retained for 60 days. Data older than 60 days is purged. Note: radar_failure events are excluded by default. Default update_type is radar_finding only. Sample response:

Fetch findings for specific radars (max 10 radar_ids per call)

If you have more than 10 radars, split into multiple calls of up to 10 IDs each.

Fetch by signal type

Incremental — only new since last check

ALWAYS store discovered_at from the last update you processed. Pass it as since on the next call.

Pagination

IF has_more: true → fetch next page:
Repeat until has_more: false.

To include radar failures in polling

Presenting findings to the user

Group by data.radar_type. Always include discovered_at. Example:
New job at openai.com — Senior Research Engineer, Alignment Detected: 2026-04-29 · View posting

Phase 5: Deactivate radars

  • Irreversible. Must create a new radar to resume monitoring.
  • No further charges after deactivation.
IF user says “stop monitoring openai.com for job openings” → look up radar_id from ./tamradar-radars.jsonl and DELETE it. For multiple radars, send one synchronous request:
Use single DELETE for one radar and bulk DELETE for 2–500 known IDs. Check every radars[] item: the top-level response is 200 even when some IDs are missing or already inactive.

Phase 6: Retrieving findings

Default: use polling. GET /v1/updates always works regardless of webhook_url. Findings are available immediately after creation and retained for 60 days. If the user later wants real-time push delivery:
“Your radars are active and I can fetch findings anytime you ask. For real-time delivery into Slack, your CRM, or an automation, connect a tool like Make.com or Clay — it generates a webhook URL you can give me and I’ll update the setup.”

Summary template — ALWAYS present when done


Endpoint reference (machine-readable)

Fetch these as raw markdown for full schema details:
  • Company radar: https://docs.tamradar.com/api-reference/create-company-radar.md
  • Contact radar: https://docs.tamradar.com/api-reference/create-contact-radar.md
  • Industry radar: https://docs.tamradar.com/api-reference/create-industry-radar.md
  • Poll updates: https://docs.tamradar.com/api-reference/poll-updates.md
  • Account: https://docs.tamradar.com/api-reference/account.md

Radar type reference

Company — POST /v1/radars/companies

Required: domain, radar_typewebhook_url optional (omit for poll-only)

Domain normalization

The API accepts any format — bare domain, URL, or with www/path/port. All are normalized automatically:
  • openai.com
  • https://www.openai.com/about ✅ → normalized to openai.com
  • www.openai.com ✅ → normalized to openai.com
Best practice: pass the bare domain (openai.com).

Contact — POST /v1/radars/contacts

Required: radar_type + type-specific identifiers — webhook_url optional (omit for poll-only):

Profile URL normalization

Pass the full URL. The API normalizes automatically:
  • https://www.linkedin.com/in/samaltman ✅ (preferred)
  • https://linkedin.com/in/samaltman ✅ → normalized to https://www.linkedin.com/in/samaltman
  • linkedin.com/in/samaltman ✅ → https:// added automatically
  • Trailing slash stripped automatically
For contact_job_changes, LinkedIn company, school, and legacy /pub/ URLs are rejected; only person profiles under /in/ are accepted. Email must identify an individual, so role-based, shared, and placeholder addresses are rejected. For contact_job_changes, uniqueness is evaluated within the same account, domain, and radar type. An exact case-insensitive email match or a normalized LinkedIn profile URL match returns 409; full_name alone is not a duplicate key. The error field is identifiers.email or identifiers.profile_url, showing which identifier matched. Different radar types for the same person are allowed.

Industry — POST /v1/radars/industry

Required: radar_type. No domain field — webhook_url optional (omit for poll-only).

Key fields reference


Hard limits

  • webhook_url is optional — omit for poll-only radars; include only when real-time push delivery is needed
  • Rate limit: 100 write requests / 60 seconds, 200 read requests / 60 seconds — need more? contact support@tamradar.com
  • Bulk max: 1000 radars per request
  • Polling radar_id filter: max 10 IDs per call — split into multiple requests if you have more
  • Polling data retention: 60 days — older data is purged
  • Company uniqueness: one radar per domain + radar_type per account — duplicates get 409
  • Contact job-change uniqueness: within the same domain + radar_type, an email or normalized profile URL match gets 409; full_name is not a duplicate key
  • Different contact radar types for the same person are allowed
  • Persistence: save mappings to ./tamradar-radars.jsonl by default