> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tamradar.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting Started with TAMradar

> Step-by-step guide to authenticate, create radars, and receive updates.

## What is TAMradar?

TAMradar monitors companies, contacts, and industries by tracking their online activity and sending real-time notifications when something changes.

## Core Concepts

* **Radars** — A monitor you configure. You define what to track (a company, a person, or an industry keyword) and what signal to look for (job openings, new hires, funding rounds, etc.).
* **Webhooks** — How you receive events. TAMradar sends a POST request to your URL when a radar fires.
* **Polling** — Alternative to webhooks. Use `GET /v1/updates` to pull events on your schedule.
* **Balance** — Radars cost balance to create and run. Check yours before creating radars.

***

## Radar Types

TAMradar has three categories of radars, each with its own creation endpoint:

| Category | Endpoint                    | Tracks             |
| -------- | --------------------------- | ------------------ |
| Company  | `POST /v1/radars/companies` | A specific company |
| Contact  | `POST /v1/radars/contacts`  | A specific person  |
| Industry | `POST /v1/radars/industry`  | A keyword or theme |

**Company radar types:** `company_job_openings`, `company_new_hires`, `company_promotions`, `company_reviews`, `company_mentions`, `company_social_posts`, `company_social_posts_cxo`, `company_social_engagements`

**Contact radar types:** `contact_job_changes`, `contact_social_posts`, `contact_social_engagements`

**Industry radar types:** `industry_mentions`, `industry_funding_rounds`, `industry_new_companies`, `industry_job_openings`

***

## Step 1: Authentication

Every request requires your API key in the `x-api-key` header:

```bash theme={null}
curl -H "x-api-key: YOUR_API_KEY" https://api.tamradar.com/v1/account
```

A `401` means your key is missing or invalid. A `200` means you're authenticated.

***

## Step 2: Check Your Balance

Before creating radars, confirm you have sufficient balance:

```bash theme={null}
curl https://api.tamradar.com/v1/account \
  -H "x-api-key: YOUR_API_KEY"
```

**Response:**

```json theme={null}
{
  "status": "success",
  "code": 200,
  "message": "Account summary retrieved",
  "timestamp": "2024-03-20T12:00:00Z",
  "data": {
    "usage": {
      "month": "2024-03",
      "radars_activated": 14,
      "radars_deactivated": 3,
      "radars_failed": 0,
      "updates_found": 42,
      "balance_used_usd": 28.50
    },
    "account": {
      "total_radars": 47,
      "active_radars": 12,
      "inactive_radars": 34,
      "failed_radars": 1,
      "total_updates_found": 312
    },
    "balance_remaining_usd": 971.50
  }
}
```

Add `?month=YYYY-MM` to get stats for a specific month (defaults to current UTC month).

***

## Step 3: Create a Radar

> **`webhook_url` is optional.** Omit it to create a poll-only radar. Updates are available via [`GET /v1/updates`](#step-5-poll-for-updates). Add it when you want TAMradar to push events to your server in real-time.

### Company Radar

Monitor a company for job openings, with optional department and seniority filters:

```bash theme={null}
curl -X POST https://api.tamradar.com/v1/radars/companies \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "stripe.com",
    "radar_type": "company_job_openings",
    "webhook_url": "https://your-domain.com/webhook",
    "departments": ["Engineering"],
    "seniorities": ["Senior", "Manager"],
    "custom_fields": {
      "crm_account_id": "0011U00000TFV7MQAX"
    }
  }'
```

**Filterable company types:** `company_job_openings`, `company_new_hires`, `company_promotions`, `company_social_posts_cxo`

**Valid departments:** `Engineering`, `Sales`, `Marketing`, `Finance`, `Human Resources`, `Product Management`, `Operations`, `Customer Success`, `Design`, `Legal`, `Information Technology`, `Research`, `Accounting`, `Administrative`, `Business Development`, `Consulting`, `Education`, `Manufacturing`, `Media and Communication`, `Project Management`, `Purchasing`, `Quality Assurance`, `Real Estate`, `Support`

**Valid seniorities:** `Owner`, `CXO`, `Vice President`, `Director`, `Manager`, `Senior`, `Entry`, `Training`, `Partner`

**Response (201):**

```json theme={null}
{
  "status": "success",
  "code": 201,
  "message": "Radar created successfully",
  "timestamp": "2024-03-20T12:05:00Z",
  "data": {
    "radar_id": "c70813b3-7e87-4ca7-90fd-8c64574d911b",
    "radar_type": "company_job_openings",
    "domain": "stripe.com",
    "webhook_url": "https://your-domain.com/webhook",
    "radar_status": "active",
    "departments": ["Engineering"],
    "seniorities": ["Senior", "Manager"],
    "custom_fields": {
      "crm_account_id": "0011U00000TFV7MQAX"
    },
    "created_at": "2024-03-20T12:05:00Z",
    "deactivated_at": null,
    "next_charge_at": "2024-04-20T12:05:00Z"
  }
}
```

Save the `radar_id`. You'll need it later.

***

### Contact Radar

Track a specific person's job changes or social activity:

```bash theme={null}
# Track job changes for a person
curl -X POST https://api.tamradar.com/v1/radars/contacts \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "radar_type": "contact_job_changes",
    "domain": "stripe.com",
    "profile_url": "https://www.linkedin.com/in/johndoe",
    "webhook_url": "https://your-domain.com/webhook",
    "custom_fields": {
      "contact_id": "con_abc123"
    }
  }'
```

```bash theme={null}
# Track social posts from a specific person
curl -X POST https://api.tamradar.com/v1/radars/contacts \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "radar_type": "contact_social_posts",
    "profile_url": "https://www.linkedin.com/in/johndoe",
    "webhook_url": "https://your-domain.com/webhook"
  }'
```

**Rules:**

* `contact_job_changes` — requires `domain` + at least one of: `profile_url`, `email`, `full_name`
* `contact_social_posts` / `contact_social_engagements` — requires `profile_url` (LinkedIn, X, or Twitter only)

***

### Industry Radar

Track a keyword or theme across companies and news:

```bash theme={null}
# Track all funding rounds (no keyword needed)
curl -X POST https://api.tamradar.com/v1/radars/industry \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "radar_type": "industry_funding_rounds",
    "webhook_url": "https://your-domain.com/webhook"
  }'
```

```bash theme={null}
# Track mentions of a topic
curl -X POST https://api.tamradar.com/v1/radars/industry \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "radar_type": "industry_mentions",
    "keyword": "zero trust security",
    "countries": ["US", "GB"],
    "webhook_url": "https://your-domain.com/webhook"
  }'
```

**Rules:**

* `industry_mentions` and `industry_job_openings` — `keyword` is required (min 3 chars)
* `industry_funding_rounds` and `industry_new_companies` — no `keyword` needed
* `countries` — optional, max 5 country codes

***

## Step 4: List and Inspect Radars

```bash theme={null}
# List all active radars
curl "https://api.tamradar.com/v1/radars?radar_status=active&limit=50" \
  -H "x-api-key: YOUR_API_KEY"

# Get a specific radar
curl "https://api.tamradar.com/v1/radars/c70813b3-7e87-4ca7-90fd-8c64574d911b" \
  -H "x-api-key: YOUR_API_KEY"

# Filter by type
curl "https://api.tamradar.com/v1/radars?radar_type=company_job_openings" \
  -H "x-api-key: YOUR_API_KEY"
```

**Query parameters:**

| Parameter      | Type                   | Default | Description                 |
| -------------- | ---------------------- | ------- | --------------------------- |
| `limit`        | number                 | 50      | Max 1000                    |
| `radar_status` | `active` \| `inactive` | —       | Filter by status            |
| `radar_type`   | string                 | —       | Single radar type value     |
| `radar_id`     | string                 | —       | Comma-separated IDs, max 50 |

**Response (200):**

```json theme={null}
{
  "status": "success",
  "code": 200,
  "message": "Radars retrieved successfully",
  "count": 2,
  "limit": 50,
  "timestamp": "2024-03-20T12:10:00Z",
  "data": [
    {
      "radar_id": "c70813b3-7e87-4ca7-90fd-8c64574d911b",
      "radar_type": "company_job_openings",
      "domain": "stripe.com",
      "webhook_url": "https://your-domain.com/webhook",
      "radar_status": "active",
      "departments": ["Engineering"],
      "seniorities": ["Senior", "Manager"],
      "custom_fields": { "crm_account_id": "0011U00000TFV7MQAX" },
      "created_at": "2024-03-20T12:05:00Z",
      "deactivated_at": null,
      "next_charge_at": "2024-04-20T12:05:00Z"
    }
  ]
}
```

Note: Filter fields (`departments`, `seniorities`, `job_titles`) and identifier fields (`profile_url`, `email`, `full_name`, `keyword`) are returned flat at the top level of each radar object. They are only present when set.

***

## Step 5: Receive Events

When a radar fires, TAMradar POSTs an event to your `webhook_url`.

### Webhook Payload Structure

All webhook events follow this envelope:

```json theme={null}
{
  "update_id": "41991828-ed31-4bd9-98d2-44b2763f9f35",
  "update_type": "radar_finding",
  "record_id": "b77af154-c369-4446-b70a-f328880c3a48",
  "discovered_at": "2024-03-20T14:30:00Z",
  "data": {
    "radar_id": "c70813b3-7e87-4ca7-90fd-8c64574d911b",
    "radar_type": "company_job_openings",
    "domain": "stripe.com",
    "next_charge_at": "2024-04-20T14:30:00Z",
    "custom_fields": {
      "crm_account_id": "0011U00000TFV7MQAX"
    }
  },
  "content": {
    "job_title": "Senior Software Engineer",
    "job_url": "https://www.linkedin.com/jobs/view/123456789",
    "job_posted_at": "2024-03-20",
    "job_description": "We are seeking...",
    "job_source": "LinkedIn",
    "country": "United States"
  }
}
```

* `data` — radar context (always present, same fields regardless of type)
* `content` — the actual finding (structure varies by `radar_type`)

### Your Webhook Must

1. Accept `POST` with a JSON body
2. Return any `2xx` status code within a reasonable timeout
3. Handle duplicates — use `update_id` as an idempotency key

### Polling Alternative

If you prefer pull over push, use `GET /v1/updates`:

```bash theme={null}
# Get the latest 25 updates (radar_finding only by default)
curl "https://api.tamradar.com/v1/updates" \
  -H "x-api-key: YOUR_API_KEY"

# Filter by radar and paginate with cursor
curl "https://api.tamradar.com/v1/updates?radar_id=c70813b3-7e87-4ca7-90fd-8c64574d911b&cursor=CURSOR_FROM_PREV_RESPONSE" \
  -H "x-api-key: YOUR_API_KEY"

# Include failures too
curl "https://api.tamradar.com/v1/updates?update_type=radar_finding,radar_failure" \
  -H "x-api-key: YOUR_API_KEY"
```

**Query parameters:** `radar_id` (comma-sep, max 10), `radar_type` (comma-sep), `domain` (comma-sep, max 10), `since` (ISO 8601), `cursor`, `limit` (1–100, default 25), `update_type` (`radar_finding` | `radar_failure`, default: `radar_finding`)

**Response shape:**

```json theme={null}
{
  "status": "success",
  "code": 200,
  "message": "Updates retrieved successfully",
  "timestamp": "2024-03-20T12:00:00Z",
  "updates": [ ],
  "has_more": true,
  "next_cursor": "eyJyIjoiMjAyNi0..."
}
```

Pass `next_cursor` as `cursor` in the next request to paginate. `has_more: false` means you've reached the end.

***

## Step 6: Bulk Create Radars

Submit a bulk request for asynchronous processing (up to 1000 items):

```bash theme={null}
curl -X POST https://api.tamradar.com/v1/radars/bulk \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook_url": "https://your-domain.com/webhook",
    "radars": [
      {
        "domain": "stripe.com",
        "radar_type": "company_job_openings",
        "departments": ["Engineering"],
        "custom_fields": { "crm_account_id": "acc_001" }
      },
      {
        "domain": "notion.so",
        "radar_type": "company_new_hires"
      },
      {
        "radar_type": "contact_social_posts",
        "profile_url": "https://www.linkedin.com/in/someone"
      }
    ]
  }'
```

* `webhook_url` is required at the envelope level for async bulk
* Items can mix company, contact, and industry types
* Max 1000 items, max 1MB request body
* Item-level validation and creation happen asynchronously after submission

**Submission response (`202 Accepted`):**

```json theme={null}
{
  "status": "success",
  "code": 202,
  "timestamp": "2024-03-20T12:05:00Z",
  "message": "Bulk submission accepted — radars are being created asynchronously",
  "bulk_id": "5f9da22e-4778-427c-b7e4-dab2a8d9d709",
  "summary": {
    "total": 3
  }
}
```

Save `bulk_id`, then poll for status:

```bash theme={null}
curl "https://api.tamradar.com/v1/radars/bulk/5f9da22e-4778-427c-b7e4-dab2a8d9d709" \
  -H "x-api-key: YOUR_API_KEY"
```

The status endpoint returns:

* `status: "processing"` while items are still running
* `status: "completed"` when all items are terminal
* Per-item outcomes in `radars[]` with `item_index` mapping back to the input order
* `radars[].update_id` as the per-item correlation key (`radar_created` / `radar_failure`)

For webhook idempotency/correlation in async bulk:

* Use top-level `update_id` on `bulk_completed` to deduplicate the batch event itself
* Use `radars[].update_id` inside `bulk_completed` to map each item back to its individual item event

***

## Step 7: Deactivate a Radar

```bash theme={null}
curl -X DELETE "https://api.tamradar.com/v1/radars/c70813b3-7e87-4ca7-90fd-8c64574d911b" \
  -H "x-api-key: YOUR_API_KEY"
```

**Response (200):**

```json theme={null}
{
  "status": "success",
  "code": 200,
  "message": "Radar deactivated successfully",
  "timestamp": "2024-03-22T14:30:00Z",
  "data": {
    "radar_id": "c70813b3-7e87-4ca7-90fd-8c64574d911b",
    "radar_type": "company_job_openings",
    "domain": "stripe.com",
    "webhook_url": "https://your-domain.com/webhook",
    "radar_status": "inactive",
    "departments": ["Engineering"],
    "seniorities": ["Senior", "Manager"],
    "custom_fields": { "crm_account_id": "0011U00000TFV7MQAX" },
    "created_at": "2024-03-20T12:05:00Z",
    "deactivated_at": "2024-03-22T14:30:00Z",
    "next_charge_at": null
  }
}
```

Deactivation is a soft delete. The radar record is retained for history.

***

## Error Responses

All errors follow the same structure:

```json theme={null}
{
  "status": "error",
  "code": 400,
  "message": "Invalid request body",
  "errors": [
    { "field": "domain", "reason": "Domain is required" },
    { "field": "radar_type", "reason": "Invalid radar type provided" }
  ],
  "error_id": "7f8d6e5c-4b3a-2a1b-0c9d-8e7f6d5c4b3a",
  "timestamp": "2024-03-20T10:15:30Z"
}
```

| Code | Meaning                    | Retryable          |
| ---- | -------------------------- | ------------------ |
| 400  | Validation error           | No                 |
| 401  | Missing or invalid API key | No                 |
| 402  | Insufficient balance       | Yes (top up first) |
| 404  | Radar not found            | No                 |
| 409  | Radar already exists       | No                 |
| 429  | Rate limited               | Yes (back off)     |
| 500  | Internal server error      | Yes                |
| 503  | Database unavailable       | Yes                |

Use `error_id` when contacting support. It traces the exact request in our logs.

***

## Key Constraints

| Rule                   | Limit                                                    |
| ---------------------- | -------------------------------------------------------- |
| Webhook URL            | Optional. Max 2048 chars, must be HTTP/HTTPS if provided |
| Domain                 | Standard format, max 253 chars                           |
| Custom fields          | Max 20 keys; key ≤ 50 chars; value ≤ 500 chars           |
| `countries` (industry) | Max 5                                                    |
| `keyword` (industry)   | Min 3 chars                                              |
| Bulk size              | Max 1000 items, 1MB body                                 |
| List `limit`           | Max 1000                                                 |
| List `radar_id` filter | Max 50 IDs                                               |
