@biggora/claude-plugins 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/.claude/settings.local.json +13 -0
  2. package/CLAUDE.md +55 -0
  3. package/LICENSE +1 -1
  4. package/README.md +208 -39
  5. package/bin/cli.js +39 -0
  6. package/package.json +30 -17
  7. package/registry/registry.json +166 -1
  8. package/registry/schema.json +10 -0
  9. package/src/commands/skills/add.js +194 -0
  10. package/src/commands/skills/list.js +52 -0
  11. package/src/commands/skills/remove.js +27 -0
  12. package/src/commands/skills/update.js +74 -0
  13. package/src/config.js +5 -0
  14. package/src/skills/codex-cli/SKILL.md +265 -0
  15. package/src/skills/commafeed-api/SKILL.md +1012 -0
  16. package/src/skills/gemini-cli/SKILL.md +379 -0
  17. package/src/skills/gemini-cli/references/commands.md +145 -0
  18. package/src/skills/gemini-cli/references/configuration.md +182 -0
  19. package/src/skills/gemini-cli/references/headless-and-scripting.md +181 -0
  20. package/src/skills/gemini-cli/references/mcp-and-extensions.md +254 -0
  21. package/src/skills/n8n-api/SKILL.md +623 -0
  22. package/src/skills/notebook-lm/SKILL.md +217 -0
  23. package/src/skills/notebook-lm/references/artifact-options.md +168 -0
  24. package/src/skills/notebook-lm/references/auth.md +58 -0
  25. package/src/skills/notebook-lm/references/workflows.md +144 -0
  26. package/src/skills/screen-recording/SKILL.md +309 -0
  27. package/src/skills/screen-recording/references/approach1-programmatic.md +311 -0
  28. package/src/skills/screen-recording/references/approach2-xvfb.md +232 -0
  29. package/src/skills/screen-recording/references/design-patterns.md +168 -0
  30. package/src/skills/test-mobile-app/SKILL.md +212 -0
  31. package/src/skills/test-mobile-app/references/report-template.md +95 -0
  32. package/src/skills/test-mobile-app/references/setup-appium.md +154 -0
  33. package/src/skills/test-mobile-app/scripts/analyze_apk.py +164 -0
  34. package/src/skills/test-mobile-app/scripts/check_environment.py +116 -0
  35. package/src/skills/test-mobile-app/scripts/generate_report.py +250 -0
  36. package/src/skills/test-mobile-app/scripts/run_tests.py +326 -0
  37. package/src/skills/test-web-ui/SKILL.md +232 -0
  38. package/src/skills/test-web-ui/references/test_case_schema.md +102 -0
  39. package/src/skills/test-web-ui/scripts/discover.py +176 -0
  40. package/src/skills/test-web-ui/scripts/generate_report.py +237 -0
  41. package/src/skills/test-web-ui/scripts/run_tests.py +296 -0
  42. package/src/skills/text-to-speech/SKILL.md +236 -0
  43. package/src/skills/text-to-speech/references/espeak-cli.md +277 -0
  44. package/src/skills/text-to-speech/references/kokoro-onnx.md +124 -0
  45. package/src/skills/text-to-speech/references/online-engines.md +128 -0
  46. package/src/skills/text-to-speech/references/pyttsx3-espeak.md +143 -0
  47. package/src/skills/tm-search/SKILL.md +240 -0
  48. package/src/skills/tm-search/references/field-guide.md +79 -0
  49. package/src/skills/tm-search/references/scraping-fallback.md +140 -0
  50. package/src/skills/tm-search/scripts/tm_search.py +375 -0
  51. package/src/skills/wp-rest-api/SKILL.md +114 -0
  52. package/src/skills/wp-rest-api/references/authentication.md +18 -0
  53. package/src/skills/wp-rest-api/references/custom-content-types.md +20 -0
  54. package/src/skills/wp-rest-api/references/discovery-and-params.md +20 -0
  55. package/src/skills/wp-rest-api/references/responses-and-fields.md +30 -0
  56. package/src/skills/wp-rest-api/references/routes-and-endpoints.md +36 -0
  57. package/src/skills/wp-rest-api/references/schema.md +22 -0
  58. package/src/skills/youtube-search/SKILL.md +412 -0
  59. package/src/skills/youtube-search/references/parsing-examples.md +159 -0
  60. package/src/skills/youtube-search/references/youtube-api-quota.md +85 -0
  61. package/src/skills/youtube-thumbnail/SKILL.md +1060 -0
  62. package/tests/commands/info.test.js +49 -0
  63. package/tests/commands/install.test.js +36 -0
  64. package/tests/commands/list.test.js +66 -0
  65. package/tests/commands/publish.test.js +182 -0
  66. package/tests/commands/search.test.js +45 -0
  67. package/tests/commands/uninstall.test.js +29 -0
  68. package/tests/commands/update.test.js +59 -0
  69. package/tests/functional/skills-lifecycle.test.js +293 -0
  70. package/tests/helpers/fixtures.js +63 -0
  71. package/tests/integration/cli.test.js +83 -0
  72. package/tests/skills/add.test.js +138 -0
  73. package/tests/skills/list.test.js +63 -0
  74. package/tests/skills/remove.test.js +38 -0
  75. package/tests/skills/update.test.js +60 -0
  76. package/tests/unit/config.test.js +31 -0
  77. package/tests/unit/registry.test.js +79 -0
  78. package/tests/unit/utils.test.js +150 -0
  79. package/tests/validation/registry-schema.test.js +112 -0
  80. package/tests/validation/skills-validation.test.js +96 -0
