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

# Create Watch

> Create a watch that fires alerts when matching trademarks change

## Overview

Creates a saved monitor that runs on every data sync. Five watch types (`mark`, `portfolio`,
`owner`, `class`, `similarity`) share a single `query` shape; `watch_type` selects which scoping
field is required. Your plan's watch limit is enforced before insert. To see what a watch would
catch before you create it, use [Preview Watch](/api-reference/monitoring/watches/preview),
which returns the actual matching marks by default.

Requires the `portfolios:manage` scope.

## Body Parameters

<ParamField body="name" type="string" required>
  Display name (1-255 chars).
</ParamField>

<ParamField body="watch_type" type="string" required>
  One of `mark`, `portfolio`, `owner`, `class`, `similarity`. Each type requires a specific field
  to be populated, see the [Watches guide](/guides/monitoring/watches) for the table.
</ParamField>

<ParamField body="query" type="object" required>
  Watch query DSL.

  <Expandable title="WatchQuery">
    <ParamField body="version" type="string" required>Non-empty string. Use `"v2"`.</ParamField>
    <ParamField body="q" type="string">Whitespace-separated keyword query (max 20 keywords, each 3+ chars, no stop words). Required for `watch_type: "similarity"`.</ParamField>
    <ParamField body="filters" type="object">Filter object. Keys are camelCase (`trademarkIds`, `ownerId`, `niceClasses`, `jurisdictions`, `offices`, `statusPrimary`, ...); unknown keys, including snake\_case typos like `nice_classes`, are rejected with `400`. See the [canonical filter-key list](/guides/monitoring/watches#the-query-dsl). Watches keep office-based scoping and do not apply the protection-scope jurisdiction expansion used by search and screening, so `filters.jurisdictions: ["DE"]` watches the German office only and does not surface EU trade marks.</ParamField>
    <ParamField body="trigger_events" type="string[]">Subset of `trademark.created`, `trademark.updated`, `trademark.status_changed`, `trademark.retracted`, `trademark.corrected`. Default: `trademark.created`, `trademark.updated`, `trademark.status_changed`.</ParamField>
    <ParamField body="strategies" type="string[]">Similarity watches only. Non-empty subset of `exact`, `phonetic`, `fuzzy`, `prefix`. Default: `exact` and `fuzzy`.</ParamField>
    <ParamField body="min_match_tier" type="string">Similarity watches only. One of `exact`, `normalized`, `fuzzy`, `phonetic`, gating which match attribution tiers can fire an alert (`exact` is narrowest, `phonetic` is broadest). Omit it and every tier can fire. See the [Watches guide](/guides/monitoring/watches#min_match_tier-similarity-only) for tier meanings.</ParamField>
    <ParamField body="score_threshold" type="number">Not currently supported — rejected on write with a `400`. Scores are informational (see `match_score` on alerts). Contact support for calibrated-band thresholds when available.</ParamField>
  </Expandable>
</ParamField>

<ParamField body="delivery_mode" type="string">
  Currently only `always_per_alert` is supported — one delivery per alert; any other value returns `400`. Digest modes are planned but not yet available. See [`delivery_mode`](/guides/monitoring/watches#delivery_mode--per-alert-delivery-today).
</ParamField>

<ParamField body="metadata" type="object">
  Free-form metadata (max 8KB).
</ParamField>

## Response

Returns the created `Watch` with status `201`.

<ResponseField name="id" type="string">Watch ID (`wat_*`).</ResponseField>
<ResponseField name="object" type="string">Always `"watch"`.</ResponseField>
<ResponseField name="name" type="string">Display name.</ResponseField>
<ResponseField name="watch_type" type="string">One of the five types.</ResponseField>
<ResponseField name="query" type="object">Saved query DSL.</ResponseField>
<ResponseField name="delivery_mode" type="string">Delivery cadence.</ResponseField>
<ResponseField name="status" type="string">Initial status: `active`.</ResponseField>
<ResponseField name="alert_count_24h" type="integer | null">Null on create.</ResponseField>
<ResponseField name="last_alerted_at" type="string | null">Null on create.</ResponseField>
<ResponseField name="metadata" type="object">Echoed back.</ResponseField>
<ResponseField name="created_at" type="string">ISO timestamp.</ResponseField>
<ResponseField name="updated_at" type="string">ISO timestamp.</ResponseField>
<ResponseField name="request_id" type="string">Request identifier.</ResponseField>

## Errors

| Status | `type`                    | When                                                                                                                                                                                                                                                 |
| ------ | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400    | `validation_error`        | Invalid `query` (forbidden DSL keys, unknown `filters` keys, `query.match` in any form, stop words, too many keywords), a `watch_type` constraint violation (e.g. `portfolio` without `filters.trademarkIds`), or a missing `Idempotency-Key` header |
| 409    | `resource_quota_exceeded` | Your plan's watch limit is exceeded                                                                                                                                                                                                                  |
| 413    | `payload_too_large`       | `query` payload exceeds 256 KB                                                                                                                                                                                                                       |

## Code Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.signa.so/v1/watches" \
    -H "Authorization: Bearer sig_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: create-class9-watch-2026-06-12" \
    -d '{
      "name": "Class 9 filings (US/EU)",
      "watch_type": "class",
      "query": {
        "version": "v2",
        "filters": {
          "niceClasses": [9],
          "jurisdictions": ["US", "EU"]
        },
        "trigger_events": ["trademark.created", "trademark.status_changed"]
      },
      "delivery_mode": "always_per_alert"
    }'
  ```

  ```typescript TypeScript theme={null}
  import { Signa } from "@signa-so/sdk";
  const signa = new Signa({ api_key: process.env.SIGNA_API_KEY });

  const watch = await signa.watches.create({
    name: "Class 9 filings (US/EU)",
    watch_type: "class",
    query: {
      version: "v2",
      filters: {
        niceClasses: [9],
        jurisdictions: ["US", "EU"],
      },
      trigger_events: ["trademark.created", "trademark.status_changed"],
    },
    delivery_mode: "always_per_alert",
  });
  ```
</CodeGroup>

<ResponseExample>
  ```json theme={null}
  {
    "id": "wat_8kLm2nPq",
    "object": "watch",
    "name": "Class 9 filings (US/EU)",
    "watch_type": "class",
    "query": {
      "version": "v2",
      "filters": {
        "niceClasses": [9],
        "jurisdictions": ["US", "EU"]
      },
      "trigger_events": ["trademark.created", "trademark.status_changed"]
    },
    "delivery_mode": "always_per_alert",
    "status": "active",
    "alert_count_24h": null,
    "last_alerted_at": null,
    "metadata": {},
    "created_at": "2026-05-11T10:00:00.000Z",
    "updated_at": "2026-05-11T10:00:00.000Z",
    "request_id": "req_5nRvXq2T"
  }
  ```
</ResponseExample>

## Related Endpoints

* [Preview Watch](/api-reference/monitoring/watches/preview) - see what a query would catch before creating it
* [Bulk Create Watches](/api-reference/monitoring/watches/bulk) - create up to 100 watches at once
* [Update Watch](/api-reference/monitoring/watches/update) - change a watch's query, name, or status
* [Watches guide](/guides/monitoring/watches) - watch types and the query DSL
