Skip to main content
This guide walks through a complete TAMradar integration from scratch. We’ll use a concrete scenario throughout: monitoring OpenAI, including job openings, executive moves, and AI funding activity across the industry. By the end you’ll have three active radars, a working webhook handler, and know how to poll for updates programmatically. Prerequisites
  • A TAMradar API key (UUID format, e.g. a1b2c3d4-...)
  • A publicly accessible HTTPS endpoint that accepts POST requests — use webhook.site for testing
  • Any HTTP client (curl, Axios, fetch, etc.)
Base URL: https://api.tamradar.com Auth header: x-api-key: YOUR_API_KEY (required on every request)

Step 1: Verify Your Account & Balance

Before creating anything, confirm your key works and you have enough balance.
balance_remaining_usd is what you have to spend. Each radar type has its own price. If you don’t have enough to cover a radar creation, you’ll get a 402 before anything is charged.

Step 2: Test Your Webhook Endpoint

Send a sample payload to your endpoint before committing balance. This is fire-and-forget. It won’t create a radar or charge anything.
Check your endpoint. You should receive a sample radar_finding payload. If it arrives, your endpoint is reachable and returning 2xx. Proceed.
You can also test a failure payload: add "update_type": "radar_failure" to the body.

Step 3: Create a Company Radar (Job Openings at OpenAI)

Track new engineering job openings posted by OpenAI, filtered to Senior-level and above.
webhook_url is optional. Include it to receive real-time push notifications. Omit it to poll for updates via GET /v1/updates instead.
201 — Created:
Save radar_id. You’ll use it to check status or deactivate the radar. next_charge_at is your next billing date, 30 days from creation. updates_since asks TAMradar to include eligible historical source events from the chosen past instant. It cannot schedule a future start. Omit it to receive updates_since: null and use the radar’s created_at as the effective cutoff.

What can go wrong


Step 4: Create a Contact Radar (Track Sam Altman)

Monitor job changes for a specific person. Requires domain + at least one identifier (email, profile_url, or full_name).
201 — Created:
Contact radar type requirements: For contact_job_changes, email must identify an individual; role-based, shared, and placeholder addresses are rejected. A supplied profile_url must be a LinkedIn person profile (linkedin.com/in/...); company, school, and legacy /pub/ URLs are rejected. Duplicate matching within the same company and radar type uses the email or normalized LinkedIn profile URL. full_name is accepted as an identifier but is not a duplicate key.

Step 5: Create an Industry Radar (AI Funding Rounds)

Track funding events across the AI industry, with no specific company or keyword needed.
201 — Created:
domain is always null for industry radars. Industry radar type requirements:

Step 6: Scale Up with Bulk Creation

Submit up to 1000 radars in one async bulk request. Useful when onboarding large account lists.
webhook_url is required for async bulk submissions. Bulk processing runs in the background and emits item outcomes (radar_created / radar_failure) plus a final bulk_completed. 202 — Accepted (request queued for async processing):
Track progress with the returned bulk_id:
The status endpoint returns:
  • status: "processing" while there are in-flight items
  • status: "completed" when all items are terminal
  • summary counts (processing, created, failed)
  • radars[] with item_index so you can map outcomes back to input order
  • radars[].update_id so you can correlate each item with its radar_created / radar_failure event
For webhook idempotency/correlation in async bulk:
  • Use top-level update_id on bulk_completed to deduplicate the whole batch event
  • Use radars[].update_id inside bulk_completed to correlate each item-level event

Step 7: Handle Failure Webhooks

When a radar fails during setup, TAMradar sends a radar_failure webhook to your endpoint and refunds the charge. missing_prerequisites — The company has no trackable public data source for this radar type. Balance is refunded.
insufficient_funds — Recurring billing failed; radar was deactivated. No refund (the radar ran; it just couldn’t renew).
Failure reference — identified by code and message:

Step 8: Receive Webhook Findings

When a radar detects something, it POSTs to your webhook_url. Every payload shares the same base structure. Only content varies by radar type.

Company job opening at OpenAI

New hire at OpenAI

Key fields for your handler:
  • update_id — use for idempotency. If you receive the same update_id twice, skip it.
  • custom_fields — your metadata, echoed back exactly as set on the radar.
  • discovered_at — use for ordering and incremental polling (see Step 9).
  • Return any 2xx status within 10 seconds. TAMradar will retry on failure (up to 3 retries: 1m, 5m, 15m).

Handling webhooks in your server

Acknowledge first, process after. TAMradar waits up to 10 seconds for a 2xx. If you do slow work (database writes, third-party calls) synchronously before responding, you risk a timeout and a retry.
The pattern applies in any language. The key constraints are to respond 2xx before doing work and deduplicate on update_id.

Step 9: Poll for Updates (Alternative to Webhooks)

GET /v1/updates returns the same payloads that webhooks deliver. Use this to backfill missed events, audit history, or as your primary data retrieval method. Do not confuse GET /v1/updates?since= with radar updates_since. updates_since is the radar’s permanent source-event eligibility boundary; the polling since parameter only filters TAMradar updates already created. Fetch all updates for your OpenAI radars since yesterday:
Fetch a specific radar type, paginated:
Response:
Paginate:
Keep fetching with next_cursor until has_more: false. Incremental polling loop:
radar_failure events are excluded by default. To include them: ?update_type=radar_finding,radar_failure Data retention: 60 days. Poll at least that often if you don’t use webhooks.

Step 10: Monitor Your Radars

List all active radars:
Get a specific radar:
Key fields to watch: radar_status (active/inactive), updates_since (stored eligibility boundary or null), next_charge_at (next billing date), and deactivated_at.

Step 11: Deactivate a Radar

When you no longer need a radar, delete it to stop billing.
Deactivation is irreversible. Create a new radar to resume monitoring. On monthly billing, the radar continues running until the end of the current billing cycle. On update-based billing, deactivation is immediate. To deactivate 2–500 known radar IDs at once, use DELETE /v1/radars/bulk. It returns final, ordered per-item outcomes synchronously; its bulk_id is for correlation, not status polling.

Before You Ship

  • Deduplicate on update_id — webhooks are at-least-once. Store processed IDs and skip duplicates.
  • Respond 2xx within 10 seconds — acknowledge the request before doing any slow work.
  • Handle radar_failure webhooks — alert your team when a radar fails so it doesn’t silently stop.
  • Monitor balance_remaining_usd — set up an alert when it drops below your comfort threshold. A zero balance deactivates radars without warning.
  • Store radar_id per account — you’ll need it to list, inspect, or deactivate a radar later.
  • Test your endpoint with /v1/webhooks/test before creating your first paid radar.
  • Use since for incremental polling — if you use /v1/updates, store the last discovered_at and pass it on the next call. Don’t re-fetch everything on every poll.

Quick Reference

Rate limits: TAMradar uses separate write/read budgets plus a dedicated bulk budget. On 429, honor Retry-After before retrying. Error codes: Every error response includes error_id. Include it when contacting support.