Office Analytics
curl --request GET \
--url https://api.signa.so/v1/analytics/offices/{code} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.signa.so/v1/analytics/offices/{code}"
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/analytics/offices/{code}', 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/analytics/offices/{code}",
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/analytics/offices/{code}"
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/analytics/offices/{code}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/analytics/offices/{code}")
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": "office_analytics",
"code": "US",
"total_marks": 8000000,
"registered_count": 4800000,
"pending_count": 900000,
"expired_count": 1200000,
"cancelled_count": 500000,
"abandoned_count": 550000,
"unknown_count": 50000,
"registration_rate": 0.8125,
"jurisdiction_count": 1,
"earliest_filing_date": "1870-01-01",
"latest_filing_date": "2026-07-11",
"top_classes": [
{
"class": 9,
"count": 700000,
"pct": 0.088
}
],
"yearly_trend": [
{
"year": 2025,
"filed": 410000,
"registered": 280000,
"abandoned": 35000
}
],
"stats_computed_at": "2026-07-12T00:00:00.000Z",
"request_id": "req_example"
}
Filing Analytics
Office Analytics
GET
/
v1
/
analytics
/
offices
/
{code}
Office Analytics
curl --request GET \
--url https://api.signa.so/v1/analytics/offices/{code} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.signa.so/v1/analytics/offices/{code}"
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/analytics/offices/{code}', 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/analytics/offices/{code}",
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/analytics/offices/{code}"
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/analytics/offices/{code}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.signa.so/v1/analytics/offices/{code}")
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": "office_analytics",
"code": "US",
"total_marks": 8000000,
"registered_count": 4800000,
"pending_count": 900000,
"expired_count": 1200000,
"cancelled_count": 500000,
"abandoned_count": 550000,
"unknown_count": 50000,
"registration_rate": 0.8125,
"jurisdiction_count": 1,
"earliest_filing_date": "1870-01-01",
"latest_filing_date": "2026-07-11",
"top_classes": [
{
"class": 9,
"count": 700000,
"pct": 0.088
}
],
"yearly_trend": [
{
"year": 2025,
"filed": 410000,
"registered": 280000,
"abandoned": 35000
}
],
"stats_computed_at": "2026-07-12T00:00:00.000Z",
"request_id": "req_example"
}
Credits: 100 per request.
Use this endpoint to benchmark one office by registration rate, leading Nice classes, and yearly filing trend. Office codes are uppercase ST.3 (legacy lowercase codes are accepted as permanent aliases).
string
required
Uppercase ST.3 office code, for example
US.Code Examples
curl https://api.signa.so/v1/analytics/offices/US \
-H "Authorization: Bearer sig_YOUR_KEY"
import { Signa } from "@signa-so/sdk";
const signa = new Signa({ api_key: process.env.SIGNA_API_KEY });
const office = await signa.analytics.office("US");
console.log(office.total_marks, office.registration_rate);
Response
number
Trademark records at the office. Every office record counts: a Madrid international registration counts for its own record, for each designation record, and again for any national office’s own record of a designation (for example a USPTO 79-series record), so the
WO counts are records, not international registrations, and a national office’s counts include its records of Madrid designations.number
Records per status bucket. Every status stage falls in exactly one bucket:
pending is every stage before registration (opposition_period included), registered includes pending_cancellation (the mark stays on the register until the cancellation is decided), cancelled includes surrendered and invalidated, and abandoned includes withdrawn and refused. unknown_count holds the records whose status stage is unknown, so the six counts sum to total_marks.number | null
Share of concluded matters that reached registration. Not reliable for
GB: the UKIPO source leaves out most abandoned applications, so the rate reads close to 1.array<{ class: number; count: number; pct: number }> | null
The ten most frequent Nice classes.
count counts class assignments, so a record in three classes counts once in each, and pct is the class’s share of all the office’s class assignments, not the share of its records.array<{ year: number; filed: number; registered: number; abandoned: number }> | null
One row per filing year, in trademark records like
total_marks. filed counts the records filed that year; registered and abandoned count how many of those records are in that status bucket now, not what happened during the year. The current year is partial.string
When these figures were computed. Office figures are recomputed nightly.
{
"object": "office_analytics",
"code": "US",
"total_marks": 8000000,
"registered_count": 4800000,
"pending_count": 900000,
"expired_count": 1200000,
"cancelled_count": 500000,
"abandoned_count": 550000,
"unknown_count": 50000,
"registration_rate": 0.8125,
"jurisdiction_count": 1,
"earliest_filing_date": "1870-01-01",
"latest_filing_date": "2026-07-11",
"top_classes": [
{
"class": 9,
"count": 700000,
"pct": 0.088
}
],
"yearly_trend": [
{
"year": 2025,
"filed": 410000,
"registered": 280000,
"abandoned": 35000
}
],
"stats_computed_at": "2026-07-12T00:00:00.000Z",
"request_id": "req_example"
}