Reconcile
curl --request POST \
--url https://api.signa.so/v1/reconcile \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"items": [
{
"office": "<string>",
"application_number": "<string>",
"registration_number": "<string>",
"your_fields": {
"status": "<string>",
"owner_name": "<string>",
"mark_text": "<string>",
"filing_date": "<string>",
"registration_date": "<string>",
"expiry_date": "<string>",
"renewal_due_date": "<string>",
"registration_number": "<string>",
"nice_classes": [
123
],
"docketed_deadlines": [
{
"type": "<string>",
"date": "<string>"
}
]
}
}
],
"verdict_detail": true
}
'import requests
url = "https://api.signa.so/v1/reconcile"
payload = {
"items": [
{
"office": "<string>",
"application_number": "<string>",
"registration_number": "<string>",
"your_fields": {
"status": "<string>",
"owner_name": "<string>",
"mark_text": "<string>",
"filing_date": "<string>",
"registration_date": "<string>",
"expiry_date": "<string>",
"renewal_due_date": "<string>",
"registration_number": "<string>",
"nice_classes": [123],
"docketed_deadlines": [
{
"type": "<string>",
"date": "<string>"
}
]
}
}
],
"verdict_detail": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
items: [
{
office: '<string>',
application_number: '<string>',
registration_number: '<string>',
your_fields: {
status: '<string>',
owner_name: '<string>',
mark_text: '<string>',
filing_date: '<string>',
registration_date: '<string>',
expiry_date: '<string>',
renewal_due_date: '<string>',
registration_number: '<string>',
nice_classes: [123],
docketed_deadlines: [{type: '<string>', date: '<string>'}]
}
}
],
verdict_detail: true
})
};
fetch('https://api.signa.so/v1/reconcile', 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/reconcile",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'items' => [
[
'office' => '<string>',
'application_number' => '<string>',
'registration_number' => '<string>',
'your_fields' => [
'status' => '<string>',
'owner_name' => '<string>',
'mark_text' => '<string>',
'filing_date' => '<string>',
'registration_date' => '<string>',
'expiry_date' => '<string>',
'renewal_due_date' => '<string>',
'registration_number' => '<string>',
'nice_classes' => [
123
],
'docketed_deadlines' => [
[
'type' => '<string>',
'date' => '<string>'
]
]
]
]
],
'verdict_detail' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/reconcile"
payload := strings.NewReader("{\n \"items\": [\n {\n \"office\": \"<string>\",\n \"application_number\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"your_fields\": {\n \"status\": \"<string>\",\n \"owner_name\": \"<string>\",\n \"mark_text\": \"<string>\",\n \"filing_date\": \"<string>\",\n \"registration_date\": \"<string>\",\n \"expiry_date\": \"<string>\",\n \"renewal_due_date\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"nice_classes\": [\n 123\n ],\n \"docketed_deadlines\": [\n {\n \"type\": \"<string>\",\n \"date\": \"<string>\"\n }\n ]\n }\n }\n ],\n \"verdict_detail\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.signa.so/v1/reconcile")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"items\": [\n {\n \"office\": \"<string>\",\n \"application_number\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"your_fields\": {\n \"status\": \"<string>\",\n \"owner_name\": \"<string>\",\n \"mark_text\": \"<string>\",\n \"filing_date\": \"<string>\",\n \"registration_date\": \"<string>\",\n \"expiry_date\": \"<string>\",\n \"renewal_due_date\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"nice_classes\": [\n 123\n ],\n \"docketed_deadlines\": [\n {\n \"type\": \"<string>\",\n \"date\": \"<string>\"\n }\n ]\n }\n }\n ],\n \"verdict_detail\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/reconcile")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"items\": [\n {\n \"office\": \"<string>\",\n \"application_number\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"your_fields\": {\n \"status\": \"<string>\",\n \"owner_name\": \"<string>\",\n \"mark_text\": \"<string>\",\n \"filing_date\": \"<string>\",\n \"registration_date\": \"<string>\",\n \"expiry_date\": \"<string>\",\n \"renewal_due_date\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"nice_classes\": [\n 123\n ],\n \"docketed_deadlines\": [\n {\n \"type\": \"<string>\",\n \"date\": \"<string>\"\n }\n ]\n }\n }\n ],\n \"verdict_detail\": true\n}"
response = http.request(request)
puts response.read_body{
"object": "list",
"data": [
{
"object": "reconciliation",
"office": "US",
"application_number": "88123456",
"registration_number": null,
"result": "mismatch",
"trademark_id": "tm_8kLm2nPq",
"register_last_updated_at": "2026-07-05T12:00:00.000Z",
"fields": [
{
"field": "status",
"your_value": "active",
"register_value": "active",
"match": true
},
{
"field": "owner_name",
"your_value": "Nike, Inc.",
"register_value": "Nike Innovate C.V.",
"match": false
}
],
"mismatch_count": 1
}
],
"has_more": false,
"pagination": { "cursor": null },
"request_id": "req_bT9kM3nP"
}
Reconcile
Reconcile
Diff your trademark records against Signa’s register data
POST
/
v1
/
reconcile
Reconcile
curl --request POST \
--url https://api.signa.so/v1/reconcile \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"items": [
{
"office": "<string>",
"application_number": "<string>",
"registration_number": "<string>",
"your_fields": {
"status": "<string>",
"owner_name": "<string>",
"mark_text": "<string>",
"filing_date": "<string>",
"registration_date": "<string>",
"expiry_date": "<string>",
"renewal_due_date": "<string>",
"registration_number": "<string>",
"nice_classes": [
123
],
"docketed_deadlines": [
{
"type": "<string>",
"date": "<string>"
}
]
}
}
],
"verdict_detail": true
}
'import requests
url = "https://api.signa.so/v1/reconcile"
payload = {
"items": [
{
"office": "<string>",
"application_number": "<string>",
"registration_number": "<string>",
"your_fields": {
"status": "<string>",
"owner_name": "<string>",
"mark_text": "<string>",
"filing_date": "<string>",
"registration_date": "<string>",
"expiry_date": "<string>",
"renewal_due_date": "<string>",
"registration_number": "<string>",
"nice_classes": [123],
"docketed_deadlines": [
{
"type": "<string>",
"date": "<string>"
}
]
}
}
],
"verdict_detail": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
items: [
{
office: '<string>',
application_number: '<string>',
registration_number: '<string>',
your_fields: {
status: '<string>',
owner_name: '<string>',
mark_text: '<string>',
filing_date: '<string>',
registration_date: '<string>',
expiry_date: '<string>',
renewal_due_date: '<string>',
registration_number: '<string>',
nice_classes: [123],
docketed_deadlines: [{type: '<string>', date: '<string>'}]
}
}
],
verdict_detail: true
})
};
fetch('https://api.signa.so/v1/reconcile', 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/reconcile",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'items' => [
[
'office' => '<string>',
'application_number' => '<string>',
'registration_number' => '<string>',
'your_fields' => [
'status' => '<string>',
'owner_name' => '<string>',
'mark_text' => '<string>',
'filing_date' => '<string>',
'registration_date' => '<string>',
'expiry_date' => '<string>',
'renewal_due_date' => '<string>',
'registration_number' => '<string>',
'nice_classes' => [
123
],
'docketed_deadlines' => [
[
'type' => '<string>',
'date' => '<string>'
]
]
]
]
],
'verdict_detail' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.signa.so/v1/reconcile"
payload := strings.NewReader("{\n \"items\": [\n {\n \"office\": \"<string>\",\n \"application_number\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"your_fields\": {\n \"status\": \"<string>\",\n \"owner_name\": \"<string>\",\n \"mark_text\": \"<string>\",\n \"filing_date\": \"<string>\",\n \"registration_date\": \"<string>\",\n \"expiry_date\": \"<string>\",\n \"renewal_due_date\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"nice_classes\": [\n 123\n ],\n \"docketed_deadlines\": [\n {\n \"type\": \"<string>\",\n \"date\": \"<string>\"\n }\n ]\n }\n }\n ],\n \"verdict_detail\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.signa.so/v1/reconcile")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"items\": [\n {\n \"office\": \"<string>\",\n \"application_number\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"your_fields\": {\n \"status\": \"<string>\",\n \"owner_name\": \"<string>\",\n \"mark_text\": \"<string>\",\n \"filing_date\": \"<string>\",\n \"registration_date\": \"<string>\",\n \"expiry_date\": \"<string>\",\n \"renewal_due_date\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"nice_classes\": [\n 123\n ],\n \"docketed_deadlines\": [\n {\n \"type\": \"<string>\",\n \"date\": \"<string>\"\n }\n ]\n }\n }\n ],\n \"verdict_detail\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/reconcile")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"items\": [\n {\n \"office\": \"<string>\",\n \"application_number\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"your_fields\": {\n \"status\": \"<string>\",\n \"owner_name\": \"<string>\",\n \"mark_text\": \"<string>\",\n \"filing_date\": \"<string>\",\n \"registration_date\": \"<string>\",\n \"expiry_date\": \"<string>\",\n \"renewal_due_date\": \"<string>\",\n \"registration_number\": \"<string>\",\n \"nice_classes\": [\n 123\n ],\n \"docketed_deadlines\": [\n {\n \"type\": \"<string>\",\n \"date\": \"<string>\"\n }\n ]\n }\n }\n ],\n \"verdict_detail\": true\n}"
response = http.request(request)
puts response.read_body{
"object": "list",
"data": [
{
"object": "reconciliation",
"office": "US",
"application_number": "88123456",
"registration_number": null,
"result": "mismatch",
"trademark_id": "tm_8kLm2nPq",
"register_last_updated_at": "2026-07-05T12:00:00.000Z",
"fields": [
{
"field": "status",
"your_value": "active",
"register_value": "active",
"match": true
},
{
"field": "owner_name",
"your_value": "Nike, Inc.",
"register_value": "Nike Innovate C.V.",
"match": false
}
],
"mismatch_count": 1
}
],
"has_more": false,
"pagination": { "cursor": null },
"request_id": "req_bT9kM3nP"
}
Credits: 1 per item.
Three-source verdicts (
Send
Each A docketed-only request always reads
Send a
When the computed side produced nothing,
Two behaviors worth knowing:
Overview
Compare the trademark records you already hold against Signa’s register data and get a field-by-field diff back. Nothing is stored. Records drift from the register over time: statuses change, owners change, registration numbers get assigned, and renewal dates move. Send the fields you have and Signa tells you, per record and per field, exactly where you still match the register and where you’ve fallen out of sync. Use it to surface exceptions, run scheduled drift checks, or audit a book of matters during onboarding. Records that aren’t found, or that match more than one register entry, come back as per-item outcomes in the response, never a request-level error.Request Body
object[]
required
Records to reconcile, max 100 items. Results are returned in the same order, with one
reconciliation per input item.Show Item object
Show Item object
string
required
Uppercase ST.3 trademark office code, e.g.
US, EM, or CA. Legacy lowercase codes (e.g. uspto, and eu for EUIPO) are accepted as permanent aliases.string
Office-native application number. Provide at least one of
application_number or registration_number.string
Office-native registration number. Provide at least one of
application_number or registration_number. For a Madrid record (an international registration or a designation of one), the zero-padded and WO-prefixed forms of the number also match: 921642, 0921642 and WO921642 all find IR 921642. With office WO, the international registration itself answers, not the WIPO-published designation records that carry the same number. A national record’s number matches exactly.object
required
Fields from your system to compare. Must include at least one key and rejects unknown keys.
Show your_fields
Show your_fields
string
Caller status value. Primary statuses compare against
status_primary; stage statuses compare against status_stage; unknown values are reported as mismatches.string
Owner name from your system. Compared with normalized legal suffix, punctuation, case, and diacritic folding.
string
Mark text from your system. Compared case-insensitively with collapsed whitespace.
string
Filing date as
YYYY-MM-DD.string
Registration date as
YYYY-MM-DD.string
Expiry date as
YYYY-MM-DD.string
Renewal due date as
YYYY-MM-DD.string
Registration number to compare against the register value, the number as the office publishes it. For an international registration that is the bare IR number (
921642). On a Madrid record the zero-padded and WO-prefixed forms (0921642, WO921642) compare as the same number; a national number compares exactly.integer[]
Nice class numbers. Compared as a set.
object[]
Your docketed maintenance deadlines for this mark, 1 to 10 entries. Requires
verdict_detail: true. Each entry produces its own field_verdicts[] row and is matched independently against the computed schedule.Show Docketed deadline
Show Docketed deadline
boolean
default:"false"
Opt in to the three-source per-field verdict. Each found item gains
field_verdicts[], a computed context block and a lookup echo. Everything v1 is unchanged: fields[], result, mismatch_count, and billing are identical with the flag on and off. Required to send your_fields.docketed_deadlines.Response
A standard list response withdata: Reconciliation[]. Pagination is not used; data[i] corresponds to items[i].
string
Always
list.object[]
Show Reconciliation
Show Reconciliation
string
Always
reconciliation.string
Office used for lookup.
string | null
Application number supplied on the input item, or
null.string | null
Registration number supplied on the input item, or
null.string
One of
match, mismatch, not_found, or ambiguous.string | null
Signa trademark ID (
tm_*) when exactly one register record resolved.string | null
Register record update timestamp as ISO 8601, or
null when unresolved.object[]
Show ReconcileFieldDiff
Show ReconcileFieldDiff
string
Compared field:
status, owner_name, mark_text, filing_date, registration_date, expiry_date, renewal_due_date, registration_number, or nice_classes.string | integer[]
Value supplied in
your_fields.string | integer[] | null
Normalized register value compared against your value.
expiry_date and renewal_due_date are the dates the office published, or null when it published none: a date Signa derived is never reported as the register’s, for any office (with verdict_detail: true, Signa’s own date is computed_value). For an international registration (Madrid IR record), expiry_date is the expiry WIPO published for the registration.boolean
Whether the field matched after field-specific normalization.
integer
Number of
fields[] entries where match is false.integer
Present only when
result is ambiguous. The lookup stops as soon as a second register record matches, so the value is always 2. It signals “more than one match”, not an exact count.object
Present only when
verdict_detail: true. How your identifiers were interpreted: office (resolved ST.3 code), office_input (the token you sent, verbatim), application_number and registration_number (the values used in the lookup), matched_on (application_number, registration_number, or both), and identifier_normalization. Present on every item, including not_found and ambiguous, where it is most useful.object
Present only when
verdict_detail: true and the record was found. The computed-schedule context: jurisdiction_code, filing_route (national, regional, or madrid), supported, reason (unsupported_jurisdiction, requires_office_date, or null; was unsupported_reason), sources (statutory citations), as_of, computed_at, horizon_years, and unsupported_rules: the rules that apply to the record but were declined because it lacks the date the statute anchors them on, each with rule_id, reason (requires_office_date), missing_field and consequence_if_missed, as on Compute Deadlines with include_missed: true, since reconcile reads missed cycles too: an expired or cancelled record with no registration date names (or, when nothing else anchors, declines as a whole for) the rules whose missed cycles it cannot date. unsupported_rules is [] when nothing was declined and when supported is false.object[]
Present only when
verdict_detail: true. One three-source verdict per field you supplied. See Three-source verdicts below.object
Present only when
verdict_detail: true. Totals over field_verdicts[] with every verdict key explicit, zeros included: agrees, caller_differs, register_differs_from_computed, all_differ, unsupported_jurisdiction, insufficient_data, not_computable.boolean
Always
false.object
Always
{ "cursor": null }.string
Unique request identifier for support and debugging.
not_found is soft: the request still returns HTTP 200, with result: "not_found" for that item and an empty fields array. ambiguous means the identifier lookup resolved to more than one register record, such as an (office, application_number) pair that is not unique; Signa does not silently choose one.
{
"object": "list",
"data": [
{
"object": "reconciliation",
"office": "US",
"application_number": "88123456",
"registration_number": null,
"result": "mismatch",
"trademark_id": "tm_8kLm2nPq",
"register_last_updated_at": "2026-07-05T12:00:00.000Z",
"fields": [
{
"field": "status",
"your_value": "active",
"register_value": "active",
"match": true
},
{
"field": "owner_name",
"your_value": "Nike, Inc.",
"register_value": "Nike Innovate C.V.",
"match": false
}
],
"mismatch_count": 1
}
],
"has_more": false,
"pagination": { "cursor": null },
"request_id": "req_bT9kM3nP"
}
Three-source verdicts (verdict_detail)
Send verdict_detail: true to turn a drift check into a docket audit. For every field you supply, Signa compares three sources: your value, the register’s value, and the value Signa’s deadline rulebook computes for the same mark (the same computation GET /v1/trademarks/{id} serves under derived.deadlines, with missed obligations included and a 10-year horizon that extends per record, up to 20 years, so the schedule always reaches the register’s stated expiry).
Enabling the flag changes nothing you already rely on.
fields[], result and mismatch_count are byte-identical with the flag on and off, and billing is unchanged (1 credit per item). A verdict where you are right and the register or the rulebook disagrees never flips result to mismatch.field_verdicts[] entry carries field, your_value, register_value, computed_value, basis, verdict, computed_unavailable_reason, and computed_provenance (the rule_id, effective_from, last_verified, due_date_adjustment, grace_expiry_adjustment and holiday_calendar behind the computed date, spelled exactly as the deadlines API spells them). Rows for docketed_deadlines entries use field: "docketed_deadline" with sibling deadline_type and index (your array position); both are null on the nine standard field rows.
For expiry_date, computed_value is the term end before any weekend or holiday roll, the same date derived.expiry_date serves. For renewal_due_date and docketed deadlines it is the due date after the roll, the date the office accepts a filing on. A value on either date counts as agreement.
A docketed-only request always reads match
Send a your_fields that contains only docketed_deadlines and the item comes back with result: "match", an empty fields[] and mismatch_count: 0. That is the designed outcome. v1 semantics are frozen: result, fields[] and mismatch_count describe the nine standard fields and nothing else, so a docketed deadline can never move any of them.
The audit you asked for lives exclusively in field_verdicts[] and verdict_counts{}, with one row per deadline you sent. Read the verdicts rather than result.
basis: which sources answered
basis | Register produced a value | Computed produced a value |
|---|---|---|
register_and_computed | yes | yes |
register | yes | no |
computed | no | yes |
none | no | no |
computed_unavailable_reason says why: not_modelled (the rulebook has no concept of this field, true for everything except expiry_date, renewal_due_date and docketed deadlines), unsupported_jurisdiction (no rulebook coverage for this record’s jurisdiction and route), or insufficient_data (coverage exists but the record lacks the statutory input, or no matching obligation was emitted).
The seven verdicts
verdict | Reading |
|---|---|
agrees | Every source that could answer agrees with you |
caller_differs | The sources that answered agree with each other and you are the outlier |
register_differs_from_computed | The office and Signa’s rules disagree; you match one of them. Both values are returned and you decide which to trust |
all_differ | Three distinct values. The highest-signal cell in a docket audit |
unsupported_jurisdiction | No rulebook coverage, and the register column is also empty, so nothing could be compared |
insufficient_data | Coverage exists but the computation declined or found no matching obligation, and the register column is also empty |
not_computable | No source could answer: the register column is empty and the rulebook does not model the field |
unsupported_jurisdictionandinsufficient_dataare verdicts only when the register is also silent. When the register did answer, the verdict describes that comparison (agreesorcaller_differs) and the computed-side gap is reported oncomputed_unavailable_reasoninstead. Nothing is hidden; the verdict names the comparison that actually happened.not_computablealso fires for a register-only field whose column is empty, for examplemark_texton a device mark.
How the computed value is chosen
Forexpiry_date and renewal_due_date, the computed counterpart is the mark’s current term end: the earliest computed renewal-family obligation due on or after today, falling back to the most recent past one (the cycle currently in force). The rulebook treats expiry and renewal-due as one date under two names. When the office-stated expiry, its grace period and any restoration window have passed with no renewal on record, no later cycle is computed, so the counterpart is that past term end, the same date as derived.expiry_date (see The term on record).
For docketed_deadlines entries, matching is deliberately about the obligation you docketed: within your entry’s type, the occurrence whose due date is nearest your date wins (ties go to the earlier one). A docketed renewal matches the whole renewal family, including a US combined Section 8 and 9 filing and a WIPO international renewal. The matched rule is echoed in computed_provenance.rule_id so the pairing is checkable.
Identifier matching
lookup.identifier_normalization is none today: the identifiers you send are matched as sent, with no trimming, leading-zero handling or separator stripping, except Madrid registration numbers, which also match the stored WO-prefixed and zero-padded forms (see registration_number above). The echo exists so office-specific normalization can ship later without a shape change. lookup.matched_on shows which identifiers were combined into the lookup, which also explains ambiguous results when you sent both.
Code Examples
curl "https://api.signa.so/v1/reconcile" \
-H "Authorization: Bearer sig_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"office": "US",
"application_number": "88123456",
"your_fields": {
"status": "active",
"owner_name": "Nike, Inc."
}
}
]
}'
import { Signa } from "@signa-so/sdk";
const signa = new Signa({ api_key: process.env.SIGNA_API_KEY });
const results = await signa.reconcile.run({
items: [{ office: "US", application_number: '88123456', your_fields: { status: 'active', owner_name: 'Nike, Inc.' } }]
});
for (const result of results.data) {
console.log(result.result, result.mismatch_count);
}
Related Endpoints
- Batch Retrieve, hydrate known IDs or office-native identifiers
- Search Trademarks, search the normalized register