Pinakel · Trademark Analytics API · v1

Integrator Guide

Aggregate trademark analytics — filing trends, Nice-class distribution, owner and representative leaderboards — computed over our worldwide corpus and served as JSON, so you can build your own dashboards without running a warehouse. Base URL:

https://api.pinakelai.com/analytics

Interactive OpenAPI reference: https://api.pinakelai.com/analytics/docs · machine-readable spec: /openapi.json

Also on this host: /data — per-record trademark search, lookup and change tracking, sold and keyed separately.

Authentication

Every request carries your API key in the X-API-Key header (or as a Bearer token). Keys are scoped per product: a key sold for analytics returns 403 product_not_enabled on the record API, and vice versa. That is a provisioning state, not a bad credential — do not rotate the key; ask us to enable the product.

curl -H "X-API-Key: pk_live_…" \
  "https://api.pinakelai.com/analytics/v1/kpis?jurisdiction=US"

Coverage: read this before you render a number

The corpus is being loaded register by register. Every response carries a coverage block describing exactly what the figures in it were computed over:

{
  "kpis": { … },
  "coverage": {
    "jurisdiction": "US",
    "rows_loaded": 200000,
    "backfill_status": "in_progress",
    "is_sample": true,
    "last_ingested_date": "2026-09-14"
  }
}
When is_sample is true the figures are indicative, not exhaustive — that register is a partial load, so counts are floors and rankings can move as it completes. Surface this in your UI. It is the one error your users cannot detect for themselves, and the only thing we ask of anyone reselling these numbers.

Live from the warehouse — 98 registers, 4,514,223 records, 98 still sampling. This table is generated per-request and never overstates.

registerrecordsbackfillbasis
AD49,134in_progresssample
AE0not_startedsample
AL26,801in_progresssample
AM47,582in_progresssample
AP8,335in_progresssample
AR50,000in_progresssample
AT50,000in_progresssample
AU50,000in_progresssample
BA31,003in_progresssample
BG50,000in_progresssample
BH50,000in_progresssample
BN50,000in_progresssample
BO0not_startedsample
BQ7,727in_progresssample
BR50,000in_progresssample
BT24,447in_progresssample
BX50,000in_progresssample
BY50,000in_progresssample
CA50,000in_progresssample
CH50,000in_progresssample
CL50,000in_progresssample
CN50,000in_progresssample
CO50,000in_progresssample
CR50,000in_progresssample
CU50,000in_progresssample
CY50,000in_progresssample
CZ50,000in_progresssample
DE50,000in_progresssample
DK50,000in_progresssample
DO0not_startedsample
DZ50,000in_progresssample
EC50,000in_progresssample
EE50,000in_progresssample
EG0not_startedsample
EM50,000in_progresssample
ES50,000in_progresssample
FI50,000in_progresssample
FR50,000in_progresssample
GB100,000in_progresssample
GE50,000in_progresssample
HK50,000in_progresssample
HR50,000in_progresssample
HU50,000in_progresssample
ID50,000in_progresssample
IE50,000in_progresssample
IL50,000in_progresssample
IN50,000in_progresssample
IS50,000in_progresssample
IT100,000in_progresssample
JO50,000in_progresssample
JP100,000in_progresssample
KH50,000in_progresssample
KR50,000in_progresssample
KW0not_startedsample
LA50,000in_progresssample
LT50,000in_progresssample
LV50,000in_progresssample
LY28,552in_progresssample
MD50,000in_progresssample
ME19,645in_progresssample
MK42,852in_progresssample
MM20,213in_progresssample
MN50,000in_progresssample
MO50,000in_progresssample
MX50,000in_progresssample
MY50,000in_progresssample
NO50,000in_progresssample
NZ50,000in_progresssample
OA50,000in_progresssample
PA50,000in_progresssample
PG38,465in_progresssample
PH50,000in_progresssample
PL50,000in_progresssample
PT50,000in_progresssample
RO50,000in_progresssample
RS0not_startedsample
RU50,000in_progresssample
SA50,000in_progresssample
SD44,463in_progresssample
SE50,000in_progresssample
SG50,000in_progresssample
SI50,000in_progresssample
SK50,000in_progresssample
SM4,746in_progresssample
SX14,751in_progresssample
TH50,000in_progresssample
TR50,000in_progresssample
TT50,000in_progresssample
TW100,000in_progresssample
UA50,000in_progresssample
UG50,000in_progresssample
US200,000in_progresssample
UY50,000in_progresssample
VN50,000in_progresssample
WO50,000in_progresssample
WS10,756in_progresssample
XK44,751in_progresssample
ZA0not_startedsample

Endpoints

All eight take an optional jurisdiction (a 2–4 letter register code, e.g. US); omit it for every register combined. Leaderboards take limit (1–500). Responses are an envelope: {"items": […], "coverage": {…}}.

GET/v1/jurisdictions

Every register we hold analytics for, with counts and year range. The machine-readable coverage table — poll it to discover what is available as the corpus loads.

GET/v1/kpis

Headline totals for a register or the whole corpus: records, live vs dead, distinct owners, registration rate.

GET/v1/filings-by-year

Filing volume per year, split live vs dead. Optional year_from / year_to (1800–2100).

GET/v1/nice-classes

Distribution of filings across the 45 Nice classes.

GET/v1/top-owners

Largest filers by volume, with their live ratio. limit defaults to 50.

GET/v1/law-firms

Representative leaderboard: volume, success rate, median days to registration, distinct clients. limit defaults to 100.

GET/v1/squatting

Owners matching the squatting heuristic — high volume, low registration rate, filings scattered across unrelated classes. A signal to investigate, not a determination.

GET/v1/collateral

Owners with security interests recorded against their marks.

GET/v1/usage

Your key's own month-to-date call count, quota and rate limit, broken down per product, so you can watch consumption without asking us.

Errors & limits

Every non-2xx response carries one envelope: {"error": {"code": "…", "message": "…", "param": "…"}} — code is the machine-readable contract, param names the offending parameter when one exists.

statuscodemeaning
400invalid_parametermalformed request — the message says exactly what to fix
401unauthorizedmissing or unknown API key
403key_revokedrevoked key
403product_not_enabledvalid key, but it was not sold analytics — do not rotate the key, ask us to enable it
404not_foundno such path — check the /analytics prefix
422query_too_broadthe query would scan more data than the endpoint allows — narrow it with a jurisdiction filter (do not blind-retry)
429rate_limited · quota_exceededper-minute rate or monthly quota — see headers
503unavailabletransient service problem — safe to retry shortly

A rate-limit 429 carries Retry-After and X-RateLimit-Limit / X-RateLimit-Remaining; a quota 429 carries X-Quota-Limit / X-Quota-Used (resets at month end). Requests refused with 429 are never counted against your usage.

Analytics figures are served from pre-computed aggregates and are cached, so repeated identical calls are cheap and fast. Aggregates refresh as backfills land; coverage.last_ingested_date tells you how current a register's numbers are.

Support

Integration questions: support@pinakelai.com · commercial: hello@pinakelai.com