List Opposition Rules
curl --request GET \
--url https://api.signa.so/v1/opposition-rules \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.signa.so/v1/opposition-rules"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.signa.so/v1/opposition-rules', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.signa.so/v1/opposition-rules",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/opposition-rules"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.signa.so/v1/opposition-rules")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/opposition-rules")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "list",
"data": [
{
"object": "opposition_rule",
"rule_id": "eu_opposition_madrid",
"effective_from": null,
"last_verified": "2026-05-06",
"jurisdiction_code": "EU",
"office_code": "EM",
"filing_route": "madrid_designation",
"trigger_event": "international_designation_publication",
"window_months": 3,
"window_days": null,
"window_starts_offset_months": 1,
"window_starts_on": "date_of_publication",
"window_ends_on": null,
"window_change_date": null,
"window_starts_on_before": null,
"window_months_before": null,
"window_days_before": null,
"window_ends_on_before": null,
"month_end_overflow": "last_day",
"office_time_zone": "Europe/Madrid",
"holiday_calendar": "euipo_alicante",
"common_extension": null,
"applicable_from_date": null,
"sources": [
{
"citation": "Article 196(2) EUTMR (Regulation (EU) 2017/1001) — opposition to IRs designating EU; period of three months begins one month after the publication pursuant to Article 190(1)",
"url": "https://eur-lex.europa.eu/eli/reg/2017/1001/oj/eng"
},
{
"citation": "Article 190(1) EUTMR — EUIPO republication in EUTM Bulletin Part M",
"url": "https://eur-lex.europa.eu/eli/reg/2017/1001/oj/eng"
},
{
"citation": "Article 67 Commission Delegated Regulation (EU) 2018/625",
"url": "https://eur-lex.europa.eu/eli/reg_del/2018/625/oj"
},
{
"citation": "Article 69 Commission Delegated Regulation (EU) 2018/625",
"url": "https://eur-lex.europa.eu/eli/reg_del/2018/625/oj"
}
]
}
],
"has_more": false,
"pagination": { "cursor": null }
}
Deadlines
List Opposition Rules
List all opposition window rules across modeled offices
GET
/
v1
/
opposition-rules
List Opposition Rules
curl --request GET \
--url https://api.signa.so/v1/opposition-rules \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.signa.so/v1/opposition-rules"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.signa.so/v1/opposition-rules', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.signa.so/v1/opposition-rules",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/opposition-rules"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.signa.so/v1/opposition-rules")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/opposition-rules")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"object": "list",
"data": [
{
"object": "opposition_rule",
"rule_id": "eu_opposition_madrid",
"effective_from": null,
"last_verified": "2026-05-06",
"jurisdiction_code": "EU",
"office_code": "EM",
"filing_route": "madrid_designation",
"trigger_event": "international_designation_publication",
"window_months": 3,
"window_days": null,
"window_starts_offset_months": 1,
"window_starts_on": "date_of_publication",
"window_ends_on": null,
"window_change_date": null,
"window_starts_on_before": null,
"window_months_before": null,
"window_days_before": null,
"window_ends_on_before": null,
"month_end_overflow": "last_day",
"office_time_zone": "Europe/Madrid",
"holiday_calendar": "euipo_alicante",
"common_extension": null,
"applicable_from_date": null,
"sources": [
{
"citation": "Article 196(2) EUTMR (Regulation (EU) 2017/1001) — opposition to IRs designating EU; period of three months begins one month after the publication pursuant to Article 190(1)",
"url": "https://eur-lex.europa.eu/eli/reg/2017/1001/oj/eng"
},
{
"citation": "Article 190(1) EUTMR — EUIPO republication in EUTM Bulletin Part M",
"url": "https://eur-lex.europa.eu/eli/reg/2017/1001/oj/eng"
},
{
"citation": "Article 67 Commission Delegated Regulation (EU) 2018/625",
"url": "https://eur-lex.europa.eu/eli/reg_del/2018/625/oj"
},
{
"citation": "Article 69 Commission Delegated Regulation (EU) 2018/625",
"url": "https://eur-lex.europa.eu/eli/reg_del/2018/625/oj"
}
]
}
],
"has_more": false,
"pagination": { "cursor": null }
}
Overview
Returns a flat list of opposition window rules: the statutory windows during which third parties may oppose a published trademark application or registration. Each rule includes the office’s local time zone, holiday calendar (used for close-date rollover), statutory citations, and any common (non-statutory but routinely granted) extensions. Each rule carries a stablerule_id, and every computed opposition window reports the rule_id that produced it, so any window Signa returns can be resolved back to the rule and citations behind it. The rule is also addressable by the combination of office_code and filing_route, which is what the compute endpoint looks up.
This endpoint exposes the same rule corpus that powers Compute Oppositions and the derived.opposition_window field on a trademark detail response. Use it to build educational UI, surface citations alongside a watch alert, or document what to expect for a given office.
Query Parameters
string
Filter by jurisdiction code (uppercase ISO-2). Comma-separated for multiple values.
string
Filter by uppercase ST.3 office code. Comma-separated for multiple values, e.g.
?office=US,EM. Legacy lowercase codes (e.g. uspto, and eu for EUIPO) are accepted as permanent aliases.Accepts every code this catalog serves, not only the offices Signa ingests a register from: ?office=JP and ?office=TR return their rules. Anything outside that set, and outside the /v1/offices vocabulary, is a 400.string
Filter by the rule’s filing route discriminator. Accepted values:
domestic, madrid_designation. Comma-separated for multiple values.string
Filter by trigger event. Accepted values:
application_publication, registration_publication, international_designation_publication. Comma-separated for multiple values.Response
A standard list response withdata: OppositionRule[]. The corpus is small and returned in a single page. This endpoint is publicly cacheable, so the response never includes request_id.
string
Always
listobject[]
Show OppositionRule
Show OppositionRule
string
Always
opposition_rulestring
Stable, permanent slug identifying this rule, e.g.
eu_opposition_madrid. Once published a slug is never renamed or repointed, so it is safe to persist and to join against rule_id on Compute Oppositions items, trademark derived.opposition_window, and watch diagnostics. Treat it as opaque: the slug looks parseable but its grammar is not part of the contract, so compare it for equality and nothing else. It is deliberately not a prefixed entity ID (tm_, own_) because it names a statutory rule, not a stored entity.string | null
Earliest date from which this rule’s modelled content is authoritative, as
YYYY-MM-DD. null when the source corpus does not establish one, which is the common case. Related to but not the same as applicable_from_date: applicable_from_date is the statutory commencement the engine gates on, so a publication dated before it yields no window at all rather than a different rule’s window, while effective_from is a statement about the modelling. (Rule lookup is a single match on office plus filing route, so there is never an alternate era rule to fall back to; where a window length changes over time, that variation is modelled inside the one rule rather than by a second rule.) Where a rule carries a cutover the two agree: in the current opposition corpus every non-null effective_from equals its rule’s applicable_from_date, and every rule without a cutover reports effective_from: null.string
Date Signa last checked this rule against its statutory sources, as
YYYY-MM-DD. This is the same value the compute endpoint returns as rule_version; it moves on a verification pass even when nothing about the rule changed.string
Jurisdiction (uppercase ISO-2)
string
Uppercase ST.3 office code (e.g.
US, EM, CA). Always present. This is the join key back to Compute Oppositions, which reports the same code, and it is what ?office= accepts. It covers every office in the corpus, including the ones Signa models for rules but does not yet ingest a register from (JP, IN, TR, KR, CN, BX, DK, FI, PL, TH, VN, PH, IS). Before 23 September 2026 this catalog served those offices as null, and they could not be filtered on.string
Either
domestic or madrid_designationstring
Which event starts the opposition clock:
application_publication, registration_publication, or international_designation_publicationinteger | null
Window duration in months (
null when expressed in days)integer | null
Window duration in days (
null when expressed in months)integer | null
Months to wait after publication before the window opens (e.g. EUIPO Madrid-EU has 1 month between Bulletin Part M republication and window opening)
string
Where the clock starts:
date_of_publication (day zero is the publication day), day_after (the publication day is not counted), or first_of_following_month (the window opens on the first day of the month AFTER the publication month: how several offices draft the window against a WIPO Gazette issue, which carries a month rather than a service date)string | null
How the close is derived when the current era opens on
first_of_following_month with a window expressed in months; null for every other rule, where the close is anchored on the publication day-number instead. It is also null for a rule that only opens that way in its EARLIER era, which reports the convention under window_ends_on_before. corresponding_day_of_start means the period ends on the same-numbered day of the Nth month (a window opening 1 August with window_months: 3 closes 1 November); day_before_corresponding_day_of_start means it ends the day before, i.e. on the last day of the Nth month (31 October). Both are real statutory readings and they differ by exactly one day, so the field says which one the office applies rather than defaulting.string | null
Date this rule changed regime, as
YYYY-MM-DD. Half-open: a publication strictly before it is governed by the four _before fields below, one on or after it by the current-era fields. null when the rule has never changed, which is most of them. One rule (tr_opposition) compares the FILING date against this boundary rather than the publication date, under its transitional provision, so pass filing_date to Compute Opposition Windows to get that reading.Not every window_change_date is a statutory date. Most are: the day the instrument itself says the new regime starts. A few are serving pivots, set earlier than commencement on purpose because the statute left a straddling cohort unaddressed and Signa publishes the shorter of the two possible windows. cn_opposition is the current example. China’s 2026 Trademark Law cuts the window from three months to two and commences on 1 January 2027, but says nothing about a period already running that day, so window_change_date is 2026-10-01, the first publication whose three months would still be open at commencement. Every publication from that day is served two months. A close published too early costs a would-be opponent nothing they can lose by relying on it; one published too late costs the right itself. Read a window_change_date that precedes the cited instrument’s commencement as a conservative serving choice, not as a claim about when the law changed, and re-check it once the office publishes its transitional guidance.string | null
Which date of the mark is compared against
window_change_date to decide the era: publication_date or filing_date. null exactly when window_change_date is null.Almost every rule compares the publication date the window runs from, and for those this field is publication_date and can be ignored. tr_opposition is the exception and the reason the field exists: SMK geçici m. 1/1 concludes an application filed before the SMK was published under the law in force on its filing date, so a mark filed under KHK 556 but published after 10 January 2017 keeps the older three-month window rather than the current two-month one. Reproducing that from window_change_date alone gives an answer two months short on exactly the straddling applications a practitioner is most likely to check by hand. Pass filing_date to Compute Oppositions and the engine applies it for you; when no filing date is supplied it falls back to the publication date, i.e. the shorter modern window, which is never later than the filing-keyed answer.string | null
window_starts_on for publications before window_change_date, when the change moved the start. null when the change moved only the length, or when there is no change, in which case window_starts_on governs both eras. bx_opposition is the example: it ran from the first of the following month until 30 September 2013 and from the publication day itself thereafter.integer | null
window_months for publications before window_change_date. null when the earlier era counted in days, when only the start convention changed, or when there is no change.integer | null
window_days for publications before window_change_date. Exactly one of window_months_before / window_days_before is non-null when the change moved the length, and a change may switch units: kr_opposition went from two months to 30 days on 22 July 2025.string | null
window_ends_on for the earlier era, when THAT era opens on the first of the following month with a month-based window. bx_opposition reports corresponding_day_of_start here and null in window_ends_on.string
What a month-counted close date does when the publication’s day number does not exist in the target month.
last_day clamps to that month’s last day, which is what every office except Mexico does and is the value returned for them. first_business_day_of_following_month runs the period into the next calendar month and ends it on that month’s first business day: an MX application published 31 March 2026 closes 4 May 2026, not 30 April (Reglamento LPI art. 4o, párrafo segundo, read together with holiday_calendar for the business-day half). Only mx_opposition returns it today, and it never applies to a window expressed in days.string
IANA office time zone (display only; date math uses calendar dates)
string | null
Holiday calendar key used for close-date rollover, e.g.
uspto_dcobject | null
string | null
Date the office changed its common-extension benchmark, as
YYYY-MM-DD. Exclusive upper bound of the earlier era: a window whose served window_closes falls strictly before it was benchmarked at common_extension_before; every other window, and a window with no publication date, at common_extension. null when the benchmark has never changed.The close date is the anchor because a non-retroactive extension request is received no later than the deadline it extends, so a window that closed before the change can only have been extended under the old benchmark. This is advisory only: the pivot never moves window_closes or a computed must_act_by. Two rules carry one today. ca_opposition: CIPO’s TMOB benchmark first extension went from four months to two on 1 December 2023, so the catalog used to show 2 for every window while Compute Oppositions correctly returned four months for a 2022 close. ph_opposition: IPOPHL MC 2022-013 replaced up to three 30-day extensions with a single 45-day extension on 30 June 2022.object | null
The
common_extension that applied before extension_change_date, in the same shape. Set together with it, and null whenever it is null.string | null
Statutory commencement this rule is gated on. A publication before this date yields no window at all —
supported: false on Compute Oppositions — not a different rule’s window: lookup is a single match on office + filing route. null means the rule has no commencement gate and always applies.boolean
Always
falseobject
Standard pagination envelope (
cursor: null){
"object": "list",
"data": [
{
"object": "opposition_rule",
"rule_id": "eu_opposition_madrid",
"effective_from": null,
"last_verified": "2026-05-06",
"jurisdiction_code": "EU",
"office_code": "EM",
"filing_route": "madrid_designation",
"trigger_event": "international_designation_publication",
"window_months": 3,
"window_days": null,
"window_starts_offset_months": 1,
"window_starts_on": "date_of_publication",
"window_ends_on": null,
"window_change_date": null,
"window_starts_on_before": null,
"window_months_before": null,
"window_days_before": null,
"window_ends_on_before": null,
"month_end_overflow": "last_day",
"office_time_zone": "Europe/Madrid",
"holiday_calendar": "euipo_alicante",
"common_extension": null,
"applicable_from_date": null,
"sources": [
{
"citation": "Article 196(2) EUTMR (Regulation (EU) 2017/1001) — opposition to IRs designating EU; period of three months begins one month after the publication pursuant to Article 190(1)",
"url": "https://eur-lex.europa.eu/eli/reg/2017/1001/oj/eng"
},
{
"citation": "Article 190(1) EUTMR — EUIPO republication in EUTM Bulletin Part M",
"url": "https://eur-lex.europa.eu/eli/reg/2017/1001/oj/eng"
},
{
"citation": "Article 67 Commission Delegated Regulation (EU) 2018/625",
"url": "https://eur-lex.europa.eu/eli/reg_del/2018/625/oj"
},
{
"citation": "Article 69 Commission Delegated Regulation (EU) 2018/625",
"url": "https://eur-lex.europa.eu/eli/reg_del/2018/625/oj"
}
]
}
],
"has_more": false,
"pagination": { "cursor": null }
}
Code Examples
curl "https://api.signa.so/v1/opposition-rules?office=EM&filing_route=madrid_designation" \
-H "Authorization: Bearer sig_YOUR_KEY"
import { Signa } from "@signa-so/sdk";
const signa = new Signa({ api_key: process.env.SIGNA_API_KEY });
const rules = await signa.references.oppositionRules({ office: "EM", filing_route: "madrid_designation" });
for (const rule of rules.data) {
console.log(rule.office_code, rule.filing_route, rule.window_months);
}
Errors
| Status | Type | Description |
|---|---|---|
| 400 | validation_error | Invalid filing_route or trigger_event value |
| 401 | unauthorized | Missing or invalid API key |
| 403 | forbidden | API key missing the trademarks:read scope |
| 429 | rate_limited | Too many requests |
Related Endpoints
- Compute Oppositions, compute per-publication opposition windows from these rules
- List Deadline Rules, maintenance deadline rules (renewals, declarations)
- List Offices, office overview