@radsoft/markbase 2026.10.1 → 2026.11.1

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.
package/README.md CHANGED
@@ -163,6 +163,7 @@ Keep the key server-side. It's a secret; don't ship it to the browser.
163
163
  |---|---|
164
164
  | `search(opts \| string)` | `SearchResult` — typo-tolerant full-text search |
165
165
  | `clearance(mark, opts?)` | `ClearanceResult` — ranked conflicts with a risk level |
166
+ | `clearanceBatch(marks, opts?)` | `ClearanceBatchResult` — 1–25 names in input order (**Launch or Scale**) |
166
167
  | `suggest(q, limit?)` | `Suggestion[]` — autocomplete, tuned for as-you-type |
167
168
  | `getTrademark(serial)` | `Trademark` — one full record |
168
169
  | `getTimeline(serial)` | prosecution history |
@@ -245,7 +246,14 @@ try {
245
246
  ## Rate limits and quota
246
247
 
247
248
  Per-minute limits and 5xx are **retried automatically** with backoff
248
- (`maxRetries`, default 2).
249
+ (`maxRetries`, default 2), except for `clearanceBatch()`.
250
+
251
+ Bulk clearance accepts 1–25 names, each up to 200 characters, with an optional
252
+ shared `trademarkClass` and `limit` of 1–50 matches per name (default 20). Every
253
+ submitted name counts toward monthly and per-minute limits, including duplicates.
254
+ A batch that exceeds the remaining monthly quota is rejected in full. Accepted
255
+ batches consume their full name count even if a search fails. The SDK never
256
+ automatically retries bulk requests because that could charge the names again.
249
257
 
250
258
  Monthly quota exhaustion is **not retried** — waiting a few seconds can't fix a
251
259
  month-long window, so it throws immediately with `resetsAt` rather than burning
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Trademark, SearchOptions, SearchResult, Suggestion, ClearanceResult, OwnerResult, BatchResult, AggregateField, AggregateResult, NiceClass, IndexInfo, RateLimitInfo, MarkStatus } from "./types.js";
1
+ import type { Trademark, SearchOptions, SearchResult, Suggestion, ClearanceResult, ClearanceBatchResult, OwnerResult, BatchResult, AggregateField, AggregateResult, NiceClass, IndexInfo, RateLimitInfo, MarkStatus } from "./types.js";
2
2
  export interface MarkbaseOptions {
3
3
  /**
4
4
  * Get one free at https://markbase.co. Omitted falls back to
@@ -54,6 +54,11 @@ export declare class Markbase {
54
54
  trademarkClass?: string | number;
55
55
  limit?: number;
56
56
  }): Promise<ClearanceResult>;
57
+ /** Screen 1–25 names on Launch or Scale. Each name consumes quota; retries are disabled. */
58
+ clearanceBatch(marks: string[], opts?: {
59
+ trademarkClass?: string | number;
60
+ limit?: number;
61
+ }): Promise<ClearanceBatchResult>;
57
62
  /** Distribution counts across a facet. */
58
63
  aggregate(by: AggregateField): Promise<AggregateResult>;
59
64
  /** All 45 Nice classification classes. */
package/dist/client.js CHANGED
@@ -68,8 +68,9 @@ export class Markbase {
68
68
  };
69
69
  }
70
70
  async request(path, init) {
71
+ const { query, retry, ...requestInit } = init ?? {};
71
72
  const url = new URL(this.baseUrl + path);
72
- for (const [k, v] of Object.entries(init?.query ?? {})) {
73
+ for (const [k, v] of Object.entries(query ?? {})) {
73
74
  if (v == null)
74
75
  continue;
75
76
  if (Array.isArray(v))
@@ -77,13 +78,14 @@ export class Markbase {
77
78
  else
78
79
  url.searchParams.set(k, String(v));
79
80
  }
81
+ const maxRetries = retry === false ? 0 : this.maxRetries;
80
82
  let lastErr;
81
- for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
83
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
82
84
  const ctrl = new AbortController();
83
85
  const timer = setTimeout(() => ctrl.abort(), this.timeout);
84
86
  try {
85
87
  const res = await this.fetchImpl(url, {
86
- ...init,
88
+ ...requestInit,
87
89
  signal: ctrl.signal,
88
90
  headers: {
89
91
  accept: "application/json",
@@ -111,13 +113,13 @@ export class Markbase {
111
113
  // per-minute limit is worth retrying
112
114
  const retryAfterMs = isQuota ? null : 1000 * (attempt + 1) * 2;
113
115
  const err = new RateLimitError(message, isQuota ? "quota" : "rate", retryAfterMs, resetsAt, body);
114
- if (isQuota || attempt >= this.maxRetries)
116
+ if (isQuota || attempt >= maxRetries)
115
117
  throw err;
116
118
  lastErr = err;
117
119
  await sleep(retryAfterMs);
118
120
  continue;
119
121
  }
120
- if (res.status >= 500 && attempt < this.maxRetries) {
122
+ if (res.status >= 500 && attempt < maxRetries) {
121
123
  lastErr = new MarkbaseError(message, res.status, body);
122
124
  await sleep(1000 * (attempt + 1));
123
125
  continue;
@@ -129,7 +131,7 @@ export class Markbase {
129
131
  throw err;
130
132
  // network error or timeout — worth one more go
131
133
  lastErr = err;
132
- if (attempt >= this.maxRetries) {
134
+ if (attempt >= maxRetries) {
133
135
  const msg = err?.name === "AbortError" ? `Request timed out after ${this.timeout}ms` : String(err);
134
136
  throw new MarkbaseError(msg, 0);
135
137
  }
@@ -199,6 +201,13 @@ export class Markbase {
199
201
  },
200
202
  });
201
203
  }
204
+ /** Screen 1–25 names on Launch or Scale. Each name consumes quota; retries are disabled. */
205
+ clearanceBatch(marks, opts = {}) {
206
+ return this.request("/clearance/batch", {
207
+ method: "POST", retry: false,
208
+ body: JSON.stringify({ marks, class: opts.trademarkClass == null ? undefined : padClass(opts.trademarkClass), limit: opts.limit }),
209
+ });
210
+ }
202
211
  /** Distribution counts across a facet. */
203
212
  aggregate(by) {
204
213
  return this.request("/aggregate", { query: { by } });
package/dist/types.d.ts CHANGED
@@ -63,6 +63,12 @@ export interface ClearanceResult {
63
63
  highest_risk: RiskLevel;
64
64
  matches: ClearanceMatch[];
65
65
  }
66
+ export interface ClearanceBatchResult {
67
+ results: ClearanceResult[];
68
+ usage: {
69
+ names: number;
70
+ };
71
+ }
66
72
  export interface OwnerResult {
67
73
  owner: string;
68
74
  hits: Trademark[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radsoft/markbase",
3
- "version": "2026.10.1",
3
+ "version": "2026.11.1",
4
4
  "description": "Official Node client for the Markbase USPTO trademark API — search, screen, and look up 14M+ US trademarks.",
5
5
  "license": "MIT",
6
6
  "type": "module",