Skip to main content
GET
/
v1
/
trademarks
Search Trademarks
curl --request GET \
  --url https://api.signa.so/v1/trademarks \
  --header 'Authorization: Bearer <token>'
{
  "object": "list",
  "data": [
    {
      "id": "tm_abc123",
      "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": "uspto",
      "jurisdiction_code": "US",
      "filing_date": "1971-02-04",
      "registration_date": "1974-04-16",
      "classifications": [
        { "nice_class": 25, "goods_services_text": "Clothing, footwear, headgear" }
      ],
      "owner_name": "Nike, Inc.",
      "owners": [
        {
          "id": "own_def456",
          "name": "Nike, Inc.",
          "country_code": "US",
          "companies": [
            {
              "source": "sec",
              "ticker": "NKE",
              "exchange": "NYSE",
              "lei": null,
              "entity_status": "active"
            }
          ]
        }
      ]
    }
  ],
  "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"],
    "total_results": 142,
    "total_count_exact": true,
    "total_count_approximate": false,
    "execution_time_ms": 15
  },
  "aggregations": {},
  "request_id": "req_xyz789"
}
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

q
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.
strategies
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.
limit
integer
default:"20"
Results per page (1-100).
cursor
string
Opaque pagination cursor from a previous response.
include_total
boolean
default:"false"
When true, includes an accurate total count in pagination.total_count.
highlights
boolean
default:"false"
When true, includes highlight snippets for mark_text and owner_names fields.

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.
offices
string
Office codes, comma-separated (e.g. ?offices=uspto,euipo).
jurisdictions
string
ISO jurisdiction codes, comma-separated (e.g. ?jurisdictions=US,EU).
nice_classes
string
Nice classification numbers 1-45, comma-separated (e.g. ?nice_classes=9,42).
status_primary
string
Primary status: active, pending, inactive, unknown. Comma-separated for multiple.
status_stage
string
Status stage, comma-separated (e.g. registered, published, examining).
mark_feature_type
string
Mark type: word, figurative, combined, three_dimensional.
filing_route
string
Filing route: direct_national, madrid_designation, direct_regional.
owner_id
string
Owner ID (own_...). Marks for that single per-office owner record.
owner_name
string
Owner name substring match.
entity_id
string
Resolved entity ID (ent_...). Returns marks across all member owners of the entity (every office) — the global-portfolio filter. Accepts a derived ent_<owner-uuid>. An entity resolving to more than 10,000 member owners returns 422 entity_too_large with error.reason: member_owners_too_large (member_count / member_count_limit). See Entities.
entity_group
string
Entity GROUP ID (ent_...). Returns marks across the whole GLEIF corporate family (root + all descendants) — “all Pfizer-group marks”. Group-level, never identity. Two 422 entity_too_large reasons apply: family_graph_too_large when the GLEIF family-graph walk exceeds its node/depth bound before owners are counted (carries related_entity_limit / depth_limit), or member_owners_too_large when the resolved member union exceeds the cap (carries member_count / member_count_limit).
owner_publicly_traded
boolean
true to return marks whose owner has a confirmed active SEC ticker match. false means no confirmed public-company match, not confirmed private.
owner_has_lei
boolean
true to return marks whose owner has a confirmed GLEIF LEI match. false means no confirmed LEI match.
owner_ticker
string
Exact owner ticker match, uppercased server-side (e.g. AAPL).
owner_lei
string
Exact owner LEI match, uppercased server-side.
attorney_id
string
Attorney ID (att_...).
firm_id
string
Firm ID (firm_...).
filing_date_gte
string
Filing date lower bound (YYYY-MM-DD).
filing_date_lt
string
Filing date upper bound (exclusive).
registration_date_gte
string
Registration date lower bound.
registration_date_lt
string
Registration date upper bound.
expiry_date_gte
string
Expiry date lower bound.
expiry_date_lt
string
Expiry date upper bound.
has_media
boolean
true to require at least one image.
is_madrid
boolean
true to restrict to Madrid Protocol filings.

Examples

curl -G "https://api.signa.so/v1/trademarks" \
  -H "Authorization: Bearer $SIGNA_API_KEY" \
  --data-urlencode "q=nike" \
  --data-urlencode "offices=uspto"

Response

{
  "object": "list",
  "data": [
    {
      "id": "tm_abc123",
      "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": "uspto",
      "jurisdiction_code": "US",
      "filing_date": "1971-02-04",
      "registration_date": "1974-04-16",
      "classifications": [
        { "nice_class": 25, "goods_services_text": "Clothing, footwear, headgear" }
      ],
      "owner_name": "Nike, Inc.",
      "owners": [
        {
          "id": "own_def456",
          "name": "Nike, Inc.",
          "country_code": "US",
          "companies": [
            {
              "source": "sec",
              "ticker": "NKE",
              "exchange": "NYSE",
              "lei": null,
              "entity_status": "active"
            }
          ]
        }
      ]
    }
  ],
  "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"],
    "total_results": 142,
    "total_count_exact": true,
    "total_count_approximate": false,
    "execution_time_ms": 15
  },
  "aggregations": {},
  "request_id": "req_xyz789"
}
data
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.
has_more
boolean
Whether more results are available.
pagination.cursor
string
Pass this as ?cursor= to get the next page.
pagination.total_count
integer
Total matches. Only present when include_total=true. Canonical location — read this field across every list endpoint.
pagination.total_count_approximate
boolean
Emitted alongside total_count. false when the count is exact; true when the search index capped the count at 10,000 for a deep search.
search_meta
object
Query metadata: search_id, query, strategies_used, execution_time_ms.
aggregations
object
Empty object {} on GET requests. Populated with faceted counts on POST when options.aggregations is provided.
relevance_score
number | null
Normalized relevance score. Present when q is provided, null for filter-only queries or when sort is specified.
match_explanation
object | undefined
Explains relevance scoring. Omitted when sort is specified.
primary_image_url
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.
owners
object[]
Summary-tier owner projections for search-backed rows. Omitted on some DB-backed summary rows.

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:
?sort=-filing_date          # newest filings first
?sort=expiry_date           # earliest expiry first
?sort=-filing_date,office_code  # multi-field (max 3)
Available sort fields: filing_date, registration_date, expiry_date, renewal_due_date, updated_at, publication_date, termination_date, office_code, jurisdiction_code.
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.

Errors

StatusTypeWhen
400validation_errorNo filter or query supplied, invalid date range, unknown sort field
401unauthorizedMissing or invalid API key
429rate_limitedRate limit exceeded (details)

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.
  • 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": ["uspto", "euipo"],
      "nice_classes": [9, 42],
      "status_stage": ["registered"],
      "filing_date": { "gte": "2020-01-01" }
    },
    "options": {
      "aggregations": ["office_code", "nice_classes", "status_stage"]
    },
    "limit": 20
  }'