T

USPTO Trademark API

Local Database Portal & API Playground

GET
/v1/trademark/phrase-search/:phrase

Search every contiguous phrase, remove punctuation from comparison text, and return cleaned matches longest-first.

Example Presets: Nike (Exact) Disney (Fulltext) Starbux (Fuzzy Trigram)
Request URL
https://tm.merchdash.net/v1/trademark/phrase-search/Just%20A%20Girl%20Who%20Loves%20School%20Recess
Request JSON Preview
💻

Run a query above to see raw JSON or parsed trademark cards.

1. System Overview

The USPTO Trademark Search API provides a localized, self-hosted search engine indexing millions of historical and daily active trademark filings. Rather than querying the USPTO Open Data Portal directly on every transaction (which is subject to connection limitations and rate throttling), this server aggregates data locally in a PostgreSQL instance optimized for heavy read loads.

It supports both fuzzy trigram searches (for matching spelling mistakes) and standard English full-text indexing, mapping trademark owner coordinates, status revisions, and international trademark classes.

2. System Architecture

The architecture isolates the heavy ingestion loops (the synchronization cron jobs) from the core API routes to prevent query performance degradation during bulk data loads.

Memory Efficiency
The sync engine utilizes the Node.js sax stream processor. Rather than loading massive USPTO files (often exceeding 1.5GB) into RAM, XML contents are parsed sequentially as a text stream, buffering rows in batches of 500. This guarantees a stable memory ceiling of less than 200MB during parser operations.

Key Components

  • Sync Daemons: Multi-threaded nodes that poll and pull ZIP batches.
  • PostgreSQL Database: Houses raw trademark records, indices, processed files records, and authorization keys.
  • API Middleware: Handles IP rate limits via Express and dynamically validates client API keys on the DB.

3. Database Schema

The database structures are optimized to facilitate immediate queries. Indices deploy customized features to accelerate specific route paths.

Index Blueprint

Index Name Type Target Column Purpose
idx_tm_word_mark_trgm GIN (Trigram) word_mark Fuzzy spelling similarity search (% operator)
idx_tm_word_mark_normalized_trgm GIN (Expression Trigram) word_mark Punctuation-insensitive fuzzy spelling similarity search
idx_tm_word_mark_normalized B-Tree (Expression) word_mark Fixed-length normalized fingerprint for punctuation-insensitive phrase matching
idx_tm_word_mark_fts GIN (FTS) word_mark Lexical keyword ranking (to_tsvector)
idx_tm_owner_fts GIN (FTS) owner_name Ranked corporate lookup
idx_tm_goods_services_fts GIN (FTS) goods_services Full-text search inside utility listings
idx_tm_int_class GIN (B-Tree Alternative) international_class Browsing marks in array blocks (e.g. ANY(int_class))
idx_tm_registration_date B-Tree (Descending) registration_date Newest-registration date windows and ordering

Auto-Updated Fields

The schema deploys a PL/pgSQL function trigger update_updated_at() on the trademarks table that updates the updated_at timestamp automatically whenever any upsert triggers a modification.

4. Sync & Ingestion Engine

Synchronization executes sequentially across two datasets:

  1. TRTYRAP (Archives): Large backfiles storing historical filings. These are imported on initial setup.
  2. TRTDXFAP (Daily Incrementals): Daily updates reflecting modifications, new filings, and status changes.
Important: Index Maintenance
Re-indexing a database with 8+ million rows on every INSERT slows ingestion. The system optimizes backfile imports by calling npm run db:optimize-ingest to drop indices prior to the ingestion run, and calling npm run db:restore-indexes to rebuild indices concurrently once the batch finishes.

Daemon Concurrency

Both historical and daily sync loops run internal worker pools (concurrency = 2). This allows parallel retrieval and parsing of files while avoiding file conflicts and table locking deadlocks.

5. Authentication & Limits

All core routes require authorization. Valid client requests must present a token via one of two channels:

# HTTP Header x-api-key: merch-mastermind-free # OR URL Query Parameter ?apiKey=merch-mastermind-free

Dynamic Rate Limit Headers

Once a client token is authorized, the server returns standard rate limit headers indicating the token balance status:

Header Type Description
X-RateLimit-Limit Integer Maximum allowed requests configured for this API Key.
X-RateLimit-Remaining Integer Remaining capacity in the current window.
X-RateLimit-Reset Unix Timestamp Time when the token limit window resets.

6. Options & Parameters Dictionary

This dictionary describes the purpose, type, and options of all settings available across the playground and the API routes.

API Base URL (Environment Setting)

The hostname of the USPTO API server. This defaults to the public domain https://tm.merchdash.net (or http://localhost:3000 when running locally).

Client API Key (Environment Setting)

