---
title: "Signalbase API / Get Job Change Signals"
description: "Signalbase tool signalbase-signals-job-changes on looot: input fields, $0.108 per call, output shape, and code to run it with curl, JavaScript or Python."
sidebar:
  hidden: true
---

{/* Generated by scripts/generate-api-reference.mjs from data/api-reference.json. Do not edit. */}

Fetch job change signals with filtering, pagination, and search. Supports role-aware position filters, department and seniority filters, LinkedIn targeting, and field-specific search. Person names are GDPR-masked (first name + last initial only).

- **Tool id:** `signalbase-signals-job-changes`
- **Provider:** [Signalbase](/providers/signalbase)
- **Job:** [Find people who changed jobs](/reference/jobs/people-job-changes) (`people.job.changes`)
- **Price:** $0.108 per call. A call that fails at the provider costs $0.

## Inputs

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `city` | string | no | Free-text search on person city and person location |
| `company_domain` | string | no | **Recommended.** Company website domain, e.g. `novartis.com`. Strict match, if no company has this domain the result is empty; never falls back to fuzzy name matching. Variants are equivalent: `novartis.com`, `www.novartis.com` and `https://novartis.com/` all match the same company. Malformed values return 400. Takes priority over `company_name`; combined identifiers must agree or the result is empty. Example: "example.com" |
| `company_linkedin_url` | string | no | **Recommended.** LinkedIn company URL, e.g. `linkedin.com/company/novartis`. Strict match, if no company has this LinkedIn page the result is empty; never falls back to fuzzy name matching. `http`/`https`, optional `www.` and trailing slash are equivalent. Non-company LinkedIn URLs (e.g. personal `/in/` profiles) return 400. Takes priority over `company_name`; combined identifiers must agree or the result is empty. (Legacy alias: `companyLinkedinUrl`.) |
| `company_name` | string | no | Search by company name (partial match) |
| `count` | string | no | When set to "true", returns only pagination metadata with an empty data array. No credits are charged. |
| `countries` | string | no | Comma-separated list of country codes to filter by (matches person country or company HQ) |
| `date_preset` | string | no | Relative date shorthand. Takes precedence over dateFrom/dateTo. |
| `dateFrom` | string | no | Filter signals from this date (ISO 8601 format: YYYY-MM-DD) |
| `dateTo` | string | no | Filter signals up to this date (ISO 8601 format: YYYY-MM-DD) |
| `departments` | string | no | Comma-separated list of departments to filter by (e.g., marketing, sales, engineering, product, design, operations, finance, people, data, customer_success, growth, legal) |
| `exclude_countries` | string | no | Comma-separated list of country names or codes to EXCLUDE (denylist), e.g. `China`. A signal is excluded when EITHER the person country or the company HQ matches; rows with a NULL field on a side are kept. |
| `keyword` | string | no | Search by keyword tag (partial match) |
| `limit` | integer | no | Number of results per page (maximum 100) |
| `new_role` | string | no | Search by new role / job title (partial match) |
| `page` | integer | no | Page number for pagination |
| `personLinkedinUrl` | string | no | Exact LinkedIn profile URL of the person |
| `positions` | string | no | Comma-separated list of positions to filter by (e.g., ceo, cto, cfo, coo, vp of engineering, head of product, engineering manager, product manager, founder, co-founder) |
| `search` | string | no | Free-text search across company name, industry, person name, role, person location, and person country |
| `seniorities` | string | no | Comma-separated list of seniority levels to filter by (e.g., founder, c_level, vp, director, head, lead, manager) |
| `sort_by` | string | no | Field to sort by |
| `sort_order` | string | no | Sort direction |
| `source` | string | no | Exact match on signal source |

## Output

The run's `result` holds the provider's answer. Signed in, `looot inspect signalbase-signals-job-changes` prints its fields.

## Run it

Every call needs your API token in `LOOOT_TOKEN`; [Sign in](/get-started/sign-in#use-the-token-in-scripts-and-agents) shows how to get one. Each run also needs a new idempotency key, so a retry never pays twice. With `wait: 30` the answer comes back inline when the run ends within 30 seconds. Otherwise you get the running run back: poll `GET /v1/runs/<runId>`.

Example input with placeholder values:

<CodeGroup>

```bash curl
curl -X POST "https://api.looot.ai/v1/runs" \
  -H "Authorization: Bearer $LOOOT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"endpointId":"signalbase-signals-job-changes","input":{"company_domain":"example.com"},"wait":30}'
```

```js JavaScript
const response = await fetch("https://api.looot.ai/v1/runs", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.LOOOT_TOKEN}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: JSON.stringify({
    endpointId: "signalbase-signals-job-changes",
    input: {
      company_domain: "example.com",
    },
    wait: 30,
  }),
});
const run = await response.json();
console.log(run.status, run.result);
```

```python Python
import os
import uuid

import requests

response = requests.post(
    "https://api.looot.ai/v1/runs",
    headers={
        "Authorization": f"Bearer {os.environ['LOOOT_TOKEN']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "endpointId": "signalbase-signals-job-changes",
        "input": {
            "company_domain": "example.com",
        },
        "wait": 30,
    },
    timeout=90,
)
run = response.json()
print(run["status"], run.get("result"))
```

</CodeGroup>

To let looot pick among every provider of this job instead, send `job:people.job.changes` as `endpointId`; see [the job page](/reference/jobs/people-job-changes).
