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

# Validate Goods & Services

> Check whether wording appears in the pre-approved catalogs available for requested offices

`listed` means the wording appears in that office's pre-approved catalog, exactly or after punctuation normalization (`match.type` says which). `not_listed` means we cannot show it there: it is an **absence of evidence, not a refusal**. These catalogs record positive membership only, so this endpoint cannot predict whether an office will allow wording that is absent.

Catalog answers are available only for `US`, `EM`, `JP`, `KR`, and `CN`. Every other recognized office returns `unsupported_office` with reason `no_catalog_data`; the endpoint does not imply broader coverage.

## Request

Send 1–100 items and 1–10 office codes. Only English (`en`) is available. Duplicate office aliases collapse and response office codes use ST.3.

<ParamField body="offices" type="string[]" required>
  Offices to report on. Catalog answers exist only for `US`, `EM`, `JP`, `KR`, and `CN`.
</ParamField>

<ParamField body="language" type="string" default="en">
  Catalog language. Only `en` is available in v1.
</ParamField>

<ParamField body="items" type="object[]" required>
  Wording to check, in response order. Each item requires `term` and may include `class_number` from
  1–45.
</ParamField>

Supplying `class_number` fixes the class used for candidate wording when the submitted term is not listed. Without one, the endpoint may match or infer a class and search that class; candidates are empty only when no class can be resolved or candidate search is not applicable. If the wording exists in another class, the item returns `class_mismatch` and `class_matches` names the class where the catalog wording actually lives. If no class is supplied and several classes match, the status is `ambiguous_class` and `class_matches` carries those rows.

`Idempotency-Key` is optional. When supplied, it is honoured for replay; it is never required. Billing is per item. `fee_impact` is reserved and always `null` in v1.

```bash theme={null}
curl -X POST "https://api.signa.so/v1/goods-services/validate" \
  -H "Authorization: Bearer sig_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "offices": ["US", "GB"],
    "language": "en",
    "items": [{
      "term": "Flowmeters for use in oil pipelines",
      "class_number": 9
    }]
  }'
```

```typescript theme={null}
const result = await signa.goodsServices.validate({
  offices: ['US', 'GB'],
  items: [
    {
      term: 'Flowmeters for use in oil pipelines',
      class_number: 9,
    },
  ],
});
```

## Candidate relations

Candidates are advisory catalog wording from the supplied or resolved class:

* `contained_in_input` means the wording appears as a contiguous run of words in what the customer wrote.
* `similar` means a lexical neighbour. It also includes rows demoted by the word-boundary check: a trigram match can be close without being a phrase the customer typed.
* `template` means the fixed wording of a USPTO drafting template appears in order. The placeholder and possible fill are in `template.slots`.

Every candidate has `span` and `template`; they are `null` when not applicable. Candidate wording is advisory, not a guarantee of acceptance.

## Coverage of your wording

`coverage` describes how many whitespace-separated tokens are supported by an exact/normalized match or by returned whole-word candidates. `uncovered` preserves the remaining wording as maximal runs. Coverage is **descriptive evidence, not an acceptance verdict**; connector words between supported spans can count structurally, while similar and template candidates never count as verified coverage.

## Template candidates

A `template` candidate is a drafting aid from the USPTO ID Manual. Fill its placeholders using `template.slots`; `filled_with` is `null` when the submitted wording cannot fill a slot unambiguously. Templates are **never `listed` matches**, even when their fixed wording appears in the input.

## Inferred classes

When an unclassified miss can be mapped to one Nice class, `class_source` is `inferred` and `class_inference` reports the method and confidence. This is a suggestion, not a classification decision. Supply `class_number` on a later request to override it.

## Warnings (indefinite wording)

`warnings` identifies wording covered by guidance for a requested office and cites the guideline in `source`. `objection` means the cited guidance calls the construction indefinite or unclear; `caution` means acceptability depends on context. A warning is guidance, **not a prediction that an examiner will refuse the wording**.

## Catalog freshness (`as_of`)

Each `summary.offices[].catalog_freshness[]` entry pairs a `catalogs` id with `as_of`, the UTC date that source was last refreshed. It tells you how fresh the evidence is—and how stale an absence may be. `null` means freshness is unknown; it never means the catalog is current.

## Candidate search completeness

