> ## 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.

# Search

> Full-text, phonetic, and fuzzy trademark search

Signa's search is powered by OpenSearch with custom analyzers for trademark-specific matching.

## Choosing GET or POST

The trademarks endpoint is exposed under both `GET /v1/trademarks` and `POST /v1/trademarks`. Both methods call the same service and return the same response shape. Pick whichever fits your call site.

| Method                | When to use                                                                        |
| --------------------- | ---------------------------------------------------------------------------------- |
| `GET /v1/trademarks`  | Quick queries, curl exploration, URL sharing, browser and wget use, simple filters |
| `POST /v1/trademarks` | Complex queries, long filter lists, aggregations, debugging                        |

A few advanced options live only on `POST` because they do not fit in a query string: `options.aggregations` and `options.aggregations_only`. Everything else (filters, strategies, pagination, `highlights`, `include_total`, `sort`) works identically on both.

For the full parameter reference, see [List Trademarks](/api-reference/trademarks/list-trademarks). The sections below show concrete usage patterns you can copy into your own code.

## Search Strategies

By default, every search runs `exact` and `fuzzy` strategies simultaneously and merges the results. For comprehensive clearance searches, use all four:

| Strategy   | What it does                                                                              |
| ---------- | ----------------------------------------------------------------------------------------- |
| `exact`    | Case-insensitive exact keyword match -- the entire mark text must match the query exactly |
| `phonetic` | Catches sound-alikes regardless of spelling (e.g., "SIGNA" / "CYGNA" / "SYNNA")           |
| `fuzzy`    | Tolerates typos and minor character differences (fuzziness is always AUTO internally)     |
| `prefix`   | Matches marks that start with the query text                                              |

You can restrict which strategies are used by passing the `strategies` array (on POST) or a comma-separated `strategies=` parameter (on GET):

<CodeGroup>
  ```bash cURL (GET) theme={null}
  curl -G "https://api.signa.so/v1/trademarks" \
    -H "Authorization: Bearer $SIGNA_API_KEY" \
    --data-urlencode "q=signa" \
    --data-urlencode "strategies=exact,phonetic"
  ```

  ```bash cURL (POST) theme={null}
  curl -X POST https://api.signa.so/v1/trademarks \
    -H "Authorization: Bearer $SIGNA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "signa",
      "strategies": ["exact", "phonetic"]
    }'
  ```

  ```typescript TypeScript theme={null}
  import { Signa } from "@signa-so/sdk";

  const signa = new Signa({ api_key: process.env.SIGNA_API_KEY });

  const results = await signa.trademarks.list({
    query: "signa",
    strategies: ["exact", "phonetic"],
  });
  ```

  ```python Python theme={null}
  import os
  import requests

  response = requests.post(
      "https://api.signa.so/v1/trademarks",
      headers={"Authorization": f"Bearer {os.environ['SIGNA_API_KEY']}"},
      json={
          "query": "signa",
          "strategies": ["exact", "phonetic"],
      },
  )
  ```
</CodeGroup>

If you omit `strategies`, `exact` and `fuzzy` are used. For comprehensive trademark clearance searches, pass all four strategies explicitly: `exact,phonetic,fuzzy,prefix`.

<Note>
  There is no user-controllable `fuzziness` parameter. Fuzzy matching always uses AUTO internally, which adjusts edit distance based on the length of the query term.
</Note>

## Filtering

Narrow results with filters. On `POST`, filters are nested under a `filters` object. On `GET`, they are flat query parameters using comma-separated values for arrays and flat underscore operators for date ranges.

<CodeGroup>
  ```bash cURL (GET) theme={null}
  curl -G "https://api.signa.so/v1/trademarks" \
    -H "Authorization: Bearer $SIGNA_API_KEY" \
    --data-urlencode "q=signa" \
    --data-urlencode "offices=uspto,euipo" \
    --data-urlencode "nice_classes=9,42" \
    --data-urlencode "status_stage=registered" \
    --data-urlencode "filing_date_gte=2020-01-01"
  ```

  ```bash cURL (POST) theme={null}
  curl -X POST https://api.signa.so/v1/trademarks \
    -H "Authorization: Bearer $SIGNA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "signa",
      "filters": {
        "offices": ["uspto", "euipo"],
        "nice_classes": [9, 42],
        "status_stage": ["registered"],
        "filing_date": { "gte": "2020-01-01" }
      }
    }'
  ```

  ```typescript TypeScript theme={null}
  const results = await signa.trademarks.list({
    query: "signa",
    filters: {
      offices: ["uspto", "euipo"],
      nice_classes: [9, 42],
      status_stage: ["registered"],
      filing_date: { gte: "2020-01-01" },
    },
  });
  ```

  ```python Python theme={null}
  response = requests.post(
      "https://api.signa.so/v1/trademarks",
      headers={"Authorization": f"Bearer {os.environ['SIGNA_API_KEY']}"},
      json={
          "query": "signa",
          "filters": {
              "offices": ["uspto", "euipo"],
              "nice_classes": [9, 42],
              "status_stage": ["registered"],
              "filing_date": {"gte": "2020-01-01"},
          },
      },
  )
  ```
</CodeGroup>

<Warning>
  On `POST`, filters must be nested under `filters`. Passing `offices`, `nice_classes`, `status_stage`, or other filter keys at the top level returns a `validation_error` with `unrecognized_keys`. There is also no top-level `search_type` or `type` field. Strategy selection happens through the `strategies` array.
</Warning>

Date filter operators:

| Operator | Meaning                                      |
| -------- | -------------------------------------------- |
| `gte`    | Greater than or equal (from date, inclusive) |
| `lt`     | Less than (to date, exclusive)               |

You can use both together for a range: `"filing_date": { "gte": "2020-01-01", "lt": "2025-01-01" }` (POST) or `filing_date_gte=2020-01-01&filing_date_lt=2025-01-01` (GET).

## Aggregations

Aggregations are `POST`-only because they do not map cleanly to query strings. Available aggregation fields:

| Field                 | Description                                               |
| --------------------- | --------------------------------------------------------- |
| `office_code`         | Counts by trademark office                                |
| `jurisdiction_code`   | Counts by jurisdiction                                    |
| `nice_classes`        | Counts by Nice classification                             |
| `status_stage`        | Counts by status stage                                    |
| `filing_year`         | Counts by filing year                                     |
| `mark_feature_type`   | Counts by mark type (word, figurative, etc.)              |
| `mark_legal_category` | Counts by legal category (trademark, certification, etc.) |
| `filing_route`        | Counts by filing route (direct\_national, madrid, etc.)   |
| `right_kind`          | Counts by right kind                                      |
| `scope_kind`          | Counts by scope kind                                      |

```json theme={null}
{
  "query": "signa",
  "options": {
    "aggregations": ["office_code", "status_stage", "nice_classes"]
  }
}
```

To get only the counts with no result documents, add `"aggregations_only": true` to `options`.

## Response Scoring

Search results include a `relevance_score` field, which is a normalized score from 0 to 100 (higher is more relevant). Results are sorted by relevance score in descending order by default.

## Suggest

For autocomplete and typeahead:

```bash theme={null}
GET /v1/trademarks/suggest?q=sig&limit=10
```
