# Search recent company hiring signals and their supporting jobs

`GET https://trawle.com/v1/signals/search`

Evidence-backed observations from available daily snapshots in the last seven UTC dates. Filter by company slug, kind, text or inclusive since date. Missing observation days are not zero activity. Counts describe recorded postings, not net headcount. Closed listings do not prove a hire; new job locations do not prove market entry. Product/project inference is not included. Data by Trawle: https://trawle.com/radar

## Authentication

- Header `x-api-key`: Read-only API key from https://trawle.com/account#api-keys. 1,000 requests per daily window. Anonymous requests are also supported with a per-IP limit.

## Query parameters

- `q` (string, optional): At most 120 characters.
- `kind` (string, optional, SignalKind): One of: `department_scaling`, `first_in_family`, `market_entry`, `leadership_opened`, `leadership_filled`, `hard_to_fill`, `hiring_slowdown`.
- `company` (string, optional): Pattern ^[a-z0-9][a-z0-9-]{0,79}$.
- `since` (string<date>, optional)
- `cursor` (string, optional): At most 1500 characters.
- `limit` (integer, optional): Default `25`. 1 to 50.

## Responses

### 200: Newest observations first, with coverage and pagination.

Schema: SignalSearchResult

- `status` (string, required): One of: `ready`, `collecting`, `not_configured`.
- `dataDate` (string<date> | null, required)
- `windowStart` (string<date>, required)
- `windowEnd` (string<date>, required)
- `observedDays` (array<string>, required)
- `legacyEventsSkipped` (integer, required): Pre-UUID events excluded because their historical ids cannot safely resolve to current postings. At least 0.
- `items` (array<object>, required, HiringSignal)
  - `key` (string, required): Stable event key, not a job or company id.
  - `day` (string<date>, required)
  - `kind` (string, required, SignalKind): One of: `department_scaling`, `first_in_family`, `market_entry`, `leadership_opened`, `leadership_filled`, `hard_to_fill`, `hiring_slowdown`.
  - `company` (object, required)
    - `slug` (string, required)
    - `name` (string, required)
    - `domain` (string | null, required)
  - `family` (object | null, required)
    - `slug` (string, required)
    - `name` (string, required)
  - `country` (object | null, required)
    - `code` (string, required)
    - `name` (string, required)
  - `title` (string, required)
  - `observation` (string, required)
  - `interpretation` (string, required)
  - `evidence` (array<object>, required)
    - `id` (string<uuid>, required)
    - `title` (string, required)
    - `url` (string<uri>, required)
    - `sourceUrl` (string<uri>, required)
    - `closedAt` (string<date-time> | null, required)
- `total` (integer, required): At least 0.
- `nextCursor` (string | null, required)

### 400: Invalid request: see `error.issues` and `error.hint`.

Schema: Error

- `error` (object, required)
  - `code` (string, required): Machine-readable: `invalid_request`, `not_found`, `forbidden`, `rate_limited`, `internal`. Example: `invalid_request`.
  - `message` (string, required): Example: `places: expected an array of GeoNames ids`.
  - `hint` (string, optional): What to do next, e.g. which lookup to call first. Example: `Resolve place names to ids with GET /v1/places?q=`.
  - `issues` (array<object>, optional): Validation problems, one per invalid field.
    - `path` (string, required)
    - `message` (string, required)

### 401: Invalid, expired or revoked API key.

Schema: Error

- `error` (object, required)
  - `code` (string, required): Machine-readable: `invalid_request`, `not_found`, `forbidden`, `rate_limited`, `internal`. Example: `invalid_request`.
  - `message` (string, required): Example: `places: expected an array of GeoNames ids`.
  - `hint` (string, optional): What to do next, e.g. which lookup to call first. Example: `Resolve place names to ids with GET /v1/places?q=`.
  - `issues` (array<object>, optional): Validation problems, one per invalid field.
    - `path` (string, required)
    - `message` (string, required)

### 429: Rate limit reached. Respect Retry-After and cache results.

Schema: Error

