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
]
}
}
]
}
'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]
}
}
] }
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]
}
}
]
})
};
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
]
]
]
]
]),
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 }\n }\n ]\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 }\n }\n ]\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 }\n }\n ]\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
]
}
}
]
}
'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]
}
}
] }
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]
}
}
]
})
};
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
]
]
]
]
]),
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 }\n }\n ]\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 }\n }\n ]\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 }\n }\n ]\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"
}
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.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.
integer[]
Nice class numbers. Compared as a set.
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.
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.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"
}
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);
}
Errors
| Status | Type | Description |
|---|---|---|
| 400 | validation_error | Malformed body, missing identifier, empty your_fields, invalid date format, 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 100 items. The error carries item_count and item_count_limit |
| 429 | rate_limited | Too many requests |
Related Endpoints
- Batch Get Trademarks, hydrate known IDs or office-native identifiers
- List Trademarks, search the normalized register
⌘I