@checkbox-site/node 0.1.0 → 0.2.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.
@@ -17,6 +17,8 @@ export interface NextAction {
17
17
  operation_id?: string;
18
18
  /** The MCP tool that performs operation_id on the Checkbox MCP server (`call_api` when there is no dedicated tool). */
19
19
  mcp_tool?: string;
20
+ /** The HTTP method and path of operation_id, with path parameters in braces. */
21
+ endpoint?: string;
20
22
  /** Documentation or dashboard URL for the step, when there is one. */
21
23
  url?: string;
22
24
  }
@@ -32,6 +34,8 @@ export interface Error {
32
34
  message: string;
33
35
  /** The parameter the error relates to, when there is one. */
34
36
  param?: string;
37
+ /** What is missing or wrong, one entry each (terms_incomplete; and every problem of a parameter_invalid / parameter_missing request, so all can be fixed in one try). */
38
+ problems?: Array<string>;
35
39
  /** Link to the documentation of this error code. */
36
40
  doc_url: string;
37
41
  /** Id of the request (also in the Request-Id header). Quote it to support. */
@@ -49,10 +53,35 @@ export interface SetupNextAction {
49
53
  operation_id?: string;
50
54
  /** The MCP tool that performs operation_id (`call_api` when there is no dedicated tool). */
51
55
  mcp_tool?: string;
56
+ /** The HTTP method and path of operation_id, with path parameters in braces. */
57
+ endpoint?: string;
52
58
  /** The equivalent `checkbox` CLI command, when there is one. */
53
59
  command?: string;
54
60
  /** Documentation or dashboard URL for the step. */
55
61
  url?: string;
62
+ /** verify_domain with a started challenge: the DNS TXT record to add. */
63
+ dns?: {
64
+ /** Record type. */
65
+ type: "TXT";
66
+ /** Full record name. */
67
+ name: string;
68
+ /** Record value. */
69
+ value: string;
70
+ };
71
+ /** verify_domain with a started challenge: the file to serve instead of the DNS record. */
72
+ well_known?: {
73
+ /** Where to serve the file. */
74
+ url: string;
75
+ /** The file content. */
76
+ content: string;
77
+ };
78
+ /** verify_domain with a started challenge: or this meta tag on the homepage. The live snippet (install.script_tag) works too: Checkbox verifies the domain when it sees it. */
79
+ meta_tag?: {
80
+ /** The page Checkbox reads (the homepage of the domain). */
81
+ url: string;
82
+ /** The tag to put in its <head>. */
83
+ html: string;
84
+ };
56
85
  }
57
86
  /** A pending device login (RFC 8628 style). */
58
87
  export interface DeviceAuthorization {
@@ -96,9 +125,11 @@ export interface DeviceAuthorizationParams {
96
125
  package_manager?: string;
97
126
  /** Detected billing platform. */
98
127
  billing_platform?: string;
128
+ /** Business name: names the site and workspace (instead of the host name). */
129
+ merchant_name?: string;
99
130
  /** Also ask for live-mode keys (live mode activates after domain verification). */
100
131
  live?: boolean;
101
- /** A HINT of the Stripe TEST key found in the project ("sk_test_…a1b2" — never the key). The human is asked once whether Checkbox may use it for synthetic test subscriptions. */
132
+ /** A HINT of the Stripe TEST key found in the project, never the key. Format: "sk_test_" or "rk_test_", the ellipsis character "…" (U+2026), then the key's last 4 characters, e.g. "sk_test_…a1b2". The human is asked once whether Checkbox may use it for synthetic test subscriptions. */
102
133
  stripe_test_key_hint?: string;
103
134
  }
104
135
  /** Keys issued after the human approved the device login. Returned exactly once. */
@@ -137,7 +168,7 @@ export interface DeviceToken {
137
168
  };
138
169
  next_action: SetupNextAction;
139
170
  }
140
- /** A subscription plan as the merchant sells it. */
171
+ /** A subscription plan as the merchant sells it: name, amount (minor units), currency, interval, interval_count, trial_days and the intro_* promo fields, the same shape the checks accept (plan_name, price and intro_price are accepted as aliases). */
141
172
  export interface SetupPlan {
142
173
  /** Plan name. */
143
174
  name?: string;
@@ -151,11 +182,83 @@ export interface SetupPlan {
151
182
  interval_count?: number;
152
183
  /** Free-trial days (0 = none). */
153
184
  trial_days?: number;
185
+ /** Intro / first-period price in minor units (800 = $8.00 for the first period). Give one of intro_amount, intro_percent_off or intro_amount_off. */
186
+ intro_amount?: number;
187
+ /** Intro discount as a percentage off `amount` (a Stripe coupon's percent_off: 20 for 20% off). */
188
+ intro_percent_off?: number;
189
+ /** Intro discount as an amount off `amount`, in minor units (a Stripe coupon's amount_off). */
190
+ intro_amount_off?: number;
191
+ /** How many billing periods the intro price lasts (default 1). */
192
+ intro_periods?: number;
193
+ /** The billing platform's price id (Stripe price_…), so `amount` is compared with the connected Price. */
194
+ price_id?: string;
195
+ /** Alias of `name` (the name the checks also accept). */
196
+ plan_name?: string;
197
+ /** Alias of `amount` in MAJOR units (19 = $19.00); `amount` (minor units) is the canonical field. */
198
+ price?: number | string;
199
+ /** Alias of `intro_amount` in MAJOR units (8 = $8.00). */
200
+ intro_price?: number | string;
154
201
  }
202
+ /** While the domain is not verified: the newest read-only scan of the site's own public pages (labeled "unverified scan": no checkout submitted, not evidence, replaced by the full scan after verification). Null otherwise. */
203
+ export type UnverifiedScan = {
204
+ /** Read-only scan id (uscan_…). */
205
+ id: string;
206
+ /** Object type. */
207
+ object: "unverified_scan";
208
+ /** Always true: read before the domain was verified. Not evidence; no certificate, receipt or monitoring comes from it. */
209
+ unverified: true;
210
+ /** The label every surface shows with these results. */
211
+ label: "unverified scan";
212
+ /** queued, running, completed, failed, or skipped (e.g. the domain got verified first, so the full scan replaces it). */
213
+ status: "queued" | "running" | "completed" | "failed" | "skipped";
214
+ /** When it was queued. Unix timestamp in seconds. */
215
+ created: number;
216
+ /** When it finished. Unix timestamp in seconds. */
217
+ finished: number | null;
218
+ /** Every page considered (at most 20 loaded). */
219
+ pages: Array<{
220
+ /** Page URL. */
221
+ url: string;
222
+ /** home, pricing, terms, privacy, refund, cancellation, account or checkout. */
223
+ kind: string;
224
+ /** captured; skipped (robots.txt, not on the site's own domain, page limit, action link); failed. */
225
+ status: "captured" | "skipped" | "failed";
226
+ /** Why it was skipped or failed. */
227
+ reason?: string;
228
+ }>;
229
+ /** Checks on the loaded pages, in memory (not findings of the site). */
230
+ findings: Array<{
231
+ /** Check id. */
232
+ check_id: string;
233
+ /** Verdict on the loaded pages alone. */
234
+ status: "pass" | "fail" | "needs_review";
235
+ /** critical, high, medium or low. */
236
+ severity: string;
237
+ /** The check, in one line. */
238
+ title: string;
239
+ }>;
240
+ /** Counts. */
241
+ counts: {
242
+ /** Pages captured. */
243
+ pages_captured: number;
244
+ /** Pages skipped. */
245
+ pages_skipped: number;
246
+ /** Failing checks. */
247
+ failing: number;
248
+ /** Checks to review. */
249
+ needs_review: number;
250
+ /** Passing checks. */
251
+ passing: number;
252
+ };
253
+ /** Why it failed or was skipped. */
254
+ error: string | null;
255
+ /** What an unverified scan is (show it with the results). */
256
+ note: string;
257
+ } | null;
155
258
  /** One step of the setup checklist. */
156
259
  export interface SetupStep {
157
260
  /** Stable step key. */
158
- key: "account" | "site" | "snippet" | "policies" | "checks" | "lifecycle_test" | "fixes" | "domain" | "owner_notified";
261
+ key: "account" | "site" | "snippet" | "policies" | "checks" | "connect_billing" | "lifecycle_test" | "fixes" | "domain" | "owner_notified";
159
262
  /** Human-readable title. */
160
263
  title: string;
161
264
  /** done; pending (waiting on Checkbox or a deploy); action_required (the agent must act: see next_action); skipped; failed. */
@@ -220,22 +323,35 @@ export interface SetupSession {
220
323
  /** Plans. */
221
324
  plans: Array<SetupPlan>;
222
325
  };
326
+ /** Notes about this request's input (createSetupSession / updateSetupSession only; never stored): plan amounts below 100 minor units or different from the connected Stripe Price. */
327
+ warnings?: Array<{
328
+ /** Stable warning code. */
329
+ code: "plan_amount_looks_like_major_units" | "plan_amount_mismatch_stripe_price";
330
+ /** What looks wrong and what to send. */
331
+ message: string;
332
+ /** The parameter. */
333
+ param: string;
334
+ }>;
223
335
  /** Policy / pricing links Checkbox found in the site's HTML (terms_url, privacy_url, refund_url, cancellation_url, pricing_url, account_url). */
224
336
  discovered: Record<string, string>;
225
337
  /** Install details. */
226
338
  install: {
227
339
  /** The exact tag to put in <head> on every page. */
228
340
  script_tag: string | null;
229
- /** Public snippet key of the site. */
341
+ /** The site's public snippet key: the data-key of script_tag (and the local part of inbound_email). Use only this key in the snippet tag. */
230
342
  snippet_key: string | null;
231
- /** Test-mode publishable key (pk_test_…) for Checkbox Elements in the browser. */
343
+ /** A different key: the account's test-mode publishable key (pk_test_…) for Checkbox Elements (<checkbox-disclosure>) and consent receipts (data-publishable-key). Not the snippet's data-key. */
232
344
  publishable_key: string | null;
233
345
  /** BCC this address on subscription emails (acknowledgment, reminders) so they are checked. */
234
346
  inbound_email: string | null;
235
347
  /** File the agent added the snippet to. */
236
348
  installed_in: string | null;
237
- /** Whether Checkbox saw the snippet on the live site at the last verify (null: not checked). */
349
+ /** Whether the snippet is live on the site: seen in the homepage at the last verify, or a capture it sent from a page of the site's verified domain (null: not checked). */
238
350
  detected_on_site: boolean | null;
351
+ /** How Checkbox knows the snippet is live: the tag in the homepage HTML, or its first capture from the site's domain. */
352
+ detected_via: "homepage" | "capture" | null;
353
+ /** The page of the snippet's first capture from the site's domain (detected_via capture). */
354
+ first_capture_url: string | null;
239
355
  };
240
356
  /** Policy documents Checkbox fetched (checked by terms.* checks). */
241
357
  policies: Array<{
@@ -243,14 +359,32 @@ export interface SetupSession {
243
359
  kind: string;
244
360
  /** URL fetched. */
245
361
  url: string;
246
- /** Fetch result. */
247
- status: "fetched" | "failed";
362
+ /** Fetch result. preview: read before the site's domain was verified (unverified preview): nothing was stored as evidence and only the Terms checks ran, in memory; it is fetched and stored once the domain is verified. */
363
+ status: "fetched" | "failed" | "preview";
248
364
  /** When it was fetched. Unix timestamp in seconds. */
249
365
  fetched: number;
250
366
  /** Why the fetch failed. */
251
367
  error: string | null;
252
368
  /** Evidence record of the stored page (ev_…). */
253
369
  evidence: string | null;
370
+ /** Not read (or only previewed) because the site's domain is not verified yet. */
371
+ held: boolean;
372
+ /** Unverified preview result (status preview), else null. */
373
+ preview: {
374
+ /** Always true: read before the domain was verified; nothing stored. */
375
+ unverified: true;
376
+ /** Terms checks on this page (none for a privacy policy). */
377
+ checks: Array<{
378
+ /** Check id. */
379
+ check_id: string;
380
+ /** Verdict on this page alone. */
381
+ status: "pass" | "fail" | "needs_review";
382
+ /** The check, in one line. */
383
+ summary: string;
384
+ /** One-sentence fix. */
385
+ fix?: string;
386
+ }>;
387
+ } | null;
254
388
  }>;
255
389
  /** Stripe test mode for lifecycle test runs. */
256
390
  stripe: {
@@ -285,22 +419,61 @@ export interface SetupSession {
285
419
  id: string;
286
420
  /** queued, running, succeeded, failed or canceled. */
287
421
  status: string;
422
+ /** The result in plain words, as the test run says it ("Finished with 2 warnings to review"). succeeded with warnings is not a clean pass. */
423
+ status_label?: string;
288
424
  /** When it started. Unix timestamp in seconds. */
289
425
  created: number;
290
426
  } | null;
427
+ /** The plans Checkbox judges the site against: the declared plans as reconciled with the connected Stripe Prices (Stripe wins), the plans the pay buttons sell and the account's Prices of a declared plan. Empty until a plan is known (updateSetupSession plans[], or connect Stripe). */
428
+ site_plans: Array<{
429
+ /** Plan name (or its price and interval). */
430
+ name: string;
431
+ /** The recurring price, formatted. */
432
+ price: string;
433
+ /** The recurring price in minor units (cents). */
434
+ amount: number;
435
+ /** Currency (lowercase ISO code). */
436
+ currency: string;
437
+ /** day, week, month or year. */
438
+ interval: string;
439
+ /** Intervals between charges. */
440
+ interval_count: number;
441
+ /** Free trial days on this plan (0: none). */
442
+ trial_days: number;
443
+ /** A lower first-period price, if any. */
444
+ intro_price: {
445
+ /** Intro price in minor units. */
446
+ amount: number;
447
+ /** Billing periods at the intro price. */
448
+ periods: number | null;
449
+ } | null;
450
+ /** Every Stripe Price id that names this plan. */
451
+ stripe_price_ids: Array<string>;
452
+ /** declared in setup, chosen in site facts, sold by the pay buttons, or read from the connected Stripe account. */
453
+ source: "declared" | "chosen" | "sold" | "stripe";
454
+ }>;
291
455
  /** Latest verdict of the test-mode site. */
292
456
  compliance: {
293
- /** 0-100. */
294
- score: number;
295
- /** No critical/high failure open. */
296
- insurable: boolean;
297
457
  /** When it was evaluated. Unix timestamp in seconds. */
298
458
  evaluated: number;
299
- /** Open failing findings. */
459
+ /**
460
+ * Deprecated: open failing findings (per check). Read `label` (counted in tasks) and `todo` instead.
461
+ * @deprecated
462
+ */
300
463
  failing: number;
301
- /** Open needs-review findings. */
464
+ /**
465
+ * Deprecated: open needs-review findings (per check). Read `label` (counted in tasks) and `todo` instead.
466
+ * @deprecated
467
+ */
302
468
  needs_review: number;
303
- /** Most urgent open findings (details: retrieveFinding; ordered tasks: `checkbox plan --json`). */
469
+ /** The site roll-up label, the same everywhere (dashboard, plan, emails): "2 fixes needed · 1 your call", "Checks pass · 2 live checks pending". */
470
+ label: string | null;
471
+ /** The site roll-up status: needs_fix, your_call, incomplete, compliant or not_checked. */
472
+ status: string | null;
473
+ /**
474
+ * Deprecated: open findings (evidence). The to-do list is `todo` (the compliance plan's ordered open tasks).
475
+ * @deprecated
476
+ */
304
477
  top_findings: Array<{
305
478
  /** Unique identifier of the finding (fnd_…). */
306
479
  id: string;
@@ -313,14 +486,37 @@ export interface SetupSession {
313
486
  /** What is wrong. */
314
487
  title: string;
315
488
  }>;
489
+ /** The to-do list: the compliance plan's ordered open required tasks (same titles, order and counts as the dashboard, MCP get_site_status and the summary email). */
490
+ todo?: Array<{
491
+ /** Plan task id (task_…); its findings are the evidence. */
492
+ task: string;
493
+ /** Task key. */
494
+ key: string;
495
+ /** Task title, the same as in the plan. */
496
+ title: string;
497
+ /** The status the site roll-up counts the task under. */
498
+ status: "needs_fix" | "not_set_up" | "your_call" | "not_checked";
499
+ /** Needs a fix, Not set up yet, Your call or Not checked yet. */
500
+ label: string;
501
+ }>;
316
502
  } | null;
503
+ unverified_scan: UnverifiedScan;
317
504
  /** The setup checklist, in order. */
318
505
  steps: Array<SetupStep>;
319
506
  next_action: SetupNextAction;
320
507
  /** Whether the human got the summary email. */
321
508
  owner_notified: boolean;
322
- /** The summary email: sent, or not_configured when this deployment has no SMTP (null before completeSetupSession). */
323
- owner_email: "sent" | "not_configured" | null;
509
+ /** The summary email, sent only by completeSetupSession and built from the plan at that moment: sent (the mail server accepted it; see owner_email_detail.at), failed (not delivered; owner_email_detail.error says why, and the next completeSetupSession retries), or not_configured when this deployment has no SMTP. Null before completeSetupSession. */
510
+ owner_email: "sent" | "not_configured" | "failed" | null;
511
+ /** Delivery details of the summary email (null before completeSetupSession). */
512
+ owner_email_detail: {
513
+ /** When the summary was handed to the mail server (or failed), unix seconds. */
514
+ at: number | null;
515
+ /** Who it was sent to. */
516
+ to: string | null;
517
+ /** Why it failed (failed only). */
518
+ error: string | null;
519
+ } | null;
324
520
  /** Dashboard page with the setup timeline (for the human). */
325
521
  review_url: string;
326
522
  }
@@ -341,16 +537,16 @@ export interface SetupSessionUpdate {
341
537
  site_url?: string;
342
538
  /** Page where customers subscribe (pricing page or checkout). */
343
539
  checkout_url?: string;
344
- /** Account page where subscribers manage / cancel. */
345
- account_url?: string;
346
- /** Terms of service page. Checkbox fetches and checks it. */
347
- terms_url?: string;
348
- /** Privacy policy page. */
349
- privacy_url?: string;
350
- /** Refund policy page. */
351
- refund_url?: string;
352
- /** Cancellation policy page (if separate from the Terms). */
353
- cancellation_url?: string;
540
+ /** Account page where subscribers manage / cancel. null clears it. */
541
+ account_url?: string | null;
542
+ /** Terms of service page. Checkbox fetches and checks it. null clears it. */
543
+ terms_url?: string | null;
544
+ /** Privacy policy page. null clears it. */
545
+ privacy_url?: string | null;
546
+ /** Refund policy page. null clears it. */
547
+ refund_url?: string | null;
548
+ /** Cancellation policy page (if separate from the Terms). null clears it. */
549
+ cancellation_url?: string | null;
354
550
  /** Support address subscribers can write to. */
355
551
  support_email?: string;
356
552
  /** The brand subscribers know (it names the seller in generated disclosures and emails). Default: the site's host name, which the plan asks you to replace. */
@@ -375,7 +571,7 @@ export interface SetupSessionUpdate {
375
571
  env_file?: string;
376
572
  /** Static files directory (for /.well-known). */
377
573
  public_dir?: string;
378
- /** Where checkout sessions / payment links are created. */
574
+ /** Where checkout sessions / payment links are created: an ARRAY of { file, kind, line?, snippet? } objects, one per place (not a string), e.g. [{"file": "app.py", "line": 40, "kind": "stripe_checkout_session"}]. */
379
575
  checkout_code?: Array<SetupCodeRef>;
380
576
  /** Where the subscribe / pay buttons are rendered. */
381
577
  pay_buttons?: Array<SetupCodeRef>;
@@ -413,6 +609,8 @@ export interface SetupVerification {
413
609
  snippet_detected: boolean | null;
414
610
  /** Why the site could not be loaded. */
415
611
  error: string | null;
612
+ /** Read as an unverified preview (domain not verified yet): one plain GET of the homepage for links and the snippet, nothing stored as evidence. */
613
+ preview: boolean;
416
614
  };
417
615
  /** Policies fetched now. */
418
616
  policies: Array<{
@@ -422,20 +620,64 @@ export interface SetupVerification {
422
620
  ok: boolean;
423
621
  /** Error. */
424
622
  error: string | null;
623
+ /** Read as an unverified preview (domain not verified yet): nothing stored. */
624
+ preview: boolean;
425
625
  }>;
426
626
  /** Synthetic-shopper scan. */
427
627
  scan: {
428
628
  /** Whether a scan was queued now. */
429
629
  queued: boolean;
430
- /** The queued scan (scan_…). */
630
+ /** The queued scan (scan_…); with reason "already scanned", the newest scan (read it with retrieveScan). */
431
631
  scan: string | null;
432
632
  /** Why not. */
433
633
  reason: string | null;
434
634
  };
435
635
  /** Whether compliance was re-evaluated now. */
436
636
  evaluated: boolean;
637
+ /** The site's domain got verified during this call (e.g. the snippet is live on the homepage). */
638
+ domain_verified: {
639
+ /** The domain. */
640
+ domain: string;
641
+ /** snippet, meta_tag, dns_txt or well_known. */
642
+ method: string;
643
+ } | null;
644
+ /** While the domain is not verified: the read-only scan of the site's own public pages (no checkout submitted). */
645
+ unverified_scan: {
646
+ /** Whether a read-only (unverified) scan was queued now. */
647
+ queued: boolean;
648
+ /** Why not (limits: one per site per 24 h, three unverified sites per account in 30 days). */
649
+ reason: string | null;
650
+ } | null;
437
651
  setup_session: SetupSession;
438
652
  }
653
+ /** Account default retention (sites without their own setting use it). */
654
+ export interface Retention {
655
+ /** Years records are kept (consent receipts, disclosures as shown, passing check results, certificates, emails sent, confirmed cancellations, evidence-chain entries). Default 7. */
656
+ records_years: number;
657
+ /** Days superseded check results are kept after a later check replaces them (with their page captures and change history); only summary counts stay. Current results are not deleted. Default 30. */
658
+ superseded_results_days: number;
659
+ /**
660
+ * Deprecated: same as records_years.
661
+ * @deprecated
662
+ */
663
+ good_practice_years: number;
664
+ /**
665
+ * Deprecated: same as superseded_results_days.
666
+ * @deprecated
667
+ */
668
+ problem_history_days: number;
669
+ }
670
+ /** Account-wide legal hold: while active, nothing of this mode's data is deleted. */
671
+ export interface LegalHold {
672
+ /** A legal hold suspends every automatic deletion and refuses deletions and retention shortening. */
673
+ active: boolean;
674
+ /** What the active hold was set on (an account hold covers every site). */
675
+ scope: "site" | "account" | null;
676
+ /** When the hold was turned on. Unix timestamp in seconds. */
677
+ set: number | null;
678
+ /** Note recorded with the hold. */
679
+ reason: string | null;
680
+ }
439
681
  /** The Checkbox account behind the API key. */
440
682
  export interface Account {
441
683
  /** Unique identifier of the account (acct_…). */
@@ -487,13 +729,37 @@ export interface Account {
487
729
  billing: {
488
730
  /** Checkbox is free to use. */
489
731
  plan: "free";
490
- /** The compliance warranty is not offered yet (waitlist only; no coverage). */
491
- warranty: "coming_soon";
492
732
  };
733
+ retention: Retention;
734
+ legal_hold: LegalHold;
493
735
  /** When the account was created. Unix timestamp in seconds. */
494
736
  created: number;
495
737
  next_action: NextAction | null;
496
738
  }
739
+ /** Default retention for every site without its own setting. A longer period for superseded check results keeps a fuller timeline of changes to your site. */
740
+ export interface RetentionParams {
741
+ /** Years records are kept (1-10). On a site, null returns to the account default. */
742
+ records_years?: number | null;
743
+ /** Days superseded check results are kept (7-730). On a site, null returns to the account default. */
744
+ superseded_results_days?: number | null;
745
+ /**
746
+ * Deprecated: use records_years.
747
+ * @deprecated
748
+ */
749
+ good_practice_years?: number | null;
750
+ /**
751
+ * Deprecated: use superseded_results_days.
752
+ * @deprecated
753
+ */
754
+ problem_history_days?: number | null;
755
+ }
756
+ /** Account-wide legal hold: suspends every deletion of the account's records until turned off. */
757
+ export interface LegalHoldParams {
758
+ /** true turns the hold on, false turns it off. */
759
+ active: boolean;
760
+ /** Note stored with the hold (who asked, matter). */
761
+ reason?: string;
762
+ }
497
763
  /** Business facts that decide which legal requirements apply. */
498
764
  export interface SiteFacts {
499
765
  /** The offer starts with a free trial. */
@@ -510,8 +776,12 @@ export interface SiteFacts {
510
776
  notice_channel_email?: boolean;
511
777
  /** Price increases need consent or allow a refund (NY). */
512
778
  price_increase_consent_or_refund?: boolean;
779
+ /** The billing-platform price this checkout sells (e.g. a Stripe price id). Terms copy and the price cross-check use only this price; without it, a connected price never rewrites Terms copy or reopens a verified task. */
780
+ plan_price_id?: string;
513
781
  /** Accepted payment methods (debit / ACH bring in Reg E). */
514
782
  payment_methods?: Array<"card" | "debit" | "ach" | "wallet" | "other">;
783
+ /** Where shoppers pay and consent. stripe_checkout / payment_link: your pages redirect to a Stripe-hosted page, so consent is checked on Stripe (consent_collection and custom_text of your registered Checkout configs or Payment Links), and your pricing page needs no checkbox of its own. Unset: detected from pay buttons that link to checkout.stripe.com / buy.stripe.com. */
784
+ checkout_type?: "own_page" | "stripe_checkout" | "payment_link";
515
785
  }
516
786
  /** Scheduled monitoring. */
517
787
  export interface SiteMonitoring {
@@ -528,18 +798,92 @@ export interface SiteMonitoring {
528
798
  /** Domains to verify before Checkbox scans the site (first: createDomainVerification for the site's own domain). */
529
799
  verify_domains: Array<string>;
530
800
  }
801
+ /** The retention in effect for the site. */
802
+ export type SiteRetention = Retention & {
803
+ /** Both values come from the account default (no site override). */
804
+ inherited: boolean;
805
+ };
806
+ /** A live check Checkbox has not observed yet, and how it completes. */
807
+ export interface PendingLiveCheck {
808
+ /** What has not been observed yet. */
809
+ what: string;
810
+ /** When / how it completes. */
811
+ completes: string;
812
+ /** How it completes: run_proof, bcc_real_sends, wait_for_event, connect_billing, resync_billing, scan, check_rendered_page, register_checkout, publish_policy. */
813
+ action: "run_proof" | "bcc_real_sends" | "wait_for_event" | "connect_billing" | "resync_billing" | "scan" | "check_rendered_page" | "register_checkout" | "publish_policy";
814
+ /** ISO date when it completes on its own (a reminder window), when known. */
815
+ due: string | null;
816
+ }
817
+ /** One plan / checkout of the site and its sign-up verdict. */
818
+ export interface CheckoutVerdict {
819
+ /** Plan name, or the checkout when no plan was matched. */
820
+ name: string;
821
+ /** Where the purchase happens: own_page, stripe_checkout (your page → Stripe Checkout), payment_link, checkout_config (a registered Checkout Session config), stripe_hosted. */
822
+ kind: "own_page" | "stripe_checkout" | "payment_link" | "checkout_config" | "stripe_hosted";
823
+ /** The declared plan this checkout sells, when matched. */
824
+ plan: string | null;
825
+ /** User-facing status. needs_fix (a requirement is clearly not met: `compliance.fix` is the one change), pending_live_check (everything Checkbox can see is right; the live event has not been observed yet — counts as passing the checks), verified_live (observed live: proof run, real BCC'd send, Stripe-confirmed cancellation), your_call (a real decision for a person: `compliance.question`), compliant (passes; grey areas carry a `compliance.note`), not_applicable, not_set_up (no sign the email or setting exists yet: `compliance.fix` is the one-click way to set it up; never counts as passing the checks), not_checked (Checkbox has not tried it yet, e.g. the cancel flow: `compliance.fix` says how; never counts as passing the checks). */
826
+ status: "needs_fix" | "pending_live_check" | "verified_live" | "your_call" | "compliant" | "not_applicable" | "not_set_up" | "not_checked";
827
+ /** Label to show. */
828
+ label: string;
829
+ /** Sign-up checks still open on this checkout. */
830
+ open: Array<{
831
+ /** Check id. */
832
+ check_id: string;
833
+ /** Short check title. */
834
+ title: string;
835
+ /** User-facing status. needs_fix (a requirement is clearly not met: `compliance.fix` is the one change), pending_live_check (everything Checkbox can see is right; the live event has not been observed yet — counts as passing the checks), verified_live (observed live: proof run, real BCC'd send, Stripe-confirmed cancellation), your_call (a real decision for a person: `compliance.question`), compliant (passes; grey areas carry a `compliance.note`), not_applicable, not_set_up (no sign the email or setting exists yet: `compliance.fix` is the one-click way to set it up; never counts as passing the checks), not_checked (Checkbox has not tried it yet, e.g. the cancel flow: `compliance.fix` says how; never counts as passing the checks). */
836
+ status: "needs_fix" | "pending_live_check" | "verified_live" | "your_call" | "compliant" | "not_applicable" | "not_set_up" | "not_checked";
837
+ }>;
838
+ }
839
+ /** Roll-up of the user-facing statuses of the required checks. */
840
+ export interface ComplianceRollup {
841
+ /** needs_fix (a required check needs a fix or something is not set up yet), your_call (a decision is needed), incomplete (only "not checked yet" items are left, e.g. the cancel flow was never tried), compliant (every required check passes; pending live checks count as passing), not_checked (never evaluated). */
842
+ status: "needs_fix" | "your_call" | "incomplete" | "compliant" | "not_checked";
843
+ /** Label to show. */
844
+ label: string;
845
+ /** Required checks per user-facing status. */
846
+ counts: {
847
+ /** Required checks that need a fix. */
848
+ needs_fix: number;
849
+ /** Decisions for a person. */
850
+ your_call: number;
851
+ /** Checks pass, live check pending. */
852
+ pending_live_check: number;
853
+ /** Verified live. */
854
+ verified_live: number;
855
+ /** Checks pass. */
856
+ compliant: number;
857
+ /** Not applicable. */
858
+ not_applicable: number;
859
+ /** Not set up yet (no sign the email or setting exists). */
860
+ not_set_up: number;
861
+ /** Not checked yet (Checkbox has not tried it). */
862
+ not_checked: number;
863
+ };
864
+ /** What each pending live check waits for and how it completes. */
865
+ pending_live_checks: Array<PendingLiveCheck & {
866
+ /** Check id. */
867
+ check_id: string;
868
+ }>;
869
+ /** Recommended / extra items open (never block the checks from passing). */
870
+ suggestions: number;
871
+ /** Per-plan / per-checkout verdicts, in the same vocabulary as the roll-up. Present when the site has two or more checkouts, or one on Stripe. */
872
+ checkouts?: Array<CheckoutVerdict>;
873
+ }
531
874
  /** Latest verdict; null until the first evaluation. */
532
875
  export type SiteCompliance = {
533
- /** Compliance score 0-100 (one decimal place). */
534
- score: number;
535
- /** No critical/high obligation failing or unverified. */
536
- insurable: boolean;
537
876
  /** When the latest evaluation ran. Unix timestamp in seconds. */
538
877
  evaluated: number;
539
878
  /** Open findings whose latest status is fail. */
540
879
  open_findings: number;
541
880
  /** Open findings waiting for a human look. */
542
881
  needs_review: number;
882
+ /** User-facing roll-up of the required checks: needs_fix > your_call > compliant (every required check passes; pending live checks count as passing). */
883
+ status: "needs_fix" | "your_call" | "incomplete" | "compliant" | "not_checked";
884
+ /** Label to show. */
885
+ label: string;
886
+ rollup: ComplianceRollup;
543
887
  } | null;
544
888
  /** What to install on the merchant site. */
545
889
  export interface SiteInstall {
@@ -552,6 +896,33 @@ export interface SiteInstall {
552
896
  /** Billing-platform webhook URLs (platform -> URL). */
553
897
  webhook_urls: Record<string, string>;
554
898
  }
899
+ /** The site's Shopify store connection; null when the site neither uses platform shopify nor has a Shopify connection. */
900
+ export type SiteShopify = {
901
+ /** How the store is connected. app: through the Checkbox Shopify app (Checkbox can publish the verified terms to the app block: publishShopifyTerms). own_app: with the store's own custom-app access token (read-only; use the standalone theme snippet). none: not connected (only the merchant can install the Checkbox app from the Shopify admin). */
902
+ connection: "app" | "own_app" | "none";
903
+ /** The store's myshopify.com domain, when connected. */
904
+ shop: string | null;
905
+ /** Status of the Shopify connection (connected, error, disconnected); null without one. */
906
+ status: string | null;
907
+ /** The newest publish of the verified renewal terms to the Checkbox app block; null when never published. Whether the block is placed on the theme shows in the scans (Checkbox does not read the theme). */
908
+ terms_published: {
909
+ /** The fix application that recorded the publish. */
910
+ application: string;
911
+ /** When the text was published. Unix timestamp in seconds. */
912
+ published: number;
913
+ /** sha256 of the published texts (disclosure + newline + consent label). */
914
+ sha256: string;
915
+ } | null;
916
+ /** Theme editor link that adds the "Renewal terms + consent" block to the product page (the merchant opens it once and clicks Save). Null without a connected store. */
917
+ theme_editor_url: string | null;
918
+ } | null;
919
+ /** The compliance status of the evaluation this scan produced (null until evaluated). Retrieve the evaluation for the checks and counts. */
920
+ export type ScanCompliance = {
921
+ /** Roll-up status of that evaluation: needs_fix, your_call, incomplete, compliant or not_checked. */
922
+ status: "needs_fix" | "your_call" | "incomplete" | "compliant" | "not_checked";
923
+ /** The status label to show, counted in tasks ("2 fixes needed", "Checks pass"). */
924
+ label: string;
925
+ } | null;
555
926
  /** Most recent scan (only with expand[]=latest_scan). */
556
927
  export interface Scan {
557
928
  /** Unique identifier of the scan (scan_…). */
@@ -574,10 +945,7 @@ export interface Scan {
574
945
  warnings: Array<string>;
575
946
  /** The evaluation this scan produced (null until evaluated). */
576
947
  evaluation: string | null;
577
- /** Score of that evaluation (0-100, one decimal place). */
578
- score: number | null;
579
- /** Insurable flag of that evaluation. */
580
- insurable: boolean | null;
948
+ compliance: ScanCompliance;
581
949
  /** When the scan started. Unix timestamp in seconds. */
582
950
  started: number | null;
583
951
  /** When the scan finished. Unix timestamp in seconds. */
@@ -595,10 +963,10 @@ export interface DomainVerification {
595
963
  site: string;
596
964
  /** Domain of the site URL. */
597
965
  domain: string | null;
598
- /** not_started until createDomainVerification; verified once the TXT record or file was found. */
966
+ /** not_started until createDomainVerification; verified once the TXT record, the file, the live snippet or the meta tag was found. */
599
967
  status: "not_started" | "pending" | "verified";
600
- /** How control was proven. */
601
- method: "dns_txt" | "well_known" | null;
968
+ /** How control was proven: dns_txt, well_known, snippet (the site's Checkbox snippet live on https://<domain>/), meta_tag (<meta name="checkbox-verify"> on https://<domain>/) or shopify_install (the domain is the primary domain of a Shopify store that installed the Checkbox app and is connected to this site). */
969
+ method: "dns_txt" | "well_known" | "snippet" | "meta_tag" | "shopify_install" | null;
602
970
  /** When it was verified. Unix timestamp in seconds. */
603
971
  verified_at: number | null;
604
972
  /** Last check. Unix timestamp in seconds. */
@@ -621,6 +989,13 @@ export interface DomainVerification {
621
989
  /** Exact file contents. */
622
990
  contents: string;
623
991
  } | null;
992
+ /** Or add this meta tag to the homepage (option 3). Option 4: install the site's Checkbox snippet (install.script_tag) on the homepage; Checkbox verifies the domain when it sees it live. */
993
+ meta_tag: {
994
+ /** The page Checkbox reads (the site's homepage, redirects only within the domain). */
995
+ url: string;
996
+ /** Put this tag in the <head> of that page. */
997
+ html: string;
998
+ } | null;
624
999
  /** Configured scan URLs outside the verified domain (certificates cover only the domain). */
625
1000
  scan_target_problems: Array<string>;
626
1001
  /** Whether live mode is activated for the account. */
@@ -635,6 +1010,8 @@ export interface DomainVerification {
635
1010
  operation_id?: string;
636
1011
  /** The MCP tool that performs operation_id (`call_api` when there is no dedicated tool). */
637
1012
  mcp_tool?: string;
1013
+ /** The HTTP method and path of operation_id. */
1014
+ endpoint?: string;
638
1015
  } | null;
639
1016
  }
640
1017
  /** A subscription business Checkbox monitors. */
@@ -674,6 +1051,8 @@ export interface Site {
674
1051
  login_url: string;
675
1052
  /** Test subscriber email. */
676
1053
  email: string;
1054
+ /** The page that re-activates the test subscription before each cancellation test (null when none is set). */
1055
+ reactivate_url: string | null;
677
1056
  } | null;
678
1057
  /** Number of explicit cancellation steps. */
679
1058
  cancel_steps: number;
@@ -681,15 +1060,38 @@ export interface Site {
681
1060
  account_url: string | null;
682
1061
  /** Terms of service page read on every scan. */
683
1062
  terms_url: string | null;
1063
+ /** The checkout page is the home page (checkout_url was omitted or set to the site root). Sign-up checks then judge the home page: set checkout_url to the page with the subscribe button unless the home page really has it. */
1064
+ homepage_as_checkout: boolean;
684
1065
  };
1066
+ /** Same as checkout.url, under the name updateSite / createSite take. */
1067
+ checkout_url: string;
1068
+ /** Same as checkout.account_url, under the name updateSite takes. */
1069
+ account_url: string | null;
1070
+ /** Same as checkout.terms_url, under the name updateSite takes. */
1071
+ terms_url: string | null;
1072
+ /** Same as checkout.test_account: the test account as saved (the password is write-only and never returned); null when none is set. */
1073
+ test_account: {
1074
+ /** Login page. */
1075
+ login_url: string;
1076
+ /** Test subscriber email. */
1077
+ email: string;
1078
+ /** The re-activation page (null when none is set). */
1079
+ reactivate_url: string | null;
1080
+ } | null;
685
1081
  monitoring: SiteMonitoring;
1082
+ /** Which requirement tiers Checkbox shows (minimum: required only; balanced: + recommended suggestions; maximum: + extras). Only required items affect compliance. */
1083
+ protection_level: "minimum" | "balanced" | "maximum";
1084
+ retention: SiteRetention;
1085
+ legal_hold: LegalHold;
686
1086
  compliance: SiteCompliance;
687
1087
  install: SiteInstall;
1088
+ shopify: SiteShopify;
688
1089
  /** Archived (soft-deleted); evidence is retained. */
689
1090
  archived: boolean;
690
1091
  /** When the site was created. Unix timestamp in seconds. */
691
1092
  created: number;
692
1093
  latest_scan?: Scan;
1094
+ unverified_scan: UnverifiedScan;
693
1095
  domain_verification?: DomainVerification;
694
1096
  }
695
1097
  /** A page of sites, newest first. */
@@ -755,7 +1157,9 @@ export interface SiteTestAccount {
755
1157
  password: string;
756
1158
  /** Custom login steps. */
757
1159
  login_steps?: Array<ScanStep>;
758
- /** Optional page on your site that re-activates the test subscription (a test-only route). The cancellation test really cancels the test account; the scanner opens this page after logging in, before cancelling, so every run starts subscribed. Without it, a run after a completed cancellation reports "already cancelled by an earlier scan" (needs review). */
1160
+ /** Optional page on your site that RE-ACTIVATES the test subscription (a test-only route). The cancellation test really cancels the test account; the scanner opens this page after logging in, before cancelling, so every scan starts subscribed. Without it, a scan after a completed cancellation reports "not observed: the test account has no active subscription" (needs review). (Replaces reset_url, now a deprecated alias.) */
1161
+ reactivate_url?: string;
1162
+ /** Deprecated alias of reactivate_url. */
759
1163
  reset_url?: string;
760
1164
  }
761
1165
  export interface CreateSiteParams {
@@ -786,6 +1190,8 @@ export interface CreateSiteParams {
786
1190
  devices?: Array<"desktop" | "mobile">;
787
1191
  /** Scheduled re-scan interval (0 = off, minimum 60). Default 1440 in live mode, 0 in test mode. */
788
1192
  monitoring_interval_minutes?: number;
1193
+ /** Which requirement tiers Checkbox shows. minimum: the legal floor only (required items). balanced (default): required items plus recommended suggestions (consent receipts, a cancellation confirmation email…), collapsed and never blocking "Checks pass". maximum: everything, including extra protections (a separate checkbox per term, a pre-purchase summary). Only required items can keep a site's checks from passing, at every level. */
1194
+ protection_level?: "minimum" | "balanced" | "maximum";
789
1195
  }
790
1196
  export interface UpdateSiteParams {
791
1197
  /** Display name. */
@@ -815,6 +1221,19 @@ export interface UpdateSiteParams {
815
1221
  devices?: Array<"desktop" | "mobile">;
816
1222
  /** Scheduled re-scan interval (0 = off, minimum 60). Default 1440 in live mode, 0 in test mode. */
817
1223
  monitoring_interval_minutes?: number;
1224
+ /** Which requirement tiers Checkbox shows. minimum: the legal floor only (required items). balanced (default): required items plus recommended suggestions (consent receipts, a cancellation confirmation email…), collapsed and never blocking "Checks pass". maximum: everything, including extra protections (a separate checkbox per term, a pre-purchase summary). Only required items can keep a site's checks from passing, at every level. */
1225
+ protection_level?: "minimum" | "balanced" | "maximum";
1226
+ /** The URLs nested as the site object returns them (checkout.url, checkout.account_url, checkout.terms_url); the flat fields win when both are given. */
1227
+ checkout?: {
1228
+ /** Same as checkout_url. */
1229
+ url?: string;
1230
+ /** Same as account_url. */
1231
+ account_url?: string | null;
1232
+ /** Same as terms_url. */
1233
+ terms_url?: string | null;
1234
+ };
1235
+ retention?: RetentionParams;
1236
+ legal_hold?: LegalHoldParams;
818
1237
  }
819
1238
  /** A billing-platform connection of a site. */
820
1239
  export interface Integration {
@@ -832,13 +1251,55 @@ export interface Integration {
832
1251
  last_synced: number | null;
833
1252
  /** A problem worth fixing, e.g. a test-mode key on a live site. */
834
1253
  warning: string | null;
1254
+ /** Chargebee, Recurly and Paddle: the webhook to add by hand (Chargebee: Settings › Configure Chargebee › API Keys and Webhooks › Webhooks; Recurly: Integrations › Webhooks; Paddle: Events › Notifications › New destination, under Developer tools in older dashboards). Null for platforms whose webhook Checkbox registers itself. */
1255
+ webhook_setup: {
1256
+ /** Webhook URL to add in the platform. */
1257
+ url: string;
1258
+ /** Authentication the webhook uses: basic (enter the username and password below; Chargebee, Recurly) or signature (the platform signs deliveries with a secret key it makes, which you paste into Checkbox; Paddle). */
1259
+ auth: "basic" | "signature";
1260
+ /** Basic-auth username to enter. Null for signature auth. */
1261
+ username: string | null;
1262
+ /** Basic-auth password to enter. Treat it as a secret. Null for signature auth. */
1263
+ password: string | null;
1264
+ /** Events to select. */
1265
+ events: Array<string>;
1266
+ /** Webhook API version to choose. */
1267
+ api_version: string | null;
1268
+ /** Payload format to choose on the endpoint (Recurly: JSON). Null when the platform has no choice. */
1269
+ payload_format: "json" | null;
1270
+ /** Recurly and Paddle: whether the endpoint’s secret key is saved in Checkbox (dashboard › Billing connection › webhook), so every delivery’s signature is checked. Paddle deliveries are refused until it is. Null for platforms without signatures. */
1271
+ signing_key_configured: boolean | null;
1272
+ /** Paddle: whether a notification destination with this URL exists in Paddle (from the settings Checkbox last read; needs the Notification settings: Read permission). Null when unknown or for other platforms. */
1273
+ destination_status: "found" | "inactive" | "missing" | null;
1274
+ /** Paddle: events the destination does not send yet. Null when unknown or for other platforms. */
1275
+ missing_events: Array<string> | null;
1276
+ } | null;
835
1277
  }
836
1278
  export interface ConnectBillingPlatformParams {
837
1279
  /** Billing platform. */
838
- platform: "stripe" | "recharge" | "shopify";
839
- /** Read-only credentials. Stripe: { "secretKey": "rk_test_…" } (a restricted key with read access; rk_test_ in test mode). Recharge: { "apiToken": "…" }. Shopify: { "shop": "store.myshopify.com", "accessToken": "shpat_…" }. */
1280
+ platform: "stripe" | "recharge" | "shopify" | "chargebee" | "recurly" | "paddle";
1281
+ /** Read-only credentials, in snake_case like the rest of the API (the camelCase spellings, secretKey / apiToken / accessToken / apiKey, are accepted too). Stripe: { "secret_key": "rk_test_…" } (a restricted key with read access; rk_test_ in test mode). Recharge: { "api_token": "…" }. Shopify: { "shop": "store.myshopify.com", "access_token": "shpat_…" }. Chargebee: { "site": "acme", "api_key": "live_…" } (the site name before .chargebee.com and a read-only API key). Recurly: { "api_key": "…", "region": "us" } (a private API key of the site; region "eu" for sites hosted in Recurly’s EU data centre, default "us"). Paddle: { "api_key": "pdl_live_apikey_…" } (a Paddle Billing API key with read permissions; sandbox keys, pdl_sdbx_…, read the sandbox; "environment": "live" or "sandbox" only for older keys without that prefix). Checkbox only reads. */
840
1282
  credentials: Record<string, string>;
841
1283
  }
1284
+ /** A queued re-read of the site's billing-platform settings, followed by a re-evaluation. */
1285
+ export interface BillingSync {
1286
+ /** String representing the object's type. Always "billing_sync". */
1287
+ object: "billing_sync";
1288
+ /** The site whose billing settings are re-read. */
1289
+ site: string;
1290
+ /** One entry per connected billing platform. */
1291
+ platforms: Array<{
1292
+ /** The connected billing platform. */
1293
+ platform: "stripe" | "shopify" | "recharge" | "chargebee" | "recurly" | "paddle" | "woocommerce" | "custom";
1294
+ /** The re-read is queued; settings refresh within a minute. */
1295
+ status: "queued";
1296
+ /** When the settings were last read successfully. Unix timestamp in seconds. */
1297
+ last_synced: number | null;
1298
+ /** Why the last read failed, if it did. */
1299
+ last_error: string | null;
1300
+ }>;
1301
+ next_action: NextAction;
1302
+ }
842
1303
  /** A page of scans, newest first. */
843
1304
  export interface ScanList {
844
1305
  /** String representing the object's type. Always "list". */
@@ -862,6 +1323,10 @@ export interface CheckSummary {
862
1323
  severity: "critical" | "high" | "medium" | "low";
863
1324
  /** Lifecycle stage. */
864
1325
  stage: "signup" | "confirmation" | "reminder" | "cancellation" | "config";
1326
+ /** User-facing status. needs_fix (a requirement is clearly not met: `compliance.fix` is the one change), pending_live_check (everything Checkbox can see is right; the live event has not been observed yet — counts as passing the checks), verified_live (observed live: proof run, real BCC'd send, Stripe-confirmed cancellation), your_call (a real decision for a person: `compliance.question`), compliant (passes; grey areas carry a `compliance.note`), not_applicable, not_set_up (no sign the email or setting exists yet: `compliance.fix` is the one-click way to set it up; never counts as passing the checks), not_checked (Checkbox has not tried it yet, e.g. the cancel flow: `compliance.fix` says how; never counts as passing the checks). */
1327
+ compliance_status: "needs_fix" | "pending_live_check" | "verified_live" | "your_call" | "compliant" | "not_applicable" | "not_set_up" | "not_checked";
1328
+ /** The status in words to show a person ("Needs a fix", "Your call", "Not set up yet", "Not checked yet", "Checks pass"…). Show this, never the machine value. */
1329
+ compliance_status_label: string;
865
1330
  }
866
1331
  /** A compliance verdict for a site at a point in time. */
867
1332
  export interface Evaluation {
@@ -875,10 +1340,6 @@ export interface Evaluation {
875
1340
  site: string;
876
1341
  /** The scan row this evaluation belongs to. */
877
1342
  scan: string;
878
- /** Compliance score 0-100 (severity-weighted, one decimal place, e.g. 82.5). */
879
- score: number;
880
- /** No critical/high check failing, no critical check undecided, no high check without evidence. */
881
- insurable: boolean;
882
1343
  /** Legal catalog / rules version used. */
883
1344
  rules_version: string;
884
1345
  /** When it was evaluated. Unix timestamp in seconds. */
@@ -896,8 +1357,9 @@ export interface Evaluation {
896
1357
  /** Checks that do not apply. */
897
1358
  not_applicable: number;
898
1359
  };
899
- /** Checks that keep the site from being insurable. */
1360
+ /** Blocking checks: critical or high-severity checks that fail, are undecided (critical) or lack evidence (high). */
900
1361
  blockers: Array<CheckSummary>;
1362
+ compliance: ComplianceRollup;
901
1363
  /** Every check evaluated. */
902
1364
  checks: Array<CheckSummary>;
903
1365
  }
@@ -943,6 +1405,78 @@ export type Remediation = {
943
1405
  code: string;
944
1406
  } | null;
945
1407
  } | null;
1408
+ /** One piece of evidence a verdict relied on. */
1409
+ export interface EvidenceItem {
1410
+ /** What kind of evidence: a captured page, an email, a billing-platform setting, a lifecycle event, a fetched policy document, a test cancellation, or the request input (preflight). */
1411
+ source: "page" | "email" | "billing" | "event" | "policy" | "flow" | "input";
1412
+ /** Id of the capture / email / event / evidence record. */
1413
+ ref?: string;
1414
+ /** Page URL. */
1415
+ url?: string;
1416
+ /** The exact text the verdict relied on. */
1417
+ quote?: string;
1418
+ /** The element on the page (CSS selector). */
1419
+ selector?: string;
1420
+ /** Where the element was, in page coordinates (the crop of the screenshot). */
1421
+ rect?: {
1422
+ /** Left edge (px). */
1423
+ x: number;
1424
+ /** Top edge (px, from the top of the page). */
1425
+ y: number;
1426
+ /** Width (px). */
1427
+ width: number;
1428
+ /** Height (px). */
1429
+ height: number;
1430
+ };
1431
+ /** Billing-platform field the verdict read. */
1432
+ field?: string;
1433
+ /** Value of that field. */
1434
+ value?: unknown;
1435
+ /** Where it was seen (region and device, email subject, …). */
1436
+ label?: string;
1437
+ /** This item’s own outcome when the check judged several. */
1438
+ status?: "pass" | "fail" | "needs_review" | "not_applicable";
1439
+ /** What the check concluded from this item. */
1440
+ detail?: string;
1441
+ /** Evidence id of the page screenshot. */
1442
+ screenshot_ref?: string;
1443
+ /** When it was captured / received. */
1444
+ at?: string;
1445
+ }
1446
+ /** What a verdict was based on. Never a pass without it; needs_review says what is missing. */
1447
+ export interface VerdictEvidence {
1448
+ /** What the verdict rests on, in one line. */
1449
+ summary: string;
1450
+ /** The exact texts, elements, emails, settings and events relied on (failing / unclear first). */
1451
+ items: Array<EvidenceItem>;
1452
+ /** For needs_review: the missing piece that would decide it. */
1453
+ missing?: string;
1454
+ }
1455
+ /** What a person should do about one check (the user-facing layer over `status`). */
1456
+ export interface ComplianceInfo {
1457
+ /** User-facing status. needs_fix (a requirement is clearly not met: `compliance.fix` is the one change), pending_live_check (everything Checkbox can see is right; the live event has not been observed yet — counts as passing the checks), verified_live (observed live: proof run, real BCC'd send, Stripe-confirmed cancellation), your_call (a real decision for a person: `compliance.question`), compliant (passes; grey areas carry a `compliance.note`), not_applicable, not_set_up (no sign the email or setting exists yet: `compliance.fix` is the one-click way to set it up; never counts as passing the checks), not_checked (Checkbox has not tried it yet, e.g. the cancel flow: `compliance.fix` says how; never counts as passing the checks). */
1458
+ status: "needs_fix" | "pending_live_check" | "verified_live" | "your_call" | "compliant" | "not_applicable" | "not_set_up" | "not_checked";
1459
+ /** Label to show: "Needs a fix", "Not set up yet", "Not checked yet", "Checks pass · live check pending", "Verified live", "Your call", "Checks pass", "Checks pass with a note", "Not applicable". */
1460
+ label: string;
1461
+ /** Stable code of the mapping rule (docs/ACCURACY.md). */
1462
+ reason: string;
1463
+ /** required (legal floor: the only tier that can keep a site's checks from passing), recommended (clearer records beyond the legal floor, conversion-neutral), extra (maximum protection). */
1464
+ tier: "required" | "recommended" | "extra";
1465
+ /** needs_fix: the one change that fixes it. */
1466
+ fix: string | null;
1467
+ /** A short note (grey area, stylistic suggestion). */
1468
+ note: string | null;
1469
+ pending_live_check: PendingLiveCheck | null;
1470
+ /** your_call: the question. */
1471
+ question: {
1472
+ /** One plain-language question. */
1473
+ text: string;
1474
+ /** The answer Checkbox recommends. */
1475
+ recommended: string;
1476
+ /** Why a person has to decide. */
1477
+ why: string;
1478
+ } | null;
1479
+ }
946
1480
  /** The latest result of one legal check for a site. */
947
1481
  export interface Finding {
948
1482
  /** Unique identifier of the finding (fnd_…). */
@@ -980,6 +1514,10 @@ export interface Finding {
980
1514
  evidence_refs: Array<string>;
981
1515
  /** Check-specific details (failing regions/devices/URLs, measurements, quotes). */
982
1516
  details: Record<string, unknown>;
1517
+ evidence: VerdictEvidence;
1518
+ /** User-facing status. needs_fix (a requirement is clearly not met: `compliance.fix` is the one change), pending_live_check (everything Checkbox can see is right; the live event has not been observed yet — counts as passing the checks), verified_live (observed live: proof run, real BCC'd send, Stripe-confirmed cancellation), your_call (a real decision for a person: `compliance.question`), compliant (passes; grey areas carry a `compliance.note`), not_applicable, not_set_up (no sign the email or setting exists yet: `compliance.fix` is the one-click way to set it up; never counts as passing the checks), not_checked (Checkbox has not tried it yet, e.g. the cancel flow: `compliance.fix` says how; never counts as passing the checks). */
1519
+ compliance_status: "needs_fix" | "pending_live_check" | "verified_live" | "your_call" | "compliant" | "not_applicable" | "not_set_up" | "not_checked";
1520
+ compliance: ComplianceInfo;
983
1521
  /** Scan that produced the latest result. */
984
1522
  scan: string | null;
985
1523
  /** First time the check was evaluated. Unix timestamp in seconds. */
@@ -1060,10 +1598,16 @@ export interface Task {
1060
1598
  key: string;
1061
1599
  /** Short imperative title. */
1062
1600
  title: string;
1063
- /** open (apply the change), in_progress (an agent claimed it), verifying (a verification is waiting for a confirming observation), done, wont_fix (the merchant declined, with a reason), manual (needs a human answer: see question). */
1064
- status: "open" | "in_progress" | "verifying" | "done" | "wont_fix" | "manual";
1601
+ /** open (apply the change), in_progress (an agent claimed it), verifying (a verification is waiting for a confirming observation), done, wont_fix (the merchant declined, with a reason), manual (needs a human answer: see question), pending_live_check (everything Checkbox can see is right; it waits for a live observation — see change for how it completes. Counts as passing the checks and never blocks the plan). */
1602
+ status: "open" | "in_progress" | "verifying" | "done" | "wont_fix" | "manual" | "pending_live_check";
1065
1603
  /** Strictest severity among the task's legal checks. */
1066
1604
  priority: "critical" | "high" | "medium" | "low";
1605
+ /** required (the legal floor: the only tier that can keep the site's checks from passing), recommended (clearer records beyond the legal floor, conversion-neutral; shown at protection level balanced and maximum, never blocks), extra (maximum protection only). Always present on API responses. */
1606
+ tier?: "required" | "recommended" | "extra";
1607
+ /** User-facing status. needs_fix (a requirement is clearly not met: `compliance.fix` is the one change), pending_live_check (everything Checkbox can see is right; the live event has not been observed yet — counts as passing the checks), verified_live (observed live: proof run, real BCC'd send, Stripe-confirmed cancellation), your_call (a real decision for a person: `compliance.question`), compliant (passes; grey areas carry a `compliance.note`), not_applicable, not_set_up (no sign the email or setting exists yet: `compliance.fix` is the one-click way to set it up; never counts as passing the checks), not_checked (Checkbox has not tried it yet, e.g. the cancel flow: `compliance.fix` says how; never counts as passing the checks). */
1608
+ compliance_status?: "needs_fix" | "pending_live_check" | "verified_live" | "your_call" | "compliant" | "not_applicable" | "not_set_up" | "not_checked";
1609
+ /** The status in words to show a person ("Needs a fix", "Your call", "Not set up yet", "Not checked yet", "Checks pass"…). Show this, never the machine value. */
1610
+ compliance_status_label?: string;
1067
1611
  /** Position in the plan (1 = do first). Dependency-aware. */
1068
1612
  order: number;
1069
1613
  /** Legal checks this task makes pass. */
@@ -1087,7 +1631,7 @@ export interface Task {
1087
1631
  where: {
1088
1632
  /** Where the change is made. */
1089
1633
  kind: "code" | "stripe_setting" | "email_template" | "policy_page" | "dns" | "checkbox_setting" | "billing_platform";
1090
- /** Likely source file (reported by `checkbox init` / updateSetupSession, else a framework convention). */
1634
+ /** Source file reported by `checkbox init` / updateSetupSession (null when none was reported: Checkbox does not guess file names; the root layout of a file-system router is named). */
1091
1635
  file_hint: string | null;
1092
1636
  /** Page (or settings page) where the problem was observed / the change is made. */
1093
1637
  url: string | null;
@@ -1172,13 +1716,24 @@ export interface Task {
1172
1716
  /** When it was requested. Unix timestamp in seconds. */
1173
1717
  created: number;
1174
1718
  } | null;
1719
+ /** Email tasks on a site with several plans: the result of each plan's own email copy (verifyTask with plan). The copy check passes only when every plan passes; one plan's copy never covers another plan. */
1720
+ plan_coverage?: Array<{
1721
+ /** The plan, by name. */
1722
+ plan: string;
1723
+ /** That plan's copy: pass, fail, needs_review, or not_checked (no copy for this plan was verified yet). */
1724
+ verdict: "pass" | "fail" | "needs_review" | "not_checked";
1725
+ /** When that plan's copy was checked. Unix timestamp in seconds. */
1726
+ checked_at: number | null;
1727
+ }>;
1175
1728
  next_action: PlanNextAction;
1729
+ /** Email tasks only (null otherwise): what Checkbox has seen of this email. not_seen (nothing yet), template_checked (a template or sample passed the email checks, but Checkbox has not seen it sent for a real event: the task stays open), delivery_seen (captured from a real event: a test run, a notice for a real subscriber, or a BCC copy matching that subscriber's billing event). Only delivery_seen satisfies the task. */
1730
+ verification_level: "not_seen" | "template_checked" | "delivery_seen" | null;
1176
1731
  /** When the task first appeared. Unix timestamp in seconds. */
1177
1732
  first_seen: number;
1178
1733
  /** When it was done. Unix timestamp in seconds. */
1179
1734
  done_at: number | null;
1180
1735
  }
1181
- /** The ordered, machine-readable list of changes that makes a site compliant, recomputed from its latest evaluation. */
1736
+ /** The ordered, machine-readable list of changes that makes a site's checks pass, recomputed from its latest evaluation. */
1182
1737
  export interface CompliancePlan {
1183
1738
  /** Unique identifier of the compliance plan (plan_…). */
1184
1739
  id: string;
@@ -1188,18 +1743,18 @@ export interface CompliancePlan {
1188
1743
  livemode: boolean;
1189
1744
  /** The site. */
1190
1745
  site: string;
1191
- /** action_required (an agent can apply open tasks now), verifying (changes applied; waiting for confirming observations), compliant (every applicable check Checkbox could observe passes — an automated assessment, not a legal determination; see coverage for what was not observed), blocked (only human answers or declined critical tasks remain). */
1746
+ /** action_required (an agent can apply open tasks now), verifying (changes applied; waiting for confirming observations), compliant (every required check passes or only waits for a live check — an automated assessment, not a legal determination; see compliance.pending_live_checks and coverage), blocked (only human answers ("Your call") or declined critical tasks remain). */
1192
1747
  status: "action_required" | "verifying" | "compliant" | "blocked";
1193
- /** Compliance score 0-100 of the latest evaluation. */
1194
- score: number | null;
1195
- /** Preview flag the planned Checkbox Warranty will key on (no checks failing at high severity). No warranty or insurance is offered yet; this is not an underwriting decision. */
1196
- insurable: boolean | null;
1748
+ /** The plan status in words to show a person: action_required "Fixes needed", verifying "Checking your changes", compliant "Checks pass", blocked "Your call". Show this, never the machine value (`compliant` is a status name, not a legal conclusion). */
1749
+ status_label?: string;
1197
1750
  /** The evaluation the plan was built from (null before the first check). */
1198
1751
  evaluation: string | null;
1199
1752
  /** When that evaluation ran. Unix timestamp in seconds. */
1200
1753
  evaluated: number | null;
1201
1754
  /** Two or three sentences for an LLM: where the site stands and what comes next. */
1202
1755
  summary: string;
1756
+ /** Declared plans (setup plans, i.e. your code) whose price, interval or trial differ from the billing platform's Price they map to. Checkbox checks and writes every fix from the Price, and the page task names the difference; update the page and setup plans, or the Price, so they agree. Absent when none. */
1757
+ plan_terms_conflicts?: Array<string>;
1203
1758
  /** Tasks per status. */
1204
1759
  counts: {
1205
1760
  /** Open tasks. */
@@ -1210,6 +1765,8 @@ export interface CompliancePlan {
1210
1765
  verifying: number;
1211
1766
  /** Tasks waiting for a human answer. */
1212
1767
  manual: number;
1768
+ /** Tasks that only wait for a live observation (count as passing the checks). */
1769
+ pending_live_check?: number;
1213
1770
  /** Done tasks. */
1214
1771
  done: number;
1215
1772
  /** Declined tasks. */
@@ -1217,7 +1774,19 @@ export interface CompliancePlan {
1217
1774
  };
1218
1775
  /** Tasks in the order to do them (done tasks last). */
1219
1776
  tasks: Array<Task>;
1220
- /** What the assessment rests on. Tell the human about not_observed and attested items; never call the site "compliant" without them. */
1777
+ /** The site's protection level: minimum lists required tasks only; balanced adds recommended suggestions; maximum adds extras. Only required tasks change the plan status. */
1778
+ protection_level: "minimum" | "balanced" | "maximum";
1779
+ /** Task ids grouped by tier, in plan order. */
1780
+ groups: {
1781
+ /** Required tasks (the legal floor). */
1782
+ required: Array<string>;
1783
+ /** Recommended suggestions (never block the checks from passing). */
1784
+ recommended: Array<string>;
1785
+ /** Extra protections (maximum only). */
1786
+ extra: Array<string>;
1787
+ };
1788
+ compliance: ComplianceRollup | null;
1789
+ /** What the assessment rests on. Tell the human about not_observed and attested items; never tell them the site "is compliant". */
1221
1790
  coverage: {
1222
1791
  /** Lifecycle stages Checkbox observed (signup, acknowledgment_email, reminders, cancellation, policies, billing_settings). */
1223
1792
  observed: Array<string>;
@@ -1229,19 +1798,56 @@ export interface CompliancePlan {
1229
1798
  billing_connected: boolean;
1230
1799
  };
1231
1800
  next_action: PlanNextAction;
1801
+ /** Evidence level per required email kind. A plan never reaches status compliant on template_checked emails. */
1802
+ email_verification: Array<{
1803
+ /** Email kind (acknowledgment, trial_ending, renewal_reminder, annual_terms, charge_notice, price_change, cancellation_confirmation). */
1804
+ kind: string;
1805
+ /** not_seen, template_checked (template or sample only: never counted as passing) or delivery_seen (sent for a real event). */
1806
+ verification_level: "not_seen" | "template_checked" | "delivery_seen";
1807
+ /** Why this level, in plain words. */
1808
+ reason: string;
1809
+ /** The email the level rests on (the delivered one, else the newest). */
1810
+ email: string | null;
1811
+ /** delivery_seen only: the real event the email came from. */
1812
+ basis: "test_run" | "synthetic_signup" | "checkbox_sent" | "notice_due" | "billing_event" | null;
1813
+ }>;
1232
1814
  /** Rules / catalog version of the evaluation. */
1233
1815
  rules_version: string | null;
1234
1816
  /** Automated assessment; not legal advice. */
1235
1817
  disclaimer: string;
1236
1818
  /** When the plan was computed. Unix timestamp in seconds. */
1237
1819
  generated: number;
1820
+ unverified_scan?: UnverifiedScan;
1821
+ /** Optional improvements beyond compliance. Never tasks, never blocking, never counted toward compliance. */
1822
+ optional_improvements?: {
1823
+ /** Conversion suggestions for this site that keep the checks passing. */
1824
+ conversion_suggestions: {
1825
+ /** What they are. */
1826
+ description: string;
1827
+ /** Always false. */
1828
+ blocking: false;
1829
+ /** Always false: they never change the status or the tasks. */
1830
+ counts_toward_compliance: false;
1831
+ /** Operation that lists them. */
1832
+ operation_id: string;
1833
+ /** MCP tool that lists them. */
1834
+ mcp_tool: string;
1835
+ /** HTTP endpoint. */
1836
+ endpoint: string;
1837
+ };
1838
+ };
1238
1839
  }
1239
1840
  export interface UpdateTaskParams {
1240
- /** in_progress claims the task (other agents see it), wont_fix declines it (needs reason; a declined critical/high task keeps the plan from being compliant), not_applicable records that the task does not apply to this business (needs reason, e.g. "no price changes are planned"; the task closes as no_longer_applicable and does not block the plan), open clears any of them. */
1841
+ /** in_progress claims the task (other agents see it), wont_fix declines it (needs reason; a declined critical/high task keeps the plan from reaching status compliant), not_applicable records that the task does not apply to this business (needs reason, e.g. "no price changes are planned"; the task closes as no_longer_applicable and does not block the plan), open clears any of them. */
1241
1842
  status: "open" | "in_progress" | "wont_fix" | "not_applicable";
1242
1843
  /** Why (required for wont_fix). */
1243
1844
  reason?: string;
1244
1845
  }
1846
+ /** The task after answerTask, with the confirmation link at the top level when the human must confirm. */
1847
+ export type AnsweredTask = Task & {
1848
+ /** When the answer waits for the human: the link they open (signed in to Checkbox) to confirm it. Same as answer.pending_confirmation_url; null when nothing waits for confirmation. */
1849
+ confirmation_url: string | null;
1850
+ };
1245
1851
  export interface AnswerTaskParams {
1246
1852
  /** One of the task's question.options (yes / no, or confirmed / needs_change). */
1247
1853
  answer: string;
@@ -1275,13 +1881,17 @@ export interface Verification {
1275
1881
  task: string | null;
1276
1882
  /** One task or the whole site. */
1277
1883
  scope: "task" | "site";
1278
- /** pending (waiting for the confirming scan / re-evaluation), passed (Checkbox observed the expected result), failed (it did not: see diff). */
1279
- status: "pending" | "passed" | "failed";
1884
+ /** pending (waiting for the confirming scan / re-evaluation), passed (Checkbox observed the expected result: every check passes or does not apply), passed_with_gaps (nothing observed fails, but some checks could not be observed: observed missing_data — not verified), passed_with_notes (nothing observed fails and the task counts as passing, but a check is still needs_review on a part that is not yours to change, such as Stripe's own page layout: see checks), not_checked (a task whose checks could only not be observed yet: nothing to change in the code; next_action says what evidence to provide), pending_live_check (an email whose content passes but that Checkbox has not seen sent for a real event yet: nothing to change; it completes on the first real send or a proof run), failed (it did not: see diff). */
1885
+ status: "pending" | "passed" | "passed_with_gaps" | "passed_with_notes" | "not_checked" | "pending_live_check" | "failed";
1280
1886
  /** How it was re-checked. */
1281
1887
  method: "page_fetch" | "policy_refetch" | "stripe_params" | "email_copy" | "platform_sync" | "attestation" | "evaluation" | "test_run";
1888
+ /** What this verification checked, in words: "the params you sent", "Checkout Sessions read from Stripe", "registered configs", "the HTML you sent", "the email copy you sent (plan …)", "the live page …, fetched now"… */
1889
+ checked: string;
1282
1890
  /** The fast pre-check run immediately (seconds). A failing pre-check fails the verification at once. */
1283
1891
  precheck: {
1284
- /** static_fetch, html, stripe_params, email or policy_fetch. */
1892
+ /** What the pre-check judged (as `checked`). */
1893
+ checked: string;
1894
+ /** static_fetch, html, stripe_params, email, policy_fetch, or billing_sync (Stripe was re-read before judging; its verdict is always needs_review and only carries the note: the re-evaluation decides). */
1285
1895
  source: string;
1286
1896
  /** Pre-check verdict for the task's checks. */
1287
1897
  verdict: "pass" | "fail" | "needs_review";
@@ -1289,6 +1899,26 @@ export interface Verification {
1289
1899
  url: string | null;
1290
1900
  /** What the pre-check can and cannot confirm. */
1291
1901
  note: string;
1902
+ /** Email tasks on a site with several plans: each plan's copy result. A later verification only replaces the result of the plan it judged. */
1903
+ plans?: Array<{
1904
+ /** The plan, by name. */
1905
+ plan: string;
1906
+ /** That plan's copy: pass, fail, needs_review, or not_checked (no copy for this plan was verified yet). */
1907
+ verdict: "pass" | "fail" | "needs_review" | "not_checked";
1908
+ /** When that plan's copy was checked. Unix timestamp in seconds. */
1909
+ checked_at: number | null;
1910
+ }>;
1911
+ /** Each pre-checked check of the task, compact (empty when the pre-check ran no engine check). */
1912
+ checks: Array<{
1913
+ /** Check id. */
1914
+ check_id: string;
1915
+ /** Pre-check result: pass, fail, needs_review or not_applicable. */
1916
+ status: string;
1917
+ /** What the pre-check found, in one line. */
1918
+ reason: string;
1919
+ /** How to fix it, in one line (absent when it passes). */
1920
+ fix?: string;
1921
+ }>;
1292
1922
  } | null;
1293
1923
  /** Confirming scan queued by the verification. */
1294
1924
  scan: string | null;
@@ -1298,6 +1928,8 @@ export interface Verification {
1298
1928
  diff: Array<VerificationCheck>;
1299
1929
  /** Plan status after this verification (null while pending). */
1300
1930
  plan_status: "action_required" | "verifying" | "compliant" | "blocked" | null;
1931
+ /** The plan status in words to show a person: action_required "Fixes needed", verifying "Checking your changes", compliant "Checks pass", blocked "Your call". Show this, never the machine value (`compliant` is a status name, not a legal conclusion). */
1932
+ plan_status_label?: string | null;
1301
1933
  next_action: PlanNextAction;
1302
1934
  /** When it was requested. Unix timestamp in seconds. */
1303
1935
  created: number;
@@ -1309,9 +1941,11 @@ export interface Verification {
1309
1941
  export interface VerifyTaskParams {
1310
1942
  /** page_fetch tasks: the rendered page HTML before you deploy, at most ~900 KB (request bodies are limited to 1 MB). Pre-check only; the confirming scan runs on the live page. */
1311
1943
  html?: string;
1312
- /** stripe_params tasks: exactly what your code now passes to stripe.checkout.sessions.create. */
1944
+ /** stripe_params tasks and the sign-up tasks (signup_disclosure): exactly what your code now passes to stripe.checkout.sessions.create. Judged together with the page (any failing check fails the verification). A task that does not use it refuses it (parameter_invalid, naming the task that takes it). */
1313
1945
  stripe_checkout_session?: Record<string, unknown>;
1314
- /** email_copy tasks: the new email template (pre-check; the real email confirms). */
1946
+ /** stripe_params tasks with several Checkout code paths (one per plan, e.g. monthly and annual-with-trial): every params object your code passes to stripe.checkout.sessions.create. The pre-check fails when any of them fails. Without either field, every registered config (newest per name) is checked. */
1947
+ stripe_checkout_sessions?: Array<Record<string, unknown>>;
1948
+ /** email_copy tasks: the new email template (pre-check; the real email confirms). On a site with several plans it is checked against every plan and passes when it matches one plan fully (pass plan or price_id to check one plan). */
1315
1949
  email?: {
1316
1950
  /** Email kind (default: from the task). */
1317
1951
  kind?: "acknowledgment" | "trial_reminder" | "renewal_reminder" | "price_change" | "annual_terms" | "charge_notice" | "cancellation_confirmation";
@@ -1322,6 +1956,10 @@ export interface VerifyTaskParams {
1322
1956
  /** HTML body. */
1323
1957
  html?: string;
1324
1958
  };
1959
+ /** email_copy tasks: check the email against this plan only (its name, e.g. "Annual"). */
1960
+ plan?: string;
1961
+ /** email_copy tasks: check the email against the plan with this Stripe Price id only. */
1962
+ price_id?: string;
1325
1963
  /** Re-check a task that is already done (or declined) instead of returning its last result: Checkbox evaluates the site again now and queues a confirming scan, so a regression shows up (pilot: a cancel page switched to phone-only stayed "passed"). */
1326
1964
  recheck?: boolean;
1327
1965
  }
@@ -1388,6 +2026,7 @@ export interface Fix {
1388
2026
  /** Why parts of the fix could not be generated (e.g. plan terms unknown). */
1389
2027
  problems: Array<string>;
1390
2028
  remediation: Remediation;
2029
+ next_action: NextAction | null;
1391
2030
  }
1392
2031
  /** A page of fix plans. */
1393
2032
  export interface FixList {
@@ -1400,6 +2039,38 @@ export interface FixList {
1400
2039
  /** The URL of this list. */
1401
2040
  url: string;
1402
2041
  }
2042
+ /** The verified renewal terms published to the Checkbox Shopify app block (an app-owned metafield; nothing else in the store changes). */
2043
+ export interface ShopifyTermsPublication {
2044
+ /** Id of the recorded fix application (the evidence trail of this publish). */
2045
+ id: string;
2046
+ /** String representing the object's type. Always "shopify_terms_publication". */
2047
+ object: "shopify_terms_publication";
2048
+ /** true for live-mode objects, false for test mode (ck_test_ keys act on an isolated sandbox). */
2049
+ livemode: boolean;
2050
+ /** The site. */
2051
+ site: string;
2052
+ /** The Shopify store (myshopify.com domain) the text was published to. */
2053
+ shop: string;
2054
+ /** The renewal disclosure the "Renewal terms + consent" block now shows (engine-verified). */
2055
+ disclosure: string;
2056
+ /** Label of the unchecked, required consent checkbox the block shows. */
2057
+ consent_label: string;
2058
+ /** sha256 of the published texts (disclosure + newline + consent label). */
2059
+ sha256: string;
2060
+ /** Sign-up checks the published text was verified against. */
2061
+ check_ids: Array<string>;
2062
+ /** When the text was published. Unix timestamp in seconds. */
2063
+ published: number;
2064
+ /** Theme editor link that adds the "Renewal terms + consent" block to the product page. The merchant opens it once and clicks Save (Checkbox never edits the theme). */
2065
+ theme_editor_url: string;
2066
+ next_action: NextAction;
2067
+ }
2068
+ export interface PublishShopifyTermsParams {
2069
+ /** Billing-platform plan / price id to write the terms for (default: the plan Checkbox resolved for the site). */
2070
+ plan?: string;
2071
+ /** Cancellation URL to state (default: the hosted cancellation page or the declared account page). */
2072
+ cancel_url?: string;
2073
+ }
1403
2074
  /** A record in the tamper-evident evidence vault. */
1404
2075
  export interface Evidence {
1405
2076
  /** Unique identifier of the evidence (ev_…). */
@@ -1457,7 +2128,7 @@ export interface EvidenceChainVerification {
1457
2128
  /** Current chain head hash. */
1458
2129
  head: string | null;
1459
2130
  }
1460
- /** A signed monitoring certificate: the site met every critical and high obligation for the required streak of days. It is not insurance. */
2131
+ /** A signed monitoring certificate: for the required streak of days the site passed the checks Checkbox ran for every critical and high obligation (emails count only when seen sent for a real event, never on templates alone). It records what was monitored and when; it is not legal advice and not a legal opinion that the site is compliant. */
1461
2132
  export interface Certificate {
1462
2133
  /** Unique identifier of the certificate (cert_…). */
1463
2134
  id: string;
@@ -1467,13 +2138,13 @@ export interface Certificate {
1467
2138
  livemode: boolean;
1468
2139
  /** Certified site. */
1469
2140
  site: string;
1470
- /** active while monitoring keeps the site insurable; lapses automatically otherwise. */
2141
+ /** active while monitoring keeps passing the checks Checkbox runs (no critical or high obligation failing or unproven); lapses automatically otherwise. */
1471
2142
  status: "active" | "lapsed" | "revoked" | "superseded";
1472
2143
  /** Verified domain frozen into the certificate. */
1473
2144
  domain: string;
1474
2145
  /** Issue time. Unix timestamp in seconds. */
1475
2146
  issued: number;
1476
- /** Expiry (renewed automatically while compliant). Unix timestamp in seconds. */
2147
+ /** Expiry (renewed automatically while the site keeps passing the checks Checkbox runs). Unix timestamp in seconds. */
1477
2148
  valid_until: number;
1478
2149
  /** Last renewal. Unix timestamp in seconds. */
1479
2150
  renewed: number | null;
@@ -1483,7 +2154,7 @@ export interface Certificate {
1483
2154
  public_reason: string | null;
1484
2155
  /** Public verification page. */
1485
2156
  verify_url: string;
1486
- /** Trust badge for the merchant site. */
2157
+ /** Monitoring badge for the merchant site: it links to the verification page, which says what was checked and when. It does not say the site is legally compliant. */
1487
2158
  badge: {
1488
2159
  /** Badge image. */
1489
2160
  svg_url: string;
@@ -1519,7 +2190,7 @@ export interface NoticeSettings {
1519
2190
  /** The site's inbound address. Copies to it confirm a notice only when your sending domain authenticates them (DKIM/SPF, a trusted sending domain) and they go to the subscriber; to confirm any copy, BCC each due notice's own bcc address instead (listDueNotices / the notice.due webhook). */
1520
2191
  bcc: string;
1521
2192
  /** mode checkbox: the notices Checkbox sends for the merchant. */
1522
- enabled_kinds: Array<"acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change">;
2193
+ enabled_kinds: Array<"acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation" | "charge_notice">;
1523
2194
  /** Brand shown in notices (defaults to the site name). */
1524
2195
  brand_name: string | null;
1525
2196
  /** Product name used in notices. */
@@ -1534,6 +2205,13 @@ export interface NoticeSettings {
1534
2205
  brand_color: string | null;
1535
2206
  /** Mailbox name of the sender. */
1536
2207
  from_local_part: string;
2208
+ /** Who Checkbox can send notices to (null when unknown). */
2209
+ subscribers: {
2210
+ /** Active subscriptions Checkbox knows from the billing platform. */
2211
+ active: number;
2212
+ /** Of those, how many Checkbox can email: an address on file, or a Stripe customer whose address it reads when sending. */
2213
+ with_email: number;
2214
+ } | null;
1537
2215
  /** Confirmed cancellation policy (required before notices go out). */
1538
2216
  policy: {
1539
2217
  /** When a cancellation takes effect. */
@@ -1560,7 +2238,7 @@ export interface NoticeSettings {
1560
2238
  /** Every notice kind. */
1561
2239
  kinds: Array<{
1562
2240
  /** Notice kind. */
1563
- kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change";
2241
+ kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation" | "charge_notice";
1564
2242
  /** Label. */
1565
2243
  label: string;
1566
2244
  /** What it is and when it is sent. */
@@ -1577,8 +2255,12 @@ export interface NoticeSettings {
1577
2255
  export interface UpdateNoticeSettingsParams {
1578
2256
  /** merchant: you send the emails (Checkbox tracks them); checkbox: Checkbox sends them. Turning an enabled_kinds notice on implies checkbox. */
1579
2257
  mode?: "merchant" | "checkbox";
1580
- /** Notices to send (turning one on needs cancel_url, a confirmed policy and a connected Stripe/Recharge account). trial_reminder is accepted as an alias of trial_ending. */
1581
- enabled_kinds?: Array<"acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "trial_reminder">;
2258
+ /** The full list of notices Checkbox sends: replaces the current list, so a kind left out is turned off. To turn one on or off without touching the others, use add_kinds / remove_kinds. Turning one on needs cancel_url, a confirmed policy and a connected Stripe, Recharge, Chargebee, Recurly or Paddle account. trial_reminder is accepted as an alias of trial_ending. */
2259
+ enabled_kinds?: Array<"acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation" | "charge_notice" | "trial_reminder">;
2260
+ /** Notices to turn on, added to the ones already on (the others stay as they are). Same prerequisites as enabled_kinds. */
2261
+ add_kinds?: Array<"acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation" | "charge_notice" | "trial_reminder">;
2262
+ /** Notices to turn off; the others stay as they are. */
2263
+ remove_kinds?: Array<"acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation" | "charge_notice" | "trial_reminder">;
1582
2264
  /** Brand name. */
1583
2265
  brand_name?: string | null;
1584
2266
  /** Product name. */
@@ -1707,9 +2389,9 @@ export interface DueNoticeList {
1707
2389
  export interface NoticeTemplate {
1708
2390
  /** Template id (`<variant>.v1`); due notices name the one they were rendered from. */
1709
2391
  id: string;
1710
- /** Notice kind. */
1711
- kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation";
1712
- /** Variant within the kind (acknowledgment vs acknowledgment_trial, cancellation_confirmation vs _immediate). */
2392
+ /** Notice kind (charge_notice: sent by you with each renewal charge; Checkbox does not schedule it). */
2393
+ kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation" | "charge_notice";
2394
+ /** Variant within the kind (acknowledgment vs acknowledgment_trial, cancellation_confirmation vs _immediate, charge_notice_upcoming before a charge vs charge_notice after it). */
1713
2395
  variant: string;
1714
2396
  /** Human label. */
1715
2397
  label: string;
@@ -1727,7 +2409,7 @@ export interface NoticeTemplate {
1727
2409
  merge_fields: Array<string>;
1728
2410
  /** The kind to pass to checkEmail (/v1/checks/email) for this template. */
1729
2411
  check_kind: string;
1730
- /** BCC address for this kind (when ?site= is given). */
2412
+ /** BCC address for this kind (when ?site= is given): the same address the plan's email task gives. A copy sent to it with the subscriber in To also confirms that subscriber's due notice of this kind. */
1731
2413
  bcc?: string;
1732
2414
  }
1733
2415
  /** Copy-ready templates for every required notice. */
@@ -1753,7 +2435,7 @@ export interface NoticeTemplateCheck {
1753
2435
  /** Always "notice_template_check". */
1754
2436
  object: "notice_template_check";
1755
2437
  /** Notice kind checked. */
1756
- kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation";
2438
+ kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation" | "charge_notice";
1757
2439
  /** pass, fail or needs_review. */
1758
2440
  verdict: string;
1759
2441
  /** Verdict per engine check. */
@@ -1790,7 +2472,7 @@ export interface CheckNoticeTemplateParams {
1790
2472
  /** Site whose plan, brand, cancel URL and jurisdictions fill the merge fields and scope the check. */
1791
2473
  site: string;
1792
2474
  /** Which notice the template is for. */
1793
- kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation";
2475
+ kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation" | "charge_notice";
1794
2476
  /** Your subject (merge fields allowed). */
1795
2477
  subject: string;
1796
2478
  /** Your plain-text body (merge fields allowed). */
@@ -1835,10 +2517,6 @@ export interface LawSiteImpact {
1835
2517
  site: string;
1836
2518
  /** What changed for the site. */
1837
2519
  summary: string;
1838
- /** Score before the change (0-100, one decimal place). */
1839
- score_before: number | null;
1840
- /** Score after re-evaluation (0-100, one decimal place). */
1841
- score_after: number | null;
1842
2520
  /** Checks whose result changed or that the change touches. */
1843
2521
  affected_checks: Array<{
1844
2522
  /** Check id. */
@@ -1922,6 +2600,10 @@ export interface CheckVerdict {
1922
2600
  fix?: string;
1923
2601
  /** Page checks on static HTML: the engine status on the estimated layout. */
1924
2602
  static_estimate?: "pass" | "fail" | "needs_review" | "not_applicable";
2603
+ evidence: VerdictEvidence;
2604
+ /** User-facing status. needs_fix (a requirement is clearly not met: `compliance.fix` is the one change), pending_live_check (everything Checkbox can see is right; the live event has not been observed yet — counts as passing the checks), verified_live (observed live: proof run, real BCC'd send, Stripe-confirmed cancellation), your_call (a real decision for a person: `compliance.question`), compliant (passes; grey areas carry a `compliance.note`), not_applicable, not_set_up (no sign the email or setting exists yet: `compliance.fix` is the one-click way to set it up; never counts as passing the checks), not_checked (Checkbox has not tried it yet, e.g. the cancel flow: `compliance.fix` says how; never counts as passing the checks). */
2605
+ compliance_status: "needs_fix" | "pending_live_check" | "verified_live" | "your_call" | "compliant" | "not_applicable" | "not_set_up" | "not_checked";
2606
+ compliance: ComplianceInfo;
1925
2607
  }
1926
2608
  /** Verdict per legal requirement. */
1927
2609
  export type CheckRequirementVerdict = CheckRequirementRef & {
@@ -1939,16 +2621,22 @@ export interface CheckWarning {
1939
2621
  /** Related parameter. */
1940
2622
  param?: string;
1941
2623
  }
1942
- /** A compliant replacement, verified by the engine. */
2624
+ /** A suggested replacement that passes the checks, verified by the engine. */
1943
2625
  export interface CheckReplacement {
1944
- /** Compliant disclosure generated from the plan terms (locked wording). */
2626
+ /** Disclosure generated from the plan terms that passes the checks (locked wording). */
1945
2627
  disclosure_text: string;
1946
2628
  /** Label for the unchecked, required consent checkbox. */
1947
2629
  consent_label: string;
1948
2630
  /** Purchase button label that itself states the renewal. */
1949
2631
  button_text: string;
1950
- /** Drop-in markup: disclosure (set off in a box) + unchecked required checkbox + button. */
2632
+ /** Drop-in markup: disclosure + unchecked required checkbox + button. When consent_on is set (the purchase completes on a Stripe Payment Link or Stripe Checkout), the terms only: no checkbox, no button. */
1951
2633
  html: string;
2634
+ /** Set when consent is collected on the Stripe-hosted page, not on this page: html is then the terms only. */
2635
+ consent_on?: "payment_link" | "stripe_checkout";
2636
+ /** What html contains and what is still needed elsewhere (set with consent_on). */
2637
+ note?: string;
2638
+ /** The same markup as JSX for React / Next.js components (className, htmlFor, style objects, self-closed inputs); the text is unchanged. */
2639
+ jsx?: string;
1952
2640
  /** Placeholders left to fill (e.g. {{cancel_url}}). */
1953
2641
  placeholders: Array<string>;
1954
2642
  /** The engine passes every targeted sign-up check on a page using this replacement. */
@@ -2002,14 +2690,19 @@ export interface DisclosureCheckResult {
2002
2690
  /** Not legal advice. */
2003
2691
  disclaimer: string;
2004
2692
  next_action: NextAction;
2693
+ /** User-facing roll-up: needs_fix > your_call > incomplete > compliant (every required check passes; pending live checks count as passing). `verdict` keeps the machine value. */
2694
+ compliance_status: "needs_fix" | "your_call" | "incomplete" | "compliant" | "not_checked";
2695
+ compliance: ComplianceRollup;
2005
2696
  replacement: CheckReplacement;
2006
2697
  }
2007
- /** A checkout disclosure to check before it ships. */
2698
+ /** A checkout disclosure to check before it ships. The plan fields (price, interval, cancel_url…) may also be nested under `terms` or `merchant`, as in the other checks. */
2008
2699
  export interface DisclosureCheckParams {
2009
2700
  /** The disclosure shown next to the purchase button, exactly as rendered. */
2010
2701
  text: string;
2011
2702
  /** Brand shown to subscribers; used in generated text. */
2012
2703
  merchant_name?: string;
2704
+ /** Alias of merchant_name (the {{brand_name}} merge field). Send one of the two. */
2705
+ brand_name?: string;
2013
2706
  /** Plan / product name. */
2014
2707
  plan_name?: string;
2015
2708
  /** Recurring price in major units (19.99). Or give `amount` in minor units. */
@@ -2024,6 +2717,16 @@ export interface DisclosureCheckParams {
2024
2717
  interval_count?: number;
2025
2718
  /** Free-trial length in days (0 or absent = no trial). */
2026
2719
  trial_days?: number;
2720
+ /** Intro / first-period price in major units ("$34.50 for your first box, then $69 every 2 weeks"). Or give `intro_amount` in minor units. */
2721
+ intro_price?: number | string;
2722
+ /** Intro / first-period price in minor units. */
2723
+ intro_amount?: number;
2724
+ /** How many billing periods the intro price lasts (default 1). */
2725
+ intro_periods?: number;
2726
+ /** Intro discount as a percentage off the recurring price (a Stripe coupon's percent_off: 20 for "20% off your first month"). Lasts `intro_periods` billing periods. Give one of intro_price / intro_amount, intro_percent_off or intro_amount_off. */
2727
+ intro_percent_off?: number;
2728
+ /** Intro discount as an amount off in minor units (a Stripe coupon's amount_off: 200 for $2.00 off). Lasts `intro_periods` billing periods. */
2729
+ intro_amount_off?: number;
2027
2730
  /** https URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise). */
2028
2731
  cancel_url?: string;
2029
2732
  /** When a cancellation takes effect (default period_end). */
@@ -2118,6 +2821,9 @@ export interface StripeCheckoutSessionCheckResult {
2118
2821
  /** Not legal advice. */
2119
2822
  disclaimer: string;
2120
2823
  next_action: NextAction;
2824
+ /** User-facing roll-up: needs_fix > your_call > incomplete > compliant (every required check passes; pending live checks count as passing). `verdict` keeps the machine value. */
2825
+ compliance_status: "needs_fix" | "your_call" | "incomplete" | "compliant" | "not_checked";
2826
+ compliance: ComplianceRollup;
2121
2827
  /** The fix. */
2122
2828
  correction: {
2123
2829
  /** JSON Patch turning params into corrected_params (empty: nothing to change). */
@@ -2146,10 +2852,12 @@ export interface StripeCheckoutSessionCheckResult {
2146
2852
  placeholders: Array<string>;
2147
2853
  };
2148
2854
  }
2149
- /** What Stripe params do not say: merchant_name, cancel_url, and price / interval when line_items reference a Price id. */
2855
+ /** What Stripe params do not say: merchant_name, cancel_url, and price / interval when line_items reference a Price id. Also accepted as `terms`. Optional with `site`. */
2150
2856
  export interface CheckPlanTerms {
2151
2857
  /** Brand shown to subscribers; used in generated text. */
2152
2858
  merchant_name?: string;
2859
+ /** Alias of merchant_name (the {{brand_name}} merge field). Send one of the two. */
2860
+ brand_name?: string;
2153
2861
  /** Plan / product name. */
2154
2862
  plan_name?: string;
2155
2863
  /** Recurring price in major units (19.99). Or give `amount` in minor units. */
@@ -2164,6 +2872,16 @@ export interface CheckPlanTerms {
2164
2872
  interval_count?: number;
2165
2873
  /** Free-trial length in days (0 or absent = no trial). */
2166
2874
  trial_days?: number;
2875
+ /** Intro / first-period price in major units ("$34.50 for your first box, then $69 every 2 weeks"). Or give `intro_amount` in minor units. */
2876
+ intro_price?: number | string;
2877
+ /** Intro / first-period price in minor units. */
2878
+ intro_amount?: number;
2879
+ /** How many billing periods the intro price lasts (default 1). */
2880
+ intro_periods?: number;
2881
+ /** Intro discount as a percentage off the recurring price (a Stripe coupon's percent_off: 20 for "20% off your first month"). Lasts `intro_periods` billing periods. Give one of intro_price / intro_amount, intro_percent_off or intro_amount_off. */
2882
+ intro_percent_off?: number;
2883
+ /** Intro discount as an amount off in minor units (a Stripe coupon's amount_off: 200 for $2.00 off). Lasts `intro_periods` billing periods. */
2884
+ intro_amount_off?: number;
2167
2885
  /** https URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise). */
2168
2886
  cancel_url?: string;
2169
2887
  /** When a cancellation takes effect (default period_end). */
@@ -2174,6 +2892,10 @@ export interface StripeCheckParams {
2174
2892
  /** Exactly the object your code passes to Stripe (checkout.sessions.create / paymentLinks.create), or a retrieved Payment Link. */
2175
2893
  params: Record<string, unknown>;
2176
2894
  merchant?: CheckPlanTerms;
2895
+ /** A site of yours (site_…): the params are judged as verifyTask judges them — the plan each line_items Price sells (the connected Stripe Prices win over plans typed in setup), the site's merchant name, cancellation URL and jurisdictions; merchant fields you send other than the plan's price / interval / trial are kept. Without it, the params are judged with merchant only (or the one site of the account with Stripe connected when you pass plan). "none" judges only what you send. */
2896
+ site?: string;
2897
+ /** With a site: judge the params against this plan (name or Stripe Price id) instead of the plan their Price id sells. An unknown plan is refused with the list of plans. */
2898
+ plan?: string;
2177
2899
  /** Where you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included). */
2178
2900
  jurisdictions?: "all" | Array<string>;
2179
2901
  /** Evaluate the law as of this date (YYYY-MM-DD, default today). */
@@ -2223,6 +2945,9 @@ export interface StripePaymentLinkCheckResult {
2223
2945
  /** Not legal advice. */
2224
2946
  disclaimer: string;
2225
2947
  next_action: NextAction;
2948
+ /** User-facing roll-up: needs_fix > your_call > incomplete > compliant (every required check passes; pending live checks count as passing). `verdict` keeps the machine value. */
2949
+ compliance_status: "needs_fix" | "your_call" | "incomplete" | "compliant" | "not_checked";
2950
+ compliance: ComplianceRollup;
2226
2951
  /** The fix. */
2227
2952
  correction: {
2228
2953
  /** JSON Patch turning params into corrected_params (empty: nothing to change). */
@@ -2299,15 +3024,22 @@ export interface EmailCheckResult {
2299
3024
  /** Not legal advice. */
2300
3025
  disclaimer: string;
2301
3026
  next_action: NextAction;
3027
+ /** User-facing roll-up: needs_fix > your_call > incomplete > compliant (every required check passes; pending live checks count as passing). `verdict` keeps the machine value. */
3028
+ compliance_status: "needs_fix" | "your_call" | "incomplete" | "compliant" | "not_checked";
3029
+ compliance: ComplianceRollup;
2302
3030
  /** The email kind checked. */
2303
3031
  email_kind: string;
3032
+ /** With a site: the site's plan the email was judged against. */
3033
+ plan?: string;
3034
+ /** Always template_checked: this checks the wording you send in, not that your system sends it. On the site, the email only counts once Checkbox sees it sent for a real event (delivery_seen: a test run, a notice for a real subscriber, or a BCC copy matching that subscriber's billing event). */
3035
+ verification_level: "template_checked";
2304
3036
  /** Requirements that make this email mandatory for this plan (empty: not legally required). */
2305
3037
  required_by: Array<string>;
2306
- /** A compliant template generated from the plan terms. */
3038
+ /** A template generated from the plan terms that passes the checks. */
2307
3039
  template: {
2308
- /** Compliant subject. */
3040
+ /** Subject that passes the checks. */
2309
3041
  subject: string;
2310
- /** Compliant plain-text body. */
3042
+ /** Plain-text body that passes the checks. */
2311
3043
  text: string;
2312
3044
  /** The same body as HTML. */
2313
3045
  html: string;
@@ -2331,8 +3063,8 @@ export interface EmailCheckParams {
2331
3063
  text?: string;
2332
3064
  /** HTML body. */
2333
3065
  html?: string;
2334
- /** The plan the email is about (price, interval and cancel_url at least). */
2335
- terms: CheckPlanTerms & {
3066
+ /** The plan the email is about (price, interval and cancel_url at least). Also accepted as `merchant`. Required unless a site with plan terms is used (`site`, or the one site of the account with Stripe connected): then the plan fields come from the price Stripe charges and the other fields (cancel_url, previous_price, support_contact) are kept. A price_change notice always takes the NEW price from here. */
3067
+ terms?: CheckPlanTerms & {
2336
3068
  /** price_change only: the OLD price before the change, major units. price / amount is the NEW price the email announces. */
2337
3069
  previous_price?: number | string;
2338
3070
  /** Price before a price change, minor units. */
@@ -2340,6 +3072,10 @@ export interface EmailCheckParams {
2340
3072
  /** Support email / URL shown in the generated template. */
2341
3073
  support_contact?: string;
2342
3074
  };
3075
+ /** A site of yours (site_…): the email is judged as verifyTask judges it, against the plan it names ("Annual") among the site's plans (the connected Stripe Prices win over plans typed in setup), with the site's jurisdictions. Without it, the one site of the account with Stripe connected is used when there is exactly one (the result says so in warnings, code site_from_stripe). "none" judges only the terms you send. */
3076
+ site?: string;
3077
+ /** With a site: the plan (name or Stripe Price id) the email is for, instead of the plan the email names. */
3078
+ plan?: string;
2343
3079
  /** Where you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included). */
2344
3080
  jurisdictions?: "all" | Array<string>;
2345
3081
  /** Evaluate the law as of this date (YYYY-MM-DD, default today). */
@@ -2389,14 +3125,17 @@ export interface PageCheckResult {
2389
3125
  /** Not legal advice. */
2390
3126
  disclaimer: string;
2391
3127
  next_action: NextAction;
3128
+ /** User-facing roll-up: needs_fix > your_call > incomplete > compliant (every required check passes; pending live checks count as passing). `verdict` keeps the machine value. */
3129
+ compliance_status: "needs_fix" | "your_call" | "incomplete" | "compliant" | "not_checked";
3130
+ compliance: ComplianceRollup;
2392
3131
  /** Whether html was given or fetched from url. */
2393
3132
  source: "html" | "url";
2394
3133
  /** What was read from the page. */
2395
3134
  extraction: {
2396
3135
  /** How the page was read. */
2397
3136
  mode: "static_html";
2398
- /** Page URL used. */
2399
- url: string;
3137
+ /** Page URL used (null when only html was sent: the page is built from the HTML you sent). */
3138
+ url: string | null;
2400
3139
  /** Purchase buttons found (primary first). */
2401
3140
  purchase_buttons: Array<string>;
2402
3141
  /** Text blocks that read like subscription terms. */
@@ -2421,6 +3160,11 @@ export interface PageCheckResult {
2421
3160
  limitations: Array<string>;
2422
3161
  };
2423
3162
  replacement?: CheckReplacement;
3163
+ /** With two or more plans: one verified replacement per plan, for that plan's own purchase button (never another plan's). */
3164
+ plan_replacements?: Array<CheckReplacement & {
3165
+ /** The plan this replacement is for (name, price, interval, trial). */
3166
+ plan: string;
3167
+ }>;
2424
3168
  }
2425
3169
  /** A checkout page to check. */
2426
3170
  export interface PageCheckParams {
@@ -2431,6 +3175,15 @@ export interface PageCheckParams {
2431
3175
  /** What the page is (default checkout). */
2432
3176
  page_kind?: "checkout" | "pricing";
2433
3177
  terms?: CheckPlanTerms;
3178
+ /** Every plan a multi-plan pricing page sells (price or amount, interval, trial_days each; the same plan fields as setup plans[] in updateSetupSession). Each plan card / button is judged against its own plan; only a price no listed plan charges is a mismatch. Without it, one plan's `terms` leaves other plan cards' prices at needs_review (warning plans_partial). */
3179
+ plans?: Array<CheckPlanTerms & {
3180
+ /** Plan name, as in setup plans[] (updateSetupSession; alias of plan_name). */
3181
+ name?: string;
3182
+ }>;
3183
+ /** Where the shopper pays: own_page (a form on this page), stripe_checkout or payment_link (a Stripe-hosted page that collects consent, so no checkbox is needed here). Inferred from a purchase link to buy.stripe.com / checkout.stripe.com when absent. */
3184
+ checkout_type?: "own_page" | "stripe_checkout" | "payment_link";
3185
+ /** A site of yours (site_…): the page is judged exactly as verifyTask judges it — against the site's plans (the connected Stripe Prices win over plans typed in setup), its jurisdictions and its checkout type. These replace terms, plans, jurisdictions and checkout_type when the site knows them. Without it, the one site of the account with Stripe connected gives the plans when there is exactly one (warning site_from_stripe says so). "none" judges only what you send. */
3186
+ site?: string;
2434
3187
  /** Where you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included). */
2435
3188
  jurisdictions?: "all" | Array<string>;
2436
3189
  /** Evaluate the law as of this date (YYYY-MM-DD, default today). */
@@ -2439,7 +3192,7 @@ export interface PageCheckParams {
2439
3192
  /** One notice to send. */
2440
3193
  export interface ScheduledNotice {
2441
3194
  /** Notice kind. */
2442
- kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change";
3195
+ kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation" | "charge_notice";
2443
3196
  /** What the notice announces. */
2444
3197
  occasion: string;
2445
3198
  /** Date of the event (YYYY-MM-DD, UTC). */
@@ -2448,9 +3201,9 @@ export interface ScheduledNotice {
2448
3201
  send_date: string;
2449
3202
  /** Recommended send time. Unix timestamp in seconds. */
2450
3203
  send_at: number;
2451
- /** Earliest compliant send time. Unix seconds. */
3204
+ /** Earliest send time that meets the notice timing. Unix seconds. */
2452
3205
  window_opens_at: number;
2453
- /** Latest compliant send time. Unix seconds. */
3206
+ /** Latest send time that meets the notice timing. Unix seconds. */
2454
3207
  window_closes_at: number;
2455
3208
  /** Days before the event (0 = right away). */
2456
3209
  days_before: number;
@@ -2462,6 +3215,8 @@ export interface ScheduledNotice {
2462
3215
  citations: Array<string>;
2463
3216
  /** No requirement states a window; Checkbox’s default window was used. */
2464
3217
  default_window: boolean;
3218
+ /** Why the window is what it is when the states narrow it to a single day, and when to send. */
3219
+ timing_note?: string;
2465
3220
  }
2466
3221
  /** When each legally required notice must be sent. */
2467
3222
  export interface NoticeScheduleResult {
@@ -2475,8 +3230,14 @@ export interface NoticeScheduleResult {
2475
3230
  created: number;
2476
3231
  /** Sign-up date planned for. */
2477
3232
  start_date: string;
3233
+ /** With a site: the site's plan the notices were scheduled for. */
3234
+ plan?: string;
2478
3235
  /** Every legally required notice, in send order. */
2479
3236
  notices: Array<ScheduledNotice>;
3237
+ /** Notes about the input (e.g. an amount that looks like the wrong unit). */
3238
+ warnings?: Array<CheckWarning>;
3239
+ /** How days before are counted when Checkbox judges a send (the email checks, test runs and Notices use the same rule). */
3240
+ rounding_rule: string;
2480
3241
  /** Notice kinds no applicable requirement demands for this plan. */
2481
3242
  not_required: Array<{
2482
3243
  /** Notice kind. */
@@ -2500,7 +3261,11 @@ export interface NoticeScheduleResult {
2500
3261
  }
2501
3262
  /** A subscription to plan the legally required notices for. */
2502
3263
  export interface NoticeScheduleParams {
2503
- terms: CheckPlanTerms;
3264
+ terms?: CheckPlanTerms;
3265
+ /** A site of yours (site_…): the plan's terms (Stripe Prices win over plans typed in setup) and jurisdictions come from the site. With several plans, name one with plan (or send terms). */
3266
+ site?: string;
3267
+ /** With a site: the plan (name or Stripe Price id) to schedule the notices for. An unknown plan is refused with the list of plans. */
3268
+ plan?: string;
2504
3269
  /** Sign-up date of the subscription to plan for (default today). */
2505
3270
  start_date?: string;
2506
3271
  /** A planned price change to schedule the notice for. */
@@ -2519,6 +3284,264 @@ export interface NoticeScheduleParams {
2519
3284
  /** Evaluate the law as of this date (YYYY-MM-DD, default today). */
2520
3285
  as_of?: string;
2521
3286
  }
3287
+ /** RFC 6902 operation. */
3288
+ export interface SuggestionPatchOp {
3289
+ /** JSON Patch operation. */
3290
+ op: "add" | "replace" | "remove";
3291
+ /** JSON Pointer. */
3292
+ path: string;
3293
+ /** Value. */
3294
+ value?: unknown;
3295
+ }
3296
+ /** A legal guardrail the suggestion respects. */
3297
+ export interface SuggestionGuardrail {
3298
+ /** What the change must respect, in plain words. */
3299
+ rule: string;
3300
+ /** Catalog requirement ids the rule comes from. */
3301
+ requirement_ids: Array<string>;
3302
+ }
3303
+ /** One optional conversion suggestion that keeps the checks passing. */
3304
+ export interface Suggestion {
3305
+ /** Stable id of the suggestion in Checkbox’s library. */
3306
+ key: string;
3307
+ /** String representing the object's type. Always "suggestion". */
3308
+ object: "suggestion";
3309
+ /** Where it applies. */
3310
+ surface: "checkout_page" | "stripe_checkout" | "acknowledgment_email" | "trial_reminder_email" | "renewal_reminder_email" | "price_change_email" | "cancellation_flow" | "cancellation_confirmation_email";
3311
+ /** What to change. */
3312
+ title: string;
3313
+ /** Why it commonly helps conversion or retention (no invented figures). */
3314
+ why: string;
3315
+ /** detected: your observed copy lacks it; recommended: the surface was not observed but it fits your plan. */
3316
+ match: "detected" | "recommended";
3317
+ /** Why it applies to you. */
3318
+ reason: string;
3319
+ /** Before. */
3320
+ before: {
3321
+ /** What is shown. */
3322
+ label: string;
3323
+ /** Your current copy (or a typical example). */
3324
+ text: string;
3325
+ /** your_copy: the text is your own copy (captured by Checkbox or sent by you); example: typical copy, not yours (label it “Example”). */
3326
+ source: "your_copy" | "example";
3327
+ };
3328
+ /** After. */
3329
+ after: {
3330
+ /** What is shown. */
3331
+ label: string;
3332
+ /** The improved copy, from your plan terms. */
3333
+ text: string;
3334
+ };
3335
+ /** How to apply it. */
3336
+ apply: {
3337
+ /** Kind of change. */
3338
+ type: "replace_text" | "insert_text" | "replace_email" | "stripe_params" | "flow_change" | "settings";
3339
+ /** Where to make it. */
3340
+ where: string;
3341
+ /** The exact copy / markup / JSON to apply. */
3342
+ content: string;
3343
+ /** stripe_params: RFC 6902 patch for the params your code passes to Stripe. */
3344
+ json_patch?: Array<SuggestionPatchOp>;
3345
+ /** One or two sentences an agent can follow literally. */
3346
+ instructions: string;
3347
+ };
3348
+ /** What must be true before you use it (never claim it otherwise). */
3349
+ preconditions: Array<string>;
3350
+ /** Legal guardrails (catalog ids) the change must respect. */
3351
+ guardrails: Array<SuggestionGuardrail>;
3352
+ /** The engine check of the after-example (only verified suggestions are offered). */
3353
+ verification: {
3354
+ /** The check the after-example was run through. */
3355
+ operation_id: "checkDisclosure" | "checkStripeCheckoutSession" | "checkEmail" | "cancellation_flow_model";
3356
+ /** Verdict of that check. */
3357
+ verdict: "pass" | "fail" | "needs_review" | "not_applicable";
3358
+ /** Nothing fails and nothing new needs review. */
3359
+ verified: boolean;
3360
+ /** Checks that did not pass (empty when verified). */
3361
+ open_checks: Array<string>;
3362
+ /** The after-example's status roll-up (the same labels as compliance on sites and check results): compliant (checks pass) for every offered suggestion. */
3363
+ compliance_status: "needs_fix" | "your_call" | "incomplete" | "compliant" | "not_checked";
3364
+ /** Its label. */
3365
+ compliance_label: string;
3366
+ /** Jurisdictions checked. */
3367
+ jurisdictions: "all" | Array<string>;
3368
+ /** How it was checked. */
3369
+ note: string;
3370
+ } | null;
3371
+ /** Placeholders you must fill (e.g. {{cancel_url}}). */
3372
+ placeholders: Array<string>;
3373
+ }
3374
+ /** Optional conversion suggestions that keep the checks passing, for a checkout, Stripe Checkout, lifecycle emails and the cancellation flow. Never a compliance task. */
3375
+ export interface SuggestionReport {
3376
+ /** Id of this report (sugr_…). Reports are computed on request and not stored. */
3377
+ id: string;
3378
+ /** String representing the object's type. Always "suggestion_report". */
3379
+ object: "suggestion_report";
3380
+ /** true for live-mode objects, false for test mode (ck_test_ keys act on an isolated sandbox). */
3381
+ livemode: boolean;
3382
+ /** When it was computed. Unix seconds. */
3383
+ created: number;
3384
+ /** The site (GET /v1/sites/:site/suggestions), or null for POST /v1/suggestions. */
3385
+ site: string | null;
3386
+ /** Always true: suggestions are optional and never block anything. */
3387
+ optional: true;
3388
+ /** Always false: suggestions never count for or against compliance or the plan status. */
3389
+ counts_toward_compliance: false;
3390
+ /** One paragraph for an LLM or a human. */
3391
+ summary: string;
3392
+ /** Jurisdictions the examples were checked for. */
3393
+ jurisdictions: "all" | Array<string>;
3394
+ /** Date the law was evaluated at. */
3395
+ as_of: string;
3396
+ /** Version of the suggestion library. */
3397
+ library_version: string;
3398
+ /** Rules engine version. */
3399
+ rules_version: string;
3400
+ /** Legal catalog version. */
3401
+ catalog_version: string;
3402
+ /** Per surface. */
3403
+ surfaces: Array<{
3404
+ /** Surface. */
3405
+ surface: "checkout_page" | "stripe_checkout" | "acknowledgment_email" | "trial_reminder_email" | "renewal_reminder_email" | "price_change_email" | "cancellation_flow" | "cancellation_confirmation_email";
3406
+ /** offered; held (a compliance check on it fails: fix that first); none (nothing to suggest). */
3407
+ status: "offered" | "held" | "none";
3408
+ /** Checkbox saw this surface (or you sent it). */
3409
+ observed: boolean;
3410
+ /** Failing checks that hold it. */
3411
+ held_by: Array<string>;
3412
+ /** The status label of those checks ("1 fix needed", "2 fixes needed"), or null. */
3413
+ held_label: string | null;
3414
+ /** Suggestions offered for it. */
3415
+ offered: number;
3416
+ }>;
3417
+ /** Offered suggestions: detected gaps in your own copy first. */
3418
+ suggestions: Array<Suggestion>;
3419
+ /** Suggestions that would apply but are withheld, and why. */
3420
+ withheld: Array<{
3421
+ /** Suggestion key. */
3422
+ key: string;
3423
+ /** Surface. */
3424
+ surface: "checkout_page" | "stripe_checkout" | "acknowledgment_email" | "trial_reminder_email" | "renewal_reminder_email" | "price_change_email" | "cancellation_flow" | "cancellation_confirmation_email";
3425
+ /** Title. */
3426
+ title: string;
3427
+ /** Why it is not offered to you (a guardrail, a failing check, or an untrue precondition). */
3428
+ reason: string;
3429
+ }>;
3430
+ /** Next step. */
3431
+ next_action: {
3432
+ /** What to do next. */
3433
+ type: "apply_suggestion" | "fix_compliance_first" | "none";
3434
+ /** One or two sentences for an agent. */
3435
+ message: string;
3436
+ /** The operation to call next, when there is one. */
3437
+ operation_id?: string;
3438
+ /** The MCP tool for operation_id. */
3439
+ mcp_tool?: string;
3440
+ /** The HTTP method and path of operation_id. */
3441
+ endpoint?: string;
3442
+ };
3443
+ /** Not legal advice; optional; results vary. */
3444
+ disclaimer: string;
3445
+ }
3446
+ /** What to suggest improvements for: the same inputs as /v1/checks/*, any subset. */
3447
+ export interface SuggestionsParams {
3448
+ terms?: CheckPlanTerms;
3449
+ /** Other plans you sell (enables “point to a cheaper plan” and plan-choice suggestions). */
3450
+ other_plans?: Array<CheckPlanTerms & {
3451
+ /** Plan name shown to subscribers (or give plan_name, as in the checks). */
3452
+ name?: string;
3453
+ }>;
3454
+ /** Where you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included). */
3455
+ jurisdictions?: "all" | Array<string>;
3456
+ /** Evaluate the law as of this date (YYYY-MM-DD, default today). */
3457
+ as_of?: string;
3458
+ /** Only suggest for these surfaces (default: all). */
3459
+ surfaces?: Array<"checkout_page" | "stripe_checkout" | "acknowledgment_email" | "trial_reminder_email" | "renewal_reminder_email" | "price_change_email" | "cancellation_flow" | "cancellation_confirmation_email">;
3460
+ /** Your own checkout: the same fields as checkDisclosure (without the plan terms, which go in terms). */
3461
+ disclosure?: {
3462
+ /** The disclosure shown next to the purchase button, exactly as rendered. */
3463
+ text: string;
3464
+ /** Label of the purchase button. */
3465
+ button_text?: string;
3466
+ /** Other text next to the button (order summary). */
3467
+ order_summary?: string;
3468
+ /** Where and how the disclosure is shown (as in checkDisclosure). */
3469
+ placement?: {
3470
+ /** Shown above the purchase button (default true). */
3471
+ above_button?: boolean;
3472
+ /** On the same page as the payment form (default true). */
3473
+ same_page_as_payment?: boolean;
3474
+ /** Font size (default 14). */
3475
+ font_size_px?: number;
3476
+ /** WCAG contrast ratio. */
3477
+ contrast_ratio?: number;
3478
+ /** Bold / semibold. */
3479
+ bold?: boolean;
3480
+ /** Set off in a box. */
3481
+ boxed?: boolean;
3482
+ /** Surrounding body text size (default 14). */
3483
+ body_font_size_px?: number;
3484
+ };
3485
+ /** The consent checkbox (as in checkDisclosure). */
3486
+ consent?: {
3487
+ /** There is a renewal consent checkbox. */
3488
+ checkbox: boolean;
3489
+ /** Ticked by default. */
3490
+ prechecked?: boolean;
3491
+ /** Its label. */
3492
+ label?: string;
3493
+ /** Required to submit (default true). */
3494
+ required?: boolean;
3495
+ };
3496
+ };
3497
+ /** Your checkout page HTML (as in checkPage; html only). */
3498
+ page?: {
3499
+ /** Rendered checkout page HTML (as in checkPage). */
3500
+ html: string;
3501
+ /** Where the page lives (resolves relative links). */
3502
+ url?: string;
3503
+ };
3504
+ /** Stripe Checkout Session params (as in checkStripeCheckoutSession; plan terms in terms). */
3505
+ stripe_checkout_session?: {
3506
+ /** Exactly what your code passes to stripe.checkout.sessions.create. */
3507
+ params: Record<string, unknown>;
3508
+ };
3509
+ /** Lifecycle emails (as in checkEmail; plan terms in terms). */
3510
+ emails?: Array<{
3511
+ /** Which lifecycle email (as in checkEmail). */
3512
+ kind: "acknowledgment" | "trial_reminder" | "trial_ending" | "renewal_reminder" | "price_change" | "annual_terms" | "charge_notice" | "cancellation_confirmation";
3513
+ /** Subject line. */
3514
+ subject: string;
3515
+ /** Plain-text body. */
3516
+ text?: string;
3517
+ /** HTML body. */
3518
+ html?: string;
3519
+ /** price_change only: the old price, major units. */
3520
+ previous_price?: number | string;
3521
+ }>;
3522
+ /** Your cancellation flow as a subscriber sees it. */
3523
+ cancellation_flow?: {
3524
+ /** Screens from the account page to the confirmation, in order. */
3525
+ steps: Array<{
3526
+ /** What the screen says. */
3527
+ text: string;
3528
+ /** Buttons and links on the screen. */
3529
+ buttons?: Array<string>;
3530
+ /** The screen shows a retention (save) offer or pause option. */
3531
+ offer?: boolean;
3532
+ }>;
3533
+ /** A confirmation is shown at the end (default true). */
3534
+ confirmation_shown?: boolean;
3535
+ };
3536
+ /** You send a trial-ending reminder to every trial subscriber (false withholds suggestions that promise one). */
3537
+ trial_reminders?: boolean;
3538
+ /** Your site’s base URL (used in example links). */
3539
+ site_url?: string;
3540
+ /** Where subscribers manage their subscription (restart and switch-plan links; never the cancel step). Default: derived from terms.cancel_url. */
3541
+ account_url?: string;
3542
+ /** You ship physical goods (boxes, deliveries): examples talk about the next box instead of access. Default: inferred from your plan names and copy. */
3543
+ sells_goods?: boolean;
3544
+ }
2522
3545
  export interface ElementsRelease {
2523
3546
  /** Semver of the bundle. */
2524
3547
  version: string;
@@ -2605,6 +3628,12 @@ export interface DisclosureTerms {
2605
3628
  interval_count?: number;
2606
3629
  /** Free-trial length in days (0 or absent: no trial). */
2607
3630
  trial_days?: number;
3631
+ /** Intro / first-period charge in minor units, stated before the regular price ("$34.50 for your first 2 weeks, then $69.00 every 2 weeks"). Must be below amount. */
3632
+ intro_amount?: number;
3633
+ /** How many billing periods the intro price lasts (default 1). */
3634
+ intro_periods?: number;
3635
+ /** The intro price as a percentage off amount (a coupon's percent_off), instead of intro_amount. Needs amount. */
3636
+ intro_percent_off?: number;
2608
3637
  /** https address where subscribers cancel online. */
2609
3638
  cancel_url?: string;
2610
3639
  /** When a cancellation takes effect (default period_end). */
@@ -2673,7 +3702,7 @@ export interface Consent {
2673
3702
  client_timestamp: number | null;
2674
3703
  /** On-screen measurement summary (null for server-recorded consents). */
2675
3704
  presentation: {
2676
- /** Guard-rail violations measured on screen. */
3705
+ /** Guard-rail issues measured on screen. */
2677
3706
  violations: Array<string>;
2678
3707
  /** Safe styles replaced the theme. */
2679
3708
  fallback_applied: boolean;
@@ -2764,7 +3793,7 @@ export interface ConsentPresentationInput {
2764
3793
  /** Viewport height (CSS px). */
2765
3794
  height: number;
2766
3795
  } | null;
2767
- /** Guard-rail violations the element detected. */
3796
+ /** Guard-rail issues the element detected. */
2768
3797
  violations?: Array<string>;
2769
3798
  /** The element replaced the theme with safe styles. */
2770
3799
  fallback_applied?: boolean;
@@ -3019,7 +4048,7 @@ export interface Receipt {
3019
4048
  /** When it was signed (unix seconds). */
3020
4049
  signed: number | null;
3021
4050
  };
3022
- /** When the receipt is deleted under your retention setting. Unix timestamp in seconds. */
4051
+ /** When the receipt is deleted: consent time plus your retention setting, pushed out to one year after its subscription ends when that is later (Cal. Bus. & Prof. Code § 17602(a)(6)). Unix timestamp in seconds. */
3023
4052
  retain_until: number;
3024
4053
  /** PNG of what the subscriber saw, re-rendered from the snapshot (renderReceipt, same auth). */
3025
4054
  render_url: string;
@@ -3129,7 +4158,7 @@ export interface ReceiptSettings {
3129
4158
  livemode: boolean;
3130
4159
  /** Receipts are collected. Off by default: turn on after adding the receipts paragraph to your privacy policy (browser receipts answer 403 receipts_disabled when off; Elements consents are recorded without a receipt). */
3131
4160
  enabled: boolean;
3132
- /** Days a receipt is kept (default 1461 = 4 years: the California Unfair Competition Law limitation period; pending attorney review). */
4161
+ /** Days a receipt is kept (default 1461 = 4 years: the California Unfair Competition Law limitation period; adjust to your counsel's advice). */
3133
4162
  retention_days: number;
3134
4163
  /** Last change. Unix timestamp in seconds. */
3135
4164
  updated: number | null;
@@ -3137,7 +4166,7 @@ export interface ReceiptSettings {
3137
4166
  export interface ReceiptSettingsUpdateParams {
3138
4167
  /** Turn receipt collection on or off. */
3139
4168
  enabled?: boolean;
3140
- /** Days to keep receipts (30–3653). Applies to new receipts. */
4169
+ /** Days to keep receipts (1096–3653, i.e. 3 to 10 years; California requires verification of consent to be kept at least three years, Cal. Bus. & Prof. Code § 17602(a)(6)). Applies to new receipts. */
3141
4170
  retention_days?: number;
3142
4171
  }
3143
4172
  /** A billing-platform TEST-mode key Checkbox uses for synthetic test subscriptions. Stored encrypted; never live mode. */
@@ -3201,6 +4230,10 @@ export interface StripeCheckoutConfig {
3201
4230
  params_hash: string;
3202
4231
  /** Parameters that were dropped because they are not mirrored (customer, URLs, metadata…). */
3203
4232
  ignored_params: Array<string>;
4233
+ /** What Checkbox did not store or judge (ignored_params in words), and on registration which older configs this one replaced. */
4234
+ warnings: Array<string>;
4235
+ /** Registration only: older configs with the same name, or for the same Price ids, that this one replaced (deleted). */
4236
+ replaced?: Array<string>;
3204
4237
  /** Up to 20 key/value string pairs you can attach to the object. */
3205
4238
  metadata: Record<string, string>;
3206
4239
  /** When the config was registered. Unix timestamp in seconds. */
@@ -3232,7 +4265,7 @@ export type TestRunRemediation = {
3232
4265
  summary: string;
3233
4266
  /** Steps to fix it. */
3234
4267
  steps: Array<string>;
3235
- /** Compliant copy to use, when there is one. */
4268
+ /** Suggested copy that passes the checks, when there is one. */
3236
4269
  suggested_copy: string | null;
3237
4270
  /** Code that applies the fix, when there is one. */
3238
4271
  snippet: {
@@ -3261,12 +4294,12 @@ export type TestRunFix = {
3261
4294
  } | null;
3262
4295
  /** One observed lifecycle step of a test run. */
3263
4296
  export interface TestRunStep {
3264
- /** Stable step key: credentials, checkout_config, checkout_page, subscribe, acknowledgment_email, trial_reminder, renewal, cancel_online, cancellation_email, cleanup. */
4297
+ /** Stable step key: credentials, checkout_config, checkout_page, subscribe, acknowledgment_email, trial_reminder, renewal, cancel_online, cancellation_email, webhooks (real_checkout), cleanup. */
3265
4298
  key: string;
3266
4299
  /** Human-readable step title. */
3267
4300
  title: string;
3268
- /** passed: observed and compliant; failed: a check failed or the step broke the run; warning: could not be fully observed (see code and fix); skipped: not applicable or turned off. */
3269
- status: "pending" | "running" | "passed" | "failed" | "warning" | "skipped";
4301
+ /** passed: observed, with evidence, and every judged check passed (never on an assumption); failed: a check failed or the step broke the run; warning: needs review — could not be fully observed or proven (see code and fix); skipped: not applicable or turned off; info: informational only (e.g. a bare Stripe-hosted test checkout that is not your checkout): its checks are listed but not counted and need no fix. */
4302
+ status: "pending" | "running" | "passed" | "failed" | "warning" | "skipped" | "info";
3270
4303
  /** What was observed, in one or two sentences. */
3271
4304
  summary: string | null;
3272
4305
  /** When the step started. Unix timestamp in seconds. */
@@ -3291,7 +4324,7 @@ export interface TestRunStep {
3291
4324
  observations: Record<string, unknown>;
3292
4325
  /** Evidence records (screenshots, page captures, raw emails) behind the step. */
3293
4326
  evidence: Array<string>;
3294
- /** Warning or failure code of the step (stable): key_missing, key_not_test_mode, key_invalid, key_permission_missing, checkout_config_missing, price_not_in_test_mode, checkout_session_failed, checkout_page_unreadable, checkout_not_completed, subscription_create_failed, test_clock_failed, no_email_received_within, reminder_not_received, portal_not_configured, cancel_not_completed, cancellation_email_not_received, scan_config_missing, domain_not_verified, scanner_failed, stripe_api_error, timeout, canceled, internal_error. */
4327
+ /** Warning or failure code of the step (stable): key_missing, key_not_test_mode, key_invalid, key_permission_missing, checkout_config_missing, price_not_in_test_mode, checkout_session_failed, checkout_page_unreadable, checkout_not_completed, subscription_create_failed, test_clock_failed, no_email_received_within, reminder_not_received, portal_not_configured, cancel_not_completed, cancellation_email_not_received, checkout_url_missing, real_checkout_not_completed, payment_link_not_found, webhook_not_delivered, reminder_outside_window, reminder_timing_not_observed, cancel_flow_not_configured, cancel_not_confirmed_in_stripe, acknowledgment_content_incomplete, cancel_replaced_by_other_subscription, not_judged, scan_config_missing, domain_not_verified, scanner_failed, stripe_api_error, timeout, canceled, internal_error. */
3295
4328
  code: string | null;
3296
4329
  fix: TestRunFix;
3297
4330
  }
@@ -3307,10 +4340,31 @@ export interface TestRun {
3307
4340
  site: string;
3308
4341
  /** stripe: Stripe test mode with a test clock; generic: any site with a test coupon / test account (no time travel). */
3309
4342
  type: "stripe" | "generic";
3310
- /** succeeded means the run finished (steps may still have failing checks); failed means it stopped early (see failure). */
4343
+ /** Stripe runs: mirror (Checkbox mirrors your checkout into test mode and moves a test clock through trial and renewal) or real_checkout (the shopper buys through YOUR checkout on your test deployment, so your own webhook handlers and email code fire: the proof that your real system works). null for generic runs. */
4344
+ mode: "mirror" | "real_checkout" | null;
4345
+ /** succeeded means the run finished and no step failed (steps may still have warnings to review); failed means it stopped early, or finished with a failed step (see failure and steps[].fix). */
3311
4346
  status: "queued" | "running" | "succeeded" | "failed" | "canceled";
4347
+ /** The status in plain words, counting steps: "Finished with 6 warnings to review", "Finished with 1 failed step", "Finished: every observed step passed". succeeded with warnings is not a clean pass. */
4348
+ status_label: string;
3312
4349
  /** Internal phase (prepare, checkout, await_ack, advance, settle, cancel, await_cancel_email, finalize, done). */
3313
4350
  phase: string;
4351
+ /** While the run is queued or running: what it waits for and until when. null once it finished. */
4352
+ waiting_for: {
4353
+ /** What the run is waiting for, in plain words. */
4354
+ what: string;
4355
+ /** When the run stops waiting for it at the latest (null: unknown). Unix timestamp in seconds. */
4356
+ until: number | null;
4357
+ /** Test-clock time the run is at, or moving to (null without a test clock). Unix timestamp in seconds. */
4358
+ clock_time: number | null;
4359
+ /** The step the run is on (1-based), of steps_total steps that will run (skipped steps not counted). */
4360
+ step: number | null;
4361
+ /** Steps that will run. */
4362
+ steps_total: number | null;
4363
+ /** When the whole run is expected to be done, from typical step times (an estimate; a wait that runs long moves it later; null: none). Unix timestamp in seconds. */
4364
+ eta: number | null;
4365
+ /** Whole minutes until eta, from typical step times (null: no estimate). */
4366
+ minutes_left: number | null;
4367
+ } | null;
3314
4368
  /** Always true: runs use the billing platform's test mode; nothing is charged. */
3315
4369
  test_mode: true;
3316
4370
  /** Email address of the synthetic test subscriber; mail sent there is captured as evidence. */
@@ -3325,7 +4379,7 @@ export interface TestRun {
3325
4379
  steps: Array<TestRunStep>;
3326
4380
  /** Why the run stopped (failed / canceled runs). */
3327
4381
  failure: {
3328
- /** Stable failure code: key_missing, key_not_test_mode, key_invalid, key_permission_missing, checkout_config_missing, price_not_in_test_mode, checkout_session_failed, checkout_page_unreadable, checkout_not_completed, subscription_create_failed, test_clock_failed, no_email_received_within, reminder_not_received, portal_not_configured, cancel_not_completed, cancellation_email_not_received, scan_config_missing, domain_not_verified, scanner_failed, stripe_api_error, timeout, canceled, internal_error. */
4382
+ /** Stable failure code: key_missing, key_not_test_mode, key_invalid, key_permission_missing, checkout_config_missing, price_not_in_test_mode, checkout_session_failed, checkout_page_unreadable, checkout_not_completed, subscription_create_failed, test_clock_failed, no_email_received_within, reminder_not_received, portal_not_configured, cancel_not_completed, cancellation_email_not_received, checkout_url_missing, real_checkout_not_completed, payment_link_not_found, webhook_not_delivered, reminder_outside_window, reminder_timing_not_observed, cancel_flow_not_configured, cancel_not_confirmed_in_stripe, acknowledgment_content_incomplete, cancel_replaced_by_other_subscription, not_judged, scan_config_missing, domain_not_verified, scanner_failed, stripe_api_error, timeout, canceled, internal_error. */
3329
4383
  code: string;
3330
4384
  /** What went wrong. */
3331
4385
  message: string;
@@ -3335,8 +4389,6 @@ export interface TestRun {
3335
4389
  } | null;
3336
4390
  /** Outcome of a finished run. */
3337
4391
  result: {
3338
- /** Compliance score (0-100) of the observed steps alone. */
3339
- score: number | null;
3340
4392
  /** Counts. */
3341
4393
  summary: {
3342
4394
  /** Checks that passed. */
@@ -3381,8 +4433,8 @@ export interface TestRun {
3381
4433
  subscription: string | null;
3382
4434
  /** Mirrored test-mode Checkout Session. */
3383
4435
  checkout_session: string | null;
3384
- /** Where the checkout configuration came from. */
3385
- mirrored_from: "registered" | "live" | "request" | null;
4436
+ /** Where the checkout configuration came from (mirror mode). stripe_session: the newest Checkout Session your code created, read with a test-mode monitoring key. */
4437
+ mirrored_from: "registered" | "live" | "request" | "payment_link" | "stripe_session" | null;
3386
4438
  /** Registered config used (scc_…). */
3387
4439
  checkout_config: string | null;
3388
4440
  /** Compliance fingerprint of the mirrored checkout. */
@@ -3392,6 +4444,54 @@ export interface TestRun {
3392
4444
  /** Whether the test clock (with its customer and subscription) was deleted. */
3393
4445
  cleaned_up: boolean;
3394
4446
  } | null;
4447
+ /** What the run proves and the evidence beyond the steps (Stripe runs). */
4448
+ proof: {
4449
+ /** The run mode. */
4450
+ mode: "mirror" | "real_checkout";
4451
+ /** What this run is evidence of, and what it is not, in one sentence. */
4452
+ what_it_proves: string;
4453
+ /** Notices mode of the site at the run: checkbox (Checkbox Notices sends; the run exercises them), merchant (you send; the run watches for yours) or off. */
4454
+ notices: "checkbox" | "merchant" | "off" | null;
4455
+ /** Who was expected to send the lifecycle emails. */
4456
+ notices_sender: "checkbox" | "merchant" | null;
4457
+ /** Payment Link mirrored or bought through (plink_…). */
4458
+ payment_link: string | null;
4459
+ /** Your Stripe test-mode webhook endpoints (host only) when the key may read them. */
4460
+ webhook_endpoints: Array<{
4461
+ /** Host of the endpoint URL (the path is not shown). */
4462
+ host: string;
4463
+ /** Event types it listens for ("*" = all). */
4464
+ enabled_events: Array<string>;
4465
+ /** enabled or disabled. */
4466
+ status: string;
4467
+ }>;
4468
+ /** Stripe events of the run's subscription (evidence). pending_webhooks > 0: an endpoint did not acknowledge it. */
4469
+ stripe_events: Array<{
4470
+ /** Stripe event id (test mode). */
4471
+ id: string;
4472
+ /** Stripe event type. */
4473
+ type: string;
4474
+ /** When Stripe created it (unix seconds). */
4475
+ created: number;
4476
+ /** Deliveries Stripe still had pending when Checkbox looked (0 = acknowledged by every endpoint, or no endpoint). */
4477
+ pending_webhooks: number | null;
4478
+ }>;
4479
+ /** How the cancellation was attempted and what Stripe showed. */
4480
+ cancellation: {
4481
+ /** Where the shopper cancelled. */
4482
+ via: "merchant_flow" | "stripe_portal" | "cancel_url";
4483
+ /** false: nothing told Checkbox how customers cancel, so it used the Stripe portal (step warning cancel_flow_not_configured: the cancel itself worked). true also when inferred (inferred_from). */
4484
+ declared_by_merchant: boolean;
4485
+ /** site_portal_link: no cancel_via was given, Stripe has cancellation on in the customer portal and your site links to it, so the portal was used as declared. registered_url: no cancel_via was given and the account or cancellation page you registered (account_url / cancellation_url) redirects or links to the Stripe customer portal, so the portal was used as declared. */
4486
+ inferred_from?: "site_portal_link" | "registered_url" | null;
4487
+ /** Stripe showed a subscription set to cancel after the shopper's flow. */
4488
+ confirmed_in_stripe: boolean;
4489
+ /** The subscription Stripe showed canceled. */
4490
+ subscription: string | null;
4491
+ /** Why Stripe could not be checked, when it could not. */
4492
+ note: string | null;
4493
+ } | null;
4494
+ } | null;
3395
4495
  next_action: NextAction;
3396
4496
  }
3397
4497
  /** A page of test runs, newest first. */
@@ -3456,7 +4556,7 @@ export interface Event {
3456
4556
  id: string;
3457
4557
  /** String representing the object's type. Always "event". */
3458
4558
  object: "event";
3459
- /** Event type: site.score_changed, site.insurable_changed, finding.created, finding.resolved, scan.completed, scan.failed, law.changed, certificate.issued, certificate.lapsed, certificate.revoked, notice.sent, notice.due, notice.overdue, consent.created, receipt.created, test_run.completed, test_run.failed, plan.updated, site.compliant, task.verified. */
4559
+ /** Event type: site.compliance_changed, finding.created, finding.resolved, scan.completed, scan.failed, law.changed, certificate.issued, certificate.lapsed, certificate.revoked, notice.sent, notice.due, notice.overdue, consent.created, receipt.created, test_run.completed, test_run.failed, plan.updated, site.checks_passed, site.compliant (deprecated), task.verified. */
3460
4560
  type: string;
3461
4561
  /** API version used to render data.object. */
3462
4562
  api_version: string;
@@ -3499,18 +4599,32 @@ export interface Feedback {
3499
4599
  /** String representing the object's type. Always "feedback". */
3500
4600
  object: "feedback";
3501
4601
  /** Kind of feedback. */
3502
- type: "bug" | "idea" | "question";
4602
+ type: "bug" | "idea" | "question" | "review";
3503
4603
  /** open until Checkbox staff reply or close it. */
3504
4604
  status: "open" | "replied" | "closed";
4605
+ /** true when text that looked like a secret, card number or email address was replaced with [redacted] before it was stored. */
4606
+ redacted: boolean;
3505
4607
  /** When it was received. Unix timestamp in seconds. */
3506
4608
  created: number;
3507
4609
  }
3508
4610
  export interface FeedbackParams {
3509
- /** bug: something is broken; idea: a missing feature or improvement; question: something unclear. Default idea. */
3510
- type?: "bug" | "idea" | "question";
3511
- /** What you tried, what happened and what you expected (at most 5000 characters). */
3512
- message: string;
3513
- /** Optional context that helps us reproduce it. */
4611
+ /** bug: something is broken; idea: a missing feature or improvement; question: something unclear; review: a structured review of Checkbox the product (send only after the human said yes and saw the text; no site names, URLs, customer data, quotes of the site's pages or emails, or claims that the site broke a law). Default idea. */
4612
+ type?: "bug" | "idea" | "question" | "review";
4613
+ /** What you tried, what happened and what you expected (at most 5000 characters). Required except for type review. Secrets, card numbers and email addresses are replaced with [redacted]. */
4614
+ message?: string;
4615
+ /** type review (required): how likely the human is to recommend Checkbox, 0-10. */
4616
+ score?: number;
4617
+ /** type review: what worked, at most 5 short phrases. */
4618
+ liked?: Array<string>;
4619
+ /** type review: what did not work, at most 5 short phrases. */
4620
+ disliked?: Array<string>;
4621
+ /** type review: Checkbox verdicts the human believes were wrong, each "<check id>: <short reason about Checkbox's verdict>" (at most 5; the reason is kept to 200 characters). */
4622
+ wrong_verdicts?: Array<string>;
4623
+ /** type review: whether the human would keep using Checkbox. */
4624
+ would_keep_using?: boolean;
4625
+ /** type review: framework and billing, short. */
4626
+ stack?: string;
4627
+ /** Optional context that helps us reproduce it. For type review only agent and tool are kept (reviews never carry the site or request id). */
3514
4628
  context?: {
3515
4629
  /** Site id the feedback is about. */
3516
4630
  site?: string;
@@ -3522,6 +4636,25 @@ export interface FeedbackParams {
3522
4636
  agent?: string;
3523
4637
  };
3524
4638
  }
4639
+ /** The one-time prompt to ask the human for a review of the session. */
4640
+ export interface ReviewPrompt {
4641
+ /** String representing the object's type. Always "review_prompt". */
4642
+ object: "review_prompt";
4643
+ /** The site. */
4644
+ site: string;
4645
+ /** true exactly once per site, while its plan status is compliant (checks pass): ask the human once whether they want to send a review. false afterwards. */
4646
+ show: boolean;
4647
+ /** Why show is true or false. */
4648
+ reason: "first_time" | "already_shown" | "not_compliant";
4649
+ /** The instruction for the agent when show is true; null otherwise. */
4650
+ message: string | null;
4651
+ /** When the prompt was first shown for this site (null before). Unix timestamp in seconds. */
4652
+ shown_at: number | null;
4653
+ }
4654
+ export interface ReviewPromptParams {
4655
+ /** What reached "Checks pass": the plan (retrieveCompliancePlan) or the verification of the last required task (verifyTask). Default plan_compliant. */
4656
+ trigger?: "plan_compliant" | "last_task_verified";
4657
+ }
3525
4658
  /** A compliance plan without task content (webhook payload). */
3526
4659
  export interface CompliancePlanSummary {
3527
4660
  /** Unique identifier of the compliance plan (plan_…). */
@@ -3532,12 +4665,10 @@ export interface CompliancePlanSummary {
3532
4665
  livemode: boolean;
3533
4666
  /** The site. */
3534
4667
  site: string;
3535
- /** action_required (an agent can apply open tasks now), verifying (changes applied; waiting for confirming observations), compliant (every applicable check Checkbox could observe passes — an automated assessment, not a legal determination; see coverage for what was not observed), blocked (only human answers or declined critical tasks remain). */
4668
+ /** action_required (an agent can apply open tasks now), verifying (changes applied; waiting for confirming observations), compliant (every required check passes or only waits for a live check — an automated assessment, not a legal determination; see compliance.pending_live_checks and coverage), blocked (only human answers ("Your call") or declined critical tasks remain). */
3536
4669
  status: "action_required" | "verifying" | "compliant" | "blocked";
3537
- /** Compliance score 0-100 of the latest evaluation. */
3538
- score: number | null;
3539
- /** Preview flag the planned Checkbox Warranty will key on (no checks failing at high severity). No warranty or insurance is offered yet; this is not an underwriting decision. */
3540
- insurable: boolean | null;
4670
+ /** The plan status in words to show a person: action_required "Fixes needed", verifying "Checking your changes", compliant "Checks pass", blocked "Your call". Show this, never the machine value (`compliant` is a status name, not a legal conclusion). */
4671
+ status_label?: string;
3541
4672
  /** Two or three sentences for an LLM: where the site stands and what comes next. */
3542
4673
  summary: string;
3543
4674
  /** Tasks per status. */
@@ -3550,13 +4681,15 @@ export interface CompliancePlanSummary {
3550
4681
  verifying: number;
3551
4682
  /** Tasks waiting for a human answer. */
3552
4683
  manual: number;
4684
+ /** Tasks that only wait for a live observation (count as passing the checks). */
4685
+ pending_live_check?: number;
3553
4686
  /** Done tasks. */
3554
4687
  done: number;
3555
4688
  /** Declined tasks. */
3556
4689
  wont_fix: number;
3557
4690
  };
3558
4691
  next_action: PlanNextAction;
3559
- /** What the assessment rests on. Tell the human about not_observed and attested items; never call the site "compliant" without them. */
4692
+ /** What the assessment rests on. Tell the human about not_observed and attested items; never tell them the site "is compliant". */
3560
4693
  coverage: {
3561
4694
  /** Lifecycle stages Checkbox observed (signup, acknowledgment_email, reminders, cancellation, policies, billing_settings). */
3562
4695
  observed: Array<string>;
@@ -3576,7 +4709,7 @@ export interface CompliancePlanSummary {
3576
4709
  /** Task key. */
3577
4710
  key: string;
3578
4711
  /** Task status. */
3579
- status: "open" | "in_progress" | "verifying" | "done" | "wont_fix" | "manual";
4712
+ status: "open" | "in_progress" | "verifying" | "done" | "wont_fix" | "manual" | "pending_live_check";
3580
4713
  /** Priority. */
3581
4714
  priority: "critical" | "high" | "medium" | "low";
3582
4715
  /** Title. */
@@ -3594,7 +4727,7 @@ export interface Notice {
3594
4727
  /** The site. */
3595
4728
  site: string;
3596
4729
  /** Notice kind. */
3597
- kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change";
4730
+ kind: "acknowledgment" | "trial_ending" | "renewal_reminder" | "annual_terms" | "price_change" | "cancellation_confirmation" | "charge_notice";
3598
4731
  /** Delivery status. */
3599
4732
  status: "claimed" | "sent" | "failed" | "bounced" | "skipped";
3600
4733
  /** Billing platform of the subscription. */
@@ -3630,6 +4763,8 @@ export interface ListSetupSessionsParams {
3630
4763
  export interface UpdateAccountParams {
3631
4764
  /** API version to pin. */
3632
4765
  api_version?: string;
4766
+ retention?: RetentionParams;
4767
+ legal_hold?: LegalHoldParams;
3633
4768
  }
3634
4769
  /** Parameters of `sites.list()` (listSites). */
3635
4770
  export interface ListSitesParams {
@@ -3813,6 +4948,11 @@ export interface ListLawUpdatesParams {
3813
4948
  /** Only changes on or after this date (YYYY-MM-DD). */
3814
4949
  since?: string;
3815
4950
  }
4951
+ /** Parameters of `suggestions.forSite()` (listSiteSuggestions). */
4952
+ export interface ListSiteSuggestionsParams {
4953
+ /** Comma-separated surfaces to include (default all). */
4954
+ surfaces?: string;
4955
+ }
3816
4956
  /** Parameters of `consents.list()` (listConsents). */
3817
4957
  export interface ListConsentsParams {
3818
4958
  /** Number of objects to return, 1-100 (default 10). */
@@ -3884,6 +5024,8 @@ export interface ListStripeCheckoutConfigsParams {
3884
5024
  }
3885
5025
  /** Parameters of `testRuns.create()` (createTestRun). */
3886
5026
  export interface CreateTestRunParams {
5027
+ /** Stripe runs. mirror (default): Checkbox mirrors your checkout into test mode and moves a test clock through every legal notice window. real_checkout ("Run proof"): the shopper buys through YOUR checkout on your test deployment (stripe.checkout_url or stripe.payment_link) with card 4242 and the run inbox, so your own webhook handlers and email code fire; Checkbox watches the inbox, Stripe's events and your cancel flow. Needs your test deployment on Stripe TEST keys with a test-mode webhook endpoint. */
5028
+ mode?: "mirror" | "real_checkout";
3887
5029
  /** stripe (default when a Stripe test key is stored or the site uses Stripe) or generic (test coupon / test account, no time travel). */
3888
5030
  type?: "stripe" | "generic";
3889
5031
  /** How long to wait for each email (acknowledgment, reminders, cancellation), 15-900 seconds (default 120). */
@@ -3896,7 +5038,7 @@ export interface CreateTestRunParams {
3896
5038
  region?: "US-FED" | "US-AL" | "US-AK" | "US-AZ" | "US-AR" | "US-CA" | "US-CO" | "US-CT" | "US-DE" | "US-DC" | "US-FL" | "US-GA" | "US-HI" | "US-ID" | "US-IL" | "US-IN" | "US-IA" | "US-KS" | "US-KY" | "US-LA" | "US-ME" | "US-MD" | "US-MA" | "US-MI" | "US-MN" | "US-MS" | "US-MO" | "US-MT" | "US-NE" | "US-NV" | "US-NH" | "US-NJ" | "US-NM" | "US-NY" | "US-NC" | "US-ND" | "US-OH" | "US-OK" | "US-OR" | "US-PA" | "US-RI" | "US-SC" | "US-SD" | "US-TN" | "US-TX" | "US-UT" | "US-VT" | "US-VA" | "US-WA" | "US-WV" | "US-WI" | "US-WY";
3897
5039
  /** Stripe options. */
3898
5040
  stripe?: {
3899
- /** Registered checkout config (scc_…) to mirror; default: the newest one, else your latest live Checkout Session. */
5041
+ /** Registered checkout config (scc_…) to mirror; default: the newest one, else your latest live Checkout Session. "none" skips the registered configs (mirror your live checkout, stripe.price or stripe.payment_link instead). */
3900
5042
  checkout_config?: string;
3901
5043
  /** A test-mode price to subscribe to when nothing is registered. */
3902
5044
  price?: string;
@@ -3906,8 +5048,33 @@ export interface CreateTestRunParams {
3906
5048
  price_map?: Record<string, string>;
3907
5049
  /** Steps that complete your hosted checkout with card 4242 4242 4242 4242 when it differs from Stripe's default page. */
3908
5050
  checkout_steps?: Array<ScanStep>;
3909
- /** Cancel on your own page instead of the Stripe customer portal (it must work for the test subscriber). */
5051
+ /** Your cancellation page (after login with test_account, or public). Checkbox never falls back to the Stripe portal when your flow fails. */
3910
5052
  cancel_url?: string;
5053
+ /** Clicks that cancel in your flow (after login / cancel_url), e.g. [{ "action": "click", "text": "Cancel subscription" }, { "action": "click", "text": "Confirm" }]. */
5054
+ cancel_steps?: Array<ScanStep>;
5055
+ /** How your customers cancel. Default: your flow when test_account / cancel_url / cancel_steps describe it; else the Stripe portal, taken as declared when Stripe has portal cancellation on and your site links to the portal, or when the account or cancellation page you registered redirects or links to the portal; otherwise reported as a warning (cancel_flow_not_configured: the cancel worked, but how your customers cancel was not given). */
5056
+ cancel_via?: "merchant_flow" | "stripe_portal";
5057
+ /** A test account the shopper logs into: to buy as a logged-in user (real_checkout) and to cancel through your in-app flow. Mail to its address counts when you BCC the site's Checkbox address. */
5058
+ test_account?: {
5059
+ /** Login page of the test account on your (test) deployment. */
5060
+ login_url: string;
5061
+ /** Its email; "{{inbox}}" = the run inbox (the account the shopper creates at checkout). */
5062
+ email: string;
5063
+ /** Its password (stored encrypted, never returned). Generated for "{{inbox}}" accounts when omitted. */
5064
+ password?: string;
5065
+ /** Custom login steps ({{email}}, {{password}}). */
5066
+ login_steps?: Array<ScanStep>;
5067
+ };
5068
+ /** A Stripe Payment Link (plink_… or its buy.stripe.com URL): mirror mode mirrors its prices, custom_text, consent_collection and trial; real_checkout buys through it (test-mode links only). */
5069
+ payment_link?: string;
5070
+ /** real_checkout: the page of your TEST deployment that leads to your Stripe test-mode checkout (a pricing page, or a route that creates the Checkout Session and redirects). */
5071
+ checkout_url?: string;
5072
+ /** real_checkout: clicks from checkout_url to the payment page, e.g. [{ "action": "click", "text": "Start free trial" }]. In fill values, {{email}} is the run inbox and {{password}} is stripe.test_account.password when a test account is given, so an account created here can log in for the cancellation. */
5073
+ pre_checkout_steps?: Array<ScanStep>;
5074
+ /** A page of your test deployment Checkbox opens before the checkout (after logging in) that CLEANS UP the test account (ends its subscription), so every run starts without one. Mirror mode opens it before cancelling the test account's subscription. */
5075
+ cleanup_url?: string;
5076
+ /** Deprecated alias of cleanup_url. */
5077
+ reset_url?: string;
3911
5078
  };
3912
5079
  /** Generic (non-Stripe) options. */
3913
5080
  generic?: {
@@ -3946,11 +5113,16 @@ export interface ListTestRunsParams {
3946
5113
  /** Cursor: an object id; returns the objects before it (newer). */
3947
5114
  ending_before?: string;
3948
5115
  }
5116
+ /** Parameters of `testRuns.retrieve()` (retrieveTestRun). */
5117
+ export interface RetrieveTestRunParams {
5118
+ /** Long-poll: wait up to this many seconds (0-30) for the run to move on (status, phase or a step changes) before answering. */
5119
+ wait?: number | null;
5120
+ }
3949
5121
  /** Parameters of `webhookEndpoints.create()` (createWebhookEndpoint). */
3950
5122
  export interface CreateWebhookEndpointParams {
3951
5123
  /** HTTPS URL. */
3952
5124
  url: string;
3953
- /** Event types to send, or ["*"] for all: site.score_changed, site.insurable_changed, finding.created, finding.resolved, scan.completed, scan.failed, law.changed, certificate.issued, certificate.lapsed, certificate.revoked, notice.sent, notice.due, notice.overdue, consent.created, receipt.created, test_run.completed, test_run.failed, plan.updated, site.compliant, task.verified. */
5125
+ /** Event types to send, or ["*"] for all: site.compliance_changed, finding.created, finding.resolved, scan.completed, scan.failed, law.changed, certificate.issued, certificate.lapsed, certificate.revoked, notice.sent, notice.due, notice.overdue, consent.created, receipt.created, test_run.completed, test_run.failed, plan.updated, site.checks_passed, site.compliant (deprecated), task.verified. */
3954
5126
  enabled_events: Array<string>;
3955
5127
  /** Description. */
3956
5128
  description?: string;
@@ -3970,7 +5142,7 @@ export interface ListWebhookEndpointsParams {
3970
5142
  export interface UpdateWebhookEndpointParams {
3971
5143
  /** HTTPS URL. */
3972
5144
  url?: string;
3973
- /** Event types to send, or ["*"] for all: site.score_changed, site.insurable_changed, finding.created, finding.resolved, scan.completed, scan.failed, law.changed, certificate.issued, certificate.lapsed, certificate.revoked, notice.sent, notice.due, notice.overdue, consent.created, receipt.created, test_run.completed, test_run.failed, plan.updated, site.compliant, task.verified. */
5145
+ /** Event types to send, or ["*"] for all: site.compliance_changed, finding.created, finding.resolved, scan.completed, scan.failed, law.changed, certificate.issued, certificate.lapsed, certificate.revoked, notice.sent, notice.due, notice.overdue, consent.created, receipt.created, test_run.completed, test_run.failed, plan.updated, site.checks_passed, site.compliant (deprecated), task.verified. */
3974
5146
  enabled_events?: Array<string>;
3975
5147
  /** Description (null clears it). */
3976
5148
  description?: string | null;
@@ -4002,7 +5174,7 @@ export type PlanUpdatedEvent = Event & {
4002
5174
  type?: "plan.updated";
4003
5175
  data?: {
4004
5176
  object: CompliancePlanSummary;
4005
- /** plan.updated: the previous status and score. */
5177
+ /** plan.updated: the previous status. */
4006
5178
  previous_attributes?: Record<string, unknown>;
4007
5179
  };
4008
5180
  };
@@ -4012,7 +5184,7 @@ export type TaskVerifiedEvent = Event & {
4012
5184
  type?: "task.verified";
4013
5185
  data?: {
4014
5186
  object: Verification;
4015
- /** plan.updated: the previous status and score. */
5187
+ /** plan.updated: the previous status. */
4016
5188
  previous_attributes?: Record<string, unknown>;
4017
5189
  };
4018
5190
  };
@@ -4066,20 +5238,10 @@ export type TestRunFailedEvent = Event & {
4066
5238
  previous_attributes?: Record<string, unknown>;
4067
5239
  };
4068
5240
  };
4069
- /** `site.score_changed`: A site's compliance score changed (data.previous_attributes.score has the old score). */
4070
- export type SiteScoreChangedEvent = Event & {
5241
+ /** `site.compliance_changed`: A re-evaluation changed the site's check results; data.object is the site, with its current compliance status and label in data.object.compliance. */
5242
+ export type SiteComplianceChangedEvent = Event & {
4071
5243
  /** Event type. */
4072
- type?: "site.score_changed";
4073
- data?: {
4074
- object: Site;
4075
- /** Previous values of changed fields. */
4076
- previous_attributes?: Record<string, unknown>;
4077
- };
4078
- };
4079
- /** `site.insurable_changed`: A site became insurable or stopped being insurable. */
4080
- export type SiteInsurableChangedEvent = Event & {
4081
- /** Event type. */
4082
- type?: "site.insurable_changed";
5244
+ type?: "site.compliance_changed";
4083
5245
  data?: {
4084
5246
  object: Site;
4085
5247
  /** Previous values of changed fields. */
@@ -4106,7 +5268,7 @@ export type FindingResolvedEvent = Event & {
4106
5268
  previous_attributes?: Record<string, unknown>;
4107
5269
  };
4108
5270
  };
4109
- /** `scan.completed`: A scan finished (the evaluation may follow in a separate site.score_changed event). */
5271
+ /** `scan.completed`: A scan finished (the evaluation may follow in a separate site.compliance_changed event). */
4110
5272
  export type ScanCompletedEvent = Event & {
4111
5273
  /** Event type. */
4112
5274
  type?: "scan.completed";
@@ -4186,7 +5348,17 @@ export type ConsentCreatedEvent = Event & {
4186
5348
  previous_attributes?: Record<string, unknown>;
4187
5349
  };
4188
5350
  };
4189
- /** `site.compliant`: A site's compliance plan became compliant: nothing is left to apply, verify or answer; data.object is the site. */
5351
+ /** `site.checks_passed`: A site's compliance plan reached the status where its checks pass (plan status value `compliant`): nothing is left to apply, verify or answer; data.object is the site. Passing the checks is not a certification of legal compliance. */
5352
+ export type SiteChecksPassedEvent = Event & {
5353
+ /** Event type. */
5354
+ type?: "site.checks_passed";
5355
+ data?: {
5356
+ object: Site;
5357
+ /** Previous values of changed fields. */
5358
+ previous_attributes?: Record<string, unknown>;
5359
+ };
5360
+ };
5361
+ /** `site.compliant`: Deprecated alias of site.checks_passed, kept so existing endpoints keep working: sent at the same moment with the same data.object. Subscribe to site.checks_passed instead (an endpoint on "*" receives both). */
4190
5362
  export type SiteCompliantEvent = Event & {
4191
5363
  /** Event type. */
4192
5364
  type?: "site.compliant";
@@ -4197,9 +5369,9 @@ export type SiteCompliantEvent = Event & {
4197
5369
  };
4198
5370
  };
4199
5371
  /** Every event Checkbox delivers to webhook endpoints, discriminated by `type`. */
4200
- export type WebhookEvent = PlanUpdatedEvent | TaskVerifiedEvent | NoticeDueEvent | NoticeOverdueEvent | ReceiptCreatedEvent | TestRunCompletedEvent | TestRunFailedEvent | SiteScoreChangedEvent | SiteInsurableChangedEvent | FindingCreatedEvent | FindingResolvedEvent | ScanCompletedEvent | ScanFailedEvent | LawChangedEvent | CertificateIssuedEvent | CertificateLapsedEvent | CertificateRevokedEvent | NoticeSentEvent | ConsentCreatedEvent | SiteCompliantEvent;
5372
+ export type WebhookEvent = PlanUpdatedEvent | TaskVerifiedEvent | NoticeDueEvent | NoticeOverdueEvent | ReceiptCreatedEvent | TestRunCompletedEvent | TestRunFailedEvent | SiteComplianceChangedEvent | FindingCreatedEvent | FindingResolvedEvent | ScanCompletedEvent | ScanFailedEvent | LawChangedEvent | CertificateIssuedEvent | CertificateLapsedEvent | CertificateRevokedEvent | NoticeSentEvent | ConsentCreatedEvent | SiteChecksPassedEvent | SiteCompliantEvent;
4201
5373
  /** Every webhook event type. */
4202
- export declare const WEBHOOK_EVENT_TYPES: readonly ["plan.updated", "task.verified", "notice.due", "notice.overdue", "receipt.created", "test_run.completed", "test_run.failed", "site.score_changed", "site.insurable_changed", "finding.created", "finding.resolved", "scan.completed", "scan.failed", "law.changed", "certificate.issued", "certificate.lapsed", "certificate.revoked", "notice.sent", "consent.created", "site.compliant"];
5374
+ export declare const WEBHOOK_EVENT_TYPES: readonly ["plan.updated", "task.verified", "notice.due", "notice.overdue", "receipt.created", "test_run.completed", "test_run.failed", "site.compliance_changed", "finding.created", "finding.resolved", "scan.completed", "scan.failed", "law.changed", "certificate.issued", "certificate.lapsed", "certificate.revoked", "notice.sent", "consent.created", "site.checks_passed", "site.compliant"];
4203
5375
  export type WebhookEventType = (typeof WEBHOOK_EVENT_TYPES)[number];
4204
5376
  /** Stable error codes (`error.code`), with HTTP status, type and meaning. Codes are never renamed. */
4205
5377
  export declare const ERROR_CODES: {
@@ -4246,7 +5418,7 @@ export declare const ERROR_CODES: {
4246
5418
  readonly test_key_missing: {
4247
5419
  readonly status: 400;
4248
5420
  readonly type: "invalid_request_error";
4249
- readonly description: "A Stripe test run needs a Stripe TEST-mode key stored for the site (createTestCredential).";
5421
+ readonly description: "A Stripe test run needs a Stripe TEST-mode key stored for the site (a person adds it in the dashboard on the site's Proof page).";
4250
5422
  };
4251
5423
  readonly test_key_not_test_mode: {
4252
5424
  readonly status: 400;
@@ -4326,7 +5498,7 @@ export declare const ERROR_CODES: {
4326
5498
  readonly test_mode_scan_budget_exhausted: {
4327
5499
  readonly status: 429;
4328
5500
  readonly type: "rate_limit_error";
4329
- readonly description: "No longer returned (round 6): test mode has no scan budget for unverified domains any more, they are refused with test_mode_domain_unverified. Kept so older clients still recognise the code.";
5501
+ readonly description: "No longer returned: test mode has no scan budget for unverified domains any more, they are refused with test_mode_domain_unverified. Kept so older clients still recognise the code.";
4330
5502
  };
4331
5503
  readonly domain_not_verified: {
4332
5504
  readonly status: 403;
@@ -4368,16 +5540,36 @@ export declare const ERROR_CODES: {
4368
5540
  readonly type: "invalid_request_error";
4369
5541
  readonly description: "The site already has a queued or running test run; wait for it (retrieveTestRun) or cancel it (cancelTestRun).";
4370
5542
  };
5543
+ readonly legal_hold_active: {
5544
+ readonly status: 409;
5545
+ readonly type: "invalid_request_error";
5546
+ readonly description: "A legal hold is on for the account or the site: deleting data and shortening retention are refused until it is turned off (updateAccount / updateSite legal_hold).";
5547
+ };
4371
5548
  readonly idempotency_key_in_use: {
4372
5549
  readonly status: 409;
4373
5550
  readonly type: "idempotency_error";
4374
5551
  readonly description: "A request with this Idempotency-Key is still being processed; retry shortly.";
4375
5552
  };
5553
+ readonly shopify_not_connected: {
5554
+ readonly status: 409;
5555
+ readonly type: "invalid_request_error";
5556
+ readonly description: "The site's Shopify store is not connected through the Checkbox Shopify app, so Checkbox cannot publish to the app block. Only the merchant can connect it: install the Checkbox app from the Shopify admin and click \"Connect to Checkbox\" (`next_action` has the exact step).";
5557
+ };
4376
5558
  readonly resource_archived: {
4377
5559
  readonly status: 410;
4378
5560
  readonly type: "invalid_request_error";
4379
5561
  readonly description: "The object is archived; restore it before changing it.";
4380
5562
  };
5563
+ readonly terms_incomplete: {
5564
+ readonly status: 422;
5565
+ readonly type: "invalid_request_error";
5566
+ readonly description: "Checkbox cannot write the exact, verified renewal terms yet: plan facts are missing (price, interval, trial, cancellation URL or merchant name). `problems` lists them; `next_action` names the call that sets them.";
5567
+ };
5568
+ readonly fix_verification_failed: {
5569
+ readonly status: 422;
5570
+ readonly type: "invalid_request_error";
5571
+ readonly description: "The generated disclosure did not pass every sign-up check of the rules engine, so nothing was published. The message names the failing checks.";
5572
+ };
4381
5573
  readonly body_too_large: {
4382
5574
  readonly status: 413;
4383
5575
  readonly type: "invalid_request_error";
@@ -4413,6 +5605,11 @@ export declare const ERROR_CODES: {
4413
5605
  readonly type: "permission_error";
4414
5606
  readonly description: "Consent receipts are turned off for this account (updateReceiptSettings enabled=true turns them on).";
4415
5607
  };
5608
+ readonly platform_error: {
5609
+ readonly status: 502;
5610
+ readonly type: "api_error";
5611
+ readonly description: "The merchant's platform (e.g. Shopify) refused or failed the change; nothing was recorded as applied. Retry later; `message` has the platform's answer.";
5612
+ };
4416
5613
  readonly feature_unavailable: {
4417
5614
  readonly status: 503;
4418
5615
  readonly type: "api_error";