@aivisibilityskill/sdk 0.0.0-stage → 1.0.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.
@@ -0,0 +1,1308 @@
1
+ import type { components, paths } from "./schema.js";
2
+ import { verifyWebhook, WebhookVerificationError } from "./webhooks.js";
3
+ export type { WebhookHeaders } from "./webhooks.js";
4
+ export { verifyWebhook, WebhookVerificationError };
5
+ /**
6
+ * aivisibilityskill API client.
7
+ *
8
+ * import { Aiv } from "@aivisibilityskill/sdk";
9
+ * const aiv = new Aiv({ apiKey: process.env.AIV_KEY! });
10
+ * const job = await aiv.checks.create({ questions: ["best invoicing app for freelancers"] });
11
+ * const done = await aiv.jobs.wait(job.id);
12
+ *
13
+ * Checks and project creation carry an Idempotency-Key, so the client can safely retry them after
14
+ * a network error or a 429/5xx without ever paying twice; other writes are never retried. Errors throw AivError with the
15
+ * API's stable `code`. Every request and response is typed from the API's OpenAPI document.
16
+ */
17
+ export type Schemas = components["schemas"];
18
+ export type Account = Schemas["Account"];
19
+ export type Job = Schemas["Job"];
20
+ export type JobResponse = Schemas["JobResponse"];
21
+ export type Answer = Schemas["Answer"];
22
+ export type Project = Schemas["Project"];
23
+ export type Key = Schemas["Key"];
24
+ export type CheckRequest = Schemas["CheckRequest"];
25
+ export type ProjectRequest = Schemas["ProjectRequest"];
26
+ export type ProjectPatch = Schemas["ProjectPatch"];
27
+ export type KeyRequest = Schemas["KeyRequest"];
28
+ export type Estimate = Schemas["Estimate"];
29
+ export type ActionResult = Schemas["ActionResult"];
30
+ export type Opportunity = Schemas["Opportunity"];
31
+ export type Fix = Schemas["Fix"];
32
+ export type Webhook = Schemas["Webhook"];
33
+ export type WebhookDelivery = Schemas["WebhookDelivery"];
34
+ export type Event = Schemas["Event"];
35
+ export type AuditEntry = Schemas["AuditEntry"];
36
+ export type DataDeletion = Schemas["DataDeletion"];
37
+ export type Usage = Schemas["Usage"];
38
+ export type Batch = Schemas["Batch"];
39
+ export type BatchRequest = Schemas["BatchRequest"];
40
+ export type EngineId = NonNullable<CheckRequest["engines"]>[number];
41
+ type Method = "get" | "post" | "patch" | "delete";
42
+ type Op<P extends keyof paths, M extends Method> = NonNullable<paths[P][M]>;
43
+ type Body<P extends keyof paths, M extends Method> = Op<P, M> extends {
44
+ requestBody?: {
45
+ content: {
46
+ "application/json": infer B;
47
+ };
48
+ };
49
+ } ? B : never;
50
+ type Query<P extends keyof paths, M extends Method> = Op<P, M> extends {
51
+ parameters: {
52
+ query?: infer Q;
53
+ };
54
+ } ? NonNullable<Q> : never;
55
+ export declare class AivError extends Error {
56
+ readonly status: number;
57
+ readonly code: string;
58
+ readonly detail: string | undefined;
59
+ readonly requestId: string | undefined;
60
+ /** Extra fields from the problem response (credits, balance, retry hints…). */
61
+ readonly body: Record<string, unknown>;
62
+ constructor(status: number, code: string, detail: string | undefined, requestId: string | undefined,
63
+ /** Extra fields from the problem response (credits, balance, retry hints…). */
64
+ body: Record<string, unknown>);
65
+ }
66
+ export interface AivOptions {
67
+ apiKey: string;
68
+ baseUrl?: string;
69
+ fetch?: (input: Request) => Promise<Response>;
70
+ /** Retries for 429/502/503/504, network errors and timeouts on safe requests. Default 2. */
71
+ maxRetries?: number;
72
+ /** Per attempt. Default 120s, above the longest server-side wait (90s). */
73
+ timeoutMs?: number;
74
+ }
75
+ /** Options for writes that spend credits: pass your own key to make retries across processes safe. */
76
+ export interface WriteOptions {
77
+ idempotencyKey?: string;
78
+ }
79
+ export interface WaitOptions {
80
+ /** Give up (and return the unfinished result) after this long. Default 10 minutes. */
81
+ timeoutMs?: number;
82
+ }
83
+ export declare const VERSION = "1.0.0";
84
+ type QueryValue = string | number | boolean | readonly string[] | undefined | null;
85
+ interface RequestOptions {
86
+ body?: unknown;
87
+ query?: Record<string, QueryValue>;
88
+ idempotencyKey?: string;
89
+ accept?: "json" | "text";
90
+ }
91
+ export declare class Aiv {
92
+ #private;
93
+ constructor(opts: AivOptions);
94
+ /** Any endpoint, for ones this version doesn't wrap yet. Retries GETs and keyed writes. */
95
+ request<T = unknown>(method: string, path: string, opts?: RequestOptions): Promise<T>;
96
+ /** Public price list: credits per engine and mode, plans. */
97
+ pricing(): Promise<{
98
+ price_version: number;
99
+ credits_per_usd: number;
100
+ credits: {
101
+ [key: string]: number;
102
+ };
103
+ engines: {
104
+ id: string;
105
+ label: string;
106
+ surface: "app" | "serp" | "api";
107
+ credits: {
108
+ [key: string]: number;
109
+ };
110
+ }[];
111
+ plans: {
112
+ id: string;
113
+ label: string;
114
+ monthly_usd: number | null;
115
+ credits: number | null;
116
+ req_per_min: number;
117
+ concurrent_tasks: number;
118
+ projects: number;
119
+ history_days: number;
120
+ reports: string;
121
+ }[];
122
+ terms: {
123
+ free_credit_expiry_days: number;
124
+ payg_min_topup_usd: number;
125
+ payg_credit_expiry_days: number;
126
+ yearly_discount: number;
127
+ };
128
+ }>;
129
+ /** What a check would cost, and whether this key may run it. Free. */
130
+ estimate(body: Body<"/v1/estimate", "post">): Promise<{
131
+ credits: number;
132
+ answers: number;
133
+ reused_answers: number;
134
+ by_engine: {
135
+ [key: string]: {
136
+ answers: number;
137
+ credits: number;
138
+ };
139
+ };
140
+ balance: number;
141
+ budget_remaining_today: number | null;
142
+ confirmation_required: boolean;
143
+ affordable: boolean;
144
+ }>;
145
+ readonly account: {
146
+ get: () => Promise<{
147
+ account: {
148
+ id: string;
149
+ plan: string;
150
+ mode: "live" | "test";
151
+ balance: number;
152
+ reserved: number;
153
+ balance_alert_below: number | null;
154
+ limits: {
155
+ requests_per_minute: number;
156
+ concurrent_answers: number;
157
+ projects: number;
158
+ history_days: number;
159
+ };
160
+ };
161
+ key: components["schemas"]["Key"] & {
162
+ used_today: number;
163
+ budget_remaining_today: number | null;
164
+ };
165
+ }>;
166
+ update: (body: Body<"/v1/account", "patch">) => Promise<{
167
+ account: {
168
+ id: string;
169
+ plan: string;
170
+ mode: "live" | "test";
171
+ balance: number;
172
+ reserved: number;
173
+ balance_alert_below: number | null;
174
+ limits: {
175
+ requests_per_minute: number;
176
+ concurrent_answers: number;
177
+ projects: number;
178
+ history_days: number;
179
+ };
180
+ };
181
+ key: components["schemas"]["Key"] & {
182
+ used_today: number;
183
+ budget_remaining_today: number | null;
184
+ };
185
+ }>;
186
+ };
187
+ readonly locales: {
188
+ list: () => Promise<{
189
+ format: string;
190
+ default: string;
191
+ updated: string;
192
+ countries: {
193
+ code: string;
194
+ name: string;
195
+ engines: ("chatgpt" | "gemini" | "ai_overviews" | "ai_mode" | "deepseek" | "perplexity" | "claude" | "grok")[];
196
+ }[];
197
+ languages: {
198
+ code: string;
199
+ name: string;
200
+ engines: ("chatgpt" | "gemini" | "ai_overviews" | "ai_mode" | "deepseek" | "perplexity" | "claude" | "grok")[];
201
+ }[];
202
+ }>;
203
+ get: (locale: string) => Promise<{
204
+ locale: string;
205
+ language: {
206
+ code: string;
207
+ name: string;
208
+ };
209
+ country: {
210
+ code: string;
211
+ name: string;
212
+ };
213
+ engines: {
214
+ engine: "chatgpt" | "gemini" | "ai_overviews" | "ai_mode" | "deepseek" | "perplexity" | "claude" | "grok";
215
+ supported: boolean;
216
+ language_code: string | null;
217
+ reason: string | null;
218
+ }[];
219
+ }>;
220
+ };
221
+ readonly checks: {
222
+ /** Starts a check. A retry with the same idempotencyKey never charges twice. */
223
+ create: (body: CheckRequest, opts?: WriteOptions) => Promise<{
224
+ id: string;
225
+ status: "running" | "succeeded" | "partial" | "failed";
226
+ created_at: string;
227
+ finished_at: string | null;
228
+ project_id: string | null;
229
+ customer: string | null;
230
+ metadata: {
231
+ [key: string]: string;
232
+ };
233
+ sandbox: boolean;
234
+ price_version: number;
235
+ credits: components["schemas"]["JobCredits"];
236
+ progress: {
237
+ total: number;
238
+ done: number;
239
+ failed: number;
240
+ running: number;
241
+ };
242
+ poll_after_seconds: number | null;
243
+ answers: components["schemas"]["Answer"][];
244
+ failures: {
245
+ engine: string;
246
+ question: string;
247
+ sample: number;
248
+ code: string;
249
+ message: string;
250
+ }[];
251
+ } & {
252
+ deduplicated: boolean;
253
+ }>;
254
+ };
255
+ readonly batches: {
256
+ /**
257
+ * Thousands of answers in one request; they run as checks of up to 200 as your plan's
258
+ * concurrency allows. Retrying with the same idempotencyKey never starts a second batch.
259
+ */
260
+ create: (body: BatchRequest, opts?: WriteOptions) => Promise<{
261
+ id: string;
262
+ status: "running" | "stopping" | "completed" | "stopped";
263
+ stop_reason: string | null;
264
+ customer: string | null;
265
+ metadata: {
266
+ [key: string]: string;
267
+ };
268
+ answers: {
269
+ total: number;
270
+ started: number;
271
+ succeeded: number;
272
+ failed: number;
273
+ running: number;
274
+ not_started: number;
275
+ };
276
+ credits: {
277
+ estimate: number;
278
+ reserved: number;
279
+ charged: number;
280
+ refunded: number;
281
+ };
282
+ checks: string[];
283
+ created_at: string;
284
+ completed_at: string | null;
285
+ poll_after_seconds: number | null;
286
+ }>;
287
+ get: (id: string) => Promise<{
288
+ id: string;
289
+ status: "running" | "stopping" | "completed" | "stopped";
290
+ stop_reason: string | null;
291
+ customer: string | null;
292
+ metadata: {
293
+ [key: string]: string;
294
+ };
295
+ answers: {
296
+ total: number;
297
+ started: number;
298
+ succeeded: number;
299
+ failed: number;
300
+ running: number;
301
+ not_started: number;
302
+ };
303
+ credits: {
304
+ estimate: number;
305
+ reserved: number;
306
+ charged: number;
307
+ refunded: number;
308
+ };
309
+ checks: string[];
310
+ created_at: string;
311
+ completed_at: string | null;
312
+ poll_after_seconds: number | null;
313
+ }>;
314
+ list: (q?: {
315
+ limit?: number;
316
+ before?: string;
317
+ customer?: string;
318
+ }) => Promise<{
319
+ batches: components["schemas"]["Batch"][];
320
+ next: string | null;
321
+ }>;
322
+ iterate: (q?: {
323
+ customer?: string;
324
+ limit?: number;
325
+ }) => AsyncGenerator<{
326
+ id: string;
327
+ status: "running" | "stopping" | "completed" | "stopped";
328
+ stop_reason: string | null;
329
+ customer: string | null;
330
+ metadata: {
331
+ [key: string]: string;
332
+ };
333
+ answers: {
334
+ total: number;
335
+ started: number;
336
+ succeeded: number;
337
+ failed: number;
338
+ running: number;
339
+ not_started: number;
340
+ };
341
+ credits: {
342
+ estimate: number;
343
+ reserved: number;
344
+ charged: number;
345
+ refunded: number;
346
+ };
347
+ checks: string[];
348
+ created_at: string;
349
+ completed_at: string | null;
350
+ poll_after_seconds: number | null;
351
+ }, any, any>;
352
+ /** Stops starting new checks; running ones finish and nothing more is charged. */
353
+ cancel: (id: string) => Promise<{
354
+ id: string;
355
+ status: "running" | "stopping" | "completed" | "stopped";
356
+ stop_reason: string | null;
357
+ customer: string | null;
358
+ metadata: {
359
+ [key: string]: string;
360
+ };
361
+ answers: {
362
+ total: number;
363
+ started: number;
364
+ succeeded: number;
365
+ failed: number;
366
+ running: number;
367
+ not_started: number;
368
+ };
369
+ credits: {
370
+ estimate: number;
371
+ reserved: number;
372
+ charged: number;
373
+ refunded: number;
374
+ };
375
+ checks: string[];
376
+ created_at: string;
377
+ completed_at: string | null;
378
+ poll_after_seconds: number | null;
379
+ }>;
380
+ /** Polls until the batch completes or stops (default timeout: 2 hours). */
381
+ wait: (id: string, opts?: WaitOptions) => Promise<{
382
+ id: string;
383
+ status: "running" | "stopping" | "completed" | "stopped";
384
+ stop_reason: string | null;
385
+ customer: string | null;
386
+ metadata: {
387
+ [key: string]: string;
388
+ };
389
+ answers: {
390
+ total: number;
391
+ started: number;
392
+ succeeded: number;
393
+ failed: number;
394
+ running: number;
395
+ not_started: number;
396
+ };
397
+ credits: {
398
+ estimate: number;
399
+ reserved: number;
400
+ charged: number;
401
+ refunded: number;
402
+ };
403
+ checks: string[];
404
+ created_at: string;
405
+ completed_at: string | null;
406
+ poll_after_seconds: number | null;
407
+ }>;
408
+ };
409
+ readonly jobs: {
410
+ get: (id: string, opts?: {
411
+ text?: boolean;
412
+ }) => Promise<{
413
+ id: string;
414
+ status: "running" | "succeeded" | "partial" | "failed";
415
+ created_at: string;
416
+ finished_at: string | null;
417
+ project_id: string | null;
418
+ customer: string | null;
419
+ metadata: {
420
+ [key: string]: string;
421
+ };
422
+ sandbox: boolean;
423
+ price_version: number;
424
+ credits: components["schemas"]["JobCredits"];
425
+ progress: {
426
+ total: number;
427
+ done: number;
428
+ failed: number;
429
+ running: number;
430
+ };
431
+ poll_after_seconds: number | null;
432
+ answers: components["schemas"]["Answer"][];
433
+ failures: {
434
+ engine: string;
435
+ question: string;
436
+ sample: number;
437
+ code: string;
438
+ message: string;
439
+ }[];
440
+ }>;
441
+ list: (q?: {
442
+ limit?: number;
443
+ before?: string;
444
+ projectId?: string;
445
+ customer?: string;
446
+ }) => Promise<{
447
+ jobs: {
448
+ id: string;
449
+ status: "running" | "succeeded" | "partial" | "failed";
450
+ created_at: string;
451
+ finished_at: string | null;
452
+ project_id: string | null;
453
+ customer: string | null;
454
+ metadata: {
455
+ [key: string]: string;
456
+ };
457
+ sandbox: boolean;
458
+ credits: components["schemas"]["JobCredits"];
459
+ }[];
460
+ next: string | null;
461
+ }>;
462
+ /** Every job, newest first, across pages. */
463
+ iterate: (q?: {
464
+ projectId?: string;
465
+ customer?: string;
466
+ limit?: number;
467
+ }) => AsyncGenerator<{
468
+ id: string;
469
+ status: "running" | "succeeded" | "partial" | "failed";
470
+ created_at: string;
471
+ finished_at: string | null;
472
+ project_id: string | null;
473
+ customer: string | null;
474
+ metadata: {
475
+ [key: string]: string;
476
+ };
477
+ sandbox: boolean;
478
+ credits: components["schemas"]["JobCredits"];
479
+ }, any, any>;
480
+ /** Polls (at the pace the API suggests) until the job finishes or the timeout passes. */
481
+ wait: (id: string, opts?: WaitOptions) => Promise<{
482
+ id: string;
483
+ status: "running" | "succeeded" | "partial" | "failed";
484
+ created_at: string;
485
+ finished_at: string | null;
486
+ project_id: string | null;
487
+ customer: string | null;
488
+ metadata: {
489
+ [key: string]: string;
490
+ };
491
+ sandbox: boolean;
492
+ price_version: number;
493
+ credits: components["schemas"]["JobCredits"];
494
+ progress: {
495
+ total: number;
496
+ done: number;
497
+ failed: number;
498
+ running: number;
499
+ };
500
+ poll_after_seconds: number | null;
501
+ answers: components["schemas"]["Answer"][];
502
+ failures: {
503
+ engine: string;
504
+ question: string;
505
+ sample: number;
506
+ code: string;
507
+ message: string;
508
+ }[];
509
+ }>;
510
+ };
511
+ readonly answers: {
512
+ get: (id: string) => Promise<{
513
+ id: string;
514
+ engine: string;
515
+ engine_label: string;
516
+ surface: string;
517
+ mode: string;
518
+ question: string;
519
+ locale: string;
520
+ collected_at: string;
521
+ has_ai_answer: boolean;
522
+ text?: string;
523
+ model: string | null;
524
+ reading: "done" | "partial" | "pending";
525
+ citations: components["schemas"]["Citation"][];
526
+ brands: components["schemas"]["BrandMention"][];
527
+ facts: components["schemas"]["Fact"][];
528
+ sandbox: boolean;
529
+ reused: boolean;
530
+ receipt: {
531
+ sha256: string;
532
+ url: string;
533
+ } | null;
534
+ }>;
535
+ /** The engine's raw response, as stored when the answer was collected. */
536
+ receipt: (id: string) => Promise<unknown>;
537
+ };
538
+ readonly projects: {
539
+ create: (body: ProjectRequest, opts?: WriteOptions) => Promise<{
540
+ id: string;
541
+ name: string;
542
+ brand: {
543
+ name: string;
544
+ aliases: string[];
545
+ domains: string[];
546
+ };
547
+ competitors: {
548
+ name: string;
549
+ aliases: string[];
550
+ domains: string[];
551
+ }[];
552
+ questions: {
553
+ id: string;
554
+ question: string;
555
+ }[];
556
+ engines: string[];
557
+ locale: string;
558
+ customer: string | null;
559
+ metadata: {
560
+ [key: string]: string;
561
+ };
562
+ schedule: {
563
+ cadence: "off" | "daily" | "weekly";
564
+ mode: string;
565
+ samples: number;
566
+ next_run_at: string | null;
567
+ credits_per_run: number;
568
+ credits_per_month: number;
569
+ };
570
+ last_run: {
571
+ at: string | null;
572
+ job_id: string | null;
573
+ error: string | null;
574
+ };
575
+ created_at: string;
576
+ updated_at: string;
577
+ }>;
578
+ list: (q?: {
579
+ customer?: string;
580
+ }) => Promise<{
581
+ projects: components["schemas"]["Project"][];
582
+ }>;
583
+ get: (id: string) => Promise<{
584
+ id: string;
585
+ name: string;
586
+ brand: {
587
+ name: string;
588
+ aliases: string[];
589
+ domains: string[];
590
+ };
591
+ competitors: {
592
+ name: string;
593
+ aliases: string[];
594
+ domains: string[];
595
+ }[];
596
+ questions: {
597
+ id: string;
598
+ question: string;
599
+ }[];
600
+ engines: string[];
601
+ locale: string;
602
+ customer: string | null;
603
+ metadata: {
604
+ [key: string]: string;
605
+ };
606
+ schedule: {
607
+ cadence: "off" | "daily" | "weekly";
608
+ mode: string;
609
+ samples: number;
610
+ next_run_at: string | null;
611
+ credits_per_run: number;
612
+ credits_per_month: number;
613
+ };
614
+ last_run: {
615
+ at: string | null;
616
+ job_id: string | null;
617
+ error: string | null;
618
+ };
619
+ created_at: string;
620
+ updated_at: string;
621
+ }>;
622
+ update: (id: string, body: ProjectPatch) => Promise<{
623
+ id: string;
624
+ name: string;
625
+ brand: {
626
+ name: string;
627
+ aliases: string[];
628
+ domains: string[];
629
+ };
630
+ competitors: {
631
+ name: string;
632
+ aliases: string[];
633
+ domains: string[];
634
+ }[];
635
+ questions: {
636
+ id: string;
637
+ question: string;
638
+ }[];
639
+ engines: string[];
640
+ locale: string;
641
+ customer: string | null;
642
+ metadata: {
643
+ [key: string]: string;
644
+ };
645
+ schedule: {
646
+ cadence: "off" | "daily" | "weekly";
647
+ mode: string;
648
+ samples: number;
649
+ next_run_at: string | null;
650
+ credits_per_run: number;
651
+ credits_per_month: number;
652
+ };
653
+ last_run: {
654
+ at: string | null;
655
+ job_id: string | null;
656
+ error: string | null;
657
+ };
658
+ created_at: string;
659
+ updated_at: string;
660
+ }>;
661
+ archive: (id: string) => Promise<void>;
662
+ visibility: (id: string, q?: AnalyticsQuery) => Promise<{
663
+ brand: string;
664
+ overall: {
665
+ answers: number;
666
+ with_ai_answer: number;
667
+ mentioned: components["schemas"]["Rate"];
668
+ mentioned_when_answered: components["schemas"]["Rate"];
669
+ recommended: components["schemas"]["Rate"];
670
+ cited: components["schemas"]["Rate"];
671
+ avg_rank: number | null;
672
+ sentiment: {
673
+ positive: number;
674
+ neutral: number;
675
+ negative: number;
676
+ };
677
+ };
678
+ engines: {
679
+ [key: string]: {
680
+ answers: number;
681
+ with_ai_answer: number;
682
+ mentioned: components["schemas"]["Rate"];
683
+ mentioned_when_answered: components["schemas"]["Rate"];
684
+ recommended: components["schemas"]["Rate"];
685
+ cited: components["schemas"]["Rate"];
686
+ avg_rank: number | null;
687
+ sentiment: {
688
+ positive: number;
689
+ neutral: number;
690
+ negative: number;
691
+ };
692
+ };
693
+ };
694
+ unread: number;
695
+ meta: {
696
+ cached: boolean;
697
+ credits_charged: number;
698
+ window: {
699
+ from: string;
700
+ days: number;
701
+ };
702
+ };
703
+ }>;
704
+ competitors: (id: string, q?: AnalyticsQuery) => Promise<{
705
+ answers: number;
706
+ brands: {
707
+ name: string;
708
+ is_you: boolean;
709
+ tracked: boolean;
710
+ mentioned: components["schemas"]["Rate"];
711
+ recommended: components["schemas"]["Rate"];
712
+ avg_rank: number | null;
713
+ share_of_voice: number;
714
+ }[];
715
+ unread: number;
716
+ meta: {
717
+ cached: boolean;
718
+ credits_charged: number;
719
+ window: {
720
+ from: string;
721
+ days: number;
722
+ };
723
+ };
724
+ }>;
725
+ sources: (id: string, q?: AnalyticsQuery) => Promise<{
726
+ answers: number;
727
+ domains: {
728
+ domain: string;
729
+ type: string;
730
+ cited: components["schemas"]["Rate"];
731
+ citations: number;
732
+ is_yours: boolean;
733
+ top_urls: {
734
+ url: string;
735
+ citations: number;
736
+ }[];
737
+ }[];
738
+ by_type: {
739
+ [key: string]: {
740
+ answers: number;
741
+ citations: number;
742
+ };
743
+ };
744
+ meta: {
745
+ cached: boolean;
746
+ credits_charged: number;
747
+ window: {
748
+ from: string;
749
+ days: number;
750
+ };
751
+ };
752
+ }>;
753
+ facts: (id: string, q?: AnalyticsQuery) => Promise<{
754
+ facts: {
755
+ type: string;
756
+ value: string;
757
+ answers: number;
758
+ engines: string[];
759
+ quote: string;
760
+ last_seen: string;
761
+ price: {
762
+ amount: number;
763
+ currency: string | null;
764
+ period: string | null;
765
+ per_user: boolean;
766
+ } | null;
767
+ }[];
768
+ meta: {
769
+ cached: boolean;
770
+ credits_charged: number;
771
+ window: {
772
+ from: string;
773
+ days: number;
774
+ };
775
+ };
776
+ }>;
777
+ history: (id: string, q?: AnalyticsQuery & {
778
+ bucket?: "week" | "day";
779
+ }) => Promise<{
780
+ points: {
781
+ period: string;
782
+ mentioned: components["schemas"]["Rate"];
783
+ }[];
784
+ meta: {
785
+ cached: boolean;
786
+ credits_charged: number;
787
+ window: {
788
+ from: string;
789
+ days: number;
790
+ };
791
+ };
792
+ }>;
793
+ /** Paid action: robots.txt, llms.txt, sitemaps and key pages, as AI crawlers see them. */
794
+ siteCheck: (id: string, body?: Body<"/v1/projects/{id}/site-check", "post">) => Promise<{
795
+ job_id: string;
796
+ kind: string;
797
+ status: "running" | "succeeded" | "partial" | "failed";
798
+ sandbox: boolean;
799
+ deduplicated: boolean;
800
+ credits: {
801
+ quoted: number;
802
+ charged: number | null;
803
+ refunded: number | null;
804
+ };
805
+ poll_after_seconds: number | null;
806
+ error: {
807
+ code: string;
808
+ message: string;
809
+ } | null;
810
+ result: {
811
+ [key: string]: unknown;
812
+ } | null;
813
+ }>;
814
+ /** Paid action: what ranks on Google for a question and what those pages say. */
815
+ research: (id: string, body: Body<"/v1/projects/{id}/research", "post">) => Promise<{
816
+ job_id: string;
817
+ kind: string;
818
+ status: "running" | "succeeded" | "partial" | "failed";
819
+ sandbox: boolean;
820
+ deduplicated: boolean;
821
+ credits: {
822
+ quoted: number;
823
+ charged: number | null;
824
+ refunded: number | null;
825
+ };
826
+ poll_after_seconds: number | null;
827
+ error: {
828
+ code: string;
829
+ message: string;
830
+ } | null;
831
+ result: {
832
+ [key: string]: unknown;
833
+ } | null;
834
+ }>;
835
+ /** Paid action: ranks what to fix first from the project's answers and checks. */
836
+ findOpportunities: (id: string, body?: Body<"/v1/projects/{id}/opportunities", "post">) => Promise<{
837
+ job_id: string;
838
+ kind: string;
839
+ status: "running" | "succeeded" | "partial" | "failed";
840
+ sandbox: boolean;
841
+ deduplicated: boolean;
842
+ credits: {
843
+ quoted: number;
844
+ charged: number | null;
845
+ refunded: number | null;
846
+ };
847
+ poll_after_seconds: number | null;
848
+ error: {
849
+ code: string;
850
+ message: string;
851
+ } | null;
852
+ result: {
853
+ [key: string]: unknown;
854
+ } | null;
855
+ }>;
856
+ opportunities: (id: string, q?: Query<"/v1/projects/{id}/opportunities", "get">) => Promise<{
857
+ opportunities: components["schemas"]["Opportunity"][];
858
+ }>;
859
+ };
860
+ readonly opportunities: {
861
+ get: (id: string) => Promise<{
862
+ [key: string]: unknown;
863
+ }>;
864
+ update: (id: string, body: Body<"/v1/opportunities/{id}", "patch">) => Promise<{
865
+ [key: string]: unknown;
866
+ }>;
867
+ /** Paid action: a step-by-step fix brief for one opportunity. */
868
+ brief: (id: string, body?: Body<"/v1/opportunities/{id}/brief", "post">) => Promise<{
869
+ job_id: string;
870
+ kind: string;
871
+ status: "running" | "succeeded" | "partial" | "failed";
872
+ sandbox: boolean;
873
+ deduplicated: boolean;
874
+ credits: {
875
+ quoted: number;
876
+ charged: number | null;
877
+ refunded: number | null;
878
+ };
879
+ poll_after_seconds: number | null;
880
+ error: {
881
+ code: string;
882
+ message: string;
883
+ } | null;
884
+ result: {
885
+ [key: string]: unknown;
886
+ } | null;
887
+ }>;
888
+ /** Records a fix you shipped; it's verified on the site and later in AI answers. */
889
+ recordFix: (id: string, body: Body<"/v1/opportunities/{id}/fixes", "post">) => Promise<{
890
+ [key: string]: unknown;
891
+ }>;
892
+ };
893
+ readonly fixes: {
894
+ get: (id: string) => Promise<{
895
+ [key: string]: unknown;
896
+ }>;
897
+ verify: (id: string, body?: Body<"/v1/fixes/{id}/verify", "post">) => Promise<{
898
+ job_id: string;
899
+ kind: string;
900
+ status: "running" | "succeeded" | "partial" | "failed";
901
+ sandbox: boolean;
902
+ deduplicated: boolean;
903
+ credits: {
904
+ quoted: number;
905
+ charged: number | null;
906
+ refunded: number | null;
907
+ };
908
+ poll_after_seconds: number | null;
909
+ error: {
910
+ code: string;
911
+ message: string;
912
+ } | null;
913
+ result: {
914
+ [key: string]: unknown;
915
+ } | null;
916
+ }>;
917
+ };
918
+ readonly actions: {
919
+ get: (id: string) => Promise<{
920
+ job_id: string;
921
+ kind: string;
922
+ status: "running" | "succeeded" | "partial" | "failed";
923
+ sandbox: boolean;
924
+ deduplicated: boolean;
925
+ credits: {
926
+ quoted: number;
927
+ charged: number | null;
928
+ refunded: number | null;
929
+ };
930
+ poll_after_seconds: number | null;
931
+ error: {
932
+ code: string;
933
+ message: string;
934
+ } | null;
935
+ result: {
936
+ [key: string]: unknown;
937
+ } | null;
938
+ }>;
939
+ /** Polls a paid action (site check, research, brief…) until it's done. */
940
+ wait: (id: string, opts?: WaitOptions) => Promise<{
941
+ job_id: string;
942
+ kind: string;
943
+ status: "running" | "succeeded" | "partial" | "failed";
944
+ sandbox: boolean;
945
+ deduplicated: boolean;
946
+ credits: {
947
+ quoted: number;
948
+ charged: number | null;
949
+ refunded: number | null;
950
+ };
951
+ poll_after_seconds: number | null;
952
+ error: {
953
+ code: string;
954
+ message: string;
955
+ } | null;
956
+ result: {
957
+ [key: string]: unknown;
958
+ } | null;
959
+ }>;
960
+ };
961
+ readonly keys: {
962
+ list: (q?: {
963
+ limit?: number;
964
+ before?: string;
965
+ customer?: string;
966
+ }) => Promise<{
967
+ keys: components["schemas"]["Key"][];
968
+ next: string | null;
969
+ }>;
970
+ iterate: (q?: {
971
+ customer?: string;
972
+ limit?: number;
973
+ }) => AsyncGenerator<{
974
+ id: string;
975
+ name: string;
976
+ mode: "live" | "test";
977
+ kind: "rest" | "mcp";
978
+ scope: "full" | "read";
979
+ display: string;
980
+ daily_budget: number | null;
981
+ daily_budget_follows_plan: boolean;
982
+ confirm_above: number | null;
983
+ customer: string | null;
984
+ allowed_ips: string[] | null;
985
+ status: "active" | "revoked" | "expired";
986
+ created_at: string;
987
+ last_used_at: string | null;
988
+ expires_at: string | null;
989
+ revoked_at: string | null;
990
+ }, any, any>;
991
+ /** The response's `secret` is shown once. */
992
+ create: (body: KeyRequest) => Promise<{
993
+ id: string;
994
+ name: string;
995
+ mode: "live" | "test";
996
+ kind: "rest" | "mcp";
997
+ scope: "full" | "read";
998
+ display: string;
999
+ daily_budget: number | null;
1000
+ daily_budget_follows_plan: boolean;
1001
+ confirm_above: number | null;
1002
+ customer: string | null;
1003
+ allowed_ips: string[] | null;
1004
+ status: "active" | "revoked" | "expired";
1005
+ created_at: string;
1006
+ last_used_at: string | null;
1007
+ expires_at: string | null;
1008
+ revoked_at: string | null;
1009
+ } & {
1010
+ secret: string;
1011
+ }>;
1012
+ update: (id: string, body: Schemas["KeyPatch"]) => Promise<{
1013
+ id: string;
1014
+ name: string;
1015
+ mode: "live" | "test";
1016
+ kind: "rest" | "mcp";
1017
+ scope: "full" | "read";
1018
+ display: string;
1019
+ daily_budget: number | null;
1020
+ daily_budget_follows_plan: boolean;
1021
+ confirm_above: number | null;
1022
+ customer: string | null;
1023
+ allowed_ips: string[] | null;
1024
+ status: "active" | "revoked" | "expired";
1025
+ created_at: string;
1026
+ last_used_at: string | null;
1027
+ expires_at: string | null;
1028
+ revoked_at: string | null;
1029
+ }>;
1030
+ revoke: (id: string) => Promise<void>;
1031
+ };
1032
+ readonly usage: {
1033
+ get: (q?: UsageQuery) => Promise<{
1034
+ from: string;
1035
+ to: string;
1036
+ group_by: ("day" | "month" | "customer" | "project" | "key" | "kind" | "engine")[];
1037
+ customer: string | null;
1038
+ project_id: string | null;
1039
+ totals: {
1040
+ credits: number;
1041
+ pending: number;
1042
+ refunded: number;
1043
+ answers: number;
1044
+ actions: number;
1045
+ analytics: number;
1046
+ failed: number;
1047
+ };
1048
+ rows: components["schemas"]["UsageRow"][];
1049
+ }>;
1050
+ /** The same report as CSV text, ready for a spreadsheet or an invoice. */
1051
+ csv: (q?: UsageQuery) => Promise<string>;
1052
+ };
1053
+ readonly webhooks: {
1054
+ list: () => Promise<{
1055
+ webhooks: components["schemas"]["Webhook"][];
1056
+ }>;
1057
+ /** The response's `secret` (whsec_…) is shown once: store it to verify deliveries. */
1058
+ create: (body: Schemas["WebhookRequest"]) => Promise<{
1059
+ id: string;
1060
+ url: string;
1061
+ description: string | null;
1062
+ events: string[];
1063
+ customer: string | null;
1064
+ status: "enabled" | "disabled";
1065
+ disabled_reason: "failing" | "manual" | null;
1066
+ disabled_at: string | null;
1067
+ failing_since: string | null;
1068
+ last_success_at: string | null;
1069
+ last_failure_at: string | null;
1070
+ previous_secret_expires_at: string | null;
1071
+ created_at: string;
1072
+ updated_at: string;
1073
+ } & {
1074
+ secret: string;
1075
+ }>;
1076
+ get: (id: string) => Promise<{
1077
+ id: string;
1078
+ url: string;
1079
+ description: string | null;
1080
+ events: string[];
1081
+ customer: string | null;
1082
+ status: "enabled" | "disabled";
1083
+ disabled_reason: "failing" | "manual" | null;
1084
+ disabled_at: string | null;
1085
+ failing_since: string | null;
1086
+ last_success_at: string | null;
1087
+ last_failure_at: string | null;
1088
+ previous_secret_expires_at: string | null;
1089
+ created_at: string;
1090
+ updated_at: string;
1091
+ }>;
1092
+ update: (id: string, body: Schemas["WebhookPatch"]) => Promise<{
1093
+ id: string;
1094
+ url: string;
1095
+ description: string | null;
1096
+ events: string[];
1097
+ customer: string | null;
1098
+ status: "enabled" | "disabled";
1099
+ disabled_reason: "failing" | "manual" | null;
1100
+ disabled_at: string | null;
1101
+ failing_since: string | null;
1102
+ last_success_at: string | null;
1103
+ last_failure_at: string | null;
1104
+ previous_secret_expires_at: string | null;
1105
+ created_at: string;
1106
+ updated_at: string;
1107
+ }>;
1108
+ delete: (id: string) => Promise<void>;
1109
+ /** A new secret; the old one keeps working for 24 hours. */
1110
+ rotateSecret: (id: string, body?: Body<"/v1/webhooks/{id}/rotate-secret", "post">) => Promise<{
1111
+ id: string;
1112
+ url: string;
1113
+ description: string | null;
1114
+ events: string[];
1115
+ customer: string | null;
1116
+ status: "enabled" | "disabled";
1117
+ disabled_reason: "failing" | "manual" | null;
1118
+ disabled_at: string | null;
1119
+ failing_since: string | null;
1120
+ last_success_at: string | null;
1121
+ last_failure_at: string | null;
1122
+ previous_secret_expires_at: string | null;
1123
+ created_at: string;
1124
+ updated_at: string;
1125
+ } & {
1126
+ secret: string;
1127
+ }>;
1128
+ /** Sends a `ping` event to this endpoint only. */
1129
+ test: (id: string, body?: Body<"/v1/webhooks/{id}/test", "post">) => Promise<{
1130
+ id: string;
1131
+ event_id: string;
1132
+ event_type: string;
1133
+ status: "pending" | "succeeded" | "failed" | "skipped";
1134
+ attempts: number;
1135
+ max_attempts: number;
1136
+ next_attempt_at: string | null;
1137
+ last_attempt_at: string | null;
1138
+ last_status: number | null;
1139
+ last_error: string | null;
1140
+ last_latency_ms: number | null;
1141
+ succeeded_at: string | null;
1142
+ created_at: string;
1143
+ } & {
1144
+ attempt_log: {
1145
+ attempt: number;
1146
+ at: string;
1147
+ status: number | null;
1148
+ error: string | null;
1149
+ latency_ms: number | null;
1150
+ response: string | null;
1151
+ }[];
1152
+ event: components["schemas"]["Event"];
1153
+ }>;
1154
+ /** Re-sends everything the endpoint missed since a time (ISO date), and re-enables it. */
1155
+ recover: (id: string, body: Body<"/v1/webhooks/{id}/recover", "post">) => Promise<{
1156
+ recovered: number;
1157
+ }>;
1158
+ deliveries: {
1159
+ list: (id: string, q?: {
1160
+ status?: Query<"/v1/webhooks/{id}/deliveries", "get">["status"];
1161
+ limit?: number;
1162
+ before?: string;
1163
+ }) => Promise<{
1164
+ deliveries: components["schemas"]["WebhookDelivery"][];
1165
+ next: string | null;
1166
+ }>;
1167
+ get: (id: string, deliveryId: string) => Promise<{
1168
+ id: string;
1169
+ event_id: string;
1170
+ event_type: string;
1171
+ status: "pending" | "succeeded" | "failed" | "skipped";
1172
+ attempts: number;
1173
+ max_attempts: number;
1174
+ next_attempt_at: string | null;
1175
+ last_attempt_at: string | null;
1176
+ last_status: number | null;
1177
+ last_error: string | null;
1178
+ last_latency_ms: number | null;
1179
+ succeeded_at: string | null;
1180
+ created_at: string;
1181
+ } & {
1182
+ attempt_log: {
1183
+ attempt: number;
1184
+ at: string;
1185
+ status: number | null;
1186
+ error: string | null;
1187
+ latency_ms: number | null;
1188
+ response: string | null;
1189
+ }[];
1190
+ event: components["schemas"]["Event"];
1191
+ }>;
1192
+ resend: (id: string, deliveryId: string) => Promise<{
1193
+ id: string;
1194
+ event_id: string;
1195
+ event_type: string;
1196
+ status: "pending" | "succeeded" | "failed" | "skipped";
1197
+ attempts: number;
1198
+ max_attempts: number;
1199
+ next_attempt_at: string | null;
1200
+ last_attempt_at: string | null;
1201
+ last_status: number | null;
1202
+ last_error: string | null;
1203
+ last_latency_ms: number | null;
1204
+ succeeded_at: string | null;
1205
+ created_at: string;
1206
+ }>;
1207
+ };
1208
+ };
1209
+ readonly events: {
1210
+ list: (q?: Query<"/v1/events", "get">) => Promise<{
1211
+ events: components["schemas"]["Event"][];
1212
+ next: string | null;
1213
+ }>;
1214
+ get: (id: string) => Promise<{
1215
+ id: string;
1216
+ type: string;
1217
+ timestamp: string;
1218
+ sandbox: boolean;
1219
+ data: {
1220
+ [key: string]: unknown;
1221
+ };
1222
+ }>;
1223
+ /** Every event, newest first (the last 30 days). */
1224
+ iterate: (q?: Omit<Query<"/v1/events", "get">, "before" | "after">) => AsyncGenerator<{
1225
+ id: string;
1226
+ type: string;
1227
+ timestamp: string;
1228
+ sandbox: boolean;
1229
+ data: {
1230
+ [key: string]: unknown;
1231
+ };
1232
+ }, any, any>;
1233
+ };
1234
+ readonly auditLog: {
1235
+ list: (q?: Query<"/v1/audit-log", "get">) => Promise<{
1236
+ entries: components["schemas"]["AuditEntry"][];
1237
+ next: number | null;
1238
+ }>;
1239
+ iterate: (q?: Omit<Query<"/v1/audit-log", "get">, "before">) => AsyncGenerator<{
1240
+ id: number;
1241
+ at: string;
1242
+ actor: string;
1243
+ actor_key_id: string | null;
1244
+ ip: string | null;
1245
+ action: string;
1246
+ target_type: string;
1247
+ target_id: string | null;
1248
+ customer: string | null;
1249
+ details: {
1250
+ [key: string]: unknown;
1251
+ } | null;
1252
+ }, any, any>;
1253
+ };
1254
+ readonly customers: {
1255
+ /**
1256
+ * Deletes everything stored for one of your customers (irreversible). Runs in the
1257
+ * background: poll `dataDeletions.get(id)` or `dataDeletions.wait(id)`.
1258
+ */
1259
+ deleteData: (customer: string) => Promise<{
1260
+ id: string;
1261
+ customer: string;
1262
+ status: "pending" | "running" | "completed" | "failed";
1263
+ counts: {
1264
+ [key: string]: number;
1265
+ } | null;
1266
+ created_at: string;
1267
+ completed_at: string | null;
1268
+ }>;
1269
+ };
1270
+ readonly dataDeletions: {
1271
+ get: (id: string) => Promise<{
1272
+ id: string;
1273
+ customer: string;
1274
+ status: "pending" | "running" | "completed" | "failed";
1275
+ counts: {
1276
+ [key: string]: number;
1277
+ } | null;
1278
+ created_at: string;
1279
+ completed_at: string | null;
1280
+ }>;
1281
+ wait: (id: string, opts?: WaitOptions & {
1282
+ intervalMs?: number;
1283
+ }) => Promise<{
1284
+ id: string;
1285
+ customer: string;
1286
+ status: "pending" | "running" | "completed" | "failed";
1287
+ counts: {
1288
+ [key: string]: number;
1289
+ } | null;
1290
+ created_at: string;
1291
+ completed_at: string | null;
1292
+ }>;
1293
+ };
1294
+ /** Checks a webhook delivery's signature and returns the parsed event. Throws if it's not ours. */
1295
+ static verifyWebhook: typeof verifyWebhook;
1296
+ }
1297
+ export interface AnalyticsQuery {
1298
+ questionId?: string;
1299
+ engines?: EngineId[];
1300
+ days?: number;
1301
+ }
1302
+ export interface UsageQuery {
1303
+ from?: string;
1304
+ to?: string;
1305
+ groupBy?: Query<"/v1/usage", "get">["group_by"];
1306
+ customer?: string;
1307
+ projectId?: string;
1308
+ }