@signa-so/sdk 0.4.0 → 0.7.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 (97) hide show
  1. package/README.md +4 -4
  2. package/dist/_internals/fetch-with-retry.d.ts.map +1 -1
  3. package/dist/_internals/fetch-with-retry.js +10 -2
  4. package/dist/_internals/fetch-with-retry.js.map +1 -1
  5. package/dist/_internals/query-string.d.ts +1 -1
  6. package/dist/_internals/query-string.js +1 -1
  7. package/dist/category-nice.d.ts +22 -0
  8. package/dist/category-nice.d.ts.map +1 -0
  9. package/dist/category-nice.js +109 -0
  10. package/dist/category-nice.js.map +1 -0
  11. package/dist/client.d.ts +26 -0
  12. package/dist/client.d.ts.map +1 -1
  13. package/dist/client.js +34 -0
  14. package/dist/client.js.map +1 -1
  15. package/dist/generated/api-types.d.ts +7780 -2215
  16. package/dist/generated/api-types.d.ts.map +1 -1
  17. package/dist/index.d.ts +4 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/pagination.d.ts +23 -1
  22. package/dist/pagination.d.ts.map +1 -1
  23. package/dist/pagination.js +27 -0
  24. package/dist/pagination.js.map +1 -1
  25. package/dist/resources/analytics.d.ts +8 -0
  26. package/dist/resources/analytics.d.ts.map +1 -0
  27. package/dist/resources/analytics.js +13 -0
  28. package/dist/resources/analytics.js.map +1 -0
  29. package/dist/resources/assignments.d.ts +25 -0
  30. package/dist/resources/assignments.d.ts.map +1 -0
  31. package/dist/resources/assignments.js +33 -0
  32. package/dist/resources/assignments.js.map +1 -0
  33. package/dist/resources/attorneys.d.ts +2 -1
  34. package/dist/resources/attorneys.d.ts.map +1 -1
  35. package/dist/resources/attorneys.js +4 -0
  36. package/dist/resources/attorneys.js.map +1 -1
  37. package/dist/resources/compare.d.ts +29 -0
  38. package/dist/resources/compare.d.ts.map +1 -0
  39. package/dist/resources/compare.js +30 -0
  40. package/dist/resources/compare.js.map +1 -0
  41. package/dist/resources/deadlines.d.ts +24 -0
  42. package/dist/resources/deadlines.d.ts.map +1 -0
  43. package/dist/resources/deadlines.js +26 -0
  44. package/dist/resources/deadlines.js.map +1 -0
  45. package/dist/resources/entities.d.ts +2 -1
  46. package/dist/resources/entities.d.ts.map +1 -1
  47. package/dist/resources/entities.js +4 -0
  48. package/dist/resources/entities.js.map +1 -1
  49. package/dist/resources/events.d.ts +2 -2
  50. package/dist/resources/events.d.ts.map +1 -1
  51. package/dist/resources/events.js +2 -2
  52. package/dist/resources/events.js.map +1 -1
  53. package/dist/resources/feedback.d.ts +19 -0
  54. package/dist/resources/feedback.d.ts.map +1 -0
  55. package/dist/resources/feedback.js +29 -0
  56. package/dist/resources/feedback.js.map +1 -0
  57. package/dist/resources/firms.d.ts +3 -2
  58. package/dist/resources/firms.d.ts.map +1 -1
  59. package/dist/resources/firms.js +5 -1
  60. package/dist/resources/firms.js.map +1 -1
  61. package/dist/resources/goods-services.d.ts +1 -1
  62. package/dist/resources/goods-services.js +1 -1
  63. package/dist/resources/oppositions.d.ts +18 -0
  64. package/dist/resources/oppositions.d.ts.map +1 -0
  65. package/dist/resources/oppositions.js +20 -0
  66. package/dist/resources/oppositions.js.map +1 -0
  67. package/dist/resources/organization.d.ts +7 -1
  68. package/dist/resources/organization.d.ts.map +1 -1
  69. package/dist/resources/organization.js +8 -0
  70. package/dist/resources/organization.js.map +1 -1
  71. package/dist/resources/owners.d.ts +2 -1
  72. package/dist/resources/owners.d.ts.map +1 -1
  73. package/dist/resources/owners.js +4 -0
  74. package/dist/resources/owners.js.map +1 -1
  75. package/dist/resources/reconcile.d.ts +22 -0
  76. package/dist/resources/reconcile.d.ts.map +1 -0
  77. package/dist/resources/reconcile.js +24 -0
  78. package/dist/resources/reconcile.js.map +1 -0
  79. package/dist/resources/references.d.ts +2 -2
  80. package/dist/resources/references.js +2 -2
  81. package/dist/resources/screening.d.ts +63 -0
  82. package/dist/resources/screening.d.ts.map +1 -0
  83. package/dist/resources/screening.js +66 -0
  84. package/dist/resources/screening.js.map +1 -0
  85. package/dist/resources/trademarks.d.ts +42 -8
  86. package/dist/resources/trademarks.d.ts.map +1 -1
  87. package/dist/resources/trademarks.js +85 -6
  88. package/dist/resources/trademarks.js.map +1 -1
  89. package/dist/resources/watches.d.ts +14 -2
  90. package/dist/resources/watches.d.ts.map +1 -1
  91. package/dist/resources/watches.js +21 -1
  92. package/dist/resources/watches.js.map +1 -1
  93. package/dist/types.d.ts +1707 -115
  94. package/dist/types.d.ts.map +1 -1
  95. package/dist/version.d.ts +1 -1
  96. package/dist/version.js +1 -1
  97. package/package.json +3 -2
