Skip to main content
GET
Search Trademarks

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 Suggest and Image search.
string
Nice classification numbers 1-45, comma-separated (e.g. ?nice_classes=9,42).
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.
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 Get 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 live coverage 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 opposition_window.status response field. Use opposition_window 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. 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.

Match modes

The match parameter controls how q is matched against the mark text.
  • similar (default) — ranked, fuzzy matching. Runs the relevance ladder (tune it with strategies / ranking_profile) and orders results by relevance_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: exact requires the whole mark to equal q, the others anchor to the start, end, or anywhere in the mark. Results are ordered by date (not relevance), every row has relevance_score: null, highlights is inert, and search_meta.strategies_used is []. Use these when you need predictable, reproducible matching rather than ranking.
The deterministic modes accept a single-character 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
cURL — exclude a substring

Validation rules

Response

object[]
Trademark summary records: the slimmer list shape with the fields most useful for result cards. See Get 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.
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
Explains relevance scoring. Omitted when sort is specified or under a deterministic match mode.
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; status: "unknown" means the office/route is modeled but no publication date is available.
object[]
Nice classifications on the row.
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).
object | null
Per-territory coverage rollup. Present only on grouped Madrid IR-family rows (international_registrations=grouped, the default); null on record-grain and direct/regional mark-of-one rows. See Get Trademark Coverage for the full per-territory shape.
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.

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:
A French national mark in the same result set instead carries { "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).

Code Examples

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.

Sort

By default, results are ranked by relevance when q is provided. For filter-only queries (no q), results are returned in index order (fast, unordered). To explicitly sort results, use the sort parameter:
Available sort fields: 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, use POST /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

Errors