- 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.)
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.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_urlis optional. Include it to receive real-time push notifications. Omit it to poll for updates viaGET /v1/updatesinstead.
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.
What can go wrong
| Code | Reason | Fix |
|---|---|---|
402 | Insufficient balance | Top up your account, then retry |
409 | Radar already exists for openai.com + company_job_openings | Use the radar_id in the error response to manage the existing radar |
400 | Invalid domain, bad department value, invalid webhook_url (if provided) | Check errors[].reason for the exact field and issue |
401 | Missing or invalid API key | Verify x-api-key header is present and correct |
Step 4: Create a Contact Radar (Track Sam Altman)
Monitor job changes for a specific person. Requiresdomain + at least one identifier (email, profile_url, or full_name).
radar_type | Required fields |
|---|---|
contact_job_changes | domain + one of (email, profile_url, full_name) |
contact_social_engagements | profile_url (must be linkedin.com/in/, x.com/, or twitter.com/) |
contact_social_posts | profile_url (same as above) |
Step 5: Create an Industry Radar (AI Funding Rounds)
Track funding events across the AI industry, with no specific company or keyword needed.domain is always null for industry radars.
Industry radar type requirements:
radar_type | Requires keyword? |
|---|---|
industry_funding_rounds | No |
industry_new_companies | No |
industry_mentions | Yes (min 3 chars) |
industry_job_openings | Yes (min 3 chars) + optional countries[] (max 5) |
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):
bulk_id:
status: "processing"while there are in-flight itemsstatus: "completed"when all items are terminalsummarycounts (processing,created,failed)radars[]withitem_indexso you can map outcomes back to input orderradars[].update_idso you can correlate each item with itsradar_created/radar_failureevent
- Use top-level
update_idonbulk_completedto deduplicate the whole batch event - Use
radars[].update_idinsidebulk_completedto correlate each item-level event
Step 7: Handle Failure Webhooks
When a radar fails during setup, TAMradar sends aradar_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).
code and message:
| Failure type | code | Refund? | What to do |
|---|---|---|---|
| Missing prerequisites | 400 | Yes | Verify the company has accessible public profiles |
| Setup failure | 400 | Yes | Contact support |
| Insufficient funds | 402 | No | Top up balance; create a new radar to resume |
| Source inaccessible | 400 | Yes | Target profile is private or has been removed |
Step 8: Receive Webhook Findings
When a radar detects something, it POSTs to yourwebhook_url. Every payload shares the same base structure. Only content varies by radar type.
Company job opening at OpenAI
New hire at OpenAI
update_id— use for idempotency. If you receive the sameupdate_idtwice, 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
2xxstatus 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.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.
Fetch all updates for your OpenAI radars since yesterday:
next_cursor until has_more: false.
Incremental polling loop:
radar_failureevents are excluded by default. To include them:?update_type=radar_finding,radar_failureData retention: 60 days. Poll at least that often if you don’t use webhooks.
Step 10: Monitor Your Radars
List all active radars:radar_status (active/inactive), next_charge_at (next billing date), deactivated_at.
Step 11: Deactivate a Radar
When you no longer need a radar, delete it to stop billing.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_failurewebhooks — 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_idper account — you’ll need it to list, inspect, or deactivate a radar later. - Test your endpoint with
/v1/webhooks/testbefore creating your first paid radar. - Use
sincefor incremental polling — if you use/v1/updates, store the lastdiscovered_atand pass it on the next call. Don’t re-fetch everything on every poll.
Quick Reference
| Method | Endpoint | What it does |
|---|---|---|
GET | /v1/account | Check balance and radar counts |
POST | /v1/webhooks/test | Send a test payload to a URL |
POST | /v1/radars/companies | Create a company radar |
POST | /v1/radars/contacts | Create a contact radar |
POST | /v1/radars/industry | Create an industry radar |
POST | /v1/radars/bulk | Queue up to 1000 radars asynchronously |
GET | /v1/radars/bulk/:bulk_id | Poll async bulk processing status |
GET | /v1/radars | List all radars |
GET | /v1/radars/:id | Get a single radar |
DELETE | /v1/radars/:id | Deactivate a radar |
GET | /v1/updates | Poll for radar findings |
| Header | Description |
|---|---|
X-RateLimit-Limit | Per-minute budget for the matched bucket |
X-RateLimit-Remaining | Remaining tokens in that bucket |
X-RateLimit-Reset | Seconds until bucket reset (when available) |
429, honor Retry-After before retrying.
Error codes:
| Code | Meaning |
|---|---|
400 | Validation error — check errors[].field and errors[].reason |
401 | Missing or invalid x-api-key |
402 | Insufficient balance — top up and retry |
409 | Radar already exists — use the radar_id in the error to manage it |
429 | Rate limit exceeded — back off and retry |
5xx | Server error — retry with exponential backoff |
error_id. Include it when contacting support.