package/dist/types.d.ts CHANGED
@@ -13,7 +13,10 @@ export interface AttorneyStats {
13
13
  cancelled_count: number | null;
14
14
  pending_count: number | null;
15
15
  abandoned_count: number | null;
16
+ /** @deprecated Use `grant_rate` — same value. `registration_rate` is a misnomer (share of concluded prosecutions ever granted, not share currently registered). */
16
17
  registration_rate: number | null;
18
+ /** Share of concluded prosecutions that were ever granted. Same value as the deprecated `registration_rate`. */
19
+ grant_rate: number | null;
17
20
  abandonment_rate: number | null;
18
21
  avg_prosecution_days: number | null;
19
22
  jurisdiction_count: number | null;
@@ -29,33 +32,24 @@ export interface OwnerStats {
29
32
  cancelled_count: number | null;
30
33
  pending_count: number | null;
31
34
  abandoned_count: number | null;
35
+ /** @deprecated Use `grant_rate` — same value. `registration_rate` is a misnomer (share of concluded prosecutions ever granted, not share currently registered). */
32
36
  registration_rate: number | null;
37
+ /** Share of concluded prosecutions that were ever granted. Same value as the deprecated `registration_rate`. */
38
+ grant_rate: number | null;
33
39
  abandonment_rate: number | null;
34
40
  jurisdiction_count: number | null;
35
41
  earliest_filing: string | null;
36
42
  latest_filing: string | null;
37
43
  computed_at: string | null;
38
44
  }
39
- /** Stats object shape returned by ?include=stats on firm detail. */
40
- export interface FirmStats {
41
- trademark_count: number | null;
42
- registered_count: number | null;
43
- expired_count: number | null;
44
- cancelled_count: number | null;
45
- pending_count: number | null;
46
- abandoned_count: number | null;
47
- registration_rate: number | null;
48
- abandonment_rate: number | null;
49
- avg_prosecution_days: number | null;
50
- jurisdiction_count: number | null;
51
- earliest_filing: string | null;
52
- latest_filing: string | null;
53
- computed_at: string | null;
54
- }
55
45
  /** Full owner detail (retrieve response). */
56
46
  export type Owner = components['schemas']['OwnerResponse'] & {
57
47
  trademark_count?: number | null;
48
+ active_count?: number | null;
49
+ /** @deprecated Use `grant_rate` — same value; `registration_rate` is a misnomer. */
58
50
  registration_rate?: number | null;
51
+ /** Share of concluded prosecutions that were ever granted. Same value as the deprecated `registration_rate`. */
52
+ grant_rate?: number | null;
59
53
  latest_filing?: string | null;
60
54
  /** Resolved-entity id this owner belongs to (the derived `ent_<owner-uuid>`
61
55
  * singleton when unlinked). Always present. */
@@ -96,10 +90,68 @@ export type Owner = components['schemas']['OwnerResponse'] & {
96
90
  };
97
91
  stats?: OwnerStats;
98
92
  };
93
+ /** Composed live portfolio analytics report for an owner, attorney, firm, or entity. */
94
+ export interface AnalyticsReport {
95
+ object: 'analytics_report';
96
+ subject: {
97
+ id: string;
98
+ object: 'owner' | 'attorney' | 'firm' | 'entity';
99
+ name: string;
100
+ };
101
+ portfolio: {
102
+ mark_count: number;
103
+ active_count: number;
104
+ dead_count: number;
105
+ status_distribution: Record<string, number>;
106
+ class_distribution: Record<string, number>;
107
+ jurisdiction_spread: Record<string, number>;
108
+ filing_trend: Record<string, number>;
109
+ };
110
+ litigation: {
111
+ subject: {
112
+ owner_id: string | null;
113
+ entity_id: string | null;
114
+ };
115
+ proceedings_total: number;
116
+ as_challenger: {
117
+ total: number;
118
+ by_type: Record<string, number>;
119
+ outcomes: Record<string, number>;
120
+ decided: number;
121
+ win_rate: number | null;
122
+ avg_duration_days: number | null;
123
+ };
124
+ as_defendant: {
125
+ total: number;
126
+ by_type: Record<string, number>;
127
+ outcomes: Record<string, number>;
128
+ decided: number;
129
+ win_rate: number | null;
130
+ avg_duration_days: number | null;
131
+ };
132
+ } | null;
133
+ transactions: {
134
+ transaction_count: number;
135
+ by_type: Record<string, number>;
136
+ unreleased_security_interests: number;
137
+ marks_with_liens: number;
138
+ acquired_count: number;
139
+ divested_count: number;
140
+ first_transaction_date: string | null;
141
+ last_transaction_date: string | null;
142
+ } | null;
143
+ generated_at: string;
144
+ /** Per-request id echoed at the top level of the response body (`AnalyticsReportResponse` in the OpenAPI spec). */
145
+ request_id: string;
146
+ }
99
147
  /** Compact owner in list responses. */
100
148
  export type OwnerSummary = components['schemas']['OwnerSummary'] & {
101
149
  trademark_count?: number | null;
150
+ active_count?: number | null;
151
+ /** @deprecated Use `grant_rate` — same value; `registration_rate` is a misnomer. */
102
152
  registration_rate?: number | null;
153
+ /** Share of concluded prosecutions that were ever granted. Same value as the deprecated `registration_rate`. */
154
+ grant_rate?: number | null;
103
155
  latest_filing?: string | null;
104
156
  entity_id?: string;
105
157
  entity_id_type?: 'resolved' | 'derived';
@@ -111,7 +163,11 @@ export type Attorney = components['schemas']['AttorneyResponse'] & {
111
163
  phone?: string | null;
112
164
  address?: unknown | null;
113
165
  trademark_count?: number | null;
166
+ active_count?: number | null;
167
+ /** @deprecated Use `grant_rate` — same value; `registration_rate` is a misnomer. */
114
168
  registration_rate?: number | null;
169
+ /** Share of concluded prosecutions that were ever granted. Same value as the deprecated `registration_rate`. */
170
+ grant_rate?: number | null;
115
171
  latest_filing?: string | null;
116
172
  recent_trademarks?: Array<Record<string, unknown>>;
117
173
  recent_trademarks_has_more?: boolean;
@@ -121,7 +177,11 @@ export type Attorney = components['schemas']['AttorneyResponse'] & {
121
177
  export type AttorneySummary = components['schemas']['AttorneySummary'] & {
122
178
  firm_id?: string | null;
123
179
  trademark_count?: number | null;
180
+ active_count?: number | null;
181
+ /** @deprecated Use `grant_rate` — same value; `registration_rate` is a misnomer. */
124
182
  registration_rate?: number | null;
183
+ /** Share of concluded prosecutions that were ever granted. Same value as the deprecated `registration_rate`. */
184
+ grant_rate?: number | null;
125
185
  latest_filing?: string | null;
126
186
  };
127
187
  /** Full firm detail (retrieve response). */
@@ -132,11 +192,14 @@ export interface Firm {
132
192
  canonical_name: string;
133
193
  attorney_count: number;
134
194
  trademark_count: number;
195
+ active_count: number;
196
+ /** @deprecated Use `grant_rate` — same value; `registration_rate` is a misnomer. */
135
197
  registration_rate: number | null;
198
+ /** Share of concluded prosecutions that were ever granted. Same value as the deprecated `registration_rate`. */
199
+ grant_rate: number | null;
136
200
  latest_filing: string | null;
137
201
  created_at: string;
138
202
  updated_at: string;
139
- stats?: FirmStats;
140
203
  attorneys?: Array<{
141
204
  id: string;
142
205
  object: 'attorney';
@@ -157,7 +220,11 @@ export interface FirmSummary {
157
220
  canonical_name: string;
158
221
  attorney_count: number;
159
222
  trademark_count: number;
223
+ active_count: number;
224
+ /** @deprecated Use `grant_rate` — same value; `registration_rate` is a misnomer. */
160
225
  registration_rate: number | null;
226
+ /** Share of concluded prosecutions that were ever granted. Same value as the deprecated `registration_rate`. */
227
+ grant_rate: number | null;
161
228
  latest_filing: string | null;
162
229
  created_at: string;
163
230
  }
@@ -174,17 +241,17 @@ export interface EntityCompany {
174
241
  verified_at?: string | null;
175
242
  verified_by?: string | null;
176
243
  }
177
- /** Whitelisted per-member link evidence on an entity-detail member. */
244
+ /** Public per-member link provenance on an entity-detail member. */
178
245
  export interface EntityMemberLink {
179
- signal: string;
180
- tier: string | null;
181
- confidence: number | null;
182
- decided_by: string;
183
- /** token-overlap count from the name guard, when present. */
184
- guard_overlap?: number;
185
- /** matched canonical IR numbers (madrid_ir tier), when present. */
246
+ /** How this member was linked into the entity (stable public vocabulary). */
247
+ method: 'international_registration' | 'shared_identifier' | 'public_company' | 'portfolio_overlap' | 'manual_review' | 'other';
248
+ /** Coarse confidence band; null when not scored. */
249
+ match_strength: 'high' | 'medium' | 'low' | null;
250
+ /** Whether the link was confirmed by adjudication/manual review. */
251
+ reviewed: boolean;
252
+ /** matched canonical IR numbers (international_registration), when present. */
186
253
  matched_irs?: string[];
187
- /** matched office-identifier values (office_identifier tier), when present. */
254
+ /** matched office-identifier values (shared_identifier), when present. */
188
255
  matched_identifiers?: string[];
189
256
  }
190
257
  /** A member owner embedded in an entity-detail response. */
@@ -211,8 +278,36 @@ export interface EntitySummary {
211
278
  ticker: string | null;
212
279
  lei: string | null;
213
280
  trademark_count: number;
281
+ active_count: number;
214
282
  member_count: number;
215
283
  }
284
+ /** The nearest listed ancestor of a `subsidiary_of_listed` entity, when it
285
+ * resolves to a live entity in our system. */
286
+ export interface EntityListedAncestor {
287
+ id: string;
288
+ object: 'entity';
289
+ name: string;
290
+ /** The listed ancestor's own ticker. */
291
+ ticker: string | null;
292
+ }
293
+ /** Public-listing decoration (ENG-117). Present on {@link EntityDetail} ONLY when
294
+ * the entity is listed or a subsidiary of a listed company; OMITTED otherwise
295
+ * (absence ≠ confirmed-private). */
296
+ export interface EntityListing {
297
+ /** 'listed' = the entity is itself publicly listed; 'subsidiary_of_listed' =
298
+ * it inherits a ticker from a listed ancestor. */
299
+ status: 'listed' | 'subsidiary_of_listed';
300
+ /** The entity's own ticker (listed) or the inherited ancestor ticker (subsidiary). */
301
+ ticker: string | null;
302
+ /** Exchange / market code (display only). */
303
+ exch_code: string | null;
304
+ /** LEI of the listed company: the entity's own LEI when listed, else the ancestor's. */
305
+ lei: string | null;
306
+ /** Derived from status: 'listed' → 'direct', 'subsidiary_of_listed' → 'inherited'. */
307
+ source: 'direct' | 'inherited';
308
+ /** The nearest listed ancestor; null for a directly-listed entity or when unresolvable. */
309
+ listed_ancestor: EntityListedAncestor | null;
310
+ }
216
311
  /** Full entity detail (`GET /v1/entities/{id}`). Resolved entities embed
217
312
  * members[] with link evidence; derived singletons carry a member-of-one. */
218
313
  export interface EntityDetail {
@@ -222,21 +317,28 @@ export interface EntityDetail {
222
317
  country_code: string | null;
223
318
  entity_type: string | null;
224
319
  entity_id_type: 'resolved' | 'derived';
225
- /** Public-company facts aggregated over member companies ("served through the
226
- * entity"). Always present. A derived singleton exposes the owner's own
227
- * public-company facts when present (pco-linked); otherwise false/null/empty. */
320
+ /** True when a member company is an active SEC ticker OR the entity itself is
321
+ * listed / a subsidiary of a listed company (ENG-117 — matches the list filter).
322
+ * A derived singleton exposes the owner's own public-company facts (pco-linked),
323
+ * else false. */
228
324
  publicly_traded: boolean;
229
325
  /** Survivorship ticker (first of {@link tickers}); null when none. */
230
326
  ticker: string | null;
231
- /** Deduped uppercased SEC tickers across all member companies. */
327
+ /** Deduped uppercased tickers: member-company SEC tickers UNION the entity's own
328
+ * direct/inherited (subsidiary_of_listed) listing_ticker (ENG-117). Includes
329
+ * inherited subsidiary tickers; direct-vs-inherited provenance is in {@link listing}. */
232
330
  tickers: string[];
233
331
  lei: string | null;
234
332
  /** Whether any member company carries a GLEIF LEI. */
235
333
  has_lei: boolean;
236
334
  trademark_count: number;
335
+ active_count: number;
237
336
  member_count: number;
238
337
  /** Resolved entities only — the GLEIF parent entity id, when present. */
239
338
  parent_entity_id?: string | null;
339
+ /** Public-listing block (ENG-117). Present only when the entity is listed or a
340
+ * subsidiary of a listed company; omitted otherwise. */
341
+ listing?: EntityListing;
240
342
  members: EntityMember[];
241
343
  updated_at: string;
242
344
  request_id: string;
@@ -263,6 +365,12 @@ export interface EntityFamily {
263
365
  export type Proceeding = components['schemas']['Proceeding'];
264
366
  /** Full proceeding detail with embedded trademark (retrieve response). */
265
367
  export type ProceedingDetail = components['schemas']['ProceedingResponse'];
368
+ /** Recorded assignment in list responses. */
369
+ export type Assignment = components['schemas']['Assignment'];
370
+ /** Full assignment detail with parties and affected marks. */
371
+ export type AssignmentDetail = components['schemas']['AssignmentResponse'];
372
+ /** Assignment item returned under a trademark's chain of title. */
373
+ export type TrademarkAssignment = components['schemas']['TrademarkAssignmentSub'];
266
374
  /** Request body for POST /v1/trademarks/batch. */
267
375
  export type TrademarkBatchBody = components['schemas']['TrademarkBatchRequest'];
268
376
  /** Response shape for POST /v1/trademarks/batch (non-paginated). */
@@ -276,15 +384,49 @@ export type TrademarkSuggestion = components['schemas']['TrademarkSuggestion'];
276
384
  /** Attorney client (owner) entry with shared count. */
277
385
  export type AttorneyClient = components['schemas']['AttorneyClient'];
278
386
  /** Search result item (V2 with match explanations and faceted aggregations). */
279
- export type SearchV2Result = components['schemas']['SearchResultV2'];
387
+ export type TrademarkSearchResult = components['schemas']['TrademarkSearchResult'];
280
388
  /** Cross-entity suggestion item. */
281
389
  export type CrossEntitySuggestion = components['schemas']['CrossEntitySuggestion'];
282
390
  /** Goods & services term (Nice classification). */
283
391
  export type GoodsServicesTerm = components['schemas']['GoodsServicesTerm'];
284
392
  /** Single maintenance deadline rule (item in `GET /v1/deadline-rules`). */
285
393
  export type DeadlineRule = components['schemas']['DeadlineRule'];
394
+ /** Single computed maintenance deadline. */
395
+ export type ComputedDeadline = components['schemas']['ComputedDeadline'];
396
+ /** Per-item result from `POST /v1/deadlines/compute`. */
397
+ export type DeadlineComputation = components['schemas']['DeadlineComputation'];
398
+ /** Input item for `POST /v1/deadlines/compute`. */
399
+ export type DeadlineComputeItem = components['schemas']['DeadlineComputeItem'];
400
+ /** Request body for `POST /v1/deadlines/compute`. */
401
+ export type DeadlineComputeParams = components['schemas']['DeadlineComputeRequest'];
402
+ /** List response from `POST /v1/deadlines/compute`. */
403
+ export type DeadlineComputeResponse = components['schemas']['DeadlineComputeResponse'];
286
404
  /** Single opposition window rule (item in `GET /v1/opposition-rules`). */
287
405
  export type OppositionRule = components['schemas']['OppositionRule'];
406
+ /** Common extension available for an opposition window, when modeled. */
407
+ export type OppositionCommonExtension = components['schemas']['OppositionCommonExtension'];
408
+ /** Source citation surfaced on an opposition window computation. */
409
+ export type OppositionWindowSource = components['schemas']['OppositionWindowSource'];
410
+ /** Per-item result from `POST /v1/oppositions/compute`. */
411
+ export type OppositionWindowComputation = components['schemas']['OppositionWindowComputation'];
412
+ /** Input item for `POST /v1/oppositions/compute`. */
413
+ export type OppositionComputeItem = components['schemas']['OppositionComputeItem'];
414
+ /** Request body for `POST /v1/oppositions/compute`. */
415
+ export type OppositionComputeParams = components['schemas']['OppositionComputeRequest'];
416
+ /** List response from `POST /v1/oppositions/compute`. */
417
+ export type OppositionComputeResponse = components['schemas']['OppositionComputeResponse'];
418
+ /** Single field comparison from `POST /v1/reconcile`. */
419
+ export type ReconcileFieldDiff = components['schemas']['ReconcileFieldDiff'];
420
+ /** Caller-supplied field values for `POST /v1/reconcile`. */
421
+ export type ReconcileYourFields = components['schemas']['ReconcileYourFields'];
422
+ /** Input item for `POST /v1/reconcile`. */
423
+ export type ReconcileItem = components['schemas']['ReconcileItem'];
424
+ /** Request body for `POST /v1/reconcile`. */
425
+ export type ReconcileParams = components['schemas']['ReconcileRequest'];
426
+ /** Per-item result from `POST /v1/reconcile`. */
427
+ export type Reconciliation = components['schemas']['Reconciliation'];
428
+ /** List response from `POST /v1/reconcile`. */
429
+ export type ReconcileResponse = components['schemas']['ReconcileResponse'];
288
430
  /** Statutory citation + URL surfaced on rule items. */
289
431
  export type RuleSource = components['schemas']['RuleSource'];
290
432
  /** Vienna design code. */
@@ -360,15 +502,22 @@ export type WatchStatus = 'active' | 'paused' | 'disabled';
360
502
  /**
361
503
  * Trigger event types — ingestion-emitted fact events a watch can subscribe to.
362
504
  *
363
- * v1 accepts exactly these 3 values. `trademark.retracted` and
364
- * `trademark.corrected` were listed in earlier SDK revisions but were NEVER
365
- * accepted by the API (create/update reject them with 400) and are never
366
- * emitted by the evaluator. Source of truth:
367
- * `api/src/modules/watches/validators.ts` `ALLOWED_TRIGGER_EVENTS`.
505
+ * All 5 values are accepted as `trigger_events` on create/update. The DEFAULT
506
+ * trigger set applied when you OMIT `trigger_events` is the original 3
507
+ * (`trademark.created`, `trademark.updated`, `trademark.status_changed`).
508
+ * `trademark.retracted` and `trademark.corrected` are OPT-IN: they fire only
509
+ * for watches that explicitly list them in `trigger_events`, and the evaluator
510
+ * actively derives + emits both. Source of truth:
511
+ * `api/src/modules/watches/validators.ts` `ALLOWED_TRIGGER_EVENTS`
512
+ * (= `ALERT_EVENT_TYPES` from `@signa/types`) and `DEFAULT_TRIGGER_EVENTS`.
368
513
  */
369
- export type WatchTriggerEvent = 'trademark.created' | 'trademark.updated' | 'trademark.status_changed';
514
+ export type WatchTriggerEvent = 'trademark.created' | 'trademark.updated' | 'trademark.status_changed' | 'trademark.retracted' | 'trademark.corrected';
515
+ /** Search strategy names accepted by watch similarity queries. */
516
+ export type WatchSearchStrategy = 'exact' | 'phonetic' | 'fuzzy' | 'prefix';
517
+ /** Attribution tier gate for watch similarity queries. */
518
+ export type WatchMinMatchTier = 'exact' | 'normalized' | 'fuzzy' | 'phonetic';
370
519
  /**
371
- * Watch query DSL (v1). Five watch types share one shape — the
520
+ * Watch query DSL. Five watch types share one shape — the
372
521
  * `watch_type` selects which scoping field is required, but the body
373
522
  * shape is identical to a trademark search body. See the
374
523
  * [Watches guide](https://docs.signa.so/guides/monitoring/watches) for
@@ -377,28 +526,40 @@ export type WatchTriggerEvent = 'trademark.created' | 'trademark.updated' | 'tra
377
526
  * `q` is a whitespace-separated keyword list (max 20, each ≥3 chars, no
378
527
  * stop words). `filters` accepts the same vocabulary as the trademark
379
528
  * search API (`trademarkIds`, `ownerId`, `niceClasses`, `jurisdictions`,
380
- * `offices`, etc.). `trigger_events` narrows which lifecycle events
381
- * fire alerts. `score_threshold` (0..1) gates similarity matches.
529
+ * `offices`, etc.). `strategies` uses the same selector as public trademark
530
+ * search. `trigger_events` narrows which lifecycle events fire alerts.
531
+ * `min_match_tier` gates similarity matches by retrieval attribution tier.
532
+ * `score_threshold` is NOT currently supported — sending it on a write is
533
+ * rejected with 400; scores are informational (see `match_score` on alerts).
382
534
  *
383
535
  * Forbidden DSL keys (`function_score`, `script`, `sort`, `cursor`,
384
536
  * `aggregations`, `highlight`) are rejected with 400. `query.match` is
385
537
  * rejected in ANY form (object or string) — earlier doc revisions described
386
538
  * shapes that were never honored by the evaluator. Use `filters.ownerId`,
387
539
  * `filters.trademarkIds`, `filters.niceClasses` for scoping and
388
- * `score_threshold` for similarity precision. Unknown `filters` keys are
540
+ * `min_match_tier` for similarity precision. Unknown `filters` keys are
389
541
  * rejected with 400 listing the allowed vocabulary; `filters.offices`
390
542
  * accepts any casing and is stored lowercase.
391
543
  */
392
544
  export interface WatchQuery {
393
- /** Always `"v1"` for monitoring v1. */
394
- version: 'v1';
545
+ /** `"v2"` for tier-based watch matching. `"v1"` is accepted during migration. */
546
+ version: 'v1' | 'v2';
395
547
  /** Optional keyword query (required for similarity watches). Whitespace-separated; each ≥3 chars; no stop words. */
396
548
  q?: string;
549
+ /** Search strategies to use. Omit for the public-search default (`exact` + `fuzzy`). */
550
+ strategies?: WatchSearchStrategy[];
397
551
  /** Filter object — same vocabulary as the trademark search API. Common keys: `trademarkIds`, `ownerId`, `niceClasses`, `jurisdictions`, `offices`, `statusPrimary`. */
398
552
  filters?: Record<string, unknown>;
399
553
  /** Restrict alert generation to specific trigger event types. */
400
554
  trigger_events?: WatchTriggerEvent[];
401
- /** Similarity score threshold (0..1). Only matches scoring at-or-above fire alerts. Valid for `watch_type: "similarity"`. */
555
+ /** Minimum attribution tier for similarity watches. `phonetic` is the broad "any tier" setting. */
556
+ min_match_tier?: WatchMinMatchTier;
557
+ /**
558
+ * NOT currently supported — sending this on create/update/bulk/preview is
559
+ * rejected with 400. Scores are informational (see `match_score` on alerts).
560
+ * The field is retained on the type so existing stored watch queries still
561
+ * deserialize on GET. Contact support for calibrated-band thresholds.
562
+ */
402
563
  score_threshold?: number;
403
564
  }
404
565
  /** Watch (retrieve / create / update response). */
@@ -413,6 +574,8 @@ export interface Watch {
413
574
  /** Last 24h alert count when retrieving a single watch; null on list responses. */
414
575
  alert_count_24h: number | null;
415
576
  last_alerted_at: string | null;
577
+ /** Customer passthrough label set on the watch; null if unset. */
578
+ customer_reference: string | null;
416
579
  metadata: Record<string, unknown>;
417
580
  created_at: string;
418
581
  updated_at: string;
@@ -420,42 +583,156 @@ export interface Watch {
420
583
  /**
421
584
  * Alert event types — what the API actually emits for `Alert.event_type`.
422
585
  *
423
- * In v1 this is identical to {@link WatchTriggerEvent}: watches can subscribe
424
- * to exactly these 3 events, and alerts only ever carry these 3 values.
425
- * (Earlier SDK revisions claimed watches accepted 5 trigger events — they
426
- * never did; the API rejects `trademark.retracted` / `trademark.corrected`
427
- * with 400.) The two types are kept separate so they can diverge in later
428
- * API versions without a breaking rename.
429
- *
430
- * R4.5 fix: previously this declared 5 values; SDK consumers switching on
431
- * `'trademark.retracted'` or `'trademark.corrected'` had dead `case` branches
432
- * that never fired.
586
+ * In v1 this is identical to {@link WatchTriggerEvent}: all 5 canonical values
587
+ * are accepted as `trigger_events`, and alerts may carry any of them. The
588
+ * DEFAULT trigger set (when `trigger_events` is omitted) is the original 3
589
+ * (`trademark.created`, `trademark.updated`, `trademark.status_changed`);
590
+ * `trademark.retracted` and `trademark.corrected` are OPT-IN and fire only for
591
+ * watches that explicitly subscribe to them — the evaluator derives + emits
592
+ * both. The two types are kept separate so they can diverge in later API
593
+ * versions without a breaking rename.
433
594
  */
434
- export type AlertEventType = 'trademark.created' | 'trademark.updated' | 'trademark.status_changed';
595
+ export type AlertEventType = 'trademark.created' | 'trademark.updated' | 'trademark.status_changed' | 'trademark.retracted' | 'trademark.corrected';
435
596
  /** Alert severity. */
436
597
  export type AlertSeverity = 'normal' | 'high' | 'critical';
437
598
  /** Opposition-window state for the matched mark, when applicable. */
438
599
  export type OppositionWindowStatus = 'open' | 'closing_soon' | 'critical' | 'closed';
439
- /** Alert (immutable — no PATCH/dismiss in monitoring v1). */
600
+ /**
601
+ * One entry in an alert's `event.diff`. Parent-field changes carry real
602
+ * `from`/`to` values; child-entity changes are opaque (`{ path, op:'changed' }`,
603
+ * `from`/`to` absent).
604
+ */
605
+ export interface AlertDiffEntry {
606
+ path: string;
607
+ op: 'set' | 'unset' | 'changed';
608
+ from?: unknown;
609
+ to?: unknown;
610
+ }
611
+ /**
612
+ * Match metadata — why/how the mark matched the watch. The whole block is
613
+ * `null` for pure-filter / pre-v2 alerts that carry no match scoring.
614
+ */
615
+ export interface AlertMatch {
616
+ /** Human-readable explanation of the match; null when not captured. */
617
+ reason: string | null;
618
+ /** Relevance score (e.g. OpenSearch); null when not applicable. */
619
+ score: number | null;
620
+ /** What the score is derived from, e.g. `opensearch_relevance`; null when none. */
621
+ score_basis: string | null;
622
+ }
623
+ /**
624
+ * Compact mark summary embedded on the alert (Alerts v2 `trademark` block).
625
+ * Mirrors the trademark SEARCH summary vocabulary. The summary fields degrade
626
+ * (absent) for pre-v2 alerts, where only `id`, `as_of`, and `links` are present.
627
+ */
628
+ export interface AlertTrademarkSnapshot {
629
+ /** Prefixed trademark ID (`tm_*`). */
630
+ id: string;
631
+ mark_text?: string | null;
632
+ mark_feature_type?: string | null;
633
+ office_code?: string;
634
+ status?: {
635
+ primary: string;
636
+ stage: string;
637
+ };
638
+ filing_date?: string | null;
639
+ registration_date?: string | null;
640
+ nice_classes?: number[];
641
+ owner_name?: string | null;
642
+ /** When the source change occurred (`source_occurred_at`); null on pre-v2 alerts. */
643
+ as_of: string | null;
644
+ links: {
645
+ self: string;
646
+ };
647
+ }
648
+ /**
649
+ * Alert (immutable — no PATCH/dismiss in monitoring v1).
650
+ *
651
+ * Alerts v2 nested shape — mirrors the REST `AlertResponse` (see
652
+ * `api/src/modules/alerts/routes.ts`). The webhook body for `alert.created`
653
+ * carries the same canonical object minus `request_id` / `evaluation_epoch`.
654
+ */
655
+ /**
656
+ * REST-only alert provenance block (ENG-170) — the alert's evidence chain.
657
+ * NOT part of the signed webhook contract (see {@link AlertCreatedPayload}).
658
+ */
659
+ export interface AlertProvenance {
660
+ /** Prefixed sync-run id (`srun_*`); omitted when the alert has no linked run. */
661
+ sync_run?: string;
662
+ /** The trademark_record version the alert froze at. */
663
+ content_version: number;
664
+ /**
665
+ * created_at minus occurred_at, in seconds. Null when occurred_at is null
666
+ * or in the future relative to created_at (unknown, never negative).
667
+ */
668
+ detection_latency_seconds: number | null;
669
+ /** True when detection latency exceeded the office's expected cadence. False whenever latency is unknown. */
670
+ late_detection: boolean;
671
+ }
440
672
  export interface Alert {
441
673
  id: string;
442
674
  object: 'alert';
443
- watch_id: string;
444
- watch_name: string;
445
- trademark_id: string;
446
- event_type: AlertEventType;
447
- /** Snapshot of trademark version at the moment of evaluation (immutable). */
448
- content_version: number;
449
- /** Computed customer-action deadline; null if no deadline applies. */
450
- must_act_by: string | null;
451
- /** Current opposition-window state for this mark; null when no window applies. */
452
- opposition_window_status: OppositionWindowStatus | null;
453
- severity: AlertSeverity;
454
- /** Optional compact mark summary (mark text, owner, office) included by some routes. */
455
- trademark_summary?: Record<string, unknown>;
456
- /** Optional human-readable explanation of why the mark matched the watch. */
457
- match_reason?: string;
458
- created_at: string;
675
+ /** Alerts v2 wire schema version, e.g. `'2026-06-01'`. */
676
+ schema_version: string;
677
+ watch: {
678
+ id: string;
679
+ name: string;
680
+ type: WatchType;
681
+ };
682
+ /** Customer passthrough set on the watch; null if unset. */
683
+ customer_reference: string | null;
684
+ event: {
685
+ type: AlertEventType;
686
+ /** Short human-readable description, e.g. `"Status primary changed: pending → registered"`. */
687
+ summary: string;
688
+ diff: AlertDiffEntry[];
689
+ /**
690
+ * Set to `true` when the diff was clipped to stay under the wire byte
691
+ * budget (entries dropped and/or long values replaced with `[truncated]`).
692
+ * Absent/undefined for normal, un-clipped alerts.
693
+ */
694
+ diff_truncated?: boolean;
695
+ };
696
+ /** Match metadata, or null for pure-filter / pre-v2 alerts. */
697
+ match: AlertMatch | null;
698
+ trademark: AlertTrademarkSnapshot;
699
+ deadline: {
700
+ severity: AlertSeverity;
701
+ /** Current opposition-window state for this mark; null when no window applies. */
702
+ opposition_window_status: OppositionWindowStatus | null;
703
+ /** Computed customer-action deadline; null if no deadline applies. */
704
+ must_act_by: string | null;
705
+ };
706
+ /**
707
+ * True when this alert was generated well after the underlying change
708
+ * occurred (e.g. the monitoring pipeline recovered from a stall and
709
+ * processed backlogged changes). Late alerts remain fully visible via the
710
+ * REST API (filter with `?detected_late=true|false`) but are EXCLUDED from
711
+ * webhook delivery by default.
712
+ */
713
+ detected_late: boolean;
714
+ timestamps: {
715
+ /** When the source change occurred; null on pre-v2 alerts. */
716
+ occurred_at: string | null;
717
+ /** When the underlying change was ingested; omitted when no change row is linked. */
718
+ ingested_at?: string;
719
+ created_at: string;
720
+ };
721
+ links: {
722
+ trademark: string;
723
+ watch: string;
724
+ };
725
+ /**
726
+ * REST-only: evaluation epoch the alert was emitted under (NOT part of the
727
+ * webhook contract). Lets clients distinguish prior-query-revision alerts
728
+ * when listing with `?epoch=all`.
729
+ */
730
+ evaluation_epoch: number;
731
+ /**
732
+ * REST-only: the alert's evidence chain (ENG-170). NOT part of the webhook
733
+ * contract; webhook consumers re-fetch the alert via the API to obtain it.
734
+ */
735
+ provenance: AlertProvenance;
459
736
  }
460
737
  /** Webhook event types delivered by the dispatcher. */
461
738
  export type WebhookEventType = 'alert.created' | 'webhook.test';
@@ -482,7 +759,12 @@ export interface WebhookEvent<T = unknown> {
482
759
  data: T;
483
760
  }
484
761
  /**
485
- * Inner payload of an `alert.created` webhook delivery.
762
+ * Preserved FLAT fields on an `alert.created` webhook delivery.
763
+ *
764
+ * These are the lean, backward-compatible top-level fields the dispatcher has
765
+ * always emitted. They are kept alongside the rich {@link Alert} object (see
766
+ * {@link AlertCreatedPayload}) so existing consumers that read flat fields
767
+ * never break.
486
768
  *
487
769
  * IDs are prefixed (Round 4 R4.5) — `alert_id`, `watch_id`, and
488
770
  * `trademark_record_id` feed straight into `GET /v1/alerts/{id}` etc.
@@ -492,7 +774,7 @@ export interface WebhookEvent<T = unknown> {
492
774
  * customer's webhook endpoint already implies the tenant, and
493
775
  * cross-referencing internal tenant UUIDs is not part of the public API.
494
776
  */
495
- export interface AlertCreatedPayload {
777
+ export interface AlertCreatedFlatFields {
496
778
  /** Prefixed alert ID, e.g. `alt_018f...`. */
497
779
  alert_id: string;
498
780
  /** Prefixed watch ID, e.g. `wat_018f...`. */
@@ -524,6 +806,30 @@ export interface AlertCreatedPayload {
524
806
  /** Hash of the source data payload that triggered the alert; null when not available. */
525
807
  source_data_hash: string | null;
526
808
  }
809
+ /**
810
+ * Inner payload of an `alert.created` webhook delivery.
811
+ *
812
+ * The dispatcher (`buildSelfContainedAlertData` in
813
+ * `workers/webhook-dispatcher/src/dispatcher.ts`) emits a SELF-CONTAINED body:
814
+ * the full rich {@link Alert} object (`watch`, `event`, `match`, `trademark`,
815
+ * `deadline`, `timestamps`, `schema_version`, `customer_reference`, `links`,
816
+ * `id`, `object`) SPREAD together with the preserved {@link AlertCreatedFlatFields}.
817
+ * Rich-first, flat-last, so the lean flat fields win on any future key overlap.
818
+ *
819
+ * The flat fields ({@link AlertCreatedFlatFields}) are ALWAYS present. The rich
820
+ * half mirrors the REST {@link Alert} resource MINUS `evaluation_epoch`
821
+ * (REST-only — the webhook carries the epoch as a flat field instead, see
822
+ * {@link AlertCreatedFlatFields.evaluation_epoch}), and is OPTIONAL: the rich
823
+ * fields (`event`, `trademark`, `match`, `watch`, `deadline`, `timestamps`,
824
+ * `schema_version`, `links`, `id`, `object`, `customer_reference`) are present
825
+ * on normal deliveries but ABSENT on the rare lean-fallback delivery — when the
826
+ * alert row was hard-deleted between emit and dispatch, hydration returns null
827
+ * and the dispatcher emits ONLY the flat fields.
828
+ *
829
+ * Consumers that read rich fields should feature-detect, e.g.
830
+ * `if (data.event) { … }`, rather than assume they are present.
831
+ */
832
+ export type AlertCreatedPayload = AlertCreatedFlatFields & Partial<Omit<Alert, 'evaluation_epoch' | 'provenance'>>;
527
833
  /** Webhook envelope for an `alert.created` delivery. */
528
834
  export type AlertCreatedEvent = WebhookEvent<AlertCreatedPayload>;
529
835
  /** Webhook endpoint status. */
@@ -618,6 +924,16 @@ export interface WatchPreviewResponse {
618
924
  * were found (partial result). Absent = exact count.
619
925
  */
620
926
  estimate_basis?: 'candidacy_upper_bound';
927
+ /**
928
+ * A page of the actual matching trademarks in the canonical summary shape
929
+ * (identical to `GET /v1/trademarks` results). Returned BY DEFAULT; omitted
930
+ * only when the request set `count_only: true`. Up to `result_limit` items.
931
+ */
932
+ results?: TrademarkSummary[];
933
+ /** Whether more matches exist beyond `results`. Omitted when count_only. */
934
+ has_more?: boolean;
935
+ /** Echo of the effective page size for `results`. Omitted when count_only. */
936
+ result_limit?: number;
621
937
  request_id: string;
622
938
  }
623
939
  /**
@@ -654,13 +970,24 @@ export interface WatchDiagnostics {
654
970
  candidacy_passed: boolean;
655
971
  trigger_event_type: string | null;
656
972
  trigger_event_in_filter: boolean;
973
+ /**
974
+ * Persisted per-match relevance score (`match_score` on the most recent
975
+ * alert for this watch+trademark); null when no alert exists or the watch
976
+ * has no scored (`q`) clause. Informational only.
977
+ */
657
978
  opensearch_score: number | null;
979
+ /**
980
+ * Stored (legacy) threshold, surfaced for existing watches that carry one.
981
+ * INERT — no longer gates matching, and rejected on new writes.
982
+ */
658
983
  score_threshold: number | null;
984
+ min_match_tier: WatchMinMatchTier | null;
659
985
  alert_fired: boolean;
660
986
  /**
661
987
  * Walked in order: alert fired → office not in scope → freshness limit →
662
- * candidacy missing → trigger event filtered → score below threshold →
663
- * rolled into digest → fallback. See the diagnostics docs for the full enum.
988
+ * candidacy missing → trigger event filtered → rolled into digest →
989
+ * fallback. (No score-threshold reason: the field is inert.) See the
990
+ * diagnostics docs for the full enum.
664
991
  */
665
992
  reason: string;
666
993
  delivery_mode_effective: 'per_alert' | 'digest' | null;
@@ -669,13 +996,15 @@ export interface WatchDiagnostics {
669
996
  /** Alert's frozen `evaluation_epoch` when emitted under a replay-bumped epoch; null otherwise. */
670
997
  replay_epoch_origin: number | null;
671
998
  last_relevant_sync_run: {
672
- id: string;
673
999
  office_code: string;
674
1000
  completed_at: string | null;
675
1001
  search_indexed_at: string | null;
676
1002
  } | null;
677
- /** `event_outbox` UUID — cross-reference against the `webhook-id` on delivery audit rows. */
678
- outbox_event_id: string | null;
1003
+ /**
1004
+ * Public ID (`alt_*`) of the alert that fired, or null. Cross-reference
1005
+ * against `alert_id` on `webhooks.listDeliveries()` rows.
1006
+ */
1007
+ alert_id: string | null;
679
1008
  opposition: {
680
1009
  must_act_by: string | null;
681
1010
  rule_source: string | null;
@@ -697,6 +1026,105 @@ export interface WatchDiagnosticsParams {
697
1026
  /** Required prefixed trademark ID (`tm_*`). */
698
1027
  trademarkId: string;
699
1028
  }
1029
+ /** A disclosed coverage gap on a per-office attestation entry. */
1030
+ export interface WatchAttestationGap {
1031
+ from: string;
1032
+ through: string;
1033
+ /**
1034
+ * `office_lagging` = coverage was stale beyond the office SLO for this
1035
+ * interval. `evaluation_failed` is reserved (not emitted in v1: gaps cover
1036
+ * coverage-staleness only).
1037
+ */
1038
+ reason: 'office_lagging' | 'evaluation_failed';
1039
+ /** True once coverage caught back up within the period. */
1040
+ resolved: boolean;
1041
+ }
1042
+ /**
1043
+ * Per-office attestation entry. `status: 'unsupported'` (an in-scope office
1044
+ * Signa does not ingest) carries NO evaluation claims — the numeric fields are
1045
+ * omitted entirely. `status: 'no_evaluations'` (a supported office with zero
1046
+ * evaluations in the period) carries zero counts, no coverage claims, and a
1047
+ * full-period gap — an un-evaluated month never reads as a clean silent month.
1048
+ */
1049
+ export interface WatchAttestationOffice {
1050
+ office_code: string;
1051
+ office_name: string;
1052
+ status: 'evaluated' | 'no_evaluations' | 'unsupported';
1053
+ evaluations_count?: number;
1054
+ sync_runs_evaluated?: string[];
1055
+ /**
1056
+ * Changes evaluated against your query this period (candidacy volume). NOT
1057
+ * the size of the whole office corpus.
1058
+ */
1059
+ changes_evaluated?: number;
1060
+ match_count?: number;
1061
+ alerts_emitted?: number;
1062
+ coverage_from?: string | null;
1063
+ coverage_through?: string | null;
1064
+ coverage_basis?: 'source_dates' | 'date_range' | 'run_completed' | null;
1065
+ gaps?: WatchAttestationGap[];
1066
+ }
1067
+ /**
1068
+ * The filable monthly proof-of-monitoring artifact. Deterministic for a closed
1069
+ * period: re-fetch and compare `content_hash` to verify integrity. The hash
1070
+ * excludes `generated_at`, `request_id`, `content_hash`,
1071
+ * `watch_status_at_generation`, `watch.name`, and
1072
+ * `watch.configuration_changed_since_period` (generation-time / display-only
1073
+ * facts).
1074
+ */
1075
+ export interface WatchAttestation {
1076
+ object: 'watch_attestation';
1077
+ schema_version: string;
1078
+ watch: {
1079
+ id: string;
1080
+ /** Display-only; excluded from `content_hash` (mutable via PATCH). */
1081
+ name: string;
1082
+ query_fingerprint: string;
1083
+ /**
1084
+ * The fingerprint describes the CURRENT watch configuration (a true
1085
+ * evaluated-time snapshot requires the deferred watch-revision history).
1086
+ */
1087
+ fingerprint_basis: 'current_configuration';
1088
+ trigger_events: string[];
1089
+ /** Evaluation-epoch deltas occurred WITHIN the period. */
1090
+ configuration_changed_in_period: boolean;
1091
+ /**
1092
+ * The live configuration is ahead of every epoch seen in the period (a
1093
+ * post-period change happened; the fingerprint no longer describes the
1094
+ * period). Generation-time fact; excluded from `content_hash`.
1095
+ */
1096
+ configuration_changed_since_period: boolean;
1097
+ epochs_in_period?: number[];
1098
+ };
1099
+ period: {
1100
+ start: string;
1101
+ end: string;
1102
+ partial: boolean;
1103
+ };
1104
+ offices: WatchAttestationOffice[];
1105
+ totals: {
1106
+ evaluations: number;
1107
+ alerts_emitted: number;
1108
+ };
1109
+ reconciliation: 'consistent' | 'mismatch';
1110
+ statement: string;
1111
+ slo_reference: string;
1112
+ /**
1113
+ * Present ('paused' | 'disabled') when the watch is not active at generation
1114
+ * time. Pause history within the period is not reconstructable in v1.
1115
+ * Generation-time fact; excluded from `content_hash`.
1116
+ */
1117
+ watch_status_at_generation?: string;
1118
+ generated_at: string;
1119
+ content_hash: string;
1120
+ request_id: string;
1121
+ }
1122
+ export interface WatchAttestationParams {
1123
+ /** UTC calendar month `YYYY-MM`. Default: previous month. */
1124
+ period?: string;
1125
+ /** Set true to allow an interim artifact for the current (open) month. */
1126
+ partial?: boolean;
1127
+ }
700
1128
  /** Result of `webhooks.test()`. */
701
1129
  export interface WebhookTestResponse {
702
1130
  object: 'webhook_test';
@@ -709,22 +1137,24 @@ export interface WebhookRedeliveryResponse {
709
1137
  delivery_attempt_id: string;
710
1138
  request_id: string;
711
1139
  }
712
- /** Org-level event list item. */
1140
+ /** Org-level event list item. IDs are evt_-prefixed opaque strings. */
713
1141
  export interface OrgEvent {
714
- id: number;
1142
+ id: string;
715
1143
  object: 'event';
716
- event_type: string;
1144
+ type: string;
717
1145
  trademark_id: string;
718
1146
  office_code: string;
719
1147
  created_at: string;
720
1148
  }
721
- /** Org-level event detail (with changes). */
1149
+ /** Org-level event detail (with field-level before/after diffs). */
722
1150
  export interface OrgEventDetail extends OrgEvent {
723
- changes: Array<{
724
- field: string;
1151
+ version: number;
1152
+ changed_fields: string[];
1153
+ changes: Record<string, {
725
1154
  before: unknown;
726
1155
  after: unknown;
727
1156
  }>;
1157
+ request_id: string;
728
1158
  }
729
1159
  /** Identity (GET /v1/organization/me). */
730
1160
  export type Identity = components['schemas']['Identity'];
@@ -750,6 +1180,12 @@ export type UsageSummaryResponse = components['schemas']['UsageSummaryResponse']
750
1180
  export type UsageSummaryItem = components['schemas']['UsageSummaryItem'];
751
1181
  /** Billing period context on a usage summary response. */
752
1182
  export type UsageBillingPeriod = components['schemas']['BillingPeriodContext'];
1183
+ /** Pooled credit balance response (GET /v1/organization/credits). */
1184
+ export type CreditBalance = components['schemas']['CreditBalanceResponse'];
1185
+ /** Remaining-credit breakdown by grant type on a credit balance response. */
1186
+ export type CreditGrantBreakdown = components['schemas']['CreditGrantBreakdown'];
1187
+ /** A single grant entry in the credit expiry schedule. */
1188
+ export type CreditExpiryScheduleEntry = components['schemas']['CreditExpiryScheduleEntry'];
753
1189
  /** Generic delete confirmation. */
754
1190
  export interface DeletedResponse {
755
1191
  id: string;
@@ -763,26 +1199,87 @@ export type TrademarkSource = components['schemas']['TrademarkSourceResponse'];
763
1199
  export type TrademarkCoverage = components['schemas']['TrademarkCoverage'];
764
1200
  /** Trademark proceeding (with parties) as returned by /trademarks/{id}/proceedings. */
765
1201
  export type TrademarkProceeding = components['schemas']['TrademarkProceedingSub'];
1202
+ /** Source synchronization state for lazy trademark document metadata. */
1203
+ export interface TrademarkDocumentSourceSync {
1204
+ status: 'synced' | 'pending' | 'unsupported';
1205
+ last_synced_at: string | null;
1206
+ }
1207
+ /** Trademark office document metadata returned by /trademarks/{id}/documents. */
1208
+ export interface TrademarkDocument {
1209
+ id: string;
1210
+ object: 'trademark_document';
1211
+ document_kind: 'office_action' | 'certificate' | 'correspondence' | 'filed_form' | 'other';
1212
+ official_date: string | null;
1213
+ description: string | null;
1214
+ mime_type: string;
1215
+ page_count: number | null;
1216
+ url: string;
1217
+ }
766
1218
  /** Owner related entity (GLEIF corporate hierarchy). */
767
1219
  export type OwnerRelated = components['schemas']['OwnerRelated'];
1220
+ /**
1221
+ * A `search_meta.warnings[]` element (mirror of the API spec). Two families
1222
+ * share this shape:
1223
+ * • strategy-skip warnings — a REQUESTED strategy produced zero clauses for
1224
+ * the query shape (e.g. `strategies=[phonetic]` on a query too short or
1225
+ * high-collision); carries `strategy`.
1226
+ * • filter-coverage warnings — an applied filter (e.g. `opposition_status`,
1227
+ * `seniority_claims`) has partial index coverage; carries `severity`,
1228
+ * `affected_filter`, `affected_offices`, `behavior`.
1229
+ */
1230
+ export interface SearchWarning {
1231
+ code: string;
1232
+ message: string;
1233
+ strategy?: string;
1234
+ severity?: 'info' | 'warning';
1235
+ affected_filter?: string;
1236
+ /** WIPO ST.3 office codes (e.g. 'US', 'EM', 'WO') affected by the caveat. */
1237
+ affected_offices?: string[];
1238
+ behavior?: string;
1239
+ }
768
1240
  /** Search metadata (V2 — timing, totals, strategy info). */
1241
+ /**
1242
+ * ENG-106 — how the query text is matched against the mark text.
1243
+ * `similar` (default) runs the ranked strategies ladder (relevance scoring).
1244
+ * `exact` | `starts_with` | `ends_with` | `contains` are deterministic
1245
+ * (date-led sort, `relevance_score` null on every row). Deterministic modes
1246
+ * require a query and disallow `strategies` / `ranking_profile`; `contains`
1247
+ * additionally needs a folded query of at least 3 characters.
1248
+ */
1249
+ export type MatchMode = 'similar' | 'exact' | 'starts_with' | 'ends_with' | 'contains';
769
1250
  export interface SearchMeta {
770
1251
  search_id: string;
771
- query: string;
1252
+ query: string | null;
1253
+ /** Public strategies used for the served set. Empty `[]` for deterministic match modes. */
772
1254
  strategies_used: string[];
773
1255
  /**
774
- * Total matching results. Only present when the caller set
775
- * `options.include_total = true` (or requested aggregations). Absent
776
- * on default searches so the API can skip OpenSearch hit counting
777
- * and return faster on broad queries. See api-spec-v1 §5.
1256
+ * ENG-106 — the match mode actually applied. Echoed for ALL modes (including
1257
+ * `'similar'`).
1258
+ */
1259
+ match: MatchMode;
1260
+ international_registrations: 'grouped' | 'expanded';
1261
+ fallback_reason?: string;
1262
+ /**
1263
+ * The `jurisdictions` matching mode actually applied: `'protection'` (default,
1264
+ * regional-membership expansion) or `'direct'` (literal territory legs).
1265
+ * Echoed on every response, including when no `jurisdictions` filter is present.
1266
+ */
1267
+ territory_match: TerritoryMatchMode;
1268
+ /**
1269
+ * Search warnings. Two families share this array: per-strategy skip warnings
1270
+ * (a REQUESTED strategy produced zero clauses for the query shape) and
1271
+ * filter-coverage warnings (an applied filter has partial index coverage).
1272
+ * Omitted when there is nothing to warn about.
778
1273
  */
779
- total_results?: number;
1274
+ warnings?: SearchWarning[];
780
1275
  /**
781
- * `true` if `total_results` is an exact count, `false` if it is a
782
- * lower bound (capped at 10k). Only present when `total_results` is
783
- * present.
1276
+ * NOTE: the total matching-result count is NOT on `search_meta`. It surfaces
1277
+ * as `pagination.total_count` (+ `pagination.total_count_approximate`) when
1278
+ * the caller sets `options.include_total = true` — see
1279
+ * `SignaList.total_count`. The former `search_meta.total_results` /
1280
+ * `total_count_exact` / `total_count_approximate` fields were removed in the
1281
+ * ENG-14 beta break.
784
1282
  */
785
- total_count_exact?: boolean;
786
1283
  execution_time_ms: number;
787
1284
  }
788
1285
  /** API error body (RFC 9457-inspired). */
@@ -803,17 +1300,43 @@ export interface APIErrorBody {
803
1300
  /** Server-suggested seconds to wait before retrying (body-level mirror of the Retry-After header). */
804
1301
  retry_after?: number;
805
1302
  }
1303
+ export type TrademarkSearchInclude = 'full_goods_services';
1304
+ export type TrademarkDetailInclude = 'office_extensions';
1305
+ /**
1306
+ * How a `jurisdictions` filter matches. `protection` (default) selects rights
1307
+ * that protect, or seek protection, in the requested territory: a country
1308
+ * request also matches regional rights whose membership covers it (a EUTM for
1309
+ * `jurisdictions: ['FR']`). `direct` matches only literal territory legs
1310
+ * (national filings + Madrid designations of the exact territory), reproducing
1311
+ * the pre-2026-07 behavior. Inert when no `jurisdictions` filter is present.
1312
+ */
1313
+ export type TerritoryMatchMode = 'protection' | 'direct';
1314
+ export type OppositionStatus = 'open' | 'not_started' | 'closed' | 'unknown';
1315
+ export type SeniorityClaims = 'claimed' | 'none' | 'unknown';
806
1316
  export interface TrademarkRetrieveParams {
807
1317
  /**
808
- * Optional relations to embed alongside the trademark detail.
1318
+ * Optional detail projections.
809
1319
  *
810
- * Currently only `history` is supported. Including `history` embeds the 50
811
- * most recent prosecution events with a `has_more` indicator. Owners,
812
- * classifications, attorneys, media, priorities, proceedings, and Madrid
813
- * coverage are always returned inline at the detail tier.
1320
+ * `office_extensions` includes the raw office-specific extension blob,
1321
+ * which is omitted from the default detail response.
814
1322
  */
815
- include?: Array<'history'>;
1323
+ include?: TrademarkDetailInclude[];
1324
+ /** Sparse top-level field projection. `id` and `object` are always retained. */
1325
+ fields?: string[];
1326
+ /**
1327
+ * Preferred goods/services language for classification rows. When multiple
1328
+ * language variants exist for the same Nice class, the API returns the
1329
+ * requested language if present; groups without that language keep all rows
1330
+ * in default classification order.
1331
+ */
1332
+ language?: string;
816
1333
  }
1334
+ /**
1335
+ * ENG-67 — the closed set of faceted aggregation dimensions accepted by both
1336
+ * `GET /v1/trademarks?aggregations=` and `POST /v1/trademarks` `options.aggregations`.
1337
+ * Mirrors the server-side `AggregationEnum` and the generated OpenAPI enum.
1338
+ */
1339
+ export type TrademarkAggregationName = 'status_stage' | 'office_code' | 'jurisdiction_code' | 'nice_classes' | 'filing_year' | 'mark_feature_type' | 'mark_legal_category' | 'filing_route' | 'right_kind' | 'scope_kind' | 'firm_id' | 'attorney_id' | 'owner_country' | 'owner_id' | 'entity_id';
817
1340
  export interface TrademarkListParams {
818
1341
  /**
819
1342
  * Coarse status bucket. Accepts a single value or an array to match any of
@@ -833,11 +1356,25 @@ export interface TrademarkListParams {
833
1356
  registration_number?: string;
834
1357
  ir_number?: string;
835
1358
  office?: string;
1359
+ /**
1360
+ * Jurisdiction codes selecting rights that protect, or seek protection, in
1361
+ * these territories. Protection-scope by default (a EUTM matches
1362
+ * `jurisdictions: ['FR']`); see `territory_match` to control expansion.
1363
+ */
836
1364
  jurisdictions?: string | string[];
1365
+ /** How `jurisdictions` matches: `protection` (default) or `direct`. */
1366
+ territory_match?: TerritoryMatchMode;
837
1367
  offices?: string | string[];
838
1368
  owner_country?: string;
839
1369
  nice_classes?: number | number[];
840
1370
  vienna_codes?: string | string[];
1371
+ us_design_codes?: string | string[];
1372
+ filing_basis?: string | string[];
1373
+ us_register_type?: 'principal' | 'supplemental';
1374
+ opposition_status?: OppositionStatus;
1375
+ opposition_closes_before?: string;
1376
+ opposition_closes_after?: string;
1377
+ seniority_claims?: SeniorityClaims;
841
1378
  filing_date_gte?: string;
842
1379
  filing_date_gt?: string;
843
1380
  filing_date_lte?: string;
@@ -858,6 +1395,22 @@ export interface TrademarkListParams {
858
1395
  publication_date_gt?: string;
859
1396
  publication_date_lte?: string;
860
1397
  publication_date_lt?: string;
1398
+ status_effective_date_gte?: string;
1399
+ status_effective_date_gt?: string;
1400
+ status_effective_date_lte?: string;
1401
+ status_effective_date_lt?: string;
1402
+ priority_date_gte?: string;
1403
+ priority_date_gt?: string;
1404
+ priority_date_lte?: string;
1405
+ priority_date_lt?: string;
1406
+ first_use_anywhere_date_gte?: string;
1407
+ first_use_anywhere_date_gt?: string;
1408
+ first_use_anywhere_date_lte?: string;
1409
+ first_use_anywhere_date_lt?: string;
1410
+ first_use_in_commerce_date_gte?: string;
1411
+ first_use_in_commerce_date_gt?: string;
1412
+ first_use_in_commerce_date_lte?: string;
1413
+ first_use_in_commerce_date_lt?: string;
861
1414
  termination_date_gte?: string;
862
1415
  termination_date_gt?: string;
863
1416
  termination_date_lte?: string;
@@ -892,18 +1445,36 @@ export interface TrademarkListParams {
892
1445
  is_madrid?: boolean;
893
1446
  is_retracted?: boolean;
894
1447
  is_series_mark?: boolean;
1448
+ international_registrations?: 'grouped' | 'expanded';
895
1449
  /** Optional text query (triggers relevance ranking when no explicit sort). */
896
1450
  q?: string;
1451
+ /** ENG-67 — faceted bucket counts (TMview "Statistics view"). Field names to aggregate. */
1452
+ aggregations?: TrademarkAggregationName[];
1453
+ /** ENG-67 — when true, return only aggregation counts (no result documents). */
1454
+ aggregations_only?: boolean;
897
1455
  /** Search strategies to apply (e.g. 'exact', 'phonetic', 'fuzzy', 'prefix'). */
898
1456
  strategies?: string[];
899
1457
  /** Ranking profile to use. */
900
1458
  ranking_profile?: string;
1459
+ /**
1460
+ * ENG-106 — how `q` matches the mark text. `'similar'` (default, ranked) vs
1461
+ * the deterministic `'exact'` / `'starts_with'` / `'ends_with'` / `'contains'`
1462
+ * modes. Deterministic modes require `q` and disallow `strategies` /
1463
+ * `ranking_profile`; `'contains'` needs a folded query ≥ 3 chars.
1464
+ */
1465
+ match?: MatchMode;
1466
+ /** ENG-106 — exclude marks whose text contains this substring (case/accent-insensitive). Composable with any match mode. */
1467
+ mark_text_not_contains?: string;
901
1468
  /** When true, include total_count in pagination (adds latency). */
902
1469
  include_total?: boolean;
903
1470
  /** When true, include match highlight spans. */
904
1471
  highlights?: boolean;
905
1472
  /** When true, include execution timing in search_meta. */
906
1473
  include_timing?: boolean;
1474
+ /** Optional row projections. `full_goods_services` disables summary G&S truncation. */
1475
+ include?: TrademarkSearchInclude[];
1476
+ /** Sparse top-level field projection. `id` and `object` are always retained. */
1477
+ fields?: string[];
907
1478
  goods_services_text?: string;
908
1479
  origin_office_code?: string;
909
1480
  renewal_due_before?: string;
@@ -938,6 +1509,8 @@ export interface TrademarkRelatedParams {
938
1509
  export interface TrademarkSuggestParams {
939
1510
  q: string;
940
1511
  jurisdictions?: string | string[];
1512
+ /** How `jurisdictions` matches: `protection` (default) or `direct`. */
1513
+ territory_match?: TerritoryMatchMode;
941
1514
  nice_classes?: number | number[];
942
1515
  status_stage?: string | string[];
943
1516
  }
@@ -952,6 +1525,20 @@ export interface TrademarkProceedingsParams {
952
1525
  limit?: number;
953
1526
  cursor?: string;
954
1527
  }
1528
+ export interface TrademarkAssignmentsParams {
1529
+ conveyance_type?: ConveyanceType;
1530
+ /** Alias for conveyance_type. */
1531
+ type?: ConveyanceType;
1532
+ limit?: number;
1533
+ cursor?: string;
1534
+ }
1535
+ export interface TrademarkDocumentParams {
1536
+ document_kind?: TrademarkDocument['document_kind'] | TrademarkDocument['document_kind'][];
1537
+ official_date_gte?: string;
1538
+ official_date_lt?: string;
1539
+ limit?: number;
1540
+ cursor?: string;
1541
+ }
955
1542
  export interface OwnerRelatedParams {
956
1543
  limit?: number;
957
1544
  cursor?: string;
@@ -961,11 +1548,9 @@ export interface OwnerRelatedParams {
961
1548
  * always returns the full detail tier (aliases, identifiers, stats, public
962
1549
  * companies). This empty params type is reserved for future use.
963
1550
  */
964
- export interface OwnerRetrieveParams {
965
- }
1551
+ export type OwnerRetrieveParams = Record<string, never>;
966
1552
  /** Entity detail accepts no query parameters (reserved for future use). */
967
- export interface EntityRetrieveParams {
968
- }
1553
+ export type EntityRetrieveParams = Record<string, never>;
969
1554
  export interface EntityListParams {
970
1555
  q?: string;
971
1556
  country_code?: string;
@@ -983,10 +1568,14 @@ export interface EntityListParams {
983
1568
  * Trademark filters for `GET /v1/entities/{id}/trademarks` — the same
984
1569
  * Appendix-A filter set as the owner/attorney sub-resources (it runs through
985
1570
  * the same `listTrademarksViaSearch` path), fanned out across ALL member owners.
1571
+ *
1572
+ * `include_family` (ENG-117) additionally expands the set to this entity AND all
1573
+ * of its family-tree descendants (via `entities.parent_entity_id`).
986
1574
  */
987
- export type EntityTrademarksParams = OwnerTrademarksParams;
988
- export interface EntityFamilyParams {
989
- }
1575
+ export type EntityTrademarksParams = OwnerTrademarksParams & {
1576
+ include_family?: boolean;
1577
+ };
1578
+ export type EntityFamilyParams = Record<string, never>;
990
1579
  export interface OwnerListParams {
991
1580
  q?: string;
992
1581
  country_code?: string;
@@ -995,7 +1584,11 @@ export interface OwnerListParams {
995
1584
  lei?: string;
996
1585
  publicly_traded?: boolean;
997
1586
  has_lei?: boolean;
998
- sort?: '-trademark_count' | 'trademark_count' | '-registration_rate' | 'registration_rate' | '-latest_filing' | 'latest_filing' | '-name' | 'name';
1587
+ sort?: '-trademark_count' | 'trademark_count'
1588
+ /** @deprecated Use `grant_rate` — same value. */
1589
+ | '-registration_rate'
1590
+ /** @deprecated Use `grant_rate` — same value. */
1591
+ | 'registration_rate' | '-grant_rate' | 'grant_rate' | '-latest_filing' | 'latest_filing' | '-name' | 'name';
999
1592
  include_total?: boolean;
1000
1593
  limit?: number;
1001
1594
  cursor?: string;
@@ -1019,11 +1612,25 @@ export interface OwnerTrademarksParams {
1019
1612
  registration_number?: string;
1020
1613
  ir_number?: string;
1021
1614
  office?: string;
1615
+ /**
1616
+ * Jurisdiction codes selecting rights that protect, or seek protection, in
1617
+ * these territories. Protection-scope by default (a EUTM matches
1618
+ * `jurisdictions: ['FR']`); see `territory_match` to control expansion.
1619
+ */
1022
1620
  jurisdictions?: string | string[];
1621
+ /** How `jurisdictions` matches: `protection` (default) or `direct`. */
1622
+ territory_match?: TerritoryMatchMode;
1023
1623
  offices?: string | string[];
1024
1624
  owner_country?: string;
1025
1625
  nice_classes?: number | number[];
1026
1626
  vienna_codes?: string | string[];
1627
+ us_design_codes?: string | string[];
1628
+ filing_basis?: string | string[];
1629
+ us_register_type?: 'principal' | 'supplemental';
1630
+ opposition_status?: OppositionStatus;
1631
+ opposition_closes_before?: string;
1632
+ opposition_closes_after?: string;
1633
+ seniority_claims?: SeniorityClaims;
1027
1634
  filing_date_gte?: string;
1028
1635
  filing_date_gt?: string;
1029
1636
  filing_date_lte?: string;
@@ -1044,6 +1651,22 @@ export interface OwnerTrademarksParams {
1044
1651
  publication_date_gt?: string;
1045
1652
  publication_date_lte?: string;
1046
1653
  publication_date_lt?: string;
1654
+ status_effective_date_gte?: string;
1655
+ status_effective_date_gt?: string;
1656
+ status_effective_date_lte?: string;
1657
+ status_effective_date_lt?: string;
1658
+ priority_date_gte?: string;
1659
+ priority_date_gt?: string;
1660
+ priority_date_lte?: string;
1661
+ priority_date_lt?: string;
1662
+ first_use_anywhere_date_gte?: string;
1663
+ first_use_anywhere_date_gt?: string;
1664
+ first_use_anywhere_date_lte?: string;
1665
+ first_use_anywhere_date_lt?: string;
1666
+ first_use_in_commerce_date_gte?: string;
1667
+ first_use_in_commerce_date_gt?: string;
1668
+ first_use_in_commerce_date_lte?: string;
1669
+ first_use_in_commerce_date_lt?: string;
1047
1670
  termination_date_gte?: string;
1048
1671
  termination_date_gt?: string;
1049
1672
  termination_date_lte?: string;
@@ -1064,6 +1687,20 @@ export interface OwnerTrademarksParams {
1064
1687
  is_madrid?: boolean;
1065
1688
  is_retracted?: boolean;
1066
1689
  is_series_mark?: boolean;
1690
+ international_registrations?: 'grouped' | 'expanded';
1691
+ include_total?: boolean;
1692
+ include?: TrademarkSearchInclude[];
1693
+ fields?: string[];
1694
+ /** Text query to match against the mark text within this portfolio. Required for any deterministic `match` mode. */
1695
+ q?: string;
1696
+ /**
1697
+ * ENG-106 — how `q` matches the mark text. `'similar'` (default, ranked) vs
1698
+ * the deterministic `'exact'` / `'starts_with'` / `'ends_with'` / `'contains'`
1699
+ * modes. Deterministic modes require `q`; `'contains'` needs a folded query ≥ 3 chars.
1700
+ */
1701
+ match?: MatchMode;
1702
+ /** ENG-106 — exclude marks whose text contains this substring (case/accent-insensitive). Composable with any match mode. */
1703
+ mark_text_not_contains?: string;
1067
1704
  limit?: number;
1068
1705
  cursor?: string;
1069
1706
  }
@@ -1072,13 +1709,16 @@ export interface OwnerTrademarksParams {
1072
1709
  * always returns the full detail tier (aliases, identifiers, scalar stats).
1073
1710
  * This empty params type is reserved for future use.
1074
1711
  */
1075
- export interface AttorneyRetrieveParams {
1076
- }
1712
+ export type AttorneyRetrieveParams = Record<string, never>;
1077
1713
  export interface AttorneyListParams {
1078
1714
  q?: string;
1079
1715
  firm_id?: string;
1080
1716
  country_code?: string;
1081
- sort?: '-trademark_count' | 'trademark_count' | '-name' | 'name';
1717
+ sort?: '-trademark_count' | 'trademark_count'
1718
+ /** @deprecated Use `grant_rate` — same value. */
1719
+ | '-registration_rate'
1720
+ /** @deprecated Use `grant_rate` — same value. */
1721
+ | 'registration_rate' | '-grant_rate' | 'grant_rate' | '-avg_prosecution_days' | 'avg_prosecution_days' | '-latest_filing' | 'latest_filing' | '-name' | 'name';
1082
1722
  limit?: number;
1083
1723
  cursor?: string;
1084
1724
  }
@@ -1101,11 +1741,25 @@ export interface AttorneyTrademarksParams {
1101
1741
  registration_number?: string;
1102
1742
  ir_number?: string;
1103
1743
  office?: string;
1744
+ /**
1745
+ * Jurisdiction codes selecting rights that protect, or seek protection, in
1746
+ * these territories. Protection-scope by default (a EUTM matches
1747
+ * `jurisdictions: ['FR']`); see `territory_match` to control expansion.
1748
+ */
1104
1749
  jurisdictions?: string | string[];
1750
+ /** How `jurisdictions` matches: `protection` (default) or `direct`. */
1751
+ territory_match?: TerritoryMatchMode;
1105
1752
  offices?: string | string[];
1106
1753
  owner_country?: string;
1107
1754
  nice_classes?: number | number[];
1108
1755
  vienna_codes?: string | string[];
1756
+ us_design_codes?: string | string[];
1757
+ filing_basis?: string | string[];
1758
+ us_register_type?: 'principal' | 'supplemental';
1759
+ opposition_status?: OppositionStatus;
1760
+ opposition_closes_before?: string;
1761
+ opposition_closes_after?: string;
1762
+ seniority_claims?: SeniorityClaims;
1109
1763
  filing_date_gte?: string;
1110
1764
  filing_date_gt?: string;
1111
1765
  filing_date_lte?: string;
@@ -1126,6 +1780,22 @@ export interface AttorneyTrademarksParams {
1126
1780
  publication_date_gt?: string;
1127
1781
  publication_date_lte?: string;
1128
1782
  publication_date_lt?: string;
1783
+ status_effective_date_gte?: string;
1784
+ status_effective_date_gt?: string;
1785
+ status_effective_date_lte?: string;
1786
+ status_effective_date_lt?: string;
1787
+ priority_date_gte?: string;
1788
+ priority_date_gt?: string;
1789
+ priority_date_lte?: string;
1790
+ priority_date_lt?: string;
1791
+ first_use_anywhere_date_gte?: string;
1792
+ first_use_anywhere_date_gt?: string;
1793
+ first_use_anywhere_date_lte?: string;
1794
+ first_use_anywhere_date_lt?: string;
1795
+ first_use_in_commerce_date_gte?: string;
1796
+ first_use_in_commerce_date_gt?: string;
1797
+ first_use_in_commerce_date_lte?: string;
1798
+ first_use_in_commerce_date_lt?: string;
1129
1799
  termination_date_gte?: string;
1130
1800
  termination_date_gt?: string;
1131
1801
  termination_date_lte?: string;
@@ -1146,6 +1816,20 @@ export interface AttorneyTrademarksParams {
1146
1816
  is_madrid?: boolean;
1147
1817
  is_retracted?: boolean;
1148
1818
  is_series_mark?: boolean;
1819
+ international_registrations?: 'grouped' | 'expanded';
1820
+ include_total?: boolean;
1821
+ include?: TrademarkSearchInclude[];
1822
+ fields?: string[];
1823
+ /** Text query to match against the mark text within this portfolio. Required for any deterministic `match` mode. */
1824
+ q?: string;
1825
+ /**
1826
+ * ENG-106 — how `q` matches the mark text. `'similar'` (default, ranked) vs
1827
+ * the deterministic `'exact'` / `'starts_with'` / `'ends_with'` / `'contains'`
1828
+ * modes. Deterministic modes require `q`; `'contains'` needs a folded query ≥ 3 chars.
1829
+ */
1830
+ match?: MatchMode;
1831
+ /** ENG-106 — exclude marks whose text contains this substring (case/accent-insensitive). Composable with any match mode. */
1832
+ mark_text_not_contains?: string;
1149
1833
  limit?: number;
1150
1834
  cursor?: string;
1151
1835
  }
@@ -1154,14 +1838,18 @@ export interface AttorneyClientsParams {
1154
1838
  cursor?: string;
1155
1839
  }
1156
1840
  export interface FirmRetrieveParams {
1157
- include?: Array<'stats' | 'specializations' | 'jurisdictions' | 'trend' | 'attorneys'>;
1841
+ include?: Array<'attorneys'>;
1158
1842
  }
1159
1843
  export interface FirmListParams {
1160
1844
  q?: string;
1161
1845
  country_code?: string;
1162
1846
  min_attorneys?: number;
1163
1847
  min_filings?: number;
1164
- sort?: '-trademark_count' | 'trademark_count' | '-attorney_count' | 'attorney_count' | '-registration_rate' | 'registration_rate' | '-name' | 'name';
1848
+ sort?: '-trademark_count' | 'trademark_count' | '-attorney_count' | 'attorney_count'
1849
+ /** @deprecated Use `grant_rate` — same value. */
1850
+ | '-registration_rate'
1851
+ /** @deprecated Use `grant_rate` — same value. */
1852
+ | 'registration_rate' | '-grant_rate' | 'grant_rate' | '-name' | 'name';
1165
1853
  limit?: number;
1166
1854
  cursor?: string;
1167
1855
  }
@@ -1188,11 +1876,25 @@ export interface FirmTrademarksParams {
1188
1876
  registration_number?: string;
1189
1877
  ir_number?: string;
1190
1878
  office?: string;
1879
+ /**
1880
+ * Jurisdiction codes selecting rights that protect, or seek protection, in
1881
+ * these territories. Protection-scope by default (a EUTM matches
1882
+ * `jurisdictions: ['FR']`); see `territory_match` to control expansion.
1883
+ */
1191
1884
  jurisdictions?: string | string[];
1885
+ /** How `jurisdictions` matches: `protection` (default) or `direct`. */
1886
+ territory_match?: TerritoryMatchMode;
1192
1887
  offices?: string | string[];
1193
1888
  owner_country?: string;
1194
1889
  nice_classes?: number | number[];
1195
1890
  vienna_codes?: string | string[];
1891
+ us_design_codes?: string | string[];
1892
+ filing_basis?: string | string[];
1893
+ us_register_type?: 'principal' | 'supplemental';
1894
+ opposition_status?: OppositionStatus;
1895
+ opposition_closes_before?: string;
1896
+ opposition_closes_after?: string;
1897
+ seniority_claims?: SeniorityClaims;
1196
1898
  filing_date_gte?: string;
1197
1899
  filing_date_gt?: string;
1198
1900
  filing_date_lte?: string;
@@ -1213,6 +1915,22 @@ export interface FirmTrademarksParams {
1213
1915
  publication_date_gt?: string;
1214
1916
  publication_date_lte?: string;
1215
1917
  publication_date_lt?: string;
1918
+ status_effective_date_gte?: string;
1919
+ status_effective_date_gt?: string;
1920
+ status_effective_date_lte?: string;
1921
+ status_effective_date_lt?: string;
1922
+ priority_date_gte?: string;
1923
+ priority_date_gt?: string;
1924
+ priority_date_lte?: string;
1925
+ priority_date_lt?: string;
1926
+ first_use_anywhere_date_gte?: string;
1927
+ first_use_anywhere_date_gt?: string;
1928
+ first_use_anywhere_date_lte?: string;
1929
+ first_use_anywhere_date_lt?: string;
1930
+ first_use_in_commerce_date_gte?: string;
1931
+ first_use_in_commerce_date_gt?: string;
1932
+ first_use_in_commerce_date_lte?: string;
1933
+ first_use_in_commerce_date_lt?: string;
1216
1934
  termination_date_gte?: string;
1217
1935
  termination_date_gt?: string;
1218
1936
  termination_date_lte?: string;
@@ -1233,15 +1951,33 @@ export interface FirmTrademarksParams {
1233
1951
  is_madrid?: boolean;
1234
1952
  is_retracted?: boolean;
1235
1953
  is_series_mark?: boolean;
1954
+ international_registrations?: 'grouped' | 'expanded';
1955
+ include_total?: boolean;
1956
+ include?: TrademarkSearchInclude[];
1957
+ fields?: string[];
1958
+ /** Text query to match against the mark text within this portfolio. Required for any deterministic `match` mode. */
1959
+ q?: string;
1960
+ /**
1961
+ * ENG-106 — how `q` matches the mark text. `'similar'` (default, ranked) vs
1962
+ * the deterministic `'exact'` / `'starts_with'` / `'ends_with'` / `'contains'`
1963
+ * modes. Deterministic modes require `q`; `'contains'` needs a folded query ≥ 3 chars.
1964
+ */
1965
+ match?: MatchMode;
1966
+ /** ENG-106 — exclude marks whose text contains this substring (case/accent-insensitive). Composable with any match mode. */
1967
+ mark_text_not_contains?: string;
1236
1968
  limit?: number;
1237
1969
  cursor?: string;
1238
1970
  }
1971
+ export type ProceedingAggregation = 'outcome' | 'party_role' | 'nice_class' | 'office_code' | 'filed_year';
1239
1972
  export interface ProceedingListParams {
1240
1973
  trademark_id?: string;
1241
1974
  proceeding_type?: string;
1242
1975
  status?: string;
1243
1976
  q?: string;
1244
1977
  party_owner_id?: string;
1978
+ party_entity_id?: string;
1979
+ /** Alias for party_entity_id. */
1980
+ entity_id?: string;
1245
1981
  party_role?: 'opponent' | 'petitioner' | 'respondent' | 'intervener' | 'other';
1246
1982
  contested_class?: number;
1247
1983
  office_code?: string;
@@ -1249,10 +1985,26 @@ export interface ProceedingListParams {
1249
1985
  filed_date_lt?: string;
1250
1986
  decision_date_gte?: string;
1251
1987
  decision_date_lt?: string;
1988
+ aggregations?: ProceedingAggregation[];
1252
1989
  sort?: '-filed_date' | 'filed_date' | '-decided_date' | 'decided_date';
1253
1990
  limit?: number;
1254
1991
  cursor?: string;
1255
1992
  }
1993
+ export type ConveyanceType = 'assignment' | 'security_interest' | 'release' | 'merger' | 'name_change' | 'license' | 'partial_assignment' | 'correction' | 'entity_conversion' | 'other';
1994
+ export interface AssignmentListParams {
1995
+ owner_id?: string;
1996
+ entity_id?: string;
1997
+ trademark_id?: string;
1998
+ conveyance_type?: ConveyanceType | ConveyanceType[];
1999
+ /** Alias for conveyance_type. */
2000
+ type?: ConveyanceType | ConveyanceType[];
2001
+ recorded_date_gte?: string;
2002
+ recorded_date_lt?: string;
2003
+ role?: 'assignor' | 'assignee';
2004
+ sort?: '-recorded_date' | 'recorded_date';
2005
+ limit?: number;
2006
+ cursor?: string;
2007
+ }
1256
2008
  export interface ClassificationListParams {
1257
2009
  q?: string;
1258
2010
  }
@@ -1279,6 +2031,110 @@ export interface DateRangeFilter {
1279
2031
  lte?: string;
1280
2032
  lt?: string;
1281
2033
  }
2034
+ /** Normalized crop box (fractions of width/height, each in [0,1]). */
2035
+ export interface ImageSearchCrop {
2036
+ x: number;
2037
+ y: number;
2038
+ w: number;
2039
+ h: number;
2040
+ }
2041
+ /** Efficient-filtered facets for image search. */
2042
+ export interface ImageSearchFilters {
2043
+ offices?: string[];
2044
+ jurisdictions?: string[];
2045
+ statuses?: string[];
2046
+ include?: 'live' | 'all';
2047
+ nice_classes?: number[];
2048
+ feature_types?: string[];
2049
+ vienna_codes?: string[];
2050
+ design_code_keys?: string[];
2051
+ }
2052
+ export type ImageSearchChannel = 'visual' | 'logo_text' | 'exact_dup' | 'vienna_overlap';
2053
+ /**
2054
+ * Image-search request. Provide EXACTLY ONE image source: raw `image` bytes
2055
+ * (multipart upload), an `image_url` (https), or a `media_id`.
2056
+ */
2057
+ export interface TrademarkImageSearchParams {
2058
+ /** Query image bytes for a multipart upload. */
2059
+ image?: Blob | ArrayBuffer | Uint8Array;
2060
+ /** Optional filename for the uploaded part. */
2061
+ image_filename?: string;
2062
+ /** https URL of the query image (SSRF-guarded server-side). */
2063
+ image_url?: string;
2064
+ /** Existing media id (med_…) — reuse its stored vector, no re-embed. */
2065
+ media_id?: string;
2066
+ filters?: ImageSearchFilters;
2067
+ /**
2068
+ * How `filters.jurisdictions` matches: `protection` (default) or `direct`.
2069
+ * Top-level field, not nested inside `filters`.
2070
+ */
2071
+ territory_match?: TerritoryMatchMode;
2072
+ crop?: ImageSearchCrop;
2073
+ /** Bounded top-K page size (1-100, default 20). */
2074
+ limit?: number;
2075
+ /** Signal channels (default: visual, logo_text, exact_dup). */
2076
+ channels?: ImageSearchChannel[];
2077
+ }
2078
+ export interface ImageSearchSignals {
2079
+ visual: {
2080
+ score: number;
2081
+ band: 'identical' | 'strong' | 'moderate' | 'weak';
2082
+ embedding_spec: string;
2083
+ };
2084
+ logo_text: {
2085
+ query_text: string;
2086
+ matched_clause: string;
2087
+ } | null;
2088
+ exact_dup: {
2089
+ checksum_match: boolean;
2090
+ phash_distance: number | null;
2091
+ } | null;
2092
+ vienna_overlap: {
2093
+ codes: string[];
2094
+ } | null;
2095
+ }
2096
+ export interface ImageSearchHit {
2097
+ object: 'image_search_hit';
2098
+ score: number;
2099
+ band: 'identical' | 'strong' | 'moderate' | 'weak';
2100
+ signals: ImageSearchSignals;
2101
+ matched_image: {
2102
+ image_id: string;
2103
+ checksum: string;
2104
+ office: string;
2105
+ jurisdiction: string;
2106
+ thumbnail_url: string | null;
2107
+ };
2108
+ thumbnail_url: string | null;
2109
+ trademark: TrademarkSummary;
2110
+ }
2111
+ export interface ImageSearchResults {
2112
+ object: 'list';
2113
+ data: ImageSearchHit[];
2114
+ has_more: boolean;
2115
+ /**
2116
+ * ENG-19 — the returned-hit count rides `pagination.total_count`
2117
+ * (`total_count_approximate` is always `false`: image search is bounded
2118
+ * top-K, the count is exact). Both are ALWAYS emitted by this endpoint.
2119
+ * The former `search_meta.total_results` was removed in the ENG-14 beta
2120
+ * break.
2121
+ */
2122
+ pagination: {
2123
+ cursor: string | null;
2124
+ total_count: number;
2125
+ total_count_approximate: false;
2126
+ };
2127
+ search_meta: {
2128
+ search_id: string;
2129
+ query_mode: 'upload' | 'image_url' | 'media_id';
2130
+ channels: ImageSearchChannel[];
2131
+ embedding_spec: string;
2132
+ retrieval_bundle: string;
2133
+ index_version: number;
2134
+ execution_time_ms: number;
2135
+ };
2136
+ request_id?: string;
2137
+ }
1282
2138
  export interface TrademarkSearchBody {
1283
2139
  /** Optional text query. When omitted, results are filter-only. */
1284
2140
  query?: string;
@@ -1286,6 +2142,15 @@ export interface TrademarkSearchBody {
1286
2142
  strategies?: ('exact' | 'phonetic' | 'fuzzy' | 'prefix')[];
1287
2143
  /** Ranking profile to use. */
1288
2144
  ranking_profile?: string;
2145
+ /**
2146
+ * ENG-106 — how `query` matches the mark text. `'similar'` (default, ranked)
2147
+ * vs the deterministic `'exact'` / `'starts_with'` / `'ends_with'` /
2148
+ * `'contains'` modes. Deterministic modes require `query` and disallow
2149
+ * `strategies` / `ranking_profile`; `'contains'` needs a folded query ≥ 3 chars.
2150
+ */
2151
+ match?: MatchMode;
2152
+ /** ENG-106 — exclude marks whose text contains this substring (case/accent-insensitive). Composable with any match mode. */
2153
+ mark_text_not_contains?: string;
1289
2154
  filters?: {
1290
2155
  /**
1291
2156
  * Coarse status bucket. Accepts a single value or an array to match any
@@ -1306,12 +2171,23 @@ export interface TrademarkSearchBody {
1306
2171
  owner_country?: string;
1307
2172
  nice_classes?: number[];
1308
2173
  vienna_codes?: string[];
2174
+ us_design_codes?: string[];
2175
+ filing_basis?: string[];
2176
+ us_register_type?: 'principal' | 'supplemental';
2177
+ opposition_status?: OppositionStatus;
2178
+ opposition_closes_before?: string;
2179
+ opposition_closes_after?: string;
2180
+ seniority_claims?: SeniorityClaims;
1309
2181
  goods_services_text?: string;
1310
2182
  filing_date?: DateRangeFilter;
1311
2183
  registration_date?: DateRangeFilter;
1312
2184
  expiry_date?: DateRangeFilter;
1313
2185
  renewal_due_date?: DateRangeFilter;
1314
2186
  publication_date?: DateRangeFilter;
2187
+ status_effective_date?: DateRangeFilter;
2188
+ priority_date?: DateRangeFilter;
2189
+ first_use_anywhere_date?: DateRangeFilter;
2190
+ first_use_in_commerce_date?: DateRangeFilter;
1315
2191
  termination_date?: DateRangeFilter;
1316
2192
  updated_at?: DateRangeFilter;
1317
2193
  owner_id?: string;
@@ -1334,7 +2210,7 @@ export interface TrademarkSearchBody {
1334
2210
  is_series_mark?: boolean;
1335
2211
  };
1336
2212
  options?: {
1337
- aggregations?: ('status_stage' | 'office_code' | 'jurisdiction_code' | 'nice_classes' | 'filing_year' | 'mark_feature_type' | 'mark_legal_category' | 'filing_route' | 'right_kind' | 'scope_kind')[];
2213
+ aggregations?: TrademarkAggregationName[];
1338
2214
  aggregations_only?: boolean;
1339
2215
  include_total?: boolean;
1340
2216
  highlights?: boolean;
@@ -1349,6 +2225,14 @@ export interface TrademarkSearchBody {
1349
2225
  sort?: string;
1350
2226
  limit?: number;
1351
2227
  cursor?: string;
2228
+ international_registrations?: 'grouped' | 'expanded';
2229
+ /**
2230
+ * How `filters.jurisdictions` matches: `protection` (default) or `direct`.
2231
+ * Top-level field, NOT nested inside `filters`.
2232
+ */
2233
+ territory_match?: TerritoryMatchMode;
2234
+ include?: TrademarkSearchInclude[];
2235
+ fields?: string[];
1352
2236
  }
1353
2237
  /**
1354
2238
  * @deprecated Use `TrademarkSearchBody` instead. The `/v1/trademarks/search`
@@ -1447,6 +2331,59 @@ export interface SavedSearchExecuteParams {
1447
2331
  limit?: number;
1448
2332
  cursor?: string;
1449
2333
  }
2334
+ /** Feedback type discriminator. */
2335
+ export type FeedbackType = 'data_issue' | 'bug' | 'feature_request' | 'other';
2336
+ /** Feedback lifecycle status. */
2337
+ export type FeedbackStatus = 'open' | 'acknowledged' | 'resolved';
2338
+ /** A submitted feedback item. */
2339
+ export interface Feedback {
2340
+ id: string;
2341
+ object: 'feedback';
2342
+ /** Public ID (key_…) of the API key that filed this report; null if unattributed. */
2343
+ api_key_id: string | null;
2344
+ type: FeedbackType;
2345
+ status: FeedbackStatus;
2346
+ message: string;
2347
+ /** Public ID of the referenced entity, if any (tm_/own_/…). */
2348
+ resource_id: string | null;
2349
+ /** The request_id the customer referenced, echoed verbatim. */
2350
+ request_ref: string | null;
2351
+ field: string | null;
2352
+ expected_value: string | null;
2353
+ context: Record<string, unknown>;
2354
+ resolution_note: string | null;
2355
+ metadata: Record<string, string>;
2356
+ created_at: string;
2357
+ updated_at: string;
2358
+ resolved_at: string | null;
2359
+ }
2360
+ /** Body for `feedback.create(...)`. */
2361
+ export interface FeedbackCreateParams {
2362
+ type: FeedbackType;
2363
+ message: string;
2364
+ /** Optional public ID of any referenced entity (tm_/own_/att_/firm_/prc_/…). */
2365
+ resource_id?: string;
2366
+ /** Optional request_id (req_…) where the problem was observed. */
2367
+ request_id?: string;
2368
+ /** For data issues: which field is wrong. */
2369
+ field?: string;
2370
+ /** For data issues: the expected value. */
2371
+ expected_value?: string;
2372
+ metadata?: Record<string, string>;
2373
+ }
2374
+ /** Query params for `feedback.list(...)`. All filters optional and combinable. */
2375
+ export interface FeedbackListParams {
2376
+ /** Filter by type(s). */
2377
+ type?: FeedbackType | FeedbackType[];
2378
+ /** Filter by status(es). */
2379
+ status?: FeedbackStatus | FeedbackStatus[];
2380
+ /** Return feedback created at or after this time (YYYY-MM-DD or ISO 8601). */
2381
+ created_at_gte?: string;
2382
+ /** Return feedback created strictly before this time (YYYY-MM-DD or ISO 8601). */
2383
+ created_at_lt?: string;
2384
+ cursor?: string;
2385
+ limit?: number;
2386
+ }
1450
2387
  /**
1451
2388
  * Body for `watches.create(...)`.
1452
2389
  *
@@ -1465,6 +2402,11 @@ export interface WatchCreateParams {
1465
2402
  * {@link WatchDeliveryMode} union for forward compatibility.
1466
2403
  */
1467
2404
  delivery_mode?: 'always_per_alert';
2405
+ /**
2406
+ * Customer passthrough label echoed back on the watch and on every alert it
2407
+ * fires. Max 200 chars on create; pass `null` to clear.
2408
+ */
2409
+ customer_reference?: string | null;
1468
2410
  metadata?: Record<string, unknown>;
1469
2411
  }
1470
2412
  /**
@@ -1486,6 +2428,11 @@ export interface WatchUpdateParams {
1486
2428
  delivery_mode?: 'always_per_alert';
1487
2429
  /** PATCH supports active/paused only — use `pause()` / `resume()` for clarity. */
1488
2430
  status?: 'active' | 'paused';
2431
+ /**
2432
+ * Customer passthrough label echoed back on the watch and on every alert it
2433
+ * fires. Max 200 chars on create; pass `null` to clear.
2434
+ */
2435
+ customer_reference?: string | null;
1489
2436
  metadata?: Record<string, unknown>;
1490
2437
  }
1491
2438
  export interface WatchListParams {
@@ -1508,6 +2455,14 @@ export interface WatchPreviewParams {
1508
2455
  query: WatchQuery | Record<string, unknown>;
1509
2456
  /** Trial window for the dry-run match count (1..365 days). Default 7. */
1510
2457
  trial_window_days?: number;
2458
+ /**
2459
+ * Skip hydrating the matching marks and return only `estimated_match_count`.
2460
+ * The cheap path for high-frequency "how many would this catch" calls.
2461
+ * Default false — `results` are returned by default.
2462
+ */
2463
+ count_only?: boolean;
2464
+ /** Page size for `results` (1..50, default 20). Ignored when count_only. */
2465
+ result_limit?: number;
1511
2466
  }
1512
2467
  /** Body for `watches.bulk(body)` — up to 100 watches in one call. */
1513
2468
  export interface WatchBulkParams {
@@ -1516,6 +2471,13 @@ export interface WatchBulkParams {
1516
2471
  export interface AlertListParams {
1517
2472
  severity?: AlertSeverity;
1518
2473
  event_type?: AlertEventType;
2474
+ /**
2475
+ * Which evaluation epochs to include. `'current'` (default) returns only
2476
+ * alerts from the watch's current evaluation epoch — alerts from prior query
2477
+ * revisions (bumped via `/replay`) are excluded. `'all'` returns every alert
2478
+ * regardless of the epoch it fired under.
2479
+ */
2480
+ epoch?: 'all' | 'current';
1519
2481
  limit?: number;
1520
2482
  cursor?: string;
1521
2483
  }
@@ -1616,6 +2578,571 @@ export interface UsageSummaryParams {
1616
2578
  /** Restrict summary to a specific endpoint type. */
1617
2579
  endpoint_type?: string;
1618
2580
  }
2581
+ /** Shared `GET /v1/screening` options (everything except the candidate). */
2582
+ export interface ScreenOptions {
2583
+ /** Intended Nice class numbers (1-45). */
2584
+ nice_classes?: number[];
2585
+ /** Free-text description of intended goods/services (max 2,000 characters). */
2586
+ goods_services?: string;
2587
+ /** Restrict to these jurisdiction (territory) codes. */
2588
+ jurisdictions?: string[];
2589
+ /** Restrict to these registering office codes. */
2590
+ offices?: string[];
2591
+ /** `live` (default) keeps live marks; `all` includes dead marks. */
2592
+ include?: 'live' | 'all';
2593
+ /** Band-admission threshold. */
2594
+ sensitivity?: 'strict' | 'standard' | 'broad';
2595
+ /**
2596
+ * BETA (flag-gated) — goods/services resolution cascade knob. `auto` (default) runs the
2597
+ * deterministic + semantic-on-refusal cascade (bimodal latency; the tier-3 LLM lane adds a
2598
+ * ~4s p50 uncached tail once it lands); `deterministic` is the budget-safe, sub-ms/SLA mode
2599
+ * that never calls the LLM lane; `llm` is not yet implemented (501). Honored only when the
2600
+ * cascade-modes flag is enabled server-side; ignored otherwise.
2601
+ */
2602
+ resolution_mode?: 'auto' | 'deterministic' | 'llm';
2603
+ /** Page size (1-50, default 20). */
2604
+ limit?: number;
2605
+ }
2606
+ /**
2607
+ * `GET /v1/screening` query parameters. EXACTLY ONE candidate is required:
2608
+ * either `q` (mark text, 2-200 non-whitespace chars) OR `trademark_id`
2609
+ * (an existing register record) — the XOR is enforced at the type level, so
2610
+ * supplying both or neither is a compile error, mirroring the API's 400.
2611
+ */
2612
+ export type ScreenParams = ScreenOptions & ({
2613
+ q: string;
2614
+ trademark_id?: never;
2615
+ } | {
2616
+ trademark_id: string;
2617
+ q?: never;
2618
+ });
2619
+ export type ScreeningRiskLevel = 'high' | 'medium' | 'low';
2620
+ /**
2621
+ * `GET /v1/screening` verdict. `needs_review` is a would-be `clear` the screen
2622
+ * could not complete to `clear` standard. The usual cause is incomplete register
2623
+ * coverage for a requested territory, but a stale corpus, a capped analysis
2624
+ * horizon, a failed lane, an unsupported language, low-confidence class
2625
+ * inference, or a coverage assessment that could not be read at all produce it
2626
+ * too. Inspect `ScreenResult.screening.coverage` for the details when present,
2627
+ * it can be absent when the assessment itself failed. Found conflicts still band
2628
+ * `high_risk` / `caution` regardless of coverage. The listing verdict
2629
+ * (`ListingCheckResult.listing.verdict`) is a SEPARATE enum without
2630
+ * `needs_review`, incomplete coverage surfaces there as `caution`.
2631
+ */
2632
+ export type ScreeningVerdict = 'clear' | 'caution' | 'needs_review' | 'high_risk';
2633
+ export type ScreeningMarkMatchLevel = 'identical' | 'strong' | 'weak';
2634
+ export type ScreeningGoodsServicesMatchLevel = 'same_class' | 'related_class' | 'unrelated';
2635
+ export type ScreeningLitigationRiskLevel = 'high' | 'medium' | 'low' | 'unknown';
2636
+ export type ScreeningCoverageStatus = 'complete' | 'partial' | 'stale' | 'unavailable';
2637
+ /** Per-office register freshness on the coverage gate's office axis. */
2638
+ export interface ScreeningOfficeCoverage {
2639
+ /** Public office code (WIPO ST.3, e.g. `US`, `EM` for the EUIPO). */
2640
+ office: string;
2641
+ status: ScreeningCoverageStatus;
2642
+ /** Corpus freshness watermark (ISO ts), or `null` when unavailable. */
2643
+ as_of: string | null;
2644
+ }
2645
+ /** Per-requested-territory protection-scope register coverage. */
2646
+ export interface ScreeningTerritoryCoverage {
2647
+ /** Requested territory code (jurisdiction code, e.g. `DE`, `EU`; `EM` normalized to `EU`). */
2648
+ territory: string;
2649
+ /** The territory's own national register; `office` is `null` when no office models it. */
2650
+ national_register: {
2651
+ office: string | null;
2652
+ covered: boolean;
2653
+ };
2654
+ /** Regional registers that also protect here (EU/BX/OA). Empty for a regional request. */
2655
+ regional_registers: Array<{
2656
+ code: string;
2657
+ covered: boolean;
2658
+ }>;
2659
+ /**
2660
+ * For a REGIONAL request (`jurisdictions: ['EU']`) only: since screening
2661
+ * expands a region down to its member states, `uncovered` lists the member
2662
+ * territories whose national register is dark. Absent for a country request.
2663
+ */
2664
+ member_registers?: {
2665
+ total: number;
2666
+ uncovered: string[];
2667
+ };
2668
+ complete: boolean;
2669
+ }
2670
+ /**
2671
+ * Register-coverage assessment behind a screening verdict. Present whenever the
2672
+ * coverage registry was readable. `complete_for_clear:false` is why an otherwise
2673
+ * `clear` verdict was downgraded to `needs_review`.
2674
+ */
2675
+ export interface ScreeningCoverage {
2676
+ /** Office-freshness axis (ST.3 codes). */
2677
+ offices: ScreeningOfficeCoverage[];
2678
+ /** Protection-scope axis (jurisdiction codes). Empty for offices-scoped/unscoped requests. */
2679
+ territories: ScreeningTerritoryCoverage[];
2680
+ classes: {
2681
+ requested: number[];
2682
+ resolved: number[];
2683
+ expanded: number[];
2684
+ searched: number[];
2685
+ source: 'requested' | 'inferred' | 'expanded';
2686
+ inference_confidence: 'high' | 'medium' | 'low' | null;
2687
+ };
2688
+ lanes: {
2689
+ planned: string[];
2690
+ completed: string[];
2691
+ capped: string[];
2692
+ failed: string[];
2693
+ };
2694
+ language: {
2695
+ detected: string | null;
2696
+ supported: boolean;
2697
+ };
2698
+ horizon: {
2699
+ analyzed: number;
2700
+ cap: number;
2701
+ capped: boolean;
2702
+ cap_reason: string | null;
2703
+ };
2704
+ complete_for_clear: boolean;
2705
+ }
2706
+ /** One banded conflict returned by `GET /v1/screening`. */
2707
+ export interface ScreeningHit {
2708
+ object: 'screening_hit';
2709
+ risk_level: ScreeningRiskLevel;
2710
+ reason_codes: string[];
2711
+ mark_match: {
2712
+ level: ScreeningMarkMatchLevel;
2713
+ admitted_match_levels: string[];
2714
+ };
2715
+ goods_services_match: {
2716
+ level: ScreeningGoodsServicesMatchLevel;
2717
+ matched_nice_classes: number[];
2718
+ };
2719
+ jurisdiction_match: {
2720
+ requested: string[];
2721
+ matched: string[];
2722
+ };
2723
+ litigation_risk: {
2724
+ level: ScreeningLitigationRiskLevel;
2725
+ owner_publicly_traded: boolean | null;
2726
+ owner_ticker: string | null;
2727
+ prior_proceedings: number | null;
2728
+ owner_portfolio_size: number | null;
2729
+ };
2730
+ trademark: TrademarkSummary;
2731
+ }
2732
+ /** `GET /v1/screening` response — bespoke list envelope. */
2733
+ export interface ScreenResult {
2734
+ object: 'list';
2735
+ screening: {
2736
+ verdict: ScreeningVerdict;
2737
+ summary: {
2738
+ high: number;
2739
+ medium: number;
2740
+ low: number;
2741
+ truncated: boolean;
2742
+ };
2743
+ litigation_risk: {
2744
+ high: number;
2745
+ medium: number;
2746
+ };
2747
+ candidate: {
2748
+ mark: string;
2749
+ normalized: string;
2750
+ trademark_id?: string;
2751
+ };
2752
+ inferred_nice_classes?: number[];
2753
+ rules_version: string;
2754
+ /**
2755
+ * BETA — present only when the cascade-modes flag is enabled server-side. Request-level
2756
+ * rollup of how the goods/services coverage was resolved, plus per-area suggestion marking
2757
+ * (TUR P1d). Each area carries two independent axes: `method` (which lane produced it) and
2758
+ * `suggested` (whether the caller should verify before relying on it) so a consumer can render
2759
+ * an uncertain answer distinctly from a certain one.
2760
+ */
2761
+ resolution?: {
2762
+ /** The resolution_mode the request asked for. */
2763
+ mode_requested: 'auto' | 'deterministic' | 'llm';
2764
+ /**
2765
+ * Deepest cascade lane that actually contributed. `llm`/`llm_cached` are reserved for
2766
+ * tier-3 and not emitted yet.
2767
+ */
2768
+ method: 'deterministic' | 'semantic' | 'llm' | 'llm_cached';
2769
+ /**
2770
+ * Top-1 semantic retrieval score (quantized scale) across the semantic areas that
2771
+ * contributed; null when method is not `semantic`.
2772
+ */
2773
+ top_semantic_score_q: number | null;
2774
+ /**
2775
+ * BETA (tier-3) — the pinned model revision that produced a billed LLM adjudication
2776
+ * (method `llm`/`llm_cached`), so a customer can verify which model they paid for. null on
2777
+ * the deterministic/semantic path.
2778
+ */
2779
+ llm_model: string | null;
2780
+ /**
2781
+ * BETA (tier-3) — cache disposition of an LLM adjudication: `hit` (replayed, billed
2782
+ * llm_cached), `miss` (a model call ran, billed llm), or null (no LLM lane / honest fallback).
2783
+ */
2784
+ cache: 'hit' | 'miss' | null;
2785
+ /** Per-area suggestion marking. */
2786
+ areas: Array<{
2787
+ nice_class: number;
2788
+ label: string;
2789
+ role: 'core' | 'related' | 'adjacent' | 'conditional' | 'administrative';
2790
+ /** WHICH LANE produced this area (provenance only, NOT a certainty claim). */
2791
+ method: 'deterministic' | 'semantic' | 'llm';
2792
+ /**
2793
+ * WHETHER THE CALLER SHOULD VERIFY before relying on this area (independent of `method`).
2794
+ * true when semantic-derived, OR confidence is below `high`, OR provenance is a
2795
+ * low-certainty deterministic source (e.g. class_fallback). Only a high-confidence
2796
+ * grounded deterministic area is false.
2797
+ */
2798
+ suggested: boolean;
2799
+ /** Semantic-derived areas are capped at medium; below-high confidence sets suggested=true. */
2800
+ confidence: 'high' | 'medium' | 'low';
2801
+ /** Machine-readable per-area provenance, e.g. `['semantic_match']`, `['class_fallback']`. */
2802
+ basis_codes: string[];
2803
+ /** Quantized semantic score for a semantic area; null on deterministic areas. */
2804
+ score_q: number | null;
2805
+ }>;
2806
+ };
2807
+ as_of: string | null;
2808
+ admitted_match_levels: string[];
2809
+ /**
2810
+ * Register-coverage assessment (protection-scope). Present whenever the
2811
+ * coverage registry was readable. `coverage.complete_for_clear:false` is why
2812
+ * a would-be `clear` was downgraded to `needs_review`.
2813
+ */
2814
+ coverage?: ScreeningCoverage;
2815
+ note?: string;
2816
+ warnings: string[];
2817
+ };
2818
+ data: ScreeningHit[];
2819
+ has_more: boolean;
2820
+ pagination: {
2821
+ cursor: string | null;
2822
+ };
2823
+ request_id?: string;
2824
+ }
2825
+ /** A structured description of the candidate's intended use. */
2826
+ export interface CompareUseProfile {
2827
+ /** Intended Nice class numbers (1-45). */
2828
+ nice_classes?: number[];
2829
+ /** Structured goods/services lines, optionally pinned to a Nice class. */
2830
+ goods_services?: Array<{
2831
+ nice_class?: number;
2832
+ text: string;
2833
+ }>;
2834
+ /** Plain-English description of the business or intended use. */
2835
+ business_description?: string;
2836
+ }
2837
+ export type CompareCandidate = {
2838
+ trademark_id: string;
2839
+ mark?: never;
2840
+ use?: never;
2841
+ } | {
2842
+ trademark_id?: never;
2843
+ mark: string;
2844
+ use: CompareUseProfile;
2845
+ };
2846
+ export type CompareConflict = {
2847
+ trademark_id: string;
2848
+ mark?: never;
2849
+ nice_classes?: never;
2850
+ goods_services?: never;
2851
+ status?: never;
2852
+ } | {
2853
+ trademark_id?: never;
2854
+ mark: string;
2855
+ nice_classes: number[];
2856
+ goods_services?: string;
2857
+ status?: 'active' | 'pending' | 'inactive' | 'unknown';
2858
+ };
2859
+ /** A compare batch contains at least one and at most ten conflicts. */
2860
+ export type CompareConflicts = [CompareConflict] | [CompareConflict, CompareConflict] | [CompareConflict, CompareConflict, CompareConflict] | [CompareConflict, CompareConflict, CompareConflict, CompareConflict] | [CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict] | [CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict] | [CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict] | [CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict] | [CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict] | [CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict, CompareConflict];
2861
+ /** `POST /v1/compare` request body. `conflicts` accepts 1-10 items. */
2862
+ export interface CompareParams {
2863
+ candidate: CompareCandidate;
2864
+ conflicts: CompareConflicts;
2865
+ jurisdictions?: string[];
2866
+ offices?: string[];
2867
+ }
2868
+ export type ComparisonStatus = 'ok' | 'not_found' | 'not_comparable';
2869
+ export type CompareRiskLevel = 'high' | 'medium' | 'low';
2870
+ export type CompareMarkMatchLevel = 'identical' | 'strong' | 'weak' | 'none';
2871
+ export type CompareGoodsServicesLevel = 'same_class' | 'related_class' | 'unrelated';
2872
+ /** One request-ordered pair result from `POST /v1/compare`. */
2873
+ export interface ComparisonResult {
2874
+ object: 'comparison_result';
2875
+ comparison_status: ComparisonStatus;
2876
+ /** Conservative human-review signal: true for ok pairs where a mark-similarity clause fired. */
2877
+ review_recommended: boolean;
2878
+ /** Open vocabulary; tolerate warnings added in future. */
2879
+ warnings: string[];
2880
+ conflict: {
2881
+ trademark_id?: string;
2882
+ mark: string | null;
2883
+ nice_classes: number[] | null;
2884
+ status_as_evaluated: string | null;
2885
+ record_as_of: string | null;
2886
+ };
2887
+ risk_level: CompareRiskLevel | null;
2888
+ /** Open vocabulary; tolerate reason codes added in future. */
2889
+ reason_codes: string[] | null;
2890
+ mark_match: {
2891
+ level: CompareMarkMatchLevel;
2892
+ /** Compare engine clauses; unlike Screening, Compare has no sensitivity admission gate. */
2893
+ matched_levels: string[];
2894
+ } | null;
2895
+ goods_services: {
2896
+ level: CompareGoodsServicesLevel;
2897
+ overlap_classes: number[];
2898
+ text_similarity: number | null;
2899
+ } | null;
2900
+ similarity: {
2901
+ string: number;
2902
+ phonetic: number;
2903
+ /** Reserved for a future semantic dimension; currently always `null`. */
2904
+ semantic: null | number;
2905
+ } | null;
2906
+ }
2907
+ /** `POST /v1/compare` response — bespoke list envelope. */
2908
+ export interface CompareResult {
2909
+ object: 'list';
2910
+ comparison: {
2911
+ candidate: {
2912
+ trademark_id?: string;
2913
+ mark: string;
2914
+ normalized: string;
2915
+ effective_nice_classes: number[];
2916
+ };
2917
+ rules_version: 'compare-v1.1';
2918
+ /** Serving screening strategy identifier; intentionally not a string literal. */
2919
+ band_rules_version: string;
2920
+ mapping_version: string;
2921
+ resolver: {
2922
+ engine_version: string;
2923
+ ruleset_version: string;
2924
+ catalog_version: string;
2925
+ };
2926
+ as_of: string | null;
2927
+ /** Open vocabulary; tolerate warnings added in future. */
2928
+ warnings: string[];
2929
+ disclaimer: string;
2930
+ };
2931
+ data: ComparisonResult[];
2932
+ summary: {
2933
+ high: number;
2934
+ medium: number;
2935
+ low: number;
2936
+ none: number;
2937
+ not_comparable: number;
2938
+ /** Count of ok results where a mark-similarity clause fired. */
2939
+ review_recommended: number;
2940
+ };
2941
+ has_more: false;
2942
+ pagination: {
2943
+ cursor: null;
2944
+ };
2945
+ request_id: string;
2946
+ }
2947
+ /**
2948
+ * Coarse listing/candidate verdict band. Beta: common-word listings are
2949
+ * over-flagged, so treat `caution` as no-signal pending the ENG-199 redesign.
2950
+ */
2951
+ export type ListingVerdict = 'clear' | 'caution' | 'high_risk';
2952
+ /** `POST /v1/screening/listings` request body. Generic commerce-text fields only. */
2953
+ export interface ListingCheckParams {
2954
+ /** Listing title (required). */
2955
+ title: string;
2956
+ /** Explicit brand/seller name — always screened, never suppressed. */
2957
+ brand?: string;
2958
+ /** Listing description — high-precision markers only (quoted / ™®-adjacent / "compatible with X"). */
2959
+ description?: string;
2960
+ /** Platform-neutral tags/keywords/search terms. */
2961
+ keywords?: string[];
2962
+ /** Listing category label — context only, never itself a candidate. */
2963
+ category?: string;
2964
+ /** Intended Nice class numbers (1-45). */
2965
+ nice_classes?: number[];
2966
+ /** Restrict to these jurisdiction (territory) codes. */
2967
+ jurisdictions?: string[];
2968
+ /** Restrict to these registering office codes. */
2969
+ offices?: string[];
2970
+ /** `live` (default) keeps live marks; `all` includes dead. */
2971
+ include?: 'live' | 'all';
2972
+ /** Band-admission threshold for the primary tier. Title/keyword tier is always `strict`. */
2973
+ sensitivity?: 'strict' | 'standard' | 'broad';
2974
+ }
2975
+ /** One DuPont-mapped factor in the informational screening ledger. */
2976
+ export interface ScreeningFactorEntry {
2977
+ factor_id: string;
2978
+ dupont_factor: number;
2979
+ assessment: string;
2980
+ confidence: string;
2981
+ evidence: Array<Record<string, unknown>>;
2982
+ limitations: string[];
2983
+ computed_by: string;
2984
+ version: string;
2985
+ }
2986
+ /** One conflict under a listing candidate (byte-identical to a GET /v1/screening hit + `informational`). */
2987
+ export interface ListingCandidateHit {
2988
+ object: 'screening_hit';
2989
+ risk_level: 'high' | 'medium' | 'low';
2990
+ reason_codes: string[];
2991
+ mark_match: {
2992
+ level: string;
2993
+ admitted_match_levels: string[];
2994
+ };
2995
+ goods_services_match: {
2996
+ level: string;
2997
+ matched_nice_classes: number[];
2998
+ };
2999
+ jurisdiction_match: {
3000
+ requested: string[];
3001
+ matched: string[];
3002
+ };
3003
+ litigation_risk: Record<string, unknown>;
3004
+ trademark: Record<string, unknown>;
3005
+ /** Surfaced but non-escalating conflict. Informational; not legal advice. */
3006
+ informational?: boolean;
3007
+ /** Closed reason explaining why the conflict is informational. Informational; not legal advice. */
3008
+ informational_reason?: 'unrelated_class_identical' | 'generic_term_no_corroboration' | 'crowded_field_no_corroboration' | 'identical_unrelated_no_corroboration' | 'nominative_compat';
3009
+ /** Origin of the served risk band. Informational; not legal advice. */
3010
+ band_source?: 'v1_table' | 'v3_scorer';
3011
+ /** Additive v3 scorer read; never the served band. Informational; not legal advice. */
3012
+ model_assessment?: {
3013
+ band: 'high' | 'medium' | 'borderline' | 'low';
3014
+ confidence: 'high' | 'medium' | 'low';
3015
+ band_source: 'v1_table' | 'v3_scorer';
3016
+ };
3017
+ /** DuPont factor ledger with supporting evidence. Informational; not legal advice. */
3018
+ factor_ledger?: ScreeningFactorEntry[];
3019
+ }
3020
+ /**
3021
+ * Analysis-completeness status — closed enum, ORTHOGONAL to verdict. Derived
3022
+ * deterministically from completeness signals; `complete` means the listing was
3023
+ * fully screened. Read this together with `auto_approve_eligible`, not the
3024
+ * tri-state verdict alone. Mirrors `ListingMeta.analysis_status` in the OpenAPI
3025
+ * contract.
3026
+ */
3027
+ export type AnalysisStatus = 'complete' | 'incomplete_budget' | 'incomplete_timeout' | 'incomplete_backend' | 'incomplete_unscreenable' | 'incomplete_variant_shed' | 'incomplete_stale_snapshot' | 'unsupported_language';
3028
+ /** Provenance of a matched candidate within the listing (evidence-first payload). */
3029
+ export interface ListingMatchCandidate {
3030
+ term: string;
3031
+ normalized: string;
3032
+ tier: 'P' | 'S';
3033
+ field: 'title' | 'brand' | 'description' | 'keywords';
3034
+ }
3035
+ /**
3036
+ * Evidence-first PRIMARY payload entry: one matched mark, deduped + attributed.
3037
+ * Discriminated on `source`: `live_register` carries live-register `registration`
3038
+ * evidence (rights_domain `trademark`); `curated_bank` carries `bank_entry`
3039
+ * provenance for a non-register persona/character right (rights_domain
3040
+ * `character_ip` | `persona_publicity` | `franchise`). Mirrors the `ListingMatch`
3041
+ * schema in the OpenAPI contract.
3042
+ */
3043
+ export type ListingMatch = {
3044
+ object: 'listing_match';
3045
+ source: 'live_register';
3046
+ disposition: 'actionable' | 'informational';
3047
+ reason_codes: string[];
3048
+ /** Live-register trademark match. */
3049
+ rights_domain: 'trademark';
3050
+ goods_services_text_available: boolean;
3051
+ candidate: ListingMatchCandidate;
3052
+ /** Registration evidence — byte-identical to the matching `data[].hits[]` entry. */
3053
+ registration: ListingCandidateHit;
3054
+ } | {
3055
+ object: 'listing_match';
3056
+ source: 'curated_bank';
3057
+ disposition: 'actionable' | 'informational';
3058
+ reason_codes: string[];
3059
+ /** Curated non-register persona/character right — NOT a live-register lookup. */
3060
+ rights_domain: 'character_ip' | 'persona_publicity' | 'franchise';
3061
+ goods_services_text_available: boolean;
3062
+ candidate: ListingMatchCandidate;
3063
+ /** Curated bank provenance — canonical name + review date. Honest labeling. */
3064
+ bank_entry: {
3065
+ canonical: string;
3066
+ review_date: string;
3067
+ note: string;
3068
+ };
3069
+ };
3070
+ /** One extracted, screened candidate mark. */
3071
+ export interface ListingCandidate {
3072
+ object: 'listing_candidate';
3073
+ term: string;
3074
+ normalized: string;
3075
+ tier: 'P' | 'S';
3076
+ reference?: boolean;
3077
+ reference_intent?: 'compat' | 'attribution' | 'prose';
3078
+ counterfeit?: boolean;
3079
+ sources: Array<{
3080
+ field: string;
3081
+ span: [number, number];
3082
+ keyword_index?: number;
3083
+ }>;
3084
+ verdict: ListingVerdict;
3085
+ nice_classes_used: number[];
3086
+ hits: ListingCandidateHit[];
3087
+ }
3088
+ /** A candidate that was NOT screened, with a closed reason code (auditability). */
3089
+ export interface SuppressedListingCandidate {
3090
+ object: 'suppressed_candidate';
3091
+ term: string;
3092
+ normalized: string;
3093
+ field: string;
3094
+ span: [number, number];
3095
+ keyword_index?: number;
3096
+ reason: 'charset' | 'stopword' | 'jargon' | 'descriptive' | 'generic_term' | 'no_index_hit' | 'containment' | 'cap' | 'protected_cap' | 'numeric_id_brand' | 'unscreenable';
3097
+ }
3098
+ /** `POST /v1/screening/listings` response — bespoke envelope. */
3099
+ export interface ListingCheckResult {
3100
+ object: 'list';
3101
+ listing: {
3102
+ verdict: ListingVerdict;
3103
+ summary: {
3104
+ high: number;
3105
+ medium: number;
3106
+ low: number;
3107
+ informational: number;
3108
+ };
3109
+ candidates_screened: number;
3110
+ rules_version: 'screening-v1';
3111
+ verdict_version: components['schemas']['ListingMeta']['verdict_version'];
3112
+ extractor_version: string;
3113
+ selector_version: string;
3114
+ as_of: string | null;
3115
+ warnings: string[];
3116
+ note?: string;
3117
+ analysis_status: AnalysisStatus;
3118
+ auto_approve_eligible: boolean;
3119
+ class_provenance: {
3120
+ source: 'provided_platform' | 'provided_unverified' | 'inferred' | 'none';
3121
+ confidence: number | null;
3122
+ };
3123
+ resolved_nice_classes: number[];
3124
+ /** Content hash of the deterministic dictionaries. */
3125
+ dictionaries_version: string;
3126
+ /** Cheap content hash over the decision-asset version tuple. */
3127
+ decision_asset_version: string;
3128
+ /** Fan-out forms actually evaluated (present whenever variant shedding occurred). */
3129
+ forms_evaluated?: number;
3130
+ /** Total fan-out forms before shedding (present whenever variant shedding occurred). */
3131
+ forms_total?: number;
3132
+ };
3133
+ /**
3134
+ * Evidence-first PRIMARY payload: one entry per matched mark (deduped,
3135
+ * attributed). Leads with disposition + reason codes + registration evidence.
3136
+ */
3137
+ matches: ListingMatch[];
3138
+ data: ListingCandidate[];
3139
+ suppressed: SuppressedListingCandidate[];
3140
+ has_more: boolean;
3141
+ pagination: {
3142
+ cursor: string | null;
3143
+ };
3144
+ request_id?: string;
3145
+ }
1619
3146
  /** Per-request overrides. Accepted as the last argument on every method. */
1620
3147
  export interface RequestOptions {
1621
3148
  /** Request timeout in ms. Overrides client default. */
@@ -1659,10 +3186,75 @@ export interface ListResponseBody<T> {
1659
3186
  pagination: {
1660
3187
  cursor: string | null;
1661
3188
  total_count?: number;
3189
+ total_count_approximate?: boolean;
1662
3190
  };
1663
3191
  request_id: string;
1664
3192
  search_meta?: SearchMeta;
3193
+ source_sync?: TrademarkDocumentSourceSync;
1665
3194
  /** Faceted aggregation buckets (V2 search and saved search results). */
1666
3195
  aggregations?: Record<string, Record<string, number>>;
3196
+ /**
3197
+ * TSK-127 — display-name labels for aggregation bucket keys, shaped
3198
+ * `{ <aggName>: { <bucketKey>: name } }`. Currently populated for the
3199
+ * `entity_id` facet (entity id → display name) so consumers can render
3200
+ * human-readable bucket labels without a follow-up lookup.
3201
+ */
3202
+ aggregation_metadata?: Record<string, Record<string, string>>;
3203
+ }
3204
+ export interface OfficeAnalytics {
3205
+ object: 'office_analytics';
3206
+ code: string;
3207
+ total_marks: number;
3208
+ registered_count: number;
3209
+ pending_count: number;
3210
+ expired_count: number;
3211
+ cancelled_count: number;
3212
+ abandoned_count: number;
3213
+ registration_rate: number | null;
3214
+ jurisdiction_count: number;
3215
+ earliest_filing: string | null;
3216
+ latest_filing: string | null;
3217
+ top_classes: Array<{
3218
+ class: number;
3219
+ count: number;
3220
+ pct: number;
3221
+ }> | null;
3222
+ yearly_trend: Array<{
3223
+ year: number;
3224
+ filed: number;
3225
+ registered: number;
3226
+ abandoned: number;
3227
+ }> | null;
3228
+ stats_computed_at: string;
3229
+ /** Per-request id echoed at the top level of the response body (`*Response` in the OpenAPI spec). */
3230
+ request_id: string;
3231
+ }
3232
+ export interface MarketAnalytics {
3233
+ object: 'market_analytics';
3234
+ total_marks: number;
3235
+ active_count: number;
3236
+ by_status: Record<string, number>;
3237
+ by_office: Record<string, number>;
3238
+ top_classes: Array<{
3239
+ class: number;
3240
+ count: number;
3241
+ pct: number;
3242
+ }>;
3243
+ filing_trend: Record<string, number>;
3244
+ computed_at: string;
3245
+ /** Per-request id echoed at the top level of the response body (`*Response` in the OpenAPI spec). */
3246
+ request_id: string;
3247
+ }
3248
+ export interface ClassificationAnalytics {
3249
+ object: 'classification_analytics';
3250
+ nice_class: number;
3251
+ total_marks: number;
3252
+ active_count: number;
3253
+ by_status: Record<string, number>;
3254
+ by_office: Record<string, number>;
3255
+ filing_trend: Record<string, number>;
3256
+ computed_at: string;
3257
+ /** Per-request id echoed at the top level of the response body (`*Response` in the OpenAPI spec). */
3258
+ request_id: string;
1667
3259
  }
1668
3260
  //# sourceMappingURL=types.d.ts.map