Create Watch
curl --request POST \
--url https://api.signa.so/v1/watches \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"watch_type": "<string>",
"query": {
"version": "<string>",
"q": "<string>",
"filters": {},
"trigger_events": [
"<string>"
],
"strategies": [
"<string>"
],
"min_match_tier": "<string>",
"score_threshold": 123
},
"delivery_mode": "<string>",
"metadata": {}
}
'import requests
url = "https://api.signa.so/v1/watches"
payload = {
"name": "<string>",
"watch_type": "<string>",
"query": {
"version": "<string>",
"q": "<string>",
"filters": {},
"trigger_events": ["<string>"],
"strategies": ["<string>"],
"min_match_tier": "<string>",
"score_threshold": 123
},
"delivery_mode": "<string>",
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
watch_type: '<string>',
query: {
version: '<string>',
q: '<string>',
filters: {},
trigger_events: ['<string>'],
strategies: ['<string>'],
min_match_tier: '<string>',
score_threshold: 123
},
delivery_mode: '<string>',
metadata: {}
})
};
fetch('https://api.signa.so/v1/watches', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.signa.so/v1/watches",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'watch_type' => '<string>',
'query' => [
'version' => '<string>',
'q' => '<string>',
'filters' => [
],
'trigger_events' => [
'<string>'
],
'strategies' => [
'<string>'
],
'min_match_tier' => '<string>',
'score_threshold' => 123
],
'delivery_mode' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/watches"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"watch_type\": \"<string>\",\n \"query\": {\n \"version\": \"<string>\",\n \"q\": \"<string>\",\n \"filters\": {},\n \"trigger_events\": [\n \"<string>\"\n ],\n \"strategies\": [\n \"<string>\"\n ],\n \"min_match_tier\": \"<string>\",\n \"score_threshold\": 123\n },\n \"delivery_mode\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.signa.so/v1/watches")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"watch_type\": \"<string>\",\n \"query\": {\n \"version\": \"<string>\",\n \"q\": \"<string>\",\n \"filters\": {},\n \"trigger_events\": [\n \"<string>\"\n ],\n \"strategies\": [\n \"<string>\"\n ],\n \"min_match_tier\": \"<string>\",\n \"score_threshold\": 123\n },\n \"delivery_mode\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/watches")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"watch_type\": \"<string>\",\n \"query\": {\n \"version\": \"<string>\",\n \"q\": \"<string>\",\n \"filters\": {},\n \"trigger_events\": [\n \"<string>\"\n ],\n \"strategies\": [\n \"<string>\"\n ],\n \"min_match_tier\": \"<string>\",\n \"score_threshold\": 123\n },\n \"delivery_mode\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"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"
}
Watches
Create Watch
Create a watch that fires alerts when matching trademarks change
POST
/
v1
/
watches
Create Watch
curl --request POST \
--url https://api.signa.so/v1/watches \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"watch_type": "<string>",
"query": {
"version": "<string>",
"q": "<string>",
"filters": {},
"trigger_events": [
"<string>"
],
"strategies": [
"<string>"
],
"min_match_tier": "<string>",
"score_threshold": 123
},
"delivery_mode": "<string>",
"metadata": {}
}
'import requests
url = "https://api.signa.so/v1/watches"
payload = {
"name": "<string>",
"watch_type": "<string>",
"query": {
"version": "<string>",
"q": "<string>",
"filters": {},
"trigger_events": ["<string>"],
"strategies": ["<string>"],
"min_match_tier": "<string>",
"score_threshold": 123
},
"delivery_mode": "<string>",
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
watch_type: '<string>',
query: {
version: '<string>',
q: '<string>',
filters: {},
trigger_events: ['<string>'],
strategies: ['<string>'],
min_match_tier: '<string>',
score_threshold: 123
},
delivery_mode: '<string>',
metadata: {}
})
};
fetch('https://api.signa.so/v1/watches', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.signa.so/v1/watches",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'watch_type' => '<string>',
'query' => [
'version' => '<string>',
'q' => '<string>',
'filters' => [
],
'trigger_events' => [
'<string>'
],
'strategies' => [
'<string>'
],
'min_match_tier' => '<string>',
'score_threshold' => 123
],
'delivery_mode' => '<string>',
'metadata' => [
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/watches"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"watch_type\": \"<string>\",\n \"query\": {\n \"version\": \"<string>\",\n \"q\": \"<string>\",\n \"filters\": {},\n \"trigger_events\": [\n \"<string>\"\n ],\n \"strategies\": [\n \"<string>\"\n ],\n \"min_match_tier\": \"<string>\",\n \"score_threshold\": 123\n },\n \"delivery_mode\": \"<string>\",\n \"metadata\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.signa.so/v1/watches")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"watch_type\": \"<string>\",\n \"query\": {\n \"version\": \"<string>\",\n \"q\": \"<string>\",\n \"filters\": {},\n \"trigger_events\": [\n \"<string>\"\n ],\n \"strategies\": [\n \"<string>\"\n ],\n \"min_match_tier\": \"<string>\",\n \"score_threshold\": 123\n },\n \"delivery_mode\": \"<string>\",\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/watches")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"watch_type\": \"<string>\",\n \"query\": {\n \"version\": \"<string>\",\n \"q\": \"<string>\",\n \"filters\": {},\n \"trigger_events\": [\n \"<string>\"\n ],\n \"strategies\": [\n \"<string>\"\n ],\n \"min_match_tier\": \"<string>\",\n \"score_threshold\": 123\n },\n \"delivery_mode\": \"<string>\",\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"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"
}
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,
which returns the actual matching marks by default.
Requires the portfolios:manage scope.
Body Parameters
string
required
Display name (1-255 chars).
string
required
One of
mark, portfolio, owner, class, similarity. Each type requires a specific field
to be populated, see the Watches guide for the table.object
required
Watch query DSL.
Show WatchQuery
Show WatchQuery
string
required
Non-empty string. Use
"v2".string
Whitespace-separated keyword query (max 20 keywords, each 3+ chars, no stop words). Required for
watch_type: "similarity".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. 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.string[]
Subset of
trademark.created, trademark.updated, trademark.status_changed, trademark.retracted, trademark.corrected. Default: trademark.created, trademark.updated, trademark.status_changed.string[]
Similarity watches only. Non-empty subset of
exact, phonetic, fuzzy, prefix. Default: exact and fuzzy.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 for tier meanings.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.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.object
Free-form metadata (max 8KB).
Response
Returns the createdWatch with status 201.
string
Watch ID (
wat_*).string
Always
"watch".string
Display name.
string
One of the five types.
object
Saved query DSL.
string
Delivery cadence.
string
Initial status:
active.integer | null
Null on create.
string | null
Null on create.
object
Echoed back.
string
ISO timestamp.
string
ISO timestamp.
string
Request identifier.
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
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"
}'
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",
});
{
"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"
}
Related Endpoints
- Preview Watch - see what a query would catch before creating it
- Bulk Create Watches - create up to 100 watches at once
- Update Watch - change a watch’s query, name, or status
- Watches guide - watch types and the query DSL
⌘I