@@ -0,0 +1,240 @@
1
+ ---
2
+ name: tm-search
3
+ description: >
4
+ Use this skill whenever the user wants to search, validate, or look up US trademarks, brand
5
+ names, or keywords in the USPTO trademark database. Triggers include: checking if a brand name
6
+ or word is trademarked, searching trademark registrations, validating whether a keyword is
7
+ available for trademark, looking up trademark status or owner, batch-checking multiple brand
8
+ names, or building any tool/script involving the USPTO trademark database. Also use for
9
+ requests like "is X trademarked?", "find trademarks for [keyword]", "check trademark
10
+ availability", "search USPTO for [name]", or "validate these words against USPTO trademarks."
11
+ Always use this skill for any trademark search or validation task — even simple lookups benefit
12
+ from the correct API patterns and output formats defined here.
13
+ ---
14
+
15
+ # US Trademark Search Skill (tm-search)
16
+
17
+ This skill enables an agent to search, validate, and analyze US trademarks via USPTO APIs.
18
+
19
+ ## API Overview
20
+
21
+ There are **two main API approaches** — choose based on needs:
22
+
23
+ | Use Case | API |
24
+ |---|---|
25
+ | Keyword/name text search, availability check | **tmsearch.uspto.gov** (web backend) |
26
+ | Status lookup by serial/registration number | **tsdrapi.uspto.gov** (official TSDR API) |
27
+ | Batch/programmatic word validation | **tmsearch.uspto.gov** or RapidAPI wrapper |
28
+
29
+ ---
30
+
31
+ ## API 1: tmsearch.uspto.gov (New Trademark Search — No API key required)
32
+
33
+ The USPTO replaced TESS in November 2023 with a new search system at `https://tmsearch.uspto.gov`.
34
+ This is a **web application** but its backend can be called directly.
35
+
36
+ ### Search Endpoint
37
+
38
+ ```
39
+ POST https://tmsearch.uspto.gov/search/keyword
40
+ Content-Type: application/json
41
+ ```
42
+
43
+ **Request body:**
44
+ ```json
45
+ {
46
+ "keyword": "APPLE",
47
+ "searchType": "1",
48
+ "statusType": "A",
49
+ "pluralVariants": false,
50
+ "start": 0,
51
+ "rows": 25
52
+ }
53
+ ```
54
+
55
+ **Parameters:**
56
+ - `keyword` — the word/phrase to search (required)
57
+ - `searchType` — `"1"` = basic keyword, `"2"` = design code, `"3"` = owner name
58
+ - `statusType` — `"A"` = active/live only, `"D"` = dead only, `""` = all
59
+ - `pluralVariants` — `true` to include plural variations
60
+ - `start` — pagination offset (0-indexed)
61
+ - `rows` — results per page (max 500)
62
+
63
+ ### Alternative: GET search
64
+
65
+ ```
66
+ GET https://tmsearch.uspto.gov/search/keyword?keyword=APPLE&statusType=A&rows=25
67
+ ```
68
+
69
+ ### Response Fields
70
+
71
+ ```json
72
+ {
73
+ "totalFound": 1247,
74
+ "trademarks": [
75
+ {
76
+ "serialNumber": "75123456",
77
+ "registrationNumber": "2345678",
78
+ "wordMark": "APPLE",
79
+ "status": "Live/Registered",
80
+ "statusCode": "A",
81
+ "filingDate": "1997-03-15",
82
+ "registrationDate": "1999-08-17",
83
+ "owner": "Apple Inc.",
84
+ "ownerAddress": "Cupertino, CALIFORNIA, UNITED STATES",
85
+ "internationalClassification": ["009", "042"],
86
+ "goodsServices": "Computers, computer software...",
87
+ "attorney": "...",
88
+ "markDrawingCode": "4"
89
+ }
90
+ ]
91
+ }
92
+ ```
93
+
94
+ > **Note:** The tmsearch.uspto.gov backend API is not officially documented. If the above endpoint
95
+ > returns errors, fall back to scraping `https://tmsearch.uspto.gov/search/search-information` or
96
+ > use the TSDR API below. See `references/scraping-fallback.md` for the web scraping approach.
97
+
98
+ ---
99
+
100
+ ## API 2: TSDR API (Official — requires API key for bulk use)
101
+
102
+ Looks up trademark **by serial number or registration number**. Returns full case status, documents.
103
+
104
+ **Base URL:** `https://tsdrapi.uspto.gov/ts/cd/`
105
+
106
+ ### Key Endpoints
107
+
108
+ ```bash
109
+ # Case status by serial number (HTML)
110
+ GET https://tsdrapi.uspto.gov/ts/cd/casestatus/sn{SERIAL_NUMBER}/content.html
111
+
112
+ # Case status as XML (machine-readable)
113
+ GET https://tsdrapi.uspto.gov/ts/cd/casestatus/sn{SERIAL_NUMBER}/info.xml
114
+
115
+ # Case status by registration number
116
+ GET https://tsdrapi.uspto.gov/ts/cd/casestatus/rn{REG_NUMBER}/info.xml
117
+
118
+ # Case documents as PDF bundle
119
+ GET https://tsdrapi.uspto.gov/ts/cd/casedocs/bundle.pdf?sn={SERIAL_NUMBER}
120
+
121
+ # Raw trademark image
122
+ GET https://tsdrapi.uspto.gov/ts/cd/rawImage/{SERIAL_NUMBER}
123
+ ```
124
+
125
+ ### API Key (required for bulk/automated use)
126
+
127
+ - Register at: https://account.uspto.gov/api-manager/
128
+ - Add key as header: `USPTO-API-KEY: YOUR_KEY_HERE`
129
+ - Rate limit: **60 requests/minute per API key**
130
+
131
+ ```bash
132
+ curl -H "USPTO-API-KEY: YOUR_KEY" \
133
+ "https://tsdrapi.uspto.gov/ts/cd/casestatus/sn78787878/info.xml"
134
+ ```
135
+
136
+ ---
137
+
138
+ ## CLI Tool Implementation (tm-search)
139
+
140
+ When building the `tm-search` command-line tool, follow this structure:
141
+
142
+ ### Core Commands
143
+
144
+ ```bash
145
+ tm-search keyword <word> # Search by keyword
146
+ tm-search keyword <word> --status=A # Active trademarks only
147
+ tm-search keyword <word> --status=D # Dead trademarks only
148
+ tm-search available <word> # Check if word is available (not registered live)
149
+ tm-search status <serial_number> # Lookup by serial number
150
+ tm-search batch <word1,word2,...> # Check multiple words
151
+ tm-search validate <file.txt> # Validate words from a file (one per line)
152
+ ```
153
+
154
+ ### Output Format
155
+
156
+ Default output: human-readable table
157
+ With `--json`: raw JSON
158
+ With `--csv`: CSV for spreadsheet use
159
+
160
+ ```
161
+ KEYWORD: "CLOUDPEAK"
162
+ Status: AVAILABLE (no live trademarks found)
163
+ Dead marks: 2 (see --show-dead for details)
164
+
165
+ KEYWORD: "APPLE"
166
+ Status: REGISTERED (1,247 live marks found)
167
+ Top matches:
168
+ - "APPLE" | Owner: Apple Inc. | Classes: 009,042 | Reg: 1078312
169
+ - "APPLE MUSIC" | Owner: Apple Inc. | Classes: 041 | Reg: 4960099
170
+ ...
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Availability Check Logic
176
+
177
+ A keyword is considered **AVAILABLE** if there are zero live/active marks with exact OR confusingly
178
+ similar text. The agent should:
179
+
180
+ 1. Search exact keyword with `statusType=A`
181
+ 2. If results > 0 → **LIKELY REGISTERED** — show matches
182
+ 3. If results == 0 → **LIKELY AVAILABLE** — note this is not legal advice
183
+ 4. Always caveat: suggest professional trademark attorney review before filing
184
+
185
+ ```python
186
+ def check_availability(keyword):
187
+ results = search_trademark(keyword, status="A")
188
+ if results["totalFound"] == 0:
189
+ return "LIKELY AVAILABLE"
190
+ else:
191
+ return f"LIKELY TAKEN ({results['totalFound']} active marks)"
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Batch Validation
197
+
198
+ For validating a list of keywords (e.g., from a CSV or text file):
199
+
200
+ ```python
201
+ words = ["CloudPeak", "SkyBridge", "NeonPulse"]
202
+ results = []
203
+ for word in words:
204
+ r = search_trademark(word.upper(), status="A")
205
+ results.append({
206
+ "keyword": word,
207
+ "status": "AVAILABLE" if r["totalFound"] == 0 else "TAKEN",
208
+ "count": r["totalFound"]
209
+ })
210
+ # Output as table or CSV
211
+ ```
212
+
213
+ Rate-limit: Add 0.5–1s delay between requests to avoid throttling.
214
+
215
+ ---
216
+
217
+ ## Implementation Notes
218
+
219
+ - The `tmsearch.uspto.gov` endpoint is a **public government site** — no auth required for search
220
+ - Always **uppercase** keywords before searching (USPTO stores marks in uppercase)
221
+ - Include `User-Agent` header to avoid bot detection: `"Mozilla/5.0 (compatible; tm-search/1.0)"`
222
+ - For `pluralVariants=true`, USPTO auto-expands COFFEE → COFFEES, etc.
223
+ - International Classification (Nice Classification) codes define goods/services category
224
+ - Serial numbers are 8 digits; Registration numbers are 7 digits
225
+
226
+ ## Reference Files
227
+
228
+ - `references/field-guide.md` — Full field descriptions and Nice Classification codes
229
+ - `references/scraping-fallback.md` — Web scraping approach if API is unavailable
230
+ - `scripts/tm_search.py` — Ready-to-use Python implementation
231
+ - `scripts/tm_validate.py` — Batch validation script
232
+
233
+ ---
234
+
235
+ ## Legal Disclaimer to Include in Output
236
+
237
+ Always include when providing availability results:
238
+ > "This is a preliminary search only. Trademark availability is complex and depends on many
239
+ > factors including similar marks, geographic use, and goods/services classification. Consult a
240
+ > licensed trademark attorney before filing."
@@ -0,0 +1,79 @@
1
+ # USPTO Trademark Field Guide
2
+
3
+ ## Response Field Descriptions
4
+
5
+ | Field | Description | Example |
6
+ |---|---|---|
7
+ | `serialNumber` | 8-digit USPTO application serial number | `"78787878"` |
8
+ | `registrationNumber` | 7-digit registration number (if registered) | `"3456789"` |
9
+ | `wordMark` | The literal text of the trademark | `"APPLE MUSIC"` |
10
+ | `status` | Human-readable status | `"Live/Registered"` |
11
+ | `statusCode` | `A` = Active/Live, `D` = Dead/Abandoned | `"A"` |
12
+ | `filingDate` | Date application was filed | `"2015-04-01"` |
13
+ | `registrationDate` | Date trademark was registered | `"2016-05-17"` |
14
+ | `owner` | Name of trademark owner/applicant | `"Apple Inc."` |
15
+ | `ownerAddress` | Owner's city, state, country | `"Cupertino, CA, US"` |
16
+ | `internationalClassification` | Nice Classification codes (list) | `["009", "041", "042"]` |
17
+ | `goodsServices` | Description of goods/services covered | `"Computer software..."` |
18
+ | `attorney` | Attorney of record | `"John Smith"` |
19
+ | `markDrawingCode` | Type of mark (see below) | `"4"` |
20
+ | `colorClaimed` | Color claim if any | `"Red and white"` |
21
+ | `disclaimers` | Disclaimed portions of the mark | `"No claim to MUSIC"` |
22
+
23
+ ## Mark Drawing Codes
24
+
25
+ | Code | Meaning |
26
+ |---|---|
27
+ | `1` | Typed drawing (word-only, no stylization) |
28
+ | `2` | Design without text |
29
+ | `3` | Design with text |
30
+ | `4` | Standard character mark (modern equivalent of typed) |
31
+ | `5` | Stylized/special form mark |
32
+ | `6` | Color mark |
33
+
34
+ ## Trademark Status Codes
35
+
36
+ | Status | Meaning |
37
+ |---|---|
38
+ | `Live/Registered` | Active registered trademark |
39
+ | `Live/Pending` | Application filed, awaiting review |
40
+ | `Dead/Abandoned` | Application abandoned, not pursued |
41
+ | `Dead/Cancelled` | Registration cancelled |
42
+ | `Dead/Expired` | Registration lapsed (not renewed) |
43
+
44
+ ## Nice Classification — Common Codes
45
+
46
+ | Class | Covers |
47
+ |---|---|
48
+ | 009 | Computer hardware, software, electronics |
49
+ | 025 | Clothing, footwear, headwear |
50
+ | 030 | Coffee, tea, flour, bread, pastry |
51
+ | 035 | Advertising, business management |
52
+ | 041 | Education, entertainment, sports |
53
+ | 042 | Software as a service, tech services |
54
+ | 043 | Restaurants, hotels, food/drink services |
55
+ | 044 | Medical, veterinary, health services |
56
+
57
+ Full 45-class list: https://www.uspto.gov/trademark/trademark-updates-and-announcements/nice-agreement-eleventh-edition-general-remarks-class
58
+
59
+ ## Search Tips
60
+
61
+ ### Proximity Searching
62
+ USPTO searches exact word matches. For broader coverage:
63
+ - Search root word AND common variants manually
64
+ - `CLOUD` then `CLOUDS`, `CLOUDY`, `CLOUDPEAK` separately
65
+
66
+ ### Common Gotchas
67
+ - Dead marks can still block registration if famous
68
+ - A search showing "available" doesn't mean no conflicts exist
69
+ - Common words like "ULTRA", "PREMIUM" are frequently refused
70
+ - Geographic terms are often descriptive and hard to register
71
+
72
+ ### Classes to Check for Tech/SaaS
73
+ Always search in classes **009, 035, 042** for software/tech products.
74
+
75
+ ### Classes to Check for Consumer Brands
76
+ - Apparel: 025
77
+ - Food/Beverages: 030, 032, 033, 043
78
+ - Health: 044
79
+ - Entertainment: 041
@@ -0,0 +1,140 @@
1
+ # Web Scraping Fallback for tmsearch.uspto.gov
2
+
3
+ Use this when the direct backend API calls return errors or unexpected responses.
4
+
5
+ ## Background
6
+
7
+ The tmsearch.uspto.gov frontend is a React SPA. The backend API it uses may change endpoint paths.
8
+ If the documented endpoints in SKILL.md fail, use browser DevTools (Network tab) on
9
+ https://tmsearch.uspto.gov/search/search-information to intercept the actual XHR/fetch requests
10
+ being made, then replicate those in code.
11
+
12
+ ## Python Requests Approach
13
+
14
+ ```python
15
+ import requests
16
+ import time
17
+
18
+ HEADERS = {
19
+ "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
20
+ "Accept": "application/json, text/plain, */*",
21
+ "Accept-Language": "en-US,en;q=0.9",
22
+ "Referer": "https://tmsearch.uspto.gov/search/search-information",
23
+ "Origin": "https://tmsearch.uspto.gov",
24
+ }
25
+
26
+ def search_trademark_web(keyword: str, status: str = "A", rows: int = 25) -> dict:
27
+ """
28
+ Search USPTO trademark database.
29
+ status: "A" = active, "D" = dead, "" = all
30
+ """
31
+ session = requests.Session()
32
+
33
+ # First GET the main page to get any session cookies
34
+ session.get("https://tmsearch.uspto.gov/search/search-information", headers=HEADERS)
35
+
36
+ # Attempt POST to backend
37
+ payload = {
38
+ "keyword": keyword.upper(),
39
+ "searchType": "1",
40
+ "statusType": status,
41
+ "pluralVariants": False,
42
+ "start": 0,
43
+ "rows": rows
44
+ }
45
+
46
+ response = session.post(
47
+ "https://tmsearch.uspto.gov/search/keyword",
48
+ json=payload,
49
+ headers=HEADERS,
50
+ timeout=30
51
+ )
52
+
53
+ if response.status_code == 200:
54
+ return response.json()
55
+
56
+ # If POST fails, try GET
57
+ params = {
58
+ "keyword": keyword.upper(),
59
+ "statusType": status,
60
+ "rows": rows,
61
+ "start": 0
62
+ }
63
+ response = session.get(
64
+ "https://tmsearch.uspto.gov/search/keyword",
65
+ params=params,
66
+ headers=HEADERS,
67
+ timeout=30
68
+ )
69
+
70
+ return response.json()
71
+ ```
72
+
73
+ ## Selenium/Playwright Approach (Last Resort)
74
+
75
+ If all HTTP approaches fail, use a headless browser to drive the UI directly:
76
+
77
+ ```python
78
+ from playwright.sync_api import sync_playwright
79
+ import json
80
+
81
+ def search_with_playwright(keyword: str) -> list:
82
+ with sync_playwright() as p:
83
+ browser = p.chromium.launch(headless=True)
84
+ page = browser.new_page()
85
+ results = []
86
+
87
+ # Intercept API responses
88
+ def handle_response(response):
89
+ if "search" in response.url and response.status == 200:
90
+ try:
91
+ data = response.json()
92
+ if "trademarks" in data:
93
+ results.extend(data["trademarks"])
94
+ except:
95
+ pass
96
+
97
+ page.on("response", handle_response)
98
+ page.goto("https://tmsearch.uspto.gov/search/search-information")
99
+
100
+ # Fill in search form
101
+ page.fill('input[placeholder*="search"]', keyword)
102
+ page.click('button[type="submit"]')
103
+ page.wait_for_load_state("networkidle")
104
+
105
+ browser.close()
106
+ return results
107
+ ```
108
+
109
+ ## Install Playwright
110
+ ```bash
111
+ pip install playwright
112
+ playwright install chromium
113
+ ```
114
+
115
+ ## Alternative: Use RapidAPI Wrapper
116
+
117
+ If USPTO direct access is problematic, the RapidAPI unofficial wrapper is reliable:
118
+
119
+ ```bash
120
+ # Endpoint: https://uspto-trademark.p.rapidapi.com
121
+ # Requires: RapidAPI key (freemium plan available)
122
+
123
+ curl --request GET \
124
+ --url "https://uspto-trademark.p.rapidapi.com/v1/trademarkSearch/{KEYWORD}/active" \
125
+ --header "x-rapidapi-host: uspto-trademark.p.rapidapi.com" \
126
+ --header "x-rapidapi-key: YOUR_RAPIDAPI_KEY"
127
+
128
+ # Availability check
129
+ curl --request GET \
130
+ --url "https://uspto-trademark.p.rapidapi.com/v1/trademarkAvailable/{KEYWORD}" \
131
+ --header "x-rapidapi-host: uspto-trademark.p.rapidapi.com" \
132
+ --header "x-rapidapi-key: YOUR_RAPIDAPI_KEY"
133
+ ```
134
+
135
+ RapidAPI wrapper endpoints:
136
+ - `/v1/trademarkSearch/{keyword}/{status}` — keyword search
137
+ - `/v1/trademarkAvailable/{keyword}` — simple yes/no availability
138
+ - `/v1/ownerSearch/{owner_name}/{postcode}` — search by owner
139
+ - `/v1/serialSearch/{serial_number}` — lookup by serial number
140
+ - `/v1/batchTrademarkSearch` — multiple keywords (POST)