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

# Compute Oppositions

> Compute trademark opposition windows from publication dates

## Overview

Compute the opposition window for a published mark — when it opens, when it closes, and how much time is left — from a publication date, without storing anything.

Opposition windows are short, unforgiving, and specific to each office. When a conflicting mark publishes, the oppose-by date is what separates a cheap, procedural opposition now from a costly cancellation later. Send a publication date and Signa returns the window, its current status, any routine extensions, and the office rule behind it.

Pair it with [List Opposition Rules](/api-reference/reference/opposition-rules) to inspect the office rules, trigger events, time zones, extensions, and citations behind each computation.

<Note>
  Reference → Oppositions is the forward-looking WINDOW/timing computed from a publication date. Records → Proceedings (per-mark) is actual filed opposition CASES. They are distinct.
</Note>

## Request Body

<ParamField body="items" type="object[]" required>
  Publications to compute, max 1,000 items. Results are returned in the same order, with one `opposition_window` per input item.

  <Expandable title="Item object">
    <ParamField body="office" type="string" required>
      Trademark office code, e.g. `uspto`, `euipo`, or `cipo`. Values are normalized to lowercase.
    </ParamField>

    <ParamField body="filing_route" type="string">
      Filing route. One of `national`, `regional`, or `madrid`. Defaults to `national`. The response reports the office rule discriminator as `domestic` or `madrid_designation`.
    </ParamField>

    <ParamField body="publication_date" type="string">
      Publication calendar date as `YYYY-MM-DD`. Omit when the publication date is unknown; the response status will be `unknown`.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="as_of_date" type="string">
  Office-local calendar date to compute relative to, as `YYYY-MM-DD`. Defaults to today.
</ParamField>

## Response

A standard list response with `data: OppositionWindowComputation[]`. Pagination is not used; `data[i]` corresponds to `items[i]`.

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

<ResponseField name="data" type="object[]">
  <Expandable title="OppositionWindowComputation">
    <ResponseField name="object" type="string">Always `opposition_window`.</ResponseField>
    <ResponseField name="supported" type="boolean">`true` when Signa has an opposition rule for the office and route.</ResponseField>
    <ResponseField name="unsupported_reason" type="string | null">`unsupported_office`, `window_not_computable`, or `null`.</ResponseField>
    <ResponseField name="jurisdiction_code" type="string | null">Jurisdiction for the office rule, e.g. `EU`.</ResponseField>
    <ResponseField name="office_code" type="string | null">Office code used for the computation, e.g. `euipo`.</ResponseField>
    <ResponseField name="filing_route" type="string | null">Rule discriminator: `domestic` or `madrid_designation`.</ResponseField>
    <ResponseField name="publication_date" type="string | null">Publication date used as the trigger.</ResponseField>
    <ResponseField name="window_opens" type="string | null">First day the opposition window is open.</ResponseField>
    <ResponseField name="window_closes" type="string | null">Last day to oppose, after office-calendar rollover.</ResponseField>
    <ResponseField name="status" type="string | null">One of `not_started`, `open`, `closed`, or `unknown`.</ResponseField>
    <ResponseField name="days_until_open" type="integer | null">Days until `window_opens` when the status is `not_started`.</ResponseField>
    <ResponseField name="days_remaining" type="integer | null">Days remaining in the window when known.</ResponseField>
    <ResponseField name="office_time_zone" type="string | null">IANA office time zone for display.</ResponseField>
    <ResponseField name="trigger_event" type="string | null">`application_publication`, `registration_publication`, or `international_designation_publication`.</ResponseField>
    <ResponseField name="rule_version" type="string | null">Date the office rule was last verified.</ResponseField>

    <ResponseField name="common_extension" type="object | null">
      <Expandable title="CommonExtension">
        <ResponseField name="days" type="integer | null">Extension length in days.</ResponseField>
        <ResponseField name="months" type="integer | null">Extension length in months.</ResponseField>
        <ResponseField name="as_of_right" type="boolean">Whether the extension is granted automatically on timely request.</ResponseField>
        <ResponseField name="notes" type="string">Human-readable note for UI surfacing.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="source" type="object | null">
      <Expandable title="Source">
        <ResponseField name="citation" type="string">Statutory or office citation.</ResponseField>
        <ResponseField name="url" type="string">Authoritative URL for the citation.</ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="has_more" type="boolean">Always `false`.</ResponseField>