- `error` (object, required)
  - `code` (string, required): Machine-readable: `invalid_request`, `not_found`, `forbidden`, `rate_limited`, `internal`. Example: `invalid_request`.
  - `message` (string, required): Example: `places: expected an array of GeoNames ids`.
  - `hint` (string, optional): What to do next, e.g. which lookup to call first. Example: `Resolve place names to ids with GET /v1/places?q=`.
  - `issues` (array<object>, optional): Validation problems, one per invalid field.
    - `path` (string, required)
    - `message` (string, required)

### 503: Signal storage is temporarily unavailable or contains malformed current-format data.

Schema: Error

- `error` (object, required)
  - `code` (string, required): Machine-readable: `invalid_request`, `not_found`, `forbidden`, `rate_limited`, `internal`. Example: `invalid_request`.
  - `message` (string, required): Example: `places: expected an array of GeoNames ids`.
  - `hint` (string, optional): What to do next, e.g. which lookup to call first. Example: `Resolve place names to ids with GET /v1/places?q=`.
  - `issues` (array<object>, optional): Validation problems, one per invalid field.
    - `path` (string, required)
    - `message` (string, required)

## Examples

### cURL

```bash
curl "https://trawle.com/v1/signals/search" \
  -H "x-api-key: $TRAWLE_API_KEY"
```

### TypeScript

```ts
import createClient from "openapi-fetch";

// npx openapi-typescript https://developers.trawle.com/openapi.json -o trawle.d.ts
import type { paths } from "./trawle";

const trawle = createClient<paths>({
  baseUrl: "https://trawle.com",
  headers: { "x-api-key": process.env.TRAWLE_API_KEY },
});

const { data, error } = await trawle.GET("/v1/signals/search");
```

### Python

```python
import os
import requests

response = requests.get(
    "https://trawle.com/v1/signals/search",
    headers={"x-api-key": os.environ["TRAWLE_API_KEY"]},
)
response.raise_for_status()
data = response.json()
```

### Response 200

```json
{
  "status": "ready",
  "dataDate": "2026-10-31",
  "windowStart": "2026-10-31",
  "windowEnd": "2026-10-31",
  "observedDays": ["2026-10-31"],
  "legacyEventsSkipped": 0,
  "items": [
    {
      "key": "string",
      "day": "2026-10-31",
      "kind": "department_scaling",
      "company": {
        "slug": "string",
        "name": "string",
        "domain": "string"
      },
      "family": {
        "slug": "string",
        "name": "string"
      },
      "country": {
        "code": "string",
        "name": "string"
      },
      "title": "string",
      "observation": "string",
      "interpretation": "string",
      "evidence": [
        {
          "id": "string",
          "title": "string",
          "url": "https://example.com",
          "sourceUrl": "https://example.com",
          "closedAt": "2026-10-31T06:12:00.000Z"
        }
      ]
    }
  ],
  "total": 0,
  "nextCursor": "string"
}
```

### Response 400

```json
{
  "error": {
    "code": "invalid_request",
    "message": "query.places.0: Invalid input: expected number, received string",
    "hint": "Fix the fields in `issues`. Ids for `places`, `roles` and `companies` come from the lookup endpoints.",
    "issues": [
      {
        "path": "query.places.0",
        "message": "Invalid input: expected number, received string"
      }
    ]
  }
}
```

### Response 401

```json
{
  "error": {
    "code": "unauthorized",
    "message": "Sign in to use this",
    "hint": "Sign in at /sign-in; requests carry the session cookie."
  }
}
```

### Response 429

```json
{
  "error": {
    "code": "invalid_request",
    "message": "places: expected an array of GeoNames ids",
    "hint": "Resolve place names to ids with GET /v1/places?q=",
    "issues": [
      {
        "path": "string",
        "message": "string"
      }
    ]
  }
}
```

### Response 503

```json
{
  "error": {
    "code": "unavailable",
    "message": "Describing agents isn't available right now",
    "hint": "Build the agent with filters instead."
  }
}
```
