US trademark search from an AI agent: live, dead and Nice classes
US trademark search from an AI agent: what live and dead mean at the USPTO, how to read Nice classes, and why the search requires every word.
Agents get asked to name things: a product, a company, a feature, an open-source package. The first sanity check is whether someone already holds a US trademark on the name. A person does this on the USPTO's search site, reading status labels and class numbers as they go. An agent needs the same information as structured data, plus enough context to avoid two classic mistakes: treating a dead record as a conflict, and treating a live mark in an unrelated class as a blocker. This article explains the fields, then shows how 402check's us_trademark tool queries the USPTO and why its defaults are what they are.
Live and dead
The USPTO groups trademark statuses as live or dead, plus an "Other" bucket for a status that is uncertain or unknown. Its Common Status Descriptors list the detailed statuses under the two main headings:
- Live application: awaiting examination, under examination, appeal of a refusal pending, published for opposition, or opposition pending.
- Live registration: issued and active, published for opposition, opposition pending, or cancellation or invalidation pending.
- Dead application: refused, dismissed or invalidated, or withdrawn or abandoned by the owner.
- Dead registration: cancelled or invalidated, surrendered by the owner, or expired, which the USPTO describes as "removed from the registry when the registration was not successfully maintained."
The USPTO's own status page uses "active (live)" as one phrase: an abandoned application "won't be active (live)", and a cancelled registration "is no longer active (live)".
For an agent, the practical reading is simple. A live record is a pending or registered mark that the owner is still pursuing or maintaining, and it is the one that matters for a naming decision. A dead record means the application or registration is no longer active at the USPTO. It does not tell you whether anyone still uses the name in commerce, so a dead hit is a reason to look further, not a green light.
That is why us_trademark returns live marks by default. Pass status=dead to see only dead records, or status=all for both.
Nice classes
A trademark is registered for specific goods or services, not for a word in the abstract. Those goods and services are grouped by the Nice Classification, which WIPO describes as two parts: 34 classes of goods and 11 classes of services, 45 classes in total.
The USPTO search backend returns classes as strings like IC 009. We strip the prefix and keep the zero-padded number, so a response carries "classes": ["009"]. One mark can be filed in several classes.
The class list is what turns a raw hit into an answer. Two identical words can be registered by different owners in different classes. An agent naming a software product should look hardest at the classes its product falls into and treat hits elsewhere as context, while a human makes the final call.
What one result looks like
This is the first live mark our test fixture returns for q=acme, complete:
{
"serial": "77724923",
"mark": "ACME",
"owner": "Acme Products Company (CORPORATION; MISSOURI, USA)",
"status": "live",
"filed": "2009-04-29",
"registered": "2010-04-06",
"classes": ["012"],
"url": "https://tsdr.uspto.gov/#caseNumber=77724923&caseType=SERIAL_NO&searchType=statusSearch"
}
The serial number is the stable identifier. registered is null for a mark that was never registered, which is normal for a pending application. owner joins all owner names with ; . The url opens the record in TSDR, the USPTO's status and document system, where a person can read the full file history.
Why the search requires every word
The USPTO's public Trademark Search runs on a JSON search backend. It is undocumented, so we read its request format from the site's own frontend and verified it with live requests. The wordmark field is called WM, and a query is a boolean of two clauses:
src/tools/usTrademark.tsfunction buildBody(query: TrademarkQuery): object {
const should = [
{ match_phrase: { WM: { query: query.q, boost: 5 } } },
{ match: { WM: { query: query.q, operator: query.match === "all" ? "and" : "or", boost: 2 } } },
];
const filter = query.status === "all" ? undefined : [{ term: { alive: query.status === "live" } }];
return {
query: { bool: { should, minimum_should_match: 1, ...(filter && { filter }) } },
size: query.limit,
from: 0,
_source: SOURCE_FIELDS,
};
}
The first clause matches the exact phrase and is weighted highest. The second matches the words in any order. With the default match=all, its operator is and: every word of the query must appear in the mark. With match=any, the operator is or and one shared word is enough.
For a naming check, all is the useful default. Take a candidate like "blue harbor". With any, every mark containing "blue" or "harbor" qualifies, so the few relevant results are buried in noise. With all, you get marks containing both words, with the exact phrase ranked first. Use match=any deliberately, when you want to see how crowded each word is on its own.
Two more details of the query:
statusis applied twice: as a filter in the request, and again on the returned records, so astatus=livecall never returns a dead mark even if the backend ignores the filter. A record without a live/dead flag comes back as"status": "unknown", and only forstatus=all.- The query text travels as a plain JSON string value, never as query syntax, so characters like
*,"orORin a name are searched as text and cannot change the query.
Limits worth stating
- US marks only. No EUIPO or WIPO Madrid data.
- It searches the wordmark text. Marks that sound alike but are spelled differently will not match, and marks that consist only of a design have no wordmark text to match.
- At most 25 marks per call (
limit, default 10). - The backend is undocumented and can change without notice. When it fails or changes shape, the tool answers
502 upstream_errorand the call is not charged.
None of this is a clearance opinion. It is a fast first pass that tells an agent when a name is clearly taken in a relevant class, and when it needs to hand the question to a person.
Try it
A search costs $0.02, and the first 10 calls a day per IP are free with no key:
curl "https://402check.com/v1/us/trademark?q=acme&status=all&limit=5"
# how crowded is each word on its own?
curl "https://402check.com/v1/us/trademark?q=blue+harbor&match=any"
Parameters, the MCP call and a live form are on the us_trademark docs page.