<ResponseField name="pagination" type="object">Always `{ "cursor": null }`.</ResponseField>
<ResponseField name="request_id" type="string">Unique request identifier for support and debugging.</ResponseField>

Unsupported offices or unsupported office-route combinations return `supported: false` with nullable window fields. A far-future or out-of-calendar-range item that cannot be rolled forward returns `unsupported_reason: "window_not_computable"` for that item only.

<ResponseExample>
  ```json theme={null}
  {
    "object": "list",
    "data": [
      {
        "object": "opposition_window",
        "supported": true,
        "unsupported_reason": null,
        "jurisdiction_code": "EU",
        "office_code": "euipo",
        "filing_route": "domestic",
        "publication_date": "2026-05-01",
        "window_opens": "2026-05-02",
        "window_closes": "2026-08-03",
        "status": "open",
        "days_until_open": null,
        "days_remaining": 29,
        "office_time_zone": "Europe/Madrid",
        "trigger_event": "application_publication",
        "rule_version": "2026-05-06",
        "common_extension": null,
        "source": {
          "citation": "Article 46(1) EUTMR (Regulation (EU) 2017/1001)",
          "url": "https://eur-lex.europa.eu/eli/reg/2017/1001/oj/eng"
        }
      }
    ],
    "has_more": false,
    "pagination": { "cursor": null },
    "request_id": "req_bT9kM3nP"
  }
  ```
</ResponseExample>

## Code Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.signa.so/v1/oppositions/compute" \
    -H "Authorization: Bearer sig_xxxxxxxxxxxx" \
    -H "Content-Type: application/json" \
    -d '{
      "items": [
        {
          "office": "euipo",
          "publication_date": "2026-05-01"
        }
      ],
      "as_of_date": "2026-07-05"
    }'
  ```

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

  const signa = new Signa({ api_key: "sig_xxxxxxxxxxxx" });

  const windows = await signa.oppositions.compute({
    items: [{ office: 'euipo', publication_date: '2026-05-01' }]
  });

  for (const window of windows.data) {
    console.log(window.office_code, window.status, window.window_closes);
  }
  ```

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

  resp = requests.post(
      "https://api.signa.so/v1/oppositions/compute",
      headers={
          "Authorization": "Bearer sig_xxxxxxxxxxxx",
          "Content-Type": "application/json",
      },
      json={
          "items": [{"office": "euipo", "publication_date": "2026-05-01"}],
          "as_of_date": "2026-07-05",
      },
  )
  for window in resp.json()["data"]:
      print(window["office_code"], window["status"], window["window_closes"])
  ```
</CodeGroup>

## Errors

| Status | Type               | Description                                                                                     |
| ------ | ------------------ | ----------------------------------------------------------------------------------------------- |
| 400    | `validation_error` | Malformed body, missing `items`, invalid date format, invalid enum value, or unknown body field |
| 401    | `unauthorized`     | Missing or invalid API key                                                                      |
| 403    | `forbidden`        | API key missing the `trademarks:read` scope                                                     |
| 422    | `batch_too_large`  | More than 1,000 items. The error carries `item_count` and `item_count_limit`                    |
| 429    | `rate_limited`     | Too many requests                                                                               |

## Related Endpoints

* [List Opposition Rules](/api-reference/reference/opposition-rules) -- inspect the office rule corpus and statutory citations
* [List Proceedings](/api-reference/proceedings/list-proceedings) -- actual filed opposition, cancellation, and appeal cases
* [Trademark Proceedings](/api-reference/trademarks/trademark-proceedings) -- proceedings scoped to one mark
