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

# Introduction

> Access real-time job change signals with role, department, and seniority filters

## Welcome to the Job Change Signals API

The Job Change Signals API provides timely insights on job changes across the web. Track role transitions and new hires with precise filters for positions, departments, and seniority levels, plus company and person-level LinkedIn targeting.

<Card title="Job Change Signals Endpoint" icon="briefcase" href="/api-reference/job-change-signals/endpoint/get">
  View the complete OpenAPI specification
</Card>

## Count Mode

You can get the total number of results matching any filter combination **without consuming credits** by adding `count=true` to your request. This returns an empty `data` array with full pagination metadata, including `totalCount`.

```bash theme={null}
curl -X GET "https://www.trysignalbase.com/api/v2/signals/job-changes?count=true&positions=CEO,CTO&date_preset=last_30d" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**

```json theme={null}
{
  "success": true,
  "data": [],
  "pagination": {
    "currentPage": 1,
    "totalPages": 5,
    "totalCount": 93,
    "hasNextPage": true,
    "hasPreviousPage": false
  },
  "meta": {
    "endpoint": "signals.job-changes",
    "creditsUsed": 0
  }
}
```

<Tip>Use count mode to preview how many results match your filters before fetching actual data. This is useful for building filter UIs, showing result counts, or validating queries — all at zero credit cost.</Tip>

## Key Features

* **Real-time Signals**: Job change signals aggregated continuously from web sources
* **Role-aware Filters**: Filter by positions, departments, and seniority levels
* **LinkedIn Targeting**: Exact-match filters on person and company LinkedIn URLs
* **Field-specific Search**: Search by person name, company name, new role, or keyword
* **Flexible Sorting**: Sort by date, person name, or company name
* **Pagination Support**: Efficiently retrieve large datasets with up to 100 results per page
* **Credit-based Usage**: Transparent credit consumption per API call

## Company vs. person location

Company headquarters use **`companyCountry`** and **`companySubcategory`** (when set). Person location uses **`personCountry`**, **`personCity`**, and related fields — see [Company fields in signal responses](/enums#company-fields-in-signal-responses).

## Service Level

* **Rate Limit**: Based on your subscription tier
* **Uptime**: 99% guaranteed uptime
* **Data Freshness**: Real-time aggregation ensures up-to-date signals
* **Maximum Results**: Up to 100 results per page

## Authentication

All API endpoints require a Bearer token in the `Authorization` header.

```bash theme={null}
curl -X GET "https://www.trysignalbase.com/api/v2/signals/job-changes?page=1&limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

## Matching by Company URL (Recommended)

If you know a company's website domain or LinkedIn page, query by URL instead of by name. Name search is fuzzy and can return lookalikes (`Novartis` also matches `Novartis UK`); URL identifiers match exactly one company.

```bash theme={null}
# By website domain
curl -X GET "https://www.trysignalbase.com/api/v2/signals/job-changes?company_domain=novartis.com" \
  -H "Authorization: Bearer YOUR_API_KEY"

# By LinkedIn company page
curl -X GET "https://www.trysignalbase.com/api/v2/signals/job-changes?company_linkedin_url=linkedin.com/company/novartis" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Accepted input formats.** URL identifiers are normalized before matching, so equivalent variants return the same results:

* `company_domain`: `novartis.com`, `www.novartis.com`, `https://www.novartis.com/`, `https://novartis.com/any/path` — scheme, `www.`, port, path and trailing slash are ignored. Values that can't be reduced to a domain return `400`.
* `company_linkedin_url`: `linkedin.com/company/novartis`, `https://www.linkedin.com/company/Novartis/` — `http`/`https`, `www.` and trailing slash are ignored, the slug is case-insensitive. URLs that aren't LinkedIn *company* pages (e.g. personal `/in/` profiles) return `400`.

**Strict matching.** When a URL identifier is provided, the API never falls back to fuzzy name matching: if no company matches, the result is empty. Identifiers combine with `AND` — `company_domain=novartis.com&company_name=Acme` returns empty because they disagree.

**Match confidence.** Every result row includes `match_confidence`:

| Value   | Meaning                                                |
| ------- | ------------------------------------------------------ |
| `exact` | Matched via `company_domain` or `company_linkedin_url` |
| `fuzzy` | Matched via `company_name` partial match only          |
| `none`  | No company identifier was part of the query            |

## Query Parameters

### Pagination

| Parameter | Type    | Default | Description                 |
| --------- | ------- | ------- | --------------------------- |
| `page`    | integer | 1       | Page number                 |
| `limit`   | integer | 20      | Results per page (max: 100) |

### Date Filters

