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

# List Goods & Services

> Browse and search accepted goods & services terms across one Nice class or all 45

## Overview

Browse and search 96,000+ pre-approved goods & services descriptions from the Harmonised Database (HDB) and the USPTO ID Manual. Use this to power goods/services autocomplete in filing tools (pass `class` to scope results to a single Nice class), or to discover which classes accept a particular term (pass `q` without `class` for a cross-class search).

For background on how office acceptance works and the data sources behind this endpoint, see the [Classifications & Goods/Services guide](/guides/classifications).

<Info>
  At least one of `q` or `class` must be provided. For semantic class discovery from a natural-language business description (e.g. "SaaS tool for HR teams"), use [Suggest Classifications](/api-reference/reference/suggest-classifications). For a drafted goods/services specification with filing-ready wording per class, use [Suggest Goods & Services](/api-reference/reference/suggest-goods-services).
</Info>

## Query Parameters

<ParamField query="q" type="string">
  Substring search across term text (2-200 characters). Optional if `class` is set. Returns `400 validation_error` if neither `q` nor `class` is provided.
</ParamField>

<ParamField query="class" type="integer">
  Nice class number (1-45). Optional if `q` is set. Returns `400` if outside the 1-45 range, or `404` if the class number is in range but not loaded in reference data.
</ParamField>

<ParamField query="language" type="string" default="en">
  Language code (e.g. `en`, `de`, `fr`, `es`, `it`, `ja`).
</ParamField>

<ParamField query="harmonised_only" type="boolean" default="false">
  When `true`, only return terms on the TMClass harmonised list.
</ParamField>

<ParamField query="limit" type="integer" default="20">
  Max results (1-100).
</ParamField>

<ParamField query="cursor" type="string">
  Pagination cursor from `pagination.cursor` of the previous page.
</ParamField>

## Response

This endpoint is publicly cacheable, so the response never includes `request_id`.

<ResponseField name="object" type="string">Always `list`.</ResponseField>

<ResponseField name="data" type="object[]">
  Array of term records ordered by term key.
</ResponseField>

<ResponseField name="data[].term" type="string">The term text.</ResponseField>
<ResponseField name="data[].term_key" type="string">Stable normalized key for the term.</ResponseField>
<ResponseField name="data[].class_number" type="integer">Nice class this term is filed under (1-45). Present on every result so cross-class searches render without follow-up fetches.</ResponseField>
<ResponseField name="data[].taxonomy_path" type="string | null">TMClass taxonomy path identifier, when available.</ResponseField>
<ResponseField name="data[].is_harmonised" type="boolean">Whether the term is on the harmonised list.</ResponseField>
<ResponseField name="data[].accepted_offices" type="string[]">Offices that accept this term (e.g. `USPTO`, `EUIPO`).</ResponseField>
<ResponseField name="data[].source" type="string">Source catalog (e.g. `tmclass`, `uspto_idm`).</ResponseField>
<ResponseField name="data[].language" type="string">Language code.</ResponseField>
<ResponseField name="has_more" type="boolean">Whether more pages are available.</ResponseField>

<ResponseField name="pagination" type="object">
  <Expandable title="Pagination">
    <ResponseField name="cursor" type="string | null">Cursor for the next page, or `null` on the last page.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json theme={null}
  {
    "object": "list",
    "data": [
      {
        "term": "3D animation software",
        "term_key": "3d animation software",
        "class_number": 9,
        "taxonomy_path": "8729051",
        "is_harmonised": true,
        "accepted_offices": ["EUIPO"],
        "source": "tmclass",
        "language": "en"
      }
    ],
    "has_more": true,
    "pagination": { "cursor": "3d animation software" }
  }
  ```
</ResponseExample>

## Code Examples

### Scoped autocomplete (user already picked a class)

<CodeGroup>
  ```bash cURL theme={null}
  curl -G "https://api.signa.so/v1/goods-services" \
    -H "Authorization: Bearer sig_YOUR_KEY" \
    --data-urlencode "q=mobile applications" \
    --data-urlencode "class=9" \
    --data-urlencode "harmonised_only=true" \
    --data-urlencode "limit=10"
  ```

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

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

  const terms = await signa.goodsServices.list({
    q: "mobile applications",
    class: 9,
    harmonised_only: true,
    limit: 10,
  });
  ```
</CodeGroup>

### Cross-class discovery (which classes accept this term?)

Pass only `q` (omit `class`) and inspect `class_number` on each result to see which classes contain the wording.

<CodeGroup>
  ```bash cURL theme={null}
  curl -G "https://api.signa.so/v1/goods-services" \
    -H "Authorization: Bearer sig_YOUR_KEY" \
    --data-urlencode "q=poster" \
    --data-urlencode "limit=25"
  ```

  ```typescript TypeScript theme={null}
  const matches = await signa.goodsServices.list({ q: "poster", limit: 25 });

  for (const t of matches.data) {
    console.log(`Class ${t.class_number}: ${t.term}`);
  }
  ```
</CodeGroup>

### Browse all terms in a class

Pass only `class` (omit `q`) to page through the full list of accepted wording for one class.

```typescript TypeScript theme={null}
let page = await signa.goodsServices.list({ class: 25, limit: 50 });
for (const t of page.data) console.log(t.term);
while (page.has_more) {
  page = await page.getNextPage();
  for (const t of page.data) console.log(t.term);
}
```

## Errors

| Status | Type               | Description                                                                                        |
| ------ | ------------------ | -------------------------------------------------------------------------------------------------- |
| 400    | `validation_error` | Neither `q` nor `class` provided, `q` shorter than 2 characters, or `class` outside the 1-45 range |
| 401    | `unauthorized`     | Missing or invalid API key                                                                         |
| 403    | `forbidden`        | API key lacks `trademarks:read` scope                                                              |
| 404    | `not_found`        | `class` is in range but not loaded in reference data                                               |

## Related Endpoints

* [Suggest Goods & Services](/api-reference/reference/suggest-goods-services), drafts a filing-ready specification from a description
* [Suggest Classifications](/api-reference/reference/suggest-classifications), lighter tier, classes only
* [Get Classification](/api-reference/reference/get-classification)
* [List Classifications](/api-reference/reference/list-classifications)
