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

# Trademark Documents

> Office documents for a mark (office actions, certificates, filed forms, correspondence) with lazy first-request metadata fetch and a streaming file proxy

## When to use this

If you run docketing or an IPMS product, you need office documents the day they issue: the non-final office action a client must answer, the registration certificate, the filed forms in the prosecution history. This endpoint returns that document list for a mark, and each row carries a `url` that streams the actual file. USPTO documents are fetched from TSDR on demand the first time you ask, so you get fresh metadata without running your own TSDR poller or fighting its throttles.

The list is `document`-type media only. Logos, drawings, and specimens live on the [`media[]`](/api-reference/trademarks/get-trademark) array of the trademark record, not here.

## Path Parameters

<ParamField path="id" type="string" required>
  Trademark ID (`tm_...`).
</ParamField>

## Query Parameters

<ParamField query="document_kind" type="string">
  Filter by one or more document kinds, comma-separated. Values: `office_action`, `certificate`, `correspondence`, `filed_form`, `other`. Example: `document_kind=office_action,certificate`.
</ParamField>

<ParamField query="official_date_gte" type="string">
  Return documents whose official date is on or after this date (`YYYY-MM-DD`).
</ParamField>

<ParamField query="official_date_lt" type="string">
  Return documents whose official date is strictly before this date (`YYYY-MM-DD`). Must be after `official_date_gte` when both are supplied.
</ParamField>

<ParamField query="limit" type="integer" default="20">
  Page size, 1 to 100.
</ParamField>

<ParamField query="cursor" type="string">
  Pagination cursor from a previous response's `pagination.cursor`.
</ParamField>

## Response

A standard list envelope with one extra field, `source_sync`, describing the freshness of this mark's document metadata.

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