Inspect `candidate_search` before interpreting `candidates`. `complete` means the search ran, so an empty array is a real absence of nearby wording in the held catalog. `not_run` means candidates were not applicable. `truncated` means the time budget expired before this item's chunk was issued, and `degraded` means a database error prevented a reliable search; neither means that no candidate exists. `candidate_search_reason` explains every non-`complete` result. Summary counts roll up complete, truncated, and degraded items.

<ResponseExample>
  ```json theme={null}
  {
    "object": "list",
    "summary": {
      "language": "en",
      "matching_policy": "lexical-v1",
      "item_count": 1,
      "unclassified_item_count": 0,
      "inferred_item_count": 0,
      "candidate_search": {
        "complete_item_count": 1,
        "truncated_item_count": 0,
        "degraded_item_count": 0
      },
      "warning_count": { "objection": 1, "caution": 0 },
      "offices": [
        { "office_code": "US", "supported": true, "catalogs": ["uspto_idm"], "catalog_freshness": [{ "source": "uspto_idm", "as_of": "2026-08-30" }], "listed_item_count": 0 },
        { "office_code": "GB", "supported": false, "catalogs": [], "catalog_freshness": [], "listed_item_count": null }
      ],
      "classes": [{ "class_number": 9, "item_count": 1 }],
      "fee_impact": null
    },
    "data": [{
      "object": "goods_services_validation",
      "term": "Flowmeters for use in oil pipelines",
      "class_number": 9,
      "class_source": "provided",
      "class_inference": null,
      "status": "not_listed",
      "match": null,
      "class_matches": [],
      "verdicts": [
        { "office_code": "US", "status": "not_listed", "reason": "not_in_catalog" },
        { "office_code": "GB", "status": "unsupported_office", "reason": "no_catalog_data" }
      ],
      "warnings": [{
        "rule_id": "us-open-ended-etc",
        "office": "US",
        "severity": "objection",
        "reason": "The office's guidelines treat “etc.” as indefinite wording.",
        "source": {
          "title": "USPTO Trademark Manual of Examining Procedure — May 2026",
          "section": "TMEP §1402.03(a)",
          "url": "https://tmep.uspto.gov/"
        }
      }],
      "candidates": [
        {
          "term": "Flowmeters for use in {indicate equipment or field of use}",
          "term_key": "flowmeters for use in {indicate equipment or field of use}",
          "class_number": 9,
          "relation": "template",
          "score": 1,
          "score_metric": "strict_word_similarity",
          "is_harmonised": false,
          "listed_by": ["US"],
          "sources": ["uspto_idm"],
          "span": { "start": 0, "end": 4 },
          "template": {
            "pattern": "Flowmeters for use in {indicate equipment or field of use}",
            "slots": [{
              "placeholder": "indicate equipment or field of use",
              "filled_with": "oil pipelines"
            }]
          }
        }
      ],
      "coverage": {
        "tokens": 7,
        "covered_tokens": 0,
        "uncovered": ["Flowmeters for use in oil pipelines"]
      },
      "candidate_search": "complete",
      "candidate_search_reason": null
    }],
    "has_more": false,
    "pagination": { "cursor": null },
    "request_id": "req_abc123"
  }
  ```
</ResponseExample>

## Statuses

| Level  | Status               | Meaning                                                                                                        |
| ------ | -------------------- | -------------------------------------------------------------------------------------------------------------- |
| Item   | `listed`             | The wording appears in a catalog Signa holds for the resolved class; use `verdicts` for each requested office. |
| Item   | `not_listed`         | The wording could not be shown in the catalogs held for that class. This is not a refusal.                     |
| Item   | `class_mismatch`     | The wording is catalogued in another class; inspect `class_matches`.                                           |
| Item   | `ambiguous_class`    | No class was supplied and catalog rows exist in several classes.                                               |
| Office | `unsupported_office` | No catalog data is held for that office; reason is `no_catalog_data`.                                          |

## Errors

| Status | Type                                                     | Description                                                                                                  |
| ------ | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| 400    | `validation_error`                                       | Invalid office, language, item count, term, or class number                                                  |
| 401    | `unauthorized`                                           | Missing or invalid API key                                                                                   |
| 403    | `forbidden`                                              | API key lacks `trademarks:read`                                                                              |
| 429    | `rate_limited`, `insufficient_credits`, `quota_exceeded` | Rate limit reached, or not enough credits/quota for the batch (a 100-item batch reserves 100 units up front) |
