Search Trademarks
curl --request GET \
--url https://api.signa.so/v1/trademarks \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.signa.so/v1/trademarks"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.signa.so/v1/trademarks', 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/trademarks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/trademarks"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.signa.so/v1/trademarks")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/trademarks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "list",
"data": [
{
"id": "tm_8kLm2nPq",
"object": "trademark",
"mark_text": "NIKE",
"relevance_score": 95,
"match_explanation": {
"strategies_matched": ["exact"],
"boost_factors": [
{ "factor": "status_active", "weight": 1.2 }
]
},
"primary_image_url": null,
"status": { "primary": "active", "stage": "registered" },
"office_code": "US",
"jurisdiction_code": "US",
"filing_date": "1971-02-04",
"registration_date": "1974-04-16",
"classifications": [
{ "nice_class": 25, "goods_services_text": "Clothing, footwear, headgear", "goods_services_text_truncated": false }
],
"nice_classes": [25],
"owners": [
{
"id": "own_R3jK9mN2",
"name": "Nike, Inc.",
"country_code": "US",
"entity_id": "ent_Wp8qLd4Z",
"entity_id_type": "resolved",
"companies": [
{
"source": "sec",
"ticker": "NKE",
"exchange": "NYSE",
"lei": null,
"entity_status": "active"
},
{
"source": "gleif",
"ticker": null,
"exchange": null,
"lei": "787RXPR0UX0O0XUXPZ81",
"entity_status": "active"
}
]
}
],
"coverage": null,
"source_records": null,
"owners_mixed": null
}
],
"has_more": true,
"pagination": {
"cursor": "eyJpZCI6ImFiYyJ9",
"total_count": 142,
"total_count_approximate": false
},
"search_meta": {
"search_id": "srch_abc123",
"query": "nike",
"strategies_used": ["exact", "fuzzy"],
"international_registrations": "grouped",
"execution_time_ms": 15
},
"request_id": "req_xyz789"
}
Search
Search Trademarks
Search, filter, and browse trademarks across all supported offices
GET
/
v1
/
trademarks
Search Trademarks
curl --request GET \
--url https://api.signa.so/v1/trademarks \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.signa.so/v1/trademarks"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.signa.so/v1/trademarks', 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/trademarks",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/trademarks"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.signa.so/v1/trademarks")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/trademarks")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "list",
"data": [
{
"id": "tm_8kLm2nPq",
"object": "trademark",
"mark_text": "NIKE",
"relevance_score": 95,
"match_explanation": {
"strategies_matched": ["exact"],
"boost_factors": [
{ "factor": "status_active", "weight": 1.2 }
]
},
"primary_image_url": null,
"status": { "primary": "active", "stage": "registered" },
"office_code": "US",
"jurisdiction_code": "US",
"filing_date": "1971-02-04",
"registration_date": "1974-04-16",
"classifications": [
{ "nice_class": 25, "goods_services_text": "Clothing, footwear, headgear", "goods_services_text_truncated": false }
],
"nice_classes": [25],
"owners": [
{
"id": "own_R3jK9mN2",
"name": "Nike, Inc.",
"country_code": "US",
"entity_id": "ent_Wp8qLd4Z",
"entity_id_type": "resolved",
"companies": [
{
"source": "sec",
"ticker": "NKE",
"exchange": "NYSE",
"lei": null,
"entity_status": "active"
},
{
"source": "gleif",
"ticker": null,
"exchange": null,
"lei": "787RXPR0UX0O0XUXPZ81",
"entity_status": "active"
}
]
}
],
"coverage": null,
"source_records": null,
"owners_mixed": null
}
],
"has_more": true,
"pagination": {
"cursor": "eyJpZCI6ImFiYyJ9",
"total_count": 142,
"total_count_approximate": false
},
"search_meta": {
"search_id": "srch_abc123",
"query": "nike",
"strategies_used": ["exact", "fuzzy"],
"international_registrations": "grouped",
"execution_time_ms": 15
},
"request_id": "req_xyz789"
}
Overview
The canonical endpoint for discovering trademarks. Pass a text query to search by brand name with relevance ranking, or use filters to browse by office, status, class, date, and more. Every request must include at least one filter or a text query (q).
Query Parameters
string
Search query text (1-500 characters). When provided, results are ranked by relevance using multi-strategy matching (exact + fuzzy by default). Optional: omit for filter-only browsing.
string
default:"exact,fuzzy"
Search strategies to apply when
q is provided, comma-separated. Any combination of exact, fuzzy, phonetic, prefix. Defaults to exact,fuzzy for fast results. Use exact,phonetic,fuzzy,prefix for comprehensive trademark clearance searches. Only applies to the default similar match mode.string
default:"similar"
How
q is matched against the mark text. similar (default) runs the ranked relevance ladder. The deterministic modes — exact, starts_with, ends_with, contains — match the folded (case- and accent-insensitive) mark text literally and return results sorted by date, with relevance_score: null. See Match modes.string
Exclude marks whose folded text contains this substring (case- and accent-insensitive). Composable with any
match mode.integer
default:"20"
Results per page (1-100).
string
Opaque pagination cursor from a previous response.
boolean
default:"false"
When
true, includes pagination.total_count in the response. Exact up to 10,000 matches; beyond that the count is capped and pagination.total_count_approximate is true. See Pagination.boolean
default:"false"
When
true, includes highlight snippets for mark_text and owner_names fields under the default similar match mode. In deterministic match modes (exact, starts_with, ends_with, contains), highlights is inert.string
default:"grouped"
How Madrid International Registrations are presented.
grouped (default) returns one row per mark/IR, with per-territory coverage folded into that row. expanded returns one row per Madrid designation instead. A request that combines expanded with something the grouped index can’t honor falls back to grouped automatically; when that happens, search_meta.fallback_reason explains why.string
Comma-separated optional row projections.
full_goods_services returns full classifications[].goods_services_text instead of the truncated (about 280 character) summary text.string
Sparse top-level field projection, comma-separated (e.g.
?fields=mark_text,status,owners). id and object are always retained. Unknown field names, or nested paths like status.primary, return 400.Filters
All filter parameters are accepted at the top level of the query string. Arrays use comma-separated values. Date ranges support_gte, _gt, _lte, and _lt suffixes.
string
Uppercase ST.3 office codes, comma-separated (e.g.
?offices=US,EM). Legacy lowercase codes (e.g. uspto, and eu for EUIPO) are accepted as permanent aliases.string
Jurisdiction codes, comma-separated (e.g.
?jurisdictions=US,EU), selecting rights that protect, or seek protection, in these territories. By default this is protection-scope: a request for a country also matches regional rights whose membership covers it, so jurisdictions=FR returns French national marks, Madrid designations of France, and EU trade marks (a EUTM protects France). Requesting a regional code (EU) matches the regional rights themselves (EUTMs and IRs designating the EUIPO), not member-state national marks. Use territory_match=direct to restore literal territory-leg matching. This is distinct from offices, which filters on the register a mark was filed with.string
default:"protection"
How
jurisdictions matches. protection (default) applies protection-scope: a country request also matches regional rights whose membership covers it (a EUTM for jurisdictions=FR). direct matches only literal territory legs (national filings and Madrid designations of the exact territory), reproducing the pre-July-2026 behavior. Inert when no jurisdictions filter is present. Also accepted by internal Suggest and Image search.string
Nice classification numbers 1-45, comma-separated (e.g.
?nice_classes=9,42). Not sure which classes to filter on? Suggest Classifications turns a plain-English description into ranked classes.string
USPTO design search codes, comma-separated.
string
Namespaced filing basis codes, comma-separated (e.g.
US:1A,US:44E).string
USPTO register type:
principal or supplemental.string
Primary status:
active, pending, inactive, unknown. Comma-separated for multiple.string
Status stage, comma-separated (e.g.
registered, published, examining).string
Derived opposition window state:
open, not_started, closed, or unknown. Rows whose indexed close date was never checked against an office holiday calendar (opposition_window.close_adjustment = not_checked) are indeterminate for the 20 days after that date, because a rollover can only push a close later: they are counted as open and excluded from closed, so a live deadline is never hidden. not_started and unknown are unaffected, because the opening date is never rolled.string
Opposition window close-date lower bound (YYYY-MM-DD).
string
Opposition window close-date upper bound (YYYY-MM-DD).
string
Seniority claim state:
claimed, none, or unknown.string
Mark type:
word, figurative, combined, three_dimensional.string
Filing route:
direct_national, madrid_designation, direct_regional.string
Owner ID (
own_...). Marks for that single per-office owner record.string
Owner name substring match.
string
Resolved entity ID (
ent_...). Returns marks across all member owners of the entity (every office): the global-portfolio filter. Accepts an entity id derived for an owner that hasn’t been linked to a cross-office entity yet. An entity resolving to more than 10,000 member owners returns 422 entity_too_large. See Entities.string
Entity GROUP ID (
ent_...). Returns marks across the whole GLEIF corporate family (root + all descendants): “all Pfizer-group marks”. Group-level, never identity. Also bounded by 422 entity_too_large (see Errors).boolean
true to return marks whose owner has an active listing association: a confirmed active SEC ticker match, OR an owner whose resolved entity is itself listed or a subsidiary of a listed company. false means no confirmed listing, not confirmed private.boolean
true to return marks whose owner has a confirmed GLEIF LEI match. false means no confirmed LEI match.string
Exact owner ticker match, uppercased server-side (e.g.
AAPL). Ticker matching is subsidiary-inclusive: owner_ticker=NKE returns Nike’s own marks and those of its subsidiaries (for example Converse marks under Nike), because each owner’s entity listing ticker, whether direct or inherited from a listed ancestor, folds into this field. Direct-vs-inherited provenance is not exposed in search; it lives on the entity listing block (see Retrieve Entity).string
Exact owner LEI match, uppercased server-side.
string
Attorney ID (
att_...).string
Firm ID (
firm_...).string
Filing date lower bound (YYYY-MM-DD).
string
Filing date upper bound (exclusive).
string
Registration date lower bound.
string
Registration date upper bound.
string
Expiry date lower bound.
string
Expiry date upper bound.
boolean
true to require at least one image.boolean
true to restrict to Madrid Protocol filings.Per-filter office support
Filter completeness varies by trademark office because each source publishes different fields. Use List Offices as the source of truth: each office returns a livecoverage block with percentages for fields that drive filters and projections, including media, goods/services text, design codes, publication dates, registration data, priority and seniority claims, filing basis, first-use dates, owner links, attorney links, and status effective dates.
opposition_status and opposition_closes_* derive from indexed opposition-window dates. opposition_status uses a UTC calendar day for the open/closed boundary, so within about one day of a window edge it can differ slightly from the office-timezone-precise dates in the opposition_window response field. Use those dates for exact timing. WIPO Madrid IR publication dates are not yet covered, so IR opposition windows are treated as unknown and the response includes search_meta.warnings[] with code partial_opposition_coverage. A record with an open-ended opposition window (window_opens set but window_closes absent) is not currently assigned to the open, not_started, or closed buckets. The close_adjustment marker that drives the indeterminate band is populated at index time, so records indexed before it shipped carry no value and are bucketed by their dates alone, exactly as before; a reindex is what applies the band to them.
seniority_claims is currently EUIPO-only with low coverage and always emits partial_seniority_coverage when used. claimed matches records with known seniority claims, none matches EUIPO records that authoritatively report no seniority claims, and unknown matches records with no seniority signal.
Grouped-grain rows currently surface design_codes for vienna and us_design_search systems only. Design codes with system='other' are omitted at mark grain until a reindex follow-up promotes them.
DB-backed embedded trademark rows, such as portfolio fallback rows that have not been hydrated from search, emit priority_date: null and design_codes: []. These are search-hydrated projections.
Show More filters
Show More filters
| Parameter | Type | Description |
|---|---|---|
office | string | Single office code shortcut |
vienna_codes | string | Vienna figurative codes, comma-separated |
status_reason | string | Status reason codes, comma-separated |
challenge_states | string | Active challenge states, comma-separated |
mark_legal_category | string | standard, certification, collective |
right_kind | string | Right kind (e.g. trademark) |
scope_kind | string | Territorial scope kind, comma-separated |
owner_country | string | Two-letter owner country code |
goods_services_text | string | Free-text search in G&S descriptions |
application_number | string | Exact application number (requires office) |
registration_number | string | Exact registration number (requires office) |
ir_number | string | Madrid International Registration number |
origin_office_code | string | Origin office code for Madrid filings |
renewal_due_date_gte | string | Renewal due date lower bound |
renewal_due_date_lt | string | Renewal due date upper bound |
publication_date_gte | string | Publication date lower bound |
publication_date_lt | string | Publication date upper bound |
status_effective_date_gte | string | Status effective date lower bound |
status_effective_date_lt | string | Status effective date upper bound |
priority_date_gte | string | Priority date lower bound |
priority_date_lt | string | Priority date upper bound |
first_use_anywhere_date_gte | string | First use anywhere date lower bound |
first_use_anywhere_date_lt | string | First use anywhere date upper bound |
first_use_in_commerce_date_gte | string | First use in commerce date lower bound |
first_use_in_commerce_date_lt | string | First use in commerce date upper bound |
termination_date_gte | string | Termination date lower bound |
termination_date_lt | string | Termination date upper bound |
updated_at_gte | string | Record updated-at lower bound. Accepts YYYY-MM-DD (coerced to start of day UTC) or full ISO 8601 datetime (e.g. 2024-01-15T00:00:00Z). |
updated_at_lt | string | Record updated-at upper bound. Accepts YYYY-MM-DD or full ISO 8601 datetime. |
has_proceedings | boolean | true to require at least one proceeding |
is_retracted | boolean | true to restrict to retracted marks |
is_series_mark | boolean | true to restrict to series marks |
renewal_due_before | string | Alias for renewal_due_date_lt |
Match modes
Thematch parameter controls how q is matched against the mark text.
similar(default) — ranked, fuzzy matching. Runs the relevance ladder (tune it withstrategies/ranking_profile) and orders results byrelevance_score. Use this for brand searches and clearance.exact,starts_with,ends_with,contains— deterministic. Each matches the folded mark text (case- and accent-insensitive) literally:exactrequires the whole mark to equalq, the others anchor to the start, end, or anywhere in the mark. Results are ordered by date (not relevance), every row hasrelevance_score: null,highlightsis inert, andsearch_meta.strategies_usedis[]. Use these when you need predictable, reproducible matching rather than ranking.
q (one non-empty folded char), whereas similar requires at least 2 folded chars and contains requires at least 3. They also treat the metacharacters ( ) [ ] { } | \ as literal text to match, so a query like mercedes (benz) searches for that exact string; the ranked similar path rejects those same characters with a 400 validation_error (use a deterministic mode to search for them literally).
search_meta.match echoes the mode that was applied on every response (including similar).
mark_text_not_contains excludes any mark whose folded text contains the given substring. It composes with every match mode (including similar), so you can, for example, search for sun while excluding sunset.
Worked examples
cURL — contains
# Every mark whose folded text contains "cola"
curl -G "https://api.signa.so/v1/trademarks" \
-H "Authorization: Bearer $SIGNA_API_KEY" \
--data-urlencode "q=cola" \
--data-urlencode "match=contains"
cURL — exclude a substring
# Ranked "sun" search, minus anything containing "sunset"
curl -G "https://api.signa.so/v1/trademarks" \
-H "Authorization: Bearer $SIGNA_API_KEY" \
--data-urlencode "q=sun" \
--data-urlencode "mark_text_not_contains=sunset"
Validation rules
| Rule | Result if violated |
|---|---|
Deterministic modes (exact/starts_with/ends_with/contains) require a q | 400 validation_error |
Deterministic q must be non-empty after folding (so combining-marks-only input is rejected), but a single folded character is accepted | 400 validation_error |
similar (default) requires a folded q of at least 2 characters | 400 validation_error |
contains requires a folded q of at least 3 characters | 400 validation_error |
strategies and ranking_profile are only valid with match=similar | 400 validation_error |
mark_text_not_contains requires at least 3 folded characters (same floor as contains, since it builds the same substring wildcard) | 400 validation_error |
match must be one of the five allowed values; mark_text_not_contains must be a string | 400 validation_error |
Response
object[]
Trademark summary records: the slimmer list shape with the fields most useful for result cards. See Retrieve Trademark for the full record shape returned by single-record lookups.
boolean
Whether more results are available.
string
Pass this as
?cursor= to get the next page.integer
Total matches. Only present when
include_total=true. Canonical location: read this field across every list endpoint.boolean
Emitted alongside
total_count. false when the count is exact (up to 10,000 matches); true when the search index capped the count at 10,000 for a deep search.object
Query metadata.
Show search_meta fields
Show search_meta fields
string
Unique search identifier.
string | null
The query text used.
string[]
Search strategies that were applied. Empty
[] for deterministic match modes.string
The match mode that was applied:
similar, exact, starts_with, ends_with, or contains. Echoed on every response.string
The Madrid presentation mode actually served:
grouped or expanded. See the international_registrations query parameter above.string
The
territory_match mode actually applied: protection (default) or direct. Echoed on every response so you can confirm which matching semantics ran.string | undefined
Present only when the requested
international_registrations mode couldn’t be honored and the response fell back to grouped.object[] | undefined
Non-fatal warnings about the search. Two families share this array: strategy-skip warnings (a requested
strategies value produced no clauses for the query shape, e.g. strategies=[phonetic] on a query too short or high-collision — carries strategy) and filter-coverage warnings (an applied filter has partial index coverage — carries severity, affected_filter, affected_offices, behavior). Filter-coverage warnings are currently emitted for opposition_status / opposition_closes_* (partial_opposition_coverage) and seniority_claims (partial_seniority_coverage).string
Stable warning code for client handling.
string
Human-readable warning message.
string | undefined
Present on strategy-skip warnings: the requested strategy that produced no clauses.
string | undefined
info or warning. Present on filter-coverage warnings.string | undefined
Filter whose behavior is qualified by the warning. Present on filter-coverage warnings.
string[] | undefined
Office codes affected by the caveat.
string | undefined
Human-readable behavior explanation. Present on filter-coverage warnings.
integer
Query execution time in milliseconds.
object
Faceted bucket counts. Present on
GET when aggregations= is provided and on POST when options.aggregations is provided.object
Human-readable labels keyed by the public ids in
owner_id, attorney_id, firm_id, and entity_id aggregation buckets. Omitted when no labels resolve.number | null
Normalized relevance score for the ranked
similar mode. Present when q is provided; null for filter-only queries, when sort is specified, and for every row under a deterministic match mode (exact/starts_with/ends_with/contains).object | undefined
string | null
URL to the primary trademark image. Format:
https://api.signa.so/v1/trademarks/{id}/media/{media_id}. Only present when has_media is true, null otherwise.string | null
Office-reported date when the current status took effect, when available.
string | null
First publication date for the mark, used as the opposition-window trigger when the office and filing route are modeled.
string | null
Date the right terminated or ceased, when the office reports it.
string | null
Earliest priority date projected from priority claims, when available. On DB-backed embedded rows such as portfolio marks not yet in the search index, this search-hydrated-only child-table projection may be
null.string | null
The source office’s own record timestamp. This is distinct from
updated_at, which is Signa’s sync/index timestamp.object[]
Design or figurative classification codes. Empty
[] when none are present. On DB-backed embedded rows such as portfolio marks not yet in the search index, this search-hydrated-only child-table projection may be [].object | null
Computed opposition window for modeled office/route rows.
null means the office/route is not modeled, the window could not be computed safely, or the grouped row spans multiple territories. Dates only, so a cached row stays a faithful function of the record. Compare them against your own “today”, or use the opposition_status filter to have the server do it.Show Opposition window fields
Show Opposition window fields
string | null
Office-local opening date, or
null when the office/route is modeled but no publication date is available.string | null
Office-local closing date, or
null when the office/route is modeled but no publication date is available. Read it with close_adjustment.string | null
Whether
window_closes was checked against the office’s holiday calendar, and whether that check moved it: moved, unchanged, or not_checked. not_checked means no calendar stands behind the date: it falls outside the calendar’s pinned coverage years, the rule carries no calendar, or there is no publication date. A rollover only ever moves a close later, so a not_checked date is correct-or-early; treat it as indeterminate for the 20 days after it rather than as a decided open/closed answer.object[]
Nice classifications on the row.
Show Classification summary fields
Show Classification summary fields
integer
Nice class number (1-45).
string | null
Goods/services description, truncated to about 280 characters unless
include=full_goods_services is requested.boolean
true when goods_services_text was shortened for this row. Request include=full_goods_services or fetch the detail record for the untruncated text.string | undefined
as_filed on grouped IR rows, where classifications reflect the filed goods and services rather than a territory-effective scope. Absent on non-IR and leg rows.integer[]
Compact Nice class numbers derived from
classifications[].nice_class.object[]
Summary-tier owner projections. Always present as an array (empty
[] when the record has no owners on file).Show Owner summary fields
Show Owner summary fields
string
Owner ID (
own_*).string
Owner display name.
string | null
Owner country code when available.
string | undefined
Resolved cross-office entity ID (
ent_*) when available, so you can group owners by entity. Filter with ?entity_id= to retrieve the entity’s whole global portfolio.string | undefined
resolved when the owner has been linked to a cross-office entity; derived when it has not been linked yet (a stable placeholder ID scoped to this owner).object[]
Public company records linked to this owner. Omitted when there are no matched companies.
string
sec or gleif.string | null
Ticker symbol for SEC matches.
string | null
Exchange for SEC matches.
string | null
Legal Entity Identifier for GLEIF matches.
string
active, inactive, or delisted.object | null
Per-territory coverage rollup (
territory_count, by_primary, by_stage, matched_territories, territories[]). Present only on grouped Madrid IR-family rows (international_registrations=grouped, the default); null on record-grain and direct/regional mark-of-one rows. Retrieve Trademark returns the same rollup with the per-designation detail the search row omits.object[] | null
WIPO/national reconciliation alternates on grouped IR-family rows;
null on record-grain and direct/regional mark-of-one rows.boolean | null
true when a grouped IR family’s territorial owners resolve to more than one distinct holder; null on record-grain and direct/regional mark-of-one rows.object[]
Present only when a
jurisdictions filter is active under the default territory_match=protection. Explains why the hit satisfied that filter: each entry maps a requested code to the stored territory it matched on and the basis of the match. Absent under territory_match=direct and when no jurisdictions filter is applied.Show territory_matches fields
Show territory_matches fields
string
The
jurisdictions code the caller requested (e.g. FR).string
The stored territory the hit actually matched on (WIPO’s
EM designation code is rendered EU). For a EUTM returned against a FR request this is EU.string
direct when the hit carries the requested territory as a literal leg; regional_membership when it matched through a regional right whose membership includes the request.Worked example: a EUTM returned for a French request
GET /v1/trademarks?q=apple&jurisdictions=FR runs under the default territory_match=protection. A EU trade mark (filed at the EUIPO, jurisdiction_code: "EU") is now returned, because a EUTM protects France, and it carries:
{
"id": "tm_…",
"mark_text": "APPLE",
"office_code": "EM",
"jurisdiction_code": "EU",
"territory_matches": [
{ "requested": "FR", "matched_via": "EU", "basis": "regional_membership" }
]
}
{ "requested": "FR", "matched_via": "FR", "basis": "direct" }. Re-run with &territory_match=direct and the EUTM drops out, leaving only literal FR legs (French national filings and Madrid designations of France).
{
"object": "list",
"data": [
{
"id": "tm_8kLm2nPq",
"object": "trademark",
"mark_text": "NIKE",
"relevance_score": 95,
"match_explanation": {
"strategies_matched": ["exact"],
"boost_factors": [
{ "factor": "status_active", "weight": 1.2 }
]
},
"primary_image_url": null,
"status": { "primary": "active", "stage": "registered" },
"office_code": "US",
"jurisdiction_code": "US",
"filing_date": "1971-02-04",
"registration_date": "1974-04-16",
"classifications": [
{ "nice_class": 25, "goods_services_text": "Clothing, footwear, headgear", "goods_services_text_truncated": false }
],
"nice_classes": [25],
"owners": [
{
"id": "own_R3jK9mN2",
"name": "Nike, Inc.",
"country_code": "US",
"entity_id": "ent_Wp8qLd4Z",
"entity_id_type": "resolved",
"companies": [
{
"source": "sec",
"ticker": "NKE",
"exchange": "NYSE",
"lei": null,
"entity_status": "active"
},
{
"source": "gleif",
"ticker": null,
"exchange": null,
"lei": "787RXPR0UX0O0XUXPZ81",
"entity_status": "active"
}
]
}
],
"coverage": null,
"source_records": null,
"owners_mixed": null
}
],
"has_more": true,
"pagination": {
"cursor": "eyJpZCI6ImFiYyJ9",
"total_count": 142,
"total_count_approximate": false
},
"search_meta": {
"search_id": "srch_abc123",
"query": "nike",
"strategies_used": ["exact", "fuzzy"],
"international_registrations": "grouped",
"execution_time_ms": 15
},
"request_id": "req_xyz789"
}
Code Examples
curl -G "https://api.signa.so/v1/trademarks" \
-H "Authorization: Bearer $SIGNA_API_KEY" \
--data-urlencode "q=nike" \
--data-urlencode "offices=US"
curl -G "https://api.signa.so/v1/trademarks" \
-H "Authorization: Bearer $SIGNA_API_KEY" \
--data-urlencode "offices=EM" \
--data-urlencode "nice_classes=9,42" \
--data-urlencode "status_stage=registered"
curl -G "https://api.signa.so/v1/trademarks" \
-H "Authorization: Bearer $SIGNA_API_KEY" \
--data-urlencode "q=nova" \
--data-urlencode "strategies=exact,phonetic,fuzzy,prefix" \
--data-urlencode "offices=US,EM" \
--data-urlencode "nice_classes=9"
curl -G "https://api.signa.so/v1/trademarks" \
-H "Authorization: Bearer $SIGNA_API_KEY" \
--data-urlencode "owner_publicly_traded=true" \
--data-urlencode "owner_ticker=AAPL" \
--data-urlencode "status_stage=registered"
import { Signa } from "@signa-so/sdk";
const signa = new Signa({ api_key: process.env.SIGNA_API_KEY });
const results = await signa.trademarks.list({
q: "nike",
offices: ["US"],
nice_classes: [25],
limit: 10,
});
for (const mark of results.data) {
console.log(mark.mark_text, mark.status.stage);
}
Statistics view
Use TMview-style facet breakdowns when building filter UIs, dashboards, or competitive landscape views that compare trademark counts by office, class, status, or party. They provide the counts needed to show the shape of a result set without downloading every matching record. Aggregations are available on GET with?aggregations=nice_classes,office_code, with semantics identical to POST options.aggregations. Add ?aggregations_only=true to return counts without result documents.
The 15 supported dimensions are status_stage, office_code, jurisdiction_code, nice_classes, filing_year, mark_feature_type, mark_legal_category, filing_route, right_kind, scope_kind, firm_id, attorney_id, owner_country, owner_id, and entity_id.
For id-bearing buckets (owner_id, attorney_id, firm_id, and entity_id), bucket keys are prefixed public ids. The top-level aggregation_metadata object maps each bucket key to a human-readable display name.
curl "https://api.signa.so/v1/trademarks?jurisdictions=US&aggregations=nice_classes,owner_id" \
-H "Authorization: Bearer $SIGNA_API_KEY"
{
"object": "list",
"data": [
{ "id": "tm_550e8400-e29b-41d4-a716-446655440000", "mark_text": "ACME CLOUD" }
],
"aggregations": {
"nice_classes": { "9": 1234, "42": 567 },
"owner_id": { "own_550e8400-e29b-41d4-a716-446655440001": 84 }
},
"aggregation_metadata": {
"owner_id": { "own_550e8400-e29b-41d4-a716-446655440001": "Acme Corporation" }
}
}
Sort
By default, results are ranked by relevance whenq is provided. For filter-only queries (no q), results are returned in index order (fast, unordered).
To explicitly sort results, use the sort parameter:
?sort=-filing_date # newest filings first
?sort=expiry_date # earliest expiry first
?sort=mark_text # alphabetical mark text
?sort=owner_name # alphabetical first owner name
?sort=-filing_date,office_code # multi-field (max 3)
filing_date, registration_date, expiry_date, renewal_due_date, updated_at, publication_date, termination_date, office_code, jurisdiction_code, mark_text, owner_name.
When
sort is specified alongside q, relevance scoring is bypassed: results are ordered purely by the sort field(s) and relevance_score will be null.Advanced: POST with JSON body
For complex queries with aggregations or long filter lists, usePOST /v1/trademarks with a JSON body. This accepts the same filters and returns the same response shape.
POST /v1/trademarks is idempotency-exempt (it is a read-shaped
search): the Idempotency-Key header is not required, and if you send one
it is not enforced or replayed (the value’s format is still validated).
GET does not take one.POST-only features
options.aggregations: an array of field names to aggregate. Returns faceted counts for building filter UIs. Valid values:status_stage,office_code,jurisdiction_code,nice_classes,filing_year,mark_feature_type,mark_legal_category,filing_route,right_kind,scope_kind,firm_id,attorney_id,owner_country,owner_id,entity_id.options.aggregations_only: return only counts, skip result documents
POST example
cURL
curl -X POST "https://api.signa.so/v1/trademarks" \
-H "Authorization: Bearer $SIGNA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "nova",
"strategies": ["exact", "phonetic", "fuzzy", "prefix"],
"filters": {
"offices": ["US", "EM"],
"nice_classes": [9, 42],
"status_stage": ["registered"],
"filing_date": { "gte": "2020-01-01" }
},
"options": {
"aggregations": ["office_code", "nice_classes", "status_stage"]
},
"limit": 20
}'
Show Full POST body reference
Show Full POST body reference
| Field | Type | Description |
|---|---|---|
query | string | Search query text (1-500 chars). Optional. |
sort | string | Sort field(s), same as GET sort parameter. |
strategies | string[] | Search strategies. Default: ["exact", "fuzzy"]. Only valid with match: "similar". |
match | string | Match mode: similar (default), exact, starts_with, ends_with, contains. Deterministic modes require query and disallow strategies/ranking_profile. |
mark_text_not_contains | string | Exclude marks whose folded text contains this substring. Composable with any match mode. |
filters | object | Same filters as GET, nested in an object. Arrays use JSON arrays, dates use {"gte": "...", "lt": "..."}. |
territory_match | string | Top-level field (not nested in filters): protection (default) or direct. Controls how filters.jurisdictions matches. See the territory_match query parameter. |
options.aggregations | string[] | Faceted counts across all 15 dimensions listed in Statistics view. |
options.aggregations_only | boolean | Return only counts, no documents. Default: false. |
options.include_total | boolean | Include accurate total count (subject to the same 10,000-match cap as include_total on GET). Default: false. |
options.highlights | boolean | Include highlight snippets. Default: false. |
include | string[] | Optional row projections. full_goods_services returns full classifications[].goods_services_text. |
fields | string[] | Sparse top-level field projection. id and object are always retained. Unknown names return 400. |
limit | integer | Results per page (0-100). Default: 20. |
cursor | string | Pagination cursor from previous response. |
Errors
Related Endpoints
- Retrieve Trademark: full detail for a single mark
- Batch Retrieve: hydrate known IDs