<ResponseField name="source_sync" type="object">
  Freshness of the document metadata for this mark.

  <Expandable title="source_sync">
    <ResponseField name="status" type="string">
      One of:

      * `synced`: metadata is present and current. `data` reflects the stored documents.
      * `pending`: a lazy fetch is in flight (another request holds the fetch lock) or upstream is still settling. `data` may be empty or partial. Request again shortly.
      * `unsupported`: the mark belongs to an office without document support (anything other than USPTO today). `data` is always empty and no fetch is attempted.
    </ResponseField>

    <ResponseField name="last_synced_at" type="string">
      ISO 8601 timestamp of the last successful sync, or `null` if never synced.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="data" type="array">
  Array of trademark document objects, newest official date first.

  <Expandable title="trademark document">
    <ResponseField name="id" type="string">
      Media ID (`med_...`). Use it against the [media proxy](#downloading-document-files) to stream the file.
    </ResponseField>

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

    <ResponseField name="document_kind" type="string">
      One of `office_action`, `certificate`, `correspondence`, `filed_form`, `other`.
    </ResponseField>

    <ResponseField name="official_date" type="string">
      Official document date (`YYYY-MM-DD`), or `null` when the office did not supply one.
    </ResponseField>

    <ResponseField name="description" type="string">
      Human-readable label from the office (e.g. `Nonfinal Office Action`), or `null`.
    </ResponseField>

    <ResponseField name="mime_type" type="string">
      Content type of the file, typically `application/pdf`.
    </ResponseField>

    <ResponseField name="page_count" type="integer">
      Page count when known, otherwise `null`.
    </ResponseField>

    <ResponseField name="url" type="string">
      Absolute media-proxy URL that streams the file bytes. See [Downloading document files](#downloading-document-files).
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="has_more" type="boolean">
  Whether more pages exist after this one.
</ResponseField>

<ResponseField name="pagination" type="object">
  Contains `cursor` (the token for the next page, or `null`).
</ResponseField>

### First call: metadata fetch in flight

The first time you request documents for a USPTO mark that has never been synced, Signa fetches the metadata inline. If another request already holds the fetch lock, or the upstream fetch is still settling, you get `status: pending` with an empty `data` array. Request again in a moment.

```json First call (pending) theme={null}
{
  "object": "list",
  "source_sync": { "status": "pending", "last_synced_at": null },
  "data": [],
  "has_more": false,
  "pagination": { "cursor": null },
  "request_id": "req_01kx22n3rpj1e6cmnpfbf482k6"
}
```

### Second call: synced with a document row

Once the fetch completes, the list is `synced` and each row carries its media-proxy `url`.

```json Second call (synced) theme={null}
{
  "object": "list",
  "source_sync": { "status": "synced", "last_synced_at": "2026-07-09T04:00:00Z" },
  "data": [
    {
      "id": "med_019d2141-6ce9-771b-872e-bc8b20e49fcf",
      "object": "trademark_document",
      "document_kind": "office_action",
      "official_date": "2025-11-04",
      "description": "Nonfinal Office Action",
      "mime_type": "application/pdf",
      "page_count": 12,
      "url": "https://api.signa.so/v1/trademarks/tm_8kLm2nPq/media/med_019d2141-6ce9-771b-872e-bc8b20e49fcf"
    }
  ],
  "has_more": false,
  "pagination": { "cursor": null },
  "request_id": "req_01kx22p7c8a0d3fjm2q9x7t4bz"
}
```

For a non-USPTO mark you always get `200` with an empty list and `source_sync.status` of `unsupported`. This endpoint never returns an error status for an office that lacks document support.

## Code Examples

<CodeGroup>
  ```bash cURL theme={null}
  # First call kicks off the lazy fetch
  curl "https://api.signa.so/v1/trademarks/tm_8kLm2nPq/documents" \
    -H "Authorization: Bearer $SIGNA_API_KEY"

  # Filter to office actions issued in 2025
  curl "https://api.signa.so/v1/trademarks/tm_8kLm2nPq/documents?document_kind=office_action&official_date_gte=2025-01-01&official_date_lt=2026-01-01" \
    -H "Authorization: Bearer $SIGNA_API_KEY"
  ```

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

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

  const docs = await signa.trademarks.documents("tm_8kLm2nPq", {
    document_kind: "office_action",
    official_date_gte: "2025-01-01",
    official_date_lt: "2026-01-01",
  });

  if (docs.source_sync?.status === "pending") {
    // metadata still settling; request again shortly
  }

  for (const doc of docs.data) {
    console.log(doc.document_kind, doc.official_date, doc.url);
  }
  ```
</CodeGroup>

## Downloading document files

Each document row's `url` points at the media proxy, `GET /v1/trademarks/{id}/media/{mediaId}`. Following it streams the file bytes:

* The response is the raw file with its real `Content-Type` (`application/pdf` for office actions and certificates).
* `X-Content-Type-Options: nosniff` is set. The proxy never relabels a file: an image row stays an image content type.
* The endpoint is **unauthenticated** so it works directly in `<a href>` and `<embed>`, but it is **IP rate-limited**, so treat it as a per-download link, not a bulk hose.

For a USPTO document, the first download is a cold fetch: the proxy pulls the file from TSDR under a shared download budget and persists it. When that budget is momentarily exhausted, the proxy returns `502 upstream_error` with a `Retry-After: 60` header. Honor it and retry after the stated delay. Once persisted, subsequent downloads serve the stored bytes and do not touch TSDR.

```bash cURL theme={null}
# Stream an office action PDF to disk
curl -L "https://api.signa.so/v1/trademarks/tm_8kLm2nPq/media/med_019d2141-6ce9-771b-872e-bc8b20e49fcf" \
  -o office-action.pdf
```

## Errors

| Status | Type               | Description                                                                                     |
| ------ | ------------------ | ----------------------------------------------------------------------------------------------- |
| 400    | `validation_error` | Invalid trademark ID, bad `document_kind`, or `official_date_gte` not before `official_date_lt` |
| 401    | `unauthorized`     | Missing or invalid API key                                                                      |
| 403    | `forbidden`        | API key lacks the `trademarks:read` scope                                                       |
| 404    | `not_found`        | Trademark does not exist                                                                        |

The media proxy returns `502 upstream_error` (with `Retry-After`) when the TSDR download budget is exhausted, and `404 not_found` when the media record or upstream file does not exist.

## Related Endpoints

* [Build a docketing system](/guides/use-cases/build-a-docketing-system): the end-to-end recipe using this endpoint
* [Trademark Media](/api-reference/trademarks/trademark-media): image proxy for logos, drawings, and specimens
* [Get Trademark](/api-reference/trademarks/get-trademark): the full record, including the `media[]` image array