The client credential token. It gets matched against keys stored in the database's api_keys table. Passing a valid key unlocks access and initiates customized rate limit rules for the token. Generate a client key during setup and keep it out of source control.

phrase (Route Parameter)

The phrase search generates every contiguous word span, from the complete phrase down to individual words. Matching ignores case, punctuation, symbols, and repeated whitespace. Semicolons, commas, dots, and other special characters are removed from comparison text and returned trademark word marks. Standalone one-character marks such as A or A! are excluded.

classes (Query Parameter)

Comma-separated international classes. Short values are zero-padded, so 25 matches 025. Phrase search defaults to 009,018,020,021,024,025,035,040,041. Latest registrations defaults to all classes. Use all to disable class filtering explicitly. The EUIPO and DPMA checks (/euipo-check, /dpma-check) take plain, non-padded Nice numbers and default to 25,24,35,40,31,21.

EUIPO Registry Check (GET /v1/trademark/euipo-check/:phrase)

Searches the European Union trademark registry (EUIPO) for a single phrase via the Productor proxy service. Unlike phrase search, the phrase is sent exactly as provided — there is no contiguous-span expansion. The adjustable classes query parameter accepts plain Nice numbers (1–45) and defaults to 25,24,35,40,31,21.

The response returns the searched phrase, the registry (euipo), the marketplace code EM, a count, and a records array. Each record carries tm, filenumber, marketplace, status, and tm_class. Any registry failure is reported in the error field instead of throwing.

DPMA Registry Check (GET /v1/trademark/dpma-check/:phrase)

Searches the German trademark registry (DPMA) for a single phrase via the Productor proxy service. Behaves identically to the EUIPO check but queries DPMA: the registry is dpma and the marketplace code is DE. The phrase is sent as-is, and the adjustable classes parameter defaults to 25,24,35,40,31,21.

days / minWords (Latest Registrations Query Parameters)

days selects an inclusive calendar-day window ending today and accepts values from 1 to 365 (default 30). minWords requires the normalized trademark word mark to contain at least that many words and accepts values from 1 to 100 (default 1).

includeOwner / includeAttorney (Query Parameters)

Optional boolean switches for including owner and attorney data in phrase-search results. Both default to false.

keyword (Route Parameter)

The alphanumeric text string representing the name or phrase of the trademark you are trying to query (e.g. nike, disney).

mode (Query Parameter)

Configures the database query algorithm to locate trademark word marks. The differences and behaviors are as follows:

Search Mode Underlying Mechanism Example Query Matches Returned Non-Matches / Excluded
exact Performs a direct SQL equality test (=) on lowercase/uppercase string versions. Fast, case-insensitive, but completely literal. nike NIKE, nike nike inc, nike shoes, red nike
fulltext (Default) Uses PostgreSQL's native lexical analyzer to parse words, stem plurals/conjugations (e.g. "run" = "running"), and rank hits. Runs on English lexicons. nike NIKE INC, NIKE ATHLETICS, NIKES nikee (no typo tolerance), nik
fuzzy Calculates trigram similarity (overlapping 3-letter parts) using the pg_trgm module. Catches typos, phonetics, and misspelled marks. starbux STARBUCKS, STARBUX COFFEE, STARBUCS star (too short/low similarity rating)
status (Query Parameter)

Filters the query based on trademark registration status. Every result also includes a one-word status.category.

  • all (Default): Returns all matches regardless of filing status (active, cancelled, abandoned, pending, or expired).
  • active: Restricts results to registered, maintained, and renewed trademarks.

Categories: application, examination, approved, published, opposition, appeal, registered, suspended, abandoned, canceled, expired, and unknown.

classCode / internationalClass (Route Parameter)

The 3-digit international classification identifier specifying the category of goods or services. Example classifications include:

  • 025: Clothing, footwear, and headwear.
  • 009: Computers, software, and consumer electronics.
  • 035: Business advertising, retail administration, and office management.
  • 041: Entertainment services, publications, and educational courses.
serialNumber (Route Parameter)

The unique 8-digit serial number assigned to a trademark application immediately upon filing at the USPTO. Consists strictly of numeric digits.

regNumber (Route Parameter)

The unique registration number assigned to a trademark application once it completes examination and is officially registered by the USPTO.

rows / limit (Query Parameter)

Configures the size of the pagination batch. Accepts integers between 1 and 250. Default is 25.

page (Query Parameter)

Sets the page offset index. Default is 1.

7. Deployment Instructions

Production deployment is completely automated by deploy.py. Run this from your deployment console:

python3 deploy.py

The provisioning script automatically copies files, configures PostgreSQL databases, builds database schemas, installs PM2 daemon configurations, and sets up Nginx to act as a proxy forwarding traffic from port 80 to port 3000.