Knockoff Data API v1
Trademark ownership facts for any brand string — who is behind a brand, and whether that operator looks like a real company or a mass trademark filer. Built on the full USPTO corpus (14M marks), refreshed nightly.
Every answer is a set of deterministic facts with receipts (USPTO serial numbers you can verify on TSDR). There is deliberately no 0–100 risk score: you compose your own policy from the variables.
Quickstart
Authenticate with a Bearer key on every request:
curl https://business.knockoff.co/api/v1/brands/tnfeeon \ -H "Authorization: Bearer kd_your_key"
{
"query": "tnfeeon",
"brand_key": "tnfeeon",
"state": "matched",
"mark_status": "live",
"owner_country": "CN",
"entity_age_months": 72,
"ownership_transfers": 0,
"operator_cluster": "Shenzhen Yibai Network Technology Co., Ltd.",
"operator_footprint": {
"owner_name": "Shenzhen Yibai Network Technology Co., Ltd.",
"owner_country": "CN",
"owner_type": "company",
"distinct_brands": 88,
"live_marks": 112,
"total_marks": 120,
"first_filed": "2016-08-30",
"last_filed": "2025-12-02",
"filing_span_years": 9.3,
"mill_filed": true,
"cluster": { "known": true, "size": 25, "basis": "human" },
"confidence": "exact_name",
"alias_count": 1,
"other_candidates": 0
},
"data_coverage": { "marks_matched": 1, "live_marks": 1, "match_basis": ["wordmark"] },
"receipts": [
{ "serial_number": "90070690", "mark_status": "live",
"tsdr_url": "https://tsdr.uspto.gov/#caseNumber=90070690&caseType=SERIAL_NO&searchType=statusSearch" }
]
}
The brand has a live trademark — and its owner holds 88
distinct brands, filed through a high-volume filing attorney, in
a human-reviewed operator cluster spanning 25 brands. Compare a real
company: bombas returns 10 brands over 12.1 years, no mill.
Same fields, opposite read — that contrast is the product.
Endpoints
Facts for one brand string. The key is any raw brand name
(vava, l.l.bean, Fjällräven) —
normalization is ours.
Score up to 100 brands in one call. Body:
{"brands": ["vava", "bombas", …]} →
{"results": [...]} in input order.
Start from a scraped product instead of a brand. Body: one of
brand, title, url (plus optional
marketplace). Parses Amazon/Walmart/eBay/Etsy/Target URLs,
returns the resolution plus the same facts object.
Any URL — marketplace or independent store — also
returns a merchant block (see the field reference).
Response fields
matched the brand's marks trace to one distinct owner. ambiguous several distinct owners use this name; we state the marks but claim no owner. no_record no USPTO mark for this string (itself a signal).
live dead none best status among the matched marks.
Present only when a resolve call's title/URL carried
product context. The brand is ambiguous register-wide
(register_state), but exactly one owner holds its marks
in the queried Nice classes — e.g.
{"classes": ["021"], "context": "cookware", "register_state":
"ambiguous"}. The verdict holds for those classes
only: do not cache or reuse it as an unconditional answer
for the brand.
One operator holds a calibrated supermajority of the
brand's live marks — e.g. {"share": 0.818, "live_marks":
108, "of_live_marks": 132, "other_candidates": [...]} —
and is reported as the owner (when the call carried product context,
only if that operator also holds live marks in the queried classes).
other_candidates discloses every
minority filer by name and live-mark count; weigh them before
treating the owner claim as exclusive.
The seller's identity card, beside the
brand's facts. domain (the merchant's identity key),
platform + platform_confidence
(deterministic = a URL shape the platform doesn't let
merchants change, e.g. Shopify's
/products/{handle}?variant=; heuristic = a
default path shape other platforms can collide with),
trademark_footprint (the store name's own facts object),
and identity_completeness — which card fields are
filled, a coverage statement, never a judgment.
domain_age (months since the domain's
RDAP registration date — young domains are the fly-by-night
signal), legal_entity (the operating entity named on the
site's own legal pages, always with its receipt: {"name",
"source_url", "quote"}), and a confirmed
platform_confidence are filled by async enrichment: the
first resolve of a domain queues it (enrichment:
"queued"), later resolves return the enriched card
("complete", or "failed"). Enriched fields
may be up to 30 days old — a domain is never re-fetched inside
that window.
Present when the URL carries an Amazon seller token
(/sp?seller=, or seller=/smid=
on a product URL): the third-party seller behind the listing.
legal_name, country,
address_present, and
registration_number_present come from the seller's
INFORM Consumers Act disclosure as observed on-page
(captured_at is the receipt; corroborated =
the address was confirmed from ≥2 distinct networks).
entity is the seller's shared-address cluster (how many
storefronts operate from the same address).
trademark_footprint appears only when
the legal name joins a trademark operator under the stated
join_basis (entity_country = distinctive
entity name + matching country — never a bare name match); it
is the seller's own portfolio (distinct_brands,
live_marks, mill_filed). An unknown seller
returns the id with nulls — the miss is recorded and coverage
grows with observation.
Is the seller of record the brand's operator?
sells_direct the seller's disclosed
identity and the brand's resolved owner fold to the same entity
(distinctive entity name + matching country, the same corroboration
bar as join_basis: entity_country), or their registered
aliases share a published operator cluster; the basis
states entity_country or published_cluster.
third_party both identities are comparable
and the entities differ. platform_direct
the marketplace itself is the seller of record (e.g. Amazon retail's
own seller id). unknown nothing provable,
with the reason stated (no_seller_token,
seller_unresolved, brand_owner_unresolved,
identity_not_comparable, or
country_mismatch — a same-named entity in a
different country proves neither sameness nor difference, so it
stays unknown). seller_entity /
brand_entity carry the two compared identities as
receipts. Never a score.
Is the listing what it claims to be? Composed from
crowd-relayed observations (extension sightings, hardened by a
2-network corroboration gate) plus our own reverse-image receipt over
the listing's hero image. status is
observed or the honest no_observation
(coverage is demand-shaped — unseen listings have no data, and
none is invented). claim carries the crowd-corroborated
identity tuple (attribution, ships-from, duties-paid language,
AI-scale flag); hints carries uncorroborated
latest-value numerics (sales, shop age); signals lists
human-checkable reasons with their evidence grade.
receipt is the reverse-image result
(catalog_matches = mass-market catalog twins, always
with caveat: "copy_direction_unverified" — copycat
sites also steal from real artisans). lean is advisory
and watch is its ceiling — “worth a human's
look, here are the receipts” (lean_basis), never a
confident “fake” label. Never a score.
ISO-2 country of the current owner. Only present
when matched — an ambiguous brand never gets an
owner claim.
Months since the earliest real filing among the matched marks.
Recorded sales of the mark (true ownership changes — renames and collateral liens don't count).
Name of a published operator cluster this brand
belongs to. Clusters publish only when public records or calibrated
matching rules clear the measured publication bar; the audit basis
is returned in operator_footprint.cluster.basis.
How many marks matched, how many live, and on what
basis (wordmark / pseudo_mark).
Up to 20 serial numbers with TSDR links — every claim is independently verifiable.
operator_footprint — the operator behind the brand
The current owner's whole-register filing pattern, precomputed nightly over all 14M marks. This is the field that separates a real company from a pseudo-brand operation: pseudo-brands almost all have trademarks — what gives them away is an owner with dozens of unrelated brands filed in bursts, often through a filing mill, often as an individual.
How many distinct brand names this operator holds
across the whole register. The headline: a real brand files a handful
for its own products; a mass operator files dozens. Counted over the
operator's resolved identity — its name variants
folded together (see confidence).
The owner's live and total mark counts.
The owner's filing window. 8 brands across a 4-month burst reads very differently from 10 brands across 12 years.
company individual null from the USPTO legal-entity code; an individual holding many brands is a strong mass-filing signal.
True if any of the owner's marks were filed through a high-volume filing attorney whose book is ≥50% CN/HK owners. Most meaningful for small-footprint owners; a century-old global filer can flag on one mark.
{known, size, basis} — whether
this operator belongs to a published cluster, how many brands it
spans, and its audit trail (record, ai,
human, or mixed). Only returned when
matched.
resolved_entity the
owner's name variants (“Procter & Gamble Company” /
“The Procter and Gamble Co.”) were folded into one
operator, corroborated by a shared country, so the counts are the
operator's true total. exact_name no
variant was found, so the counts are keyed on the single filing
string and are a floor: an operator filing under variants we
couldn't corroborate is undercounted. The fold is a deterministic
name+country match, separate from the published
cluster inference.
How many distinct owner-name strings were folded
into this resolved operator. 1 means none were found (so
the counts equal the exact-name floor); higher means variants were
merged.
On ambiguous brands the footprint shown
is the most prolific candidate owner's; this is how many other
candidates exist. 0 when matched.
Worked example: scoring a search results page
Score a slice of a real Amazon search page in one call:
curl -X POST https://business.knockoff.co/api/v1/batch \ -H "Authorization: Bearer kd_your_key" \ -H "Content-Type: application/json" \ -d '{"brands": ["bombas", "tnfeeon", "jxrev", "zzznotabrand"]}'
| Brand | state | Footprint | Read |
|---|---|---|---|
bombas | matched | US company · 10 brands · 2013→2025 · no mill | Real company. |
tnfeeon | matched | CN company · 88 brands · 2016→2025 · mill | Mass operator. |
jxrev | matched | CN individual · 8 brands · 4-month burst · mill | Spun-up brand swarm. |
zzznotabrand | no_record | null | No trademark at all. |
Every row has (or lacks) receipts you can check on TSDR. Where you set the line — 20 brands? mill + individual? — is your policy; the variables are ours.
Errors & limits
| Status | When |
|---|---|
401 | Missing or invalid API key. |
400 | Missing required parameters (e.g. no
brand/title/url on resolve). |
422 | Batch over 100 items. |
429 | Rate limit exceeded (default 120
requests/min per key) — retry after the
Retry-After seconds. Throttled calls are not
billed. |
Every served query is metered per key, hits and misses alike.
Get a key
Keys are issued by hand while the API is in pilot. Email a line about what you're building; you'll have a key the same day.
Data: USPTO trademark corpus (applications, registrations, assignments), refreshed nightly. Facts are published freely; operator-identity inferences ship only when the evidence clears a measured publication bar.