| Parameter     | Type   | Description                                                                                                  |
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------ |
| `dateFrom`    | string | Filter by date from (ISO-8601 string)                                                                        |
| `dateTo`      | string | Filter by date to (ISO-8601 string)                                                                          |
| `date_preset` | string | Relative date shorthand — takes precedence over `dateFrom`/`dateTo`. See [Date Presets](/enums#date-presets) |

### Text Search

| Parameter | Type   | Description                                                           |
| --------- | ------ | --------------------------------------------------------------------- |
| `search`  | string | Free-text search across company name, industry, person name, and role |

### Exact Match Filters

| Parameter              | Type   | Description                                                                                                                                                                                          |
| ---------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `personLinkedinUrl`    | string | Exact LinkedIn URL for a person                                                                                                                                                                      |
| `company_linkedin_url` | string | **Recommended.** LinkedIn company URL (e.g. `linkedin.com/company/novartis`). Strict match — see [Matching by company URL](#matching-by-company-url-recommended). Legacy alias: `companyLinkedinUrl` |
| `company_domain`       | string | **Recommended.** Company website domain (e.g. `novartis.com`), matched via the linked company record. Strict match                                                                                   |
| `source`               | string | Exact match on source: `linkedin`, `press_release`, `other`                                                                                                                                          |

### Field-specific Search (partial match)

| Parameter      | Type   | Description                                                                                                          |
| -------------- | ------ | -------------------------------------------------------------------------------------------------------------------- |
| `company_name` | string | Search by company name (partial match, fuzzy). Prefer `company_domain` or `company_linkedin_url` for strict matching |
| `new_role`     | string | Search by new role / job title                                                                                       |
| `keyword`      | string | Search by keyword tag                                                                                                |

<Note>
  There is no `person_name` filter. For privacy (GDPR), people are queryable only by `personLinkedinUrl`, and `personName` is returned masked (first name + last initial). To locate a specific person, filter by their LinkedIn URL.
</Note>

### Role Category Filters

| Parameter     | Type   | Description                                                                                           |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------- |
| `positions`   | string | Comma-separated position IDs (e.g., `CEO,CTO,CFO`). See [Positions](/enums#positions)                 |
| `departments` | string | Comma-separated department IDs (e.g., `marketing,engineering`). See [Departments](/enums#departments) |
| `seniorities` | string | Comma-separated seniority IDs (e.g., `c_level,vp,director`). See [Seniorities](/enums#seniorities)    |

### Sorting

| Parameter    | Type   | Default       | Description                                                               |
| ------------ | ------ | ------------- | ------------------------------------------------------------------------- |
| `sort_by`    | string | `occurred_at` | Sort field: `occurred_at`, `discovered_at`, `person_name`, `company_name` |
| `sort_order` | string | `desc`        | Sort direction: `asc` or `desc`                                           |

## Enum Values

**Positions**

```
"ceo", "cto", "cfo", "coo", "vp of engineering", "vp of sales", "vp of marketing",
"head of product", "head of growth", "head of engineering", "engineering manager",
"product manager", "sales manager", "marketing manager", "founder", "co-founder"
```

**Departments**

```
"marketing", "sales", "engineering", "product", "design", "operations", "finance", "people",
"data", "customer_success", "growth", "legal"
```

**Seniorities**

```
"founder", "c_level", "vp", "director", "head", "lead", "manager"
```

## Response Structure

All successful responses follow this structure:

```json theme={null}
{
  "success": true,
  "data": [...],
  "pagination": {
    "currentPage": 1,
    "totalPages": 10,
    "totalCount": 200,
    "hasNextPage": true,
    "hasPreviousPage": false
  },
  "meta": {
    "endpoint": "signals.job-changes",
    "creditsUsed": 1
  }
}
```

## Error Handling

The API returns standard HTTP status codes:

* **200**: Success
* **401**: Unauthorized - Invalid or missing API key
* **429**: Rate limit exceeded
* **500**: Internal server error

Error responses include:

```json theme={null}
{
  "success": false,
  "error": "Error message description"
}
```

## Example Usage

### Filter by Position and Date Preset

```bash theme={null}
curl -X GET "https://www.trysignalbase.com/api/v2/signals/job-changes?date_preset=last_30d&positions=CEO,CTO" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Filter by Company and Seniority

```bash theme={null}
curl -X GET "https://www.trysignalbase.com/api/v2/signals/job-changes?company_name=Google&seniorities=c_level" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Search by New Role with Sorting

```bash theme={null}
curl -X GET "https://www.trysignalbase.com/api/v2/signals/job-changes?new_role=VP%20Engineering&sort_by=occurred_at&sort_order=desc" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Target by LinkedIn URLs

```bash theme={null}
curl -X GET "https://www.trysignalbase.com/api/v2/signals/job-changes?personLinkedinUrl=https://www.linkedin.com/in/example&company_linkedin_url=linkedin.com/company/example" \
  -H "Authorization: Bearer YOUR_API_KEY"
```
