@hunt-labs/bytekit-sdk 0.11.8 → 0.11.10

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.
@@ -153,7 +153,9 @@ export interface paths {
153
153
  put?: never;
154
154
  /**
155
155
  * Capture a screenshot
156
- * @description Sync by default (holds up to 28s). Pass `?async=true` to return 202 immediately.
156
+ * @description Sync by default (holds up to 28s). Pass `async: true` in the body or `?async=true` in the
157
+ * query string to return 202 immediately; either one is enough, and `false` in one never
158
+ * cancels `true` in the other.
157
159
  * Poll via GET /v1/screenshots/{id}.
158
160
  *
159
161
  * **Limits:** request bodies are capped at 512 KB. An oversized body
@@ -198,13 +200,15 @@ export interface paths {
198
200
  *
199
201
  * **The response shape is decided by your request, not by how we route it.** In precedence order:
200
202
  *
201
- * 1. `async: true` → **202** with a `ScrapeQueuedEnvelope` receipt, returned immediately. Poll `GET /v1/scrape/{id}` for the result.
203
+ * 1. `async: true` in the body, or `?async=true` in the query string (either one is enough; `false` in one never cancels `true` in the other) → **202** with a `ScrapeQueuedEnvelope` receipt, returned immediately. Poll `GET /v1/scrape/{id}` for the result.
202
204
  * 2. Otherwise, a request that needs a full page render — today that is `delay_ms > 0` — is **held open** until the render reaches a terminal state, then returns **200** with the content envelope (`success` or `failed`). If the render is still running when the hold window expires (28 seconds by default), the request returns the **202** receipt instead and the job continues in the background.
203
205
  * 3. Otherwise the request is served by the fast HTTP path and returns **200** with the content envelope, typically in under a second.
204
206
  *
205
207
  * **A failed fetch is a result, not a transport error.** An unreachable host, a refused connection, or a target whose bot protection defeats every proxy tier all come back on the same **200** as a `failed` envelope — never a 5xx. Narrow on the envelope's `status` before reading the body. A failure the fast path decides inline is recorded as a failed job, so its envelope normally carries that job's `id` and `GET /v1/scrape/{id}` returns the same envelope; if recording the failed job itself fails, the envelope still arrives on the same 200 with `id` set to `null` and there is nothing to poll. A failure a held render reaches carries that render's real `id`. Either way the request transfers no billable bytes and is charged nothing.
206
208
  *
207
- * So a 202 means one of exactly two things: you asked for one with `async: true`, or the hold window expired. `wait_for_selector` and `wait_until` are `ScreenshotRequest` options, not `ScrapeRequest` options — sending either to this endpoint returns `422 validation_error`, so neither can produce a 202 here.
209
+ * **A target that rate-limits us is not ByteKit rate-limiting you.** The `failed` envelope's `error.code` is `target_rate_limited` when the target rate-limits the request. On the fast path that means our proxy attempts end on an HTTP 429 and no bot protection is identified on any attempt, even if the browser fallback then fails or reaches only an unidentified block page; the inline failure carries `error.retry_after_seconds` when the target sent a usable `Retry-After`. On a held render the browser's own answer decides: it observes a 429 on the page itself, or it fails outright after the proxy attempts ended on an HTTP 429. A bot-protection verdict on an earlier fetch attempt does not keep a held render `blocked` when the browser then observes the 429. A held render never carries `error.retry_after_seconds`. Retrying a `target_rate_limited` failure later is likely to work. A held render whose browser reaches an unidentified 403 or 503 page after a proxy 429 is `blocked`. A 429 that bot protection sends as a block stays `blocked` when it is the answer that decides the code: the fast path's proxy attempts, or the browser render on a held render. Your own per-key limit is a separate case: it answers HTTP 429 `rate_limited` with a `Retry-After` header (see the `429` response).
210
+ *
211
+ * So a 202 means one of exactly two things: you asked for one with `async: true` or `?async=true`, or the hold window expired. `wait_for_selector` and `wait_until` are `ScreenshotRequest` options, not `ScrapeRequest` options — sending either to this endpoint returns `422 validation_error`, so neither can produce a 202 here.
208
212
  */
209
213
  post: operations["createScrape"];
210
214
  delete?: never;
@@ -249,6 +253,12 @@ export interface paths {
249
253
  * `BulkCompletedWebhook` contract: at most 500 complete items and 1 MiB,
250
254
  * followed by cursor recovery through `GET /v1/scrape/bulk/{id}` whenever
251
255
  * `recovery_required` is true.
256
+ *
257
+ * **Unknown keys.** An unknown key on an `items[]` entry, or at the top level of
258
+ * the body, is rejected with `422 validation_error`. An unknown key inside
259
+ * `defaults` is not: it is dropped without a warning and the request is accepted
260
+ * with `202`. The exception is `cookies` and `headers`, on an item or in `defaults`: they
261
+ * answer `400 validation_error`.
252
262
  */
253
263
  post: operations["createScrapeBulk"];
254
264
  delete?: never;
@@ -277,6 +287,17 @@ export interface paths {
277
287
  * stored, or whose object cannot be signed, is omitted from `formats` and
278
288
  * reported as `artifact_unavailable` in `warnings`. The private unsigned
279
289
  * storage URL is never returned.
290
+ *
291
+ * **Cancelled by the platform.** When the account can no longer spend (its bandwidth
292
+ * balance is exhausted, or the account is deleted) while items are still pending, ByteKit
293
+ * cancels the job itself. It then reads `status: cancelled` even though you never called
294
+ * `DELETE /v1/bulk/{id}`, and the cancellation sends no webhook.
295
+ *
296
+ * **Job ids from other create routes.** The job is looked up by account only, so the id
297
+ * of a job created by `POST /v1/fetch/bulk` or `POST /v1/bulk` is found here too, not a `404`.
298
+ * The items listed are the job's scrape rows: a fetch-bulk job's items appear, and a
299
+ * `POST /v1/bulk` job shows its scrape items but not its screenshots. An id from another
300
+ * account answers `404`.
280
301
  */
281
302
  get: operations["getScrapeBulk"];
282
303
  put?: never;
@@ -296,15 +317,20 @@ export interface paths {
296
317
  };
297
318
  /**
298
319
  * Fetch a URL (GET)
299
- * @description Direct HTTP fetch. Successful responses return the upstream response bytes verbatim;
300
- * metadata is returned in X-Fetch-* headers. Non-2xx upstream responses use the
301
- * `upstream_error` JSON envelope with the upstream HTTP status.
320
+ * @description Direct HTTP fetch. Metadata is returned in X-Fetch-* headers. What the body holds
321
+ * depends on `X-Fetch-Fast-Path`. When it is `true`, a successful response returns the
322
+ * upstream response bytes verbatim. When it is `false` the request fell back to a browser
323
+ * render, and the body is the rendered page rather than the bytes the target sent;
324
+ * `X-Fetch-Content-Length` is then the compressed size of that page. Non-2xx upstream
325
+ * responses use the `upstream_error` JSON envelope with the upstream HTTP status.
302
326
  */
303
327
  get: operations["getFetch"];
304
328
  put?: never;
305
329
  /**
306
330
  * Fetch a URL (POST)
307
- * @description Same as GET /v1/fetch but with a JSON request body.
331
+ * @description Same as GET /v1/fetch but with a JSON request body. The response is the same, including
332
+ * the `X-Fetch-Fast-Path` rule for what the body holds: the upstream bytes verbatim when
333
+ * it is `true`, the rendered page when it is `false`.
308
334
  *
309
335
  * **Limits:** request bodies are capped at 512 KB. An oversized body
310
336
  * returns a `400` with error code `request_too_large`.
@@ -373,6 +399,16 @@ export interface paths {
373
399
  * stored object, or completed items whose object cannot be signed, carry
374
400
  * `null`; the latter report `artifact_unavailable`. The private unsigned
375
401
  * storage URL is never returned.
402
+ *
403
+ * **Cancelled by the platform.** When the account can no longer spend (its bandwidth
404
+ * balance is exhausted, or the account is deleted) while items are still pending, ByteKit
405
+ * cancels the job itself. It then reads `status: cancelled` even though you never called
406
+ * `DELETE /v1/bulk/{id}`, and the cancellation sends no webhook.
407
+ *
408
+ * **Job ids from other create routes.** The job is looked up by account only, so the id
409
+ * of a job created by `POST /v1/scrape/bulk` or `POST /v1/bulk` is found here too, not a
410
+ * `404`, with the job envelope and `items: []`: only items fetched through
411
+ * `POST /v1/fetch/bulk` are listed. An id from another account answers `404`.
376
412
  */
377
413
  get: operations["getFetchBulk"];
378
414
  put?: never;
@@ -436,7 +472,19 @@ export interface paths {
436
472
  path?: never;
437
473
  cookie?: never;
438
474
  };
439
- /** Get bulk job status */
475
+ /**
476
+ * Get bulk job status
477
+ * @description Returns the job envelope. Items are listed by `GET /v1/bulk/{id}/screenshots`.
478
+ *
479
+ * **Cancelled by the platform.** When the account can no longer spend (its bandwidth
480
+ * balance is exhausted, or the account is deleted) while items are still pending, ByteKit
481
+ * cancels the job itself. It then reads `status: cancelled` even though you never called
482
+ * `DELETE /v1/bulk/{id}`, and the cancellation sends no webhook.
483
+ *
484
+ * **Job ids from other create routes.** The job is looked up by account only, so the id
485
+ * of a job created by `POST /v1/scrape/bulk` or `POST /v1/fetch/bulk` is found here too, not
486
+ * a `404`, with that job's envelope. An id from another account answers `404`.
487
+ */
440
488
  get: operations["getBulk"];
441
489
  put?: never;
442
490
  post?: never;
@@ -567,6 +615,20 @@ export interface paths {
567
615
  * `X-ByteKit-Event: sitemap.failed` so receivers can dispatch on the
568
616
  * header without parsing the body shape.
569
617
  *
618
+ * The webhook body is `{ event, data }`. For a job the worker ran, `data` is not a
619
+ * `SitemapResponse`:
620
+ *
621
+ * - `sitemap.completed` `data` carries `id`, `url`, `strategy`, `status`,
622
+ * `total_urls`, `sources`, `total_bytes`, `results_url`, `warnings`,
623
+ * `metadata`, `compact` and `billing`.
624
+ * - `sitemap.failed` `data` carries `id`, `url`, `strategy`, `status`,
625
+ * `error_code`, `error_message`, `warnings` and `metadata`.
626
+ *
627
+ * In both, `url` is the host as `scheme://host`, and `warnings` is the
628
+ * worker's own warnings or `null`. When the request is answered from a cached job
629
+ * (`cache: hit`), the `sitemap.completed` `data` is instead the full job object, the
630
+ * same fields as a `SitemapResponse`.
631
+ *
570
632
  * **Limits:** request bodies are capped at 512 KB. An oversized body
571
633
  * returns a `400` with error code `request_too_large`.
572
634
  */
@@ -644,9 +706,6 @@ export interface paths {
644
706
  * endpoint factor (a 100 KiB estimate is pre-charged, then reconciled). The
645
707
  * bandwidth is still billed when the scrape succeeds but extraction later
646
708
  * fails; both axes are refunded only when the scrape itself never runs.
647
- *
648
- * Availability is gated by a server-side feature flag; when disabled the
649
- * endpoint returns `404`.
650
709
  */
651
710
  post: operations["createSchemaExtraction"];
652
711
  delete?: never;
@@ -743,7 +802,11 @@ export interface paths {
743
802
  put?: never;
744
803
  /**
745
804
  * Create Stripe checkout session
746
- * @description Creates a Stripe Checkout Session for subscription sign-up.
805
+ * @description Creates an Elements-mode Stripe Checkout session for subscription sign-up
806
+ * and returns its client secret. The dashboard mounts Stripe's Payment
807
+ * Element on `client_secret` and the user pays in-page; the plan activates
808
+ * asynchronously once Stripe's subscription webhook settles. The card paid
809
+ * with becomes the customer's default when none is set.
747
810
  */
748
811
  post: operations["createCheckout"];
749
812
  delete?: never;
@@ -761,7 +824,11 @@ export interface paths {
761
824
  };
762
825
  get?: never;
763
826
  put?: never;
764
- /** Create Stripe billing portal session */
827
+ /**
828
+ * Retired billing-portal compatibility terminal
829
+ * @description Returns 410 for every request and reads no body. Card update, cancellation and
830
+ * invoice history all stay in the dashboard at `/settings/billing`.
831
+ */
765
832
  post: operations["createPortal"];
766
833
  delete?: never;
767
834
  options?: never;
@@ -779,9 +846,8 @@ export interface paths {
779
846
  get?: never;
780
847
  put?: never;
781
848
  /**
782
- * PAYG onboarding
783
- * @description Creates a Stripe customer and setup-mode Checkout Session to collect
784
- * a payment method without charging. For pay-as-you-go accounts.
849
+ * Legacy card-setup compatibility terminal
850
+ * @description Returns 410. Card setup moved to `POST /v1/billing/payment-methods/setup`.
785
851
  */
786
852
  post: operations["registerPayg"];
787
853
  delete?: never;
@@ -801,10 +867,11 @@ export interface paths {
801
867
  put?: never;
802
868
  /**
803
869
  * One-time dollar deposit
804
- * @description Creates a hosted Stripe Checkout session for a deposit into the account's
805
- * USD balance and returns its URL. The caller redirects the user to
806
- * `checkout_url`; the balance is credited asynchronously by the
807
- * `payment_intent.succeeded` webhook once payment completes. The balance
870
+ * @description Creates an Elements-mode Stripe Checkout session for a deposit into the
871
+ * account's USD balance and returns its client secret. The dashboard mounts
872
+ * Stripe's Payment Element on `client_secret` and the user pays in-page; the
873
+ * balance is credited asynchronously once Stripe's payment webhook settles.
874
+ * The card paid with becomes the customer's default when none is set. The balance
808
875
  * never expires and pays for usage beyond the included allowance, for
809
876
  * bandwidth and search credits alike, at the plan's rate when it is used.
810
877
  */
@@ -822,15 +889,22 @@ export interface paths {
822
889
  path?: never;
823
890
  cookie?: never;
824
891
  };
825
- get?: never;
892
+ /**
893
+ * Read whether the plan is cancelling
894
+ * @description Whether the subscription is set to end at the end of the current period, read from Stripe on each call.
895
+ */
896
+ get: operations["getCancellation"];
826
897
  put?: never;
827
898
  /**
828
- * Legacy cancellation compatibility terminal
829
- * @description Returns 410. Customer cancellation is initiated through the hosted
830
- * Billing Portal and projected through Stripe webhooks.
899
+ * Cancel the plan at the period end
900
+ * @description Sets the subscription to end at the end of the current period instead of renewing; the plan stays active until then and the account then moves to Pay As You Go. A plan change booked for the period end is released first. Send the current cancellation disclosure revision in the `Billing-Disclosure-Revision` header: without it, or with a stale one, the call answers `409 billing_disclosure_stale` with the current terms.
831
901
  */
832
902
  post: operations["cancelSubscription"];
833
- delete?: never;
903
+ /**
904
+ * Keep a cancelling plan
905
+ * @description Undoes a pending cancellation, so the subscription renews at the end of the current period as before.
906
+ */
907
+ delete: operations["keepSubscription"];
834
908
  options?: never;
835
909
  head?: never;
836
910
  patch?: never;
@@ -849,7 +923,10 @@ export interface paths {
849
923
  */
850
924
  get: operations["getPlanChange"];
851
925
  put?: never;
852
- /** Change subscription plan */
926
+ /**
927
+ * Change subscription plan
928
+ * @description A plan change made while the plan is cancelling clears the pending cancellation, so the subscription keeps renewing.
929
+ */
853
930
  post: operations["changePlan"];
854
931
  /**
855
932
  * Revoke a scheduled plan change
@@ -868,7 +945,10 @@ export interface paths {
868
945
  path?: never;
869
946
  cookie?: never;
870
947
  };
871
- /** List Stripe invoices */
948
+ /**
949
+ * List Stripe invoices
950
+ * @description Invoices are ordered newest first. Page older with `starting_after` set to the last `id` of the previous page.
951
+ */
872
952
  get: operations["listInvoices"];
873
953
  put?: never;
874
954
  post?: never;
@@ -994,6 +1074,7 @@ export interface paths {
994
1074
  /**
995
1075
  * Detach a payment method
996
1076
  * @description Detaches the specified payment method from the Stripe customer.
1077
+ * Removing the last card also turns auto-topup off.
997
1078
  */
998
1079
  delete: operations["deletePaymentMethod"];
999
1080
  options?: never;
@@ -1148,8 +1229,9 @@ export interface paths {
1148
1229
  put?: never;
1149
1230
  /**
1150
1231
  * Accept current Terms of Service
1151
- * @description Records the authenticated account's acceptance of the current Terms of
1152
- * Service version (clickwrap re-acceptance). The server always records the
1232
+ * @description Records the signed-in person's own acceptance of the current Terms of
1233
+ * Service version (clickwrap). The record is per person, so each member of
1234
+ * an account accepts for themselves. The server always records the
1153
1235
  * current version — the client cannot accept an arbitrary version. The
1154
1236
  * client IP and User-Agent are captured as legal evidence. Requires an
1155
1237
  * active membership.
@@ -1172,9 +1254,10 @@ export interface paths {
1172
1254
  put?: never;
1173
1255
  /**
1174
1256
  * Mark onboarding as finished
1175
- * @description Records that the account left the dashboard's onboarding flow through one
1176
- * of its exits, so `onboarding_completed` on GET /v1/account reads true from
1177
- * then on. Idempotent: a repeat call keeps the first timestamp and still
1257
+ * @description Records that the signed-in person left the dashboard's onboarding flow
1258
+ * through one of its exits, so both `onboarding_completed` (the account) and
1259
+ * `user_onboarding_completed` (this person) on GET /v1/account read true
1260
+ * from then on. Idempotent: a repeat call keeps the first timestamps and still
1178
1261
  * answers 200. Requires an active membership (admin or member).
1179
1262
  */
1180
1263
  post: operations["completeOnboarding"];
@@ -1464,6 +1547,14 @@ export interface components {
1464
1547
  details?: unknown;
1465
1548
  };
1466
1549
  };
1550
+ /** @description The vendor-masked `503` body of `POST /v1/search`. */
1551
+ CreateSearchResponse503: {
1552
+ /**
1553
+ * @description Fixed vendor-masked error code. Always `search_provider_error`; the upstream provider's identity and failure detail are withheld by design.
1554
+ * @enum {string}
1555
+ */
1556
+ error: "search_provider_error";
1557
+ };
1467
1558
  /**
1468
1559
  * @description Item-local terminal artifact failure. The item's stable id remains usable for paginated recovery, but the requested stored content or signed reference could not be produced. Wherever this code is raised the URL field it describes is `null`; a private object-storage URL is never returned as a substitute for it. Endpoints that do not raise this code document their own fallback — see `image_url` on `GET /v1/bulk/{id}/screenshots`.
1469
1560
  *
@@ -1648,10 +1739,11 @@ export interface components {
1648
1739
  BillingNode: {
1649
1740
  /**
1650
1741
  * @description The unmultiplied basis of the charge. For byte-billed endpoints this is
1651
- * the upstream wire bytes actually transferred. For screenshots and
1652
- * recordings it is the Phase 1 HTML fetch's wire bytes — the only proxied
1653
- * traffic in the happy path — never the size of the returned PNG/JPEG/MP4
1654
- * artifact.
1742
+ * the upstream wire bytes actually transferred. For a page served by the
1743
+ * hosted-browser tier it is the browser's full measured transfer. For
1744
+ * screenshots and recordings it is the Phase 1 HTML fetch's wire bytes — the
1745
+ * only proxied traffic in the happy path — never the size of the returned
1746
+ * PNG/JPEG/MP4 artifact.
1655
1747
  * @example 1024
1656
1748
  */
1657
1749
  raw_bytes: number;
@@ -1674,11 +1766,19 @@ export interface components {
1674
1766
  /** Format: uri */
1675
1767
  url: string;
1676
1768
  /**
1769
+ * @description What to return. Each entry is either a string format (`raw`, `markdown`, `links`
1770
+ * or `images`) or a `json` object entry that extracts structured data from the page.
1771
+ * The string `"json"` is not a format value; the `json` entry is an object, described
1772
+ * by `ScrapeRequestJsonFormat`. A list may hold at most one `json` entry, and a list
1773
+ * holding only the `json` entry still captures `raw`. The `json` entry exists on
1774
+ * `POST /v1/scrape` only: the bulk and monitor `formats` fields accept the string
1775
+ * formats alone. Its result is `formats.json` on the response, and its price is
1776
+ * described on `ScrapeRequestJsonFormat`.
1677
1777
  * @default [
1678
1778
  * "raw"
1679
1779
  * ]
1680
1780
  */
1681
- formats: ("raw" | "markdown" | "links" | "images")[];
1781
+ formats: (components["schemas"]["ScrapeRequestFormatsItem"] | components["schemas"]["ScrapeRequestJsonFormat"])[];
1682
1782
  /** @default US */
1683
1783
  country: string;
1684
1784
  /**
@@ -1686,10 +1786,10 @@ export interface components {
1686
1786
  * @default 0
1687
1787
  */
1688
1788
  delay_ms: number;
1689
- /** @default 30000 */
1789
+ /** @default 60000 */
1690
1790
  timeout_ms: number;
1691
1791
  /**
1692
- * @description When true, the request returns 202 with a `ScrapeQueuedEnvelope` receipt immediately and the scrape runs in the background; poll `GET /v1/scrape/{id}` for the result. This is the only way to ASK for a receipt, and it outranks every routing consequence: with `async: false` (the default) a browser-path request is held to completion instead of being receipted. A 202 can still arrive with `async: false`, but only when the hold window expires.
1792
+ * @description When true, the request returns 202 with a `ScrapeQueuedEnvelope` receipt immediately and the scrape runs in the background; poll `GET /v1/scrape/{id}` for the result. The `?async=true` query parameter is a second spelling of this field: the request is async when either one says true, and `false` in one never cancels `true` in the other. Asking for a receipt this way outranks every routing consequence: when neither is set (the default) a browser-path request is held to completion instead of being receipted. A 202 can still arrive without either, but only when the hold window expires.
1693
1793
  * @default false
1694
1794
  */
1695
1795
  async: boolean;
@@ -1794,6 +1894,47 @@ export interface components {
1794
1894
  */
1795
1895
  x_internal_scrape_path?: "lean-forced";
1796
1896
  };
1897
+ /**
1898
+ * @description A string entry of `ScrapeRequest.formats`.
1899
+ * @enum {string}
1900
+ */
1901
+ ScrapeRequestFormatsItem: "raw" | "markdown" | "links" | "images";
1902
+ /**
1903
+ * @description The `json` entry of `ScrapeRequest.formats`: structured extraction over the scraped
1904
+ * page, using the same extractor as `POST /v1/schema`.
1905
+ *
1906
+ * **Price.** Each `json` entry costs 10 credits, charged only when the extraction
1907
+ * validates (`formats.json.validated` is `true`). The charge is on top of the scrape's
1908
+ * own charge and is never scaled by the scrape's factors. The 10 credits are reserved at
1909
+ * admission in every billing mode and released again when the extraction does not
1910
+ * validate. This price is provisional.
1911
+ *
1912
+ * **Errors.** A `schema` the extractor cannot take is refused with
1913
+ * `422 schema_incompatible`, and a deployment with no extraction provider refuses the
1914
+ * request with `503 provider_unavailable`. Both are refused before anything is drawn. Once
1915
+ * the page is scraped, an extraction that does not validate never fails the scrape: the
1916
+ * result carries `validated: false` and `data: null`, with an extraction warning in
1917
+ * `warnings`.
1918
+ */
1919
+ ScrapeRequestJsonFormat: {
1920
+ /** @enum {string} */
1921
+ type: "json";
1922
+ /**
1923
+ * @description JSON Schema describing the desired output. It is held to the same guards as the
1924
+ * `schema` field of `POST /v1/schema`: serialized size at most 50 KB, nesting depth at
1925
+ * most 8, it must compile under Ajv, and it must be normalizable into the extractor's
1926
+ * strict subset (root `type: object`, and only the keyword allowlist given there).
1927
+ */
1928
+ schema: Record<string, never>;
1929
+ /**
1930
+ * @description Extraction model.
1931
+ * @default openai/gpt-oss-20b
1932
+ * @enum {string}
1933
+ */
1934
+ model: "openai/gpt-oss-20b" | "openai/gpt-oss-120b";
1935
+ /** @description Optional natural-language extraction hint. */
1936
+ prompt?: string;
1937
+ };
1797
1938
  ScrapeScoredLink: {
1798
1939
  /** Format: uri */
1799
1940
  url: string;
@@ -1818,8 +1959,11 @@ export interface components {
1818
1959
  cols: number;
1819
1960
  };
1820
1961
  ScrapeWarning: {
1821
- /** @enum {string} */
1822
- code: "lossy_table" | "complex_math" | "unsupported_element" | "extraction_fallback" | "truncated" | "query_no_match" | "mode_disabled_fallback" | "artifact_unavailable" | "llm_clean_unavailable" | "llm_clean_failed" | "low_quality_extraction" | "fragment_menu_stripped";
1962
+ /**
1963
+ * @description Machine-readable warning code. `truncated` means the markdown was cut to fit the requested `tokenBudget`. `short_content` means a successful browser capture of an HTML page produced very little readable text (under 100 characters), which usually means the page needed an interaction such as scrolling or clicking that the capture did not perform; a genuinely short page can raise it too. `frames_skipped` means a browser capture left out one or more iframes (cross-origin ones, which the capture cannot read, or same-origin ones that failed or were still loading), so content inside them may be missing from the returned HTML. `short_content` and `frames_skipped` are advisory: they never change the response status, error code or billed bytes.
1964
+ * @enum {string}
1965
+ */
1966
+ code: "lossy_table" | "complex_math" | "unsupported_element" | "extraction_fallback" | "truncated" | "query_no_match" | "mode_disabled_fallback" | "artifact_unavailable" | "llm_clean_unavailable" | "llm_clean_failed" | "low_quality_extraction" | "fragment_menu_stripped" | "extract_validation_failed" | "exhausted_retries" | "content_truncated" | "model_refusal" | "empty_extraction" | "short_content" | "frames_skipped";
1823
1967
  message: string;
1824
1968
  element: string | null;
1825
1969
  };
@@ -1844,6 +1988,19 @@ export interface components {
1844
1988
  links?: string[] | components["schemas"]["ScrapeScoredLink"][];
1845
1989
  /** @description Plain URL strings by default. When markdownIncludeMedia=true, an array of ScrapeScoredImage objects. */
1846
1990
  images?: string[] | components["schemas"]["ScrapeScoredImage"][];
1991
+ /**
1992
+ * @description The result of the request's `json` format entry. Present on every outcome of a
1993
+ * request that carried one. A failed extraction never fails the scrape: it sets
1994
+ * `validated` to `false` and adds an extraction warning code to `warnings`.
1995
+ */
1996
+ json?: {
1997
+ /** @description The extracted object, or `null` whenever `validated` is `false`. */
1998
+ data: Record<string, never> | null;
1999
+ /** @description Whether the extraction produced output matching the schema. The `json` credits are charged only when `true`. */
2000
+ validated: boolean;
2001
+ /** @description The extraction model that ran. */
2002
+ model: string;
2003
+ };
1847
2004
  };
1848
2005
  ScrapeMetadata: {
1849
2006
  title: string | null;
@@ -1955,6 +2112,8 @@ export interface components {
1955
2112
  * @description Compressed wire bytes transferred for this request — the basis for
1956
2113
  * bandwidth-billed plans. Reflects what crossed the network on your behalf
1957
2114
  * (e.g. gzip/brotli-compressed size), not the decompressed content length.
2115
+ * A page served by the hosted-browser tier reports the browser's full
2116
+ * measured transfer instead: every response it loaded plus the requests it sent.
1958
2117
  */
1959
2118
  content_length: number;
1960
2119
  status_code: number | null;
@@ -2026,9 +2185,11 @@ export interface components {
2026
2185
  id: string | null;
2027
2186
  error: {
2028
2187
  /** @enum {string} */
2029
- code: "validation_error" | "invalid_url" | "request_too_large" | "payload_too_large" | "unsupported_content_type" | "rate_limited" | "upstream_error" | "blocked" | "timeout" | "internal_error";
2188
+ code: "validation_error" | "invalid_url" | "request_too_large" | "payload_too_large" | "unsupported_content_type" | "rate_limited" | "upstream_error" | "blocked" | "target_rate_limited" | "timeout" | "internal_error";
2030
2189
  message: string;
2031
2190
  http_status?: number;
2191
+ /** @description Whole seconds the target site asked us to wait before the next request. Present only with `code: target_rate_limited`, only on the inline `POST /v1/scrape` failure the fast path decides, and only when the target sent a usable `Retry-After` (delta-seconds, or an HTTP-date still in the future, converted to seconds; values above 2147483647 are reported as 2147483647). Informational: ByteKit never enforces it on your next request. A held render (`delay_ms > 0`), `GET /v1/scrape/{id}` and webhooks omit it, because the value is relative to the moment the target answered. */
2192
+ retry_after_seconds?: number;
2032
2193
  /** Format: date-time */
2033
2194
  failed_at: string;
2034
2195
  };
@@ -2069,7 +2230,10 @@ export interface components {
2069
2230
  FetchRequest: {
2070
2231
  /** Format: uri */
2071
2232
  url: string;
2072
- /** @default US */
2233
+ /**
2234
+ * @description Two-letter country code. Either case is accepted; the value is upper-cased.
2235
+ * @default US
2236
+ */
2073
2237
  country: string;
2074
2238
  /** @default 60000 */
2075
2239
  timeout_ms: number;
@@ -2096,6 +2260,11 @@ export interface components {
2096
2260
  device: "desktop" | "mobile";
2097
2261
  /** @default null */
2098
2262
  viewport: components["schemas"]["Viewport"] | null;
2263
+ /**
2264
+ * @description When true, the request returns 202 immediately and the screenshot is captured in the background; poll `GET /v1/screenshots/{id}`. The `?async=true` query parameter is a second spelling of this field: the request is async when either one says true, and `false` in one never cancels `true` in the other.
2265
+ * @default false
2266
+ */
2267
+ async: boolean;
2099
2268
  /** @default false */
2100
2269
  full_page: boolean;
2101
2270
  /**
@@ -2432,9 +2601,26 @@ export interface components {
2432
2601
  captured_at: string;
2433
2602
  };
2434
2603
  SitemapRequest: {
2435
- /** Format: uri */
2604
+ /**
2605
+ * Format: uri
2606
+ * @description The site to discover. Sitemap discovery is host-scoped (`robots.txt`
2607
+ * and `/sitemap.xml` live at the host root), so only the scheme and host
2608
+ * are used: a path, query string or fragment is accepted but ignored,
2609
+ * and the `202` response carries a `warnings` entry saying so. A bare
2610
+ * host, or a host with just a trailing `/`, produces no warning.
2611
+ */
2436
2612
  url: string;
2437
2613
  /**
2614
+ * @description How much discovery work the job does.
2615
+ *
2616
+ * - `quick` — reads `robots.txt` and the XML sitemaps only. Every
2617
+ * result has `source: sitemap`.
2618
+ * - `standard` — the `quick` sources, then fills any remaining
2619
+ * `max_urls` budget with URLs from your account's completed scrapes of
2620
+ * the host in the last 90 days (`source: known`).
2621
+ * - `deep` — the `standard` sources, then crawls page links outward from
2622
+ * the URLs found so far, up to `max_depth` levels, until `max_urls` is
2623
+ * reached (`source: links`).
2438
2624
  * @default standard
2439
2625
  * @enum {string}
2440
2626
  */
@@ -2443,7 +2629,11 @@ export interface components {
2443
2629
  max_depth: number;
2444
2630
  /** @default 5000 */
2445
2631
  max_urls: number;
2446
- /** @default null */
2632
+ /**
2633
+ * @description Accepted, stored and echoed back on the job, but it has no effect: the
2634
+ * worker logs that the trigger is not implemented and ignores it.
2635
+ * @default null
2636
+ */
2447
2637
  process: {
2448
2638
  action?: string;
2449
2639
  options?: {
@@ -2472,6 +2662,17 @@ export interface components {
2472
2662
  SitemapResponse: {
2473
2663
  /** @example sm_01j9abc123 */
2474
2664
  id: string;
2665
+ /**
2666
+ * @description On the `202` creation response, the submitted URL after ByteKit has
2667
+ * normalised it, when that URL carried a path, query string or fragment
2668
+ * (discovery still ran on the host only; see `warnings`). Normalisation
2669
+ * lowercases the scheme and host, puts an international host in
2670
+ * punycode, percent-encodes non-ASCII characters and trims surrounding
2671
+ * spaces, so the value can differ from the string you sent. In every
2672
+ * other case (a bare-host request, `GET /v1/sitemap/{id}` and the
2673
+ * webhook `data` object) it is the host the job is scoped to, as
2674
+ * `scheme://host`.
2675
+ */
2475
2676
  url: string;
2476
2677
  strategy: string;
2477
2678
  max_depth: number;
@@ -2510,17 +2711,42 @@ export interface components {
2510
2711
  * for jobs that completed before the billing node was persisted.
2511
2712
  */
2512
2713
  billing?: components["schemas"]["BillingNode"];
2714
+ /**
2715
+ * @description On the `202` creation response, a single entry naming the path, query
2716
+ * string or fragment of the submitted `url` that host-scoped discovery
2717
+ * ignored. It never fails the request. It is not stored with the job:
2718
+ * `GET /v1/sitemap/{id}` and the webhook `data` object report the
2719
+ * worker's own warnings, or `null`.
2720
+ */
2513
2721
  warnings: string[] | null;
2722
+ /**
2723
+ * @description Why a `failed` job failed; `null` otherwise. One of the values below. It is typed as
2724
+ * a free string so that a code added later does not break a client.
2725
+ *
2726
+ * - `job_timeout` — the job ran past its time limit.
2727
+ * - `blocked` — the host sits behind a WAF that blocks every discovery
2728
+ * phase, so the job did not run.
2729
+ * - `no_urls_found` — discovery finished with no URLs for the host.
2730
+ * - `internal_error` — an unexpected error while discovering.
2731
+ * - `worker_crash` — the job sat in `processing` far past the recovery
2732
+ * threshold, so it was failed as a worker crash.
2733
+ */
2514
2734
  error_code: string | null;
2515
2735
  error_message: string | null;
2516
2736
  compact: boolean;
2737
+ /** @description The `process` value from the request, echoed back. It has no effect. */
2517
2738
  process: Record<string, never> | null;
2518
2739
  metadata: Record<string, never> | null;
2519
2740
  /** Format: date-time */
2520
2741
  created_at: string;
2521
2742
  /** Format: date-time */
2522
2743
  completed_at: string | null;
2523
- /** Format: date-time */
2744
+ /**
2745
+ * Format: date-time
2746
+ * @description When the job and its results expire: 90 days after the job completes. `null` until the
2747
+ * job completes, and on a failed job. A `cache: hit` response keeps the expiry of the job
2748
+ * that answered it.
2749
+ */
2524
2750
  expires_at: string | null;
2525
2751
  };
2526
2752
  WebhookDeliveryResponse: {
@@ -2531,7 +2757,7 @@ export interface components {
2531
2757
  * @example bulk.completed
2532
2758
  * @enum {string}
2533
2759
  */
2534
- event_type: "bulk.completed" | "scrape.completed" | "scrape.failed" | "monitor.change_detected" | "monitor.captured" | "sitemap.completed" | "sitemap.failed";
2760
+ event_type: "bulk.completed" | "scrape.completed" | "scrape.failed" | "monitor.change_detected" | "monitor.captured" | "monitor.suspended" | "sitemap.completed" | "sitemap.failed";
2535
2761
  target_url: string;
2536
2762
  /** @enum {string} */
2537
2763
  status: "pending" | "delivered" | "failed" | "exhausted";
@@ -2730,7 +2956,7 @@ export interface components {
2730
2956
  /** @description Whether the account admin wants an email when bandwidth reaches 100 % of the plan limit. */
2731
2957
  bandwidth_100_enabled: boolean;
2732
2958
  };
2733
- /** @description The Terms of Service version this account has accepted. An empty string means the account predates clickwrap acceptance (issue #1025). The dashboard diffs this against the published current version to decide whether to show the re-acceptance prompt. */
2959
+ /** @description The Terms of Service version the calling person has accepted. The record is per person, not per account: each member of an account accepts for themselves. An empty string means this person has never accepted the Terms; acceptance is recorded only by `POST /v1/account/accept-terms`, never by bootstrap (issues #5055, #5057). The dashboard diffs this against the published current version to decide whether to show the re-acceptance prompt. */
2734
2960
  terms_version: string;
2735
2961
  /** Format: date-time */
2736
2962
  created_at: string;
@@ -2738,6 +2964,8 @@ export interface components {
2738
2964
  has_activity: boolean;
2739
2965
  /** @description True once a member of the account left onboarding through one of its exits (POST /v1/account/complete-onboarding). Never reset. With `has_activity` it gates the dashboard: the app shows the guided onboarding flow until either one is true, so a user whose first request failed can still reach the dashboard. */
2740
2966
  onboarding_completed: boolean;
2967
+ /** @description True once the calling person left onboarding through one of its exits (POST /v1/account/complete-onboarding). Never reset. False sends this person through the guided onboarding flow even when the account itself is active or finished onboarding, so a teammate invited into an existing account still accepts the Terms and sees the API key once. */
2968
+ user_onboarding_completed: boolean;
2741
2969
  /** @description True when the account has a Stripe subscription, keyed on the same `stripe_subscription_id` column that GET /v1/billing/change-plan's `no_subscription` guard tests — so a client can use it to decide whether that endpoint will answer at all. Stays TRUE while a subscription is mid-cancellation (cancelled but running to the period end): the subscription still exists and a booked plan change is still revocable. It is a boolean, not the bearer path's `subscription` object: this response has no role-dependent fields, so a non-admin member receives it too, and plan pricing does not belong there. */
2742
2970
  has_subscription: boolean;
2743
2971
  };
@@ -2768,7 +2996,7 @@ export interface components {
2768
2996
  /** @description Whether the account admin wants an email when bandwidth reaches 100 % of the plan limit. */
2769
2997
  bandwidth_100_enabled: boolean;
2770
2998
  };
2771
- /** @description The Terms of Service version this account has accepted. An empty string means the account predates clickwrap acceptance (issue #1025). The dashboard diffs this against the published current version to decide whether to show the re-acceptance prompt. */
2999
+ /** @description The Terms of Service version the calling person has accepted. The record is per person, not per account: each member of an account accepts for themselves. An empty string means this person has never accepted the Terms; acceptance is recorded only by `POST /v1/account/accept-terms`, never by bootstrap (issues #5055, #5057). The dashboard diffs this against the published current version to decide whether to show the re-acceptance prompt. */
2772
3000
  terms_version: string;
2773
3001
  /** @description True when the account has a Stripe subscription, keyed on the same `stripe_subscription_id` column that GET /v1/billing/change-plan's `no_subscription` guard tests. */
2774
3002
  has_subscription: boolean;
@@ -2886,6 +3114,45 @@ export interface components {
2886
3114
  "application/json": components["schemas"]["Error"];
2887
3115
  };
2888
3116
  };
3117
+ /**
3118
+ * @description Unauthorized. The request carried no valid credential, and no work was
3119
+ * performed. The unified `Error` envelope carries one of the codes below
3120
+ * in `error.code`; match on the code, never on the prose.
3121
+ *
3122
+ * - `invalid_api_key` — a bearer API key was presented and rejected:
3123
+ * unknown, revoked, expired or malformed. The bearer-only operations
3124
+ * (`/v1/webhook-deliveries*` among them) also return it when no
3125
+ * `Authorization` header is sent. `GET /v1/account` is the exception
3126
+ * to "malformed": it returns `invalid_api_key` only for a key that
3127
+ * starts `sk_test_` or `sk_live_` and is unknown, revoked or expired.
3128
+ * - `unauthorized` — the `Authorization` header is absent or malformed on
3129
+ * an operation that also accepts a dashboard session (the dual-auth and
3130
+ * billing operations). `GET /v1/account` also returns it, for no
3131
+ * `Authorization` header and for any bearer value that does not start
3132
+ * `sk_test_` or `sk_live_` (that value is checked as a dashboard
3133
+ * session token).
3134
+ *
3135
+ * Not retryable as-is: supply a valid API key first.
3136
+ */
3137
+ Unauthorized: {
3138
+ headers: {
3139
+ [name: string]: unknown;
3140
+ };
3141
+ content: {
3142
+ /**
3143
+ * @example {
3144
+ * "status": "failed",
3145
+ * "error": {
3146
+ * "code": "invalid_api_key",
3147
+ * "message": "Missing or invalid API key.",
3148
+ * "http_status": 401,
3149
+ * "failed_at": "2026-01-15T12:00:00Z"
3150
+ * }
3151
+ * }
3152
+ */
3153
+ "application/json": components["schemas"]["Error"];
3154
+ };
3155
+ };
2889
3156
  };
2890
3157
  parameters: {
2891
3158
  /**
@@ -2905,7 +3172,16 @@ export interface components {
2905
3172
  */
2906
3173
  ClientSurfaceMarker: string;
2907
3174
  FetchUrl: string;
3175
+ /** @description Two-letter country code. Either case is accepted; the value is upper-cased. */
2908
3176
  FetchCountry: string;
3177
+ /**
3178
+ * @description A JSON-encoded object, URL-encoded in the query string. It is echoed back base64-encoded in
3179
+ * the `X-Fetch-Custom` response header so callers can correlate the response to caller-side
3180
+ * state. Capped at 4096 UTF-8 bytes after JSON serialization, and not part of the cache key.
3181
+ * A value that is not valid JSON answers `422 validation_error` ("custom must be a
3182
+ * JSON-encoded object"); valid JSON that is not an object is also rejected with `422`.
3183
+ */
3184
+ FetchCustom: string;
2909
3185
  FetchTimeoutMs: number;
2910
3186
  /** @description How long a freshly fetched URL may be served from cache. `0` skips the cache read; cache-eligible fresh results are still written with the default 7-day TTL so later non-zero-TTL callers can HIT. Safety-classified WAF husks remain live-only and are not written. Accepts `Nh` (hours, up to 168h), `Nd` (days, up to 7d), or the integer `0`. Examples: `0`, `48h`, `2d`. Invalid values receive a 422 validation_error with an actionable message. */
2911
3187
  FetchCacheTtl: string | 0;
@@ -2944,9 +3220,10 @@ export interface components {
2944
3220
  XFetchURL: string;
2945
3221
  /**
2946
3222
  * @description Byte length of the response body served on this request (integer as string) — NOT the
2947
- * billing basis. The body is always the upstream response bytes, so this equals the upstream wire byte
2948
- * count. Billing always reads the upstream compressed wire bytes from `X-Raw-Bytes` /
2949
- * `X-Billable-Bytes`, on every path.
3223
+ * billing basis. When `X-Fetch-Fast-Path` is `true` the body is the upstream response
3224
+ * bytes, so this equals the upstream wire byte count. When it is `false` the body is the
3225
+ * rendered page, and this is that page's compressed size. Billing always reads the
3226
+ * compressed wire bytes from `X-Raw-Bytes` / `X-Billable-Bytes`, on every path.
2950
3227
  */
2951
3228
  XFetchContentLength: string;
2952
3229
  XFetchCreditsCharged: string;
@@ -3037,6 +3314,7 @@ export interface operations {
3037
3314
  "application/json": components["schemas"]["AccountBearerResponse"] | components["schemas"]["AccountSessionResponse"];
3038
3315
  };
3039
3316
  };
3317
+ 401: components["responses"]["Unauthorized"];
3040
3318
  /** @description Rate limit exceeded (`rate_limited`). Only reachable when authenticated via Clerk session (the 60-request/60-second per-user window) — the bearer and in-process auth branches are not rate-limited at this endpoint. Carries a `Retry-After` header derived from the same clock as the window reset. */
3041
3319
  429: {
3042
3320
  headers: {
@@ -3389,6 +3667,7 @@ export interface operations {
3389
3667
  createScreenshot: {
3390
3668
  parameters: {
3391
3669
  query?: {
3670
+ /** @description Query-string spelling of the body `async` field. `true` returns the 202 immediately; any other value is ignored. */
3392
3671
  async?: boolean;
3393
3672
  };
3394
3673
  header?: never;
@@ -3494,7 +3773,25 @@ export interface operations {
3494
3773
  "application/json": components["schemas"]["Error"];
3495
3774
  };
3496
3775
  };
3776
+ 401: components["responses"]["Unauthorized"];
3497
3777
  402: components["responses"]["PaymentRequired"];
3778
+ /**
3779
+ * @description The target is on ByteKit's blocklist. Nothing is captured and nothing is billed.
3780
+ * The unified `Error` envelope carries one of two codes:
3781
+ *
3782
+ * - `host_forbidden` — a blocked domain, any `.gov` host, or a blocked port.
3783
+ * `details` is `{ host }`.
3784
+ * - `path_forbidden` — an authentication-style path such as a login page.
3785
+ * `details` is `{ path }`.
3786
+ */
3787
+ 403: {
3788
+ headers: {
3789
+ [name: string]: unknown;
3790
+ };
3791
+ content: {
3792
+ "application/json": components["schemas"]["Error"];
3793
+ };
3794
+ };
3498
3795
  /**
3499
3796
  * @description Validation error, or a screenshot that failed inside the sync hold.
3500
3797
  * The two carry DIFFERENT bodies (issue #2679):
@@ -3583,6 +3880,7 @@ export interface operations {
3583
3880
  "application/json": components["schemas"]["ScreenshotResponse"];
3584
3881
  };
3585
3882
  };
3883
+ 401: components["responses"]["Unauthorized"];
3586
3884
  /** @description Resource not found. */
3587
3885
  404: {
3588
3886
  headers: {
@@ -3596,7 +3894,10 @@ export interface operations {
3596
3894
  };
3597
3895
  createScrape: {
3598
3896
  parameters: {
3599
- query?: never;
3897
+ query?: {
3898
+ /** @description Query-string spelling of the body `async` field. `true` returns the 202 receipt immediately; any other value is ignored. Either spelling turns async on, and `false` in one never cancels `true` in the other. */
3899
+ async?: boolean;
3900
+ };
3600
3901
  header?: never;
3601
3902
  path?: never;
3602
3903
  cookie?: never;
@@ -3627,7 +3928,7 @@ export interface operations {
3627
3928
  };
3628
3929
  };
3629
3930
  responses: {
3630
- /** @description Scrape reached a terminal state and the body is that terminal envelope: `success` carrying content, or `failed` carrying the error envelope. Returned by the fast HTTP path in one round trip, and by a browser-path request without `async: true` once its render reaches a terminal state inside the hold window. A held render that ends in failure answers 200 with the same `failed` envelope `GET /v1/scrape/{id}` returns — narrow on `status` before reading the body. A definitive upstream outcome is a result, not a transport error: an unreachable host, a refused connection, or a target whose bot protection defeats every proxy tier all answer 200 with the `failed` envelope, never a 5xx. An inline failure is recorded as a failed job, so its envelope normally carries that job's `id` and polling it returns the same envelope; `id` is `null` only when recording the failed job itself failed. `error.http_status` is present only when a real upstream HTTP status is known. */
3931
+ /** @description Scrape reached a terminal state and the body is that terminal envelope: `success` carrying content, or `failed` carrying the error envelope. Returned by the fast HTTP path in one round trip, and by a browser-path request without `async: true` or `?async=true` once its render reaches a terminal state inside the hold window. A held render that ends in failure answers 200 with the same `failed` envelope `GET /v1/scrape/{id}` returns — narrow on `status` before reading the body. A definitive upstream outcome is a result, not a transport error: an unreachable host, a refused connection, or a target whose bot protection defeats every proxy tier all answer 200 with the `failed` envelope, never a 5xx. An inline failure is recorded as a failed job, so its envelope normally carries that job's `id` and polling it returns the same envelope; `id` is `null` only when recording the failed job itself failed. `error.http_status` is present only when a real upstream HTTP status is known. */
3631
3932
  200: {
3632
3933
  headers: {
3633
3934
  /** @description Stable scrape identifier (also present on the envelope as `id`). */
@@ -3650,7 +3951,7 @@ export interface operations {
3650
3951
  "X-Scrape-Status-Code"?: number;
3651
3952
  /** @description Compressed wire bytes — the basis for bandwidth billing. */
3652
3953
  "X-Scrape-Content-Length"?: number;
3653
- /** @description Uncompressed body byte count measured before any billing multiplication. */
3954
+ /** @description Compressed wire byte count of the body, measured before any billing multiplication. It is not the decompressed size. */
3654
3955
  "X-Raw-Bytes"?: number;
3655
3956
  /** @description Chargeable bytes after applying the billing multiplier. Equals round(X-Raw-Bytes × X-Billing-Multiplier). */
3656
3957
  "X-Billable-Bytes"?: number;
@@ -3678,9 +3979,9 @@ export interface operations {
3678
3979
  "X-Scrape-Markdown-URL"?: string;
3679
3980
  /** @description Byte length of the markdown artifact. Present only on fast-path responses when formats includes markdown. */
3680
3981
  "X-Scrape-Markdown-Length"?: number;
3681
- /** @description Legacy numeric form of the tier that served: 1 datacenter, 2 residential, 3 mobile. Omitted for the lean-browser tier, which has no numeric form. Deprecated — use X-Scrape-Proxy-Tier-Label. */
3982
+ /** @description Legacy numeric form of the tier that served: 1 datacenter, 2 residential, 3 mobile. Omitted for the lean-browser and hosted-browser tiers, which have no numeric form. Deprecated — use X-Scrape-Proxy-Tier-Label. */
3682
3983
  "X-Scrape-Proxy-Tier"?: number;
3683
- /** @description The proxy tier that actually served this request's fetch, after any escalation — never the tier first attempted. One of datacenter, residential, mobile, lean. Diagnostic only: it is never an input to routing, billing, caching or escalation. Present on sync fast-path responses. Omitted on a cache hit, which replayed stored bytes and ran no tier; and on responses the fast path did not serve. A third omission — a response replayed from stored bytes after this request's own cache lookup missed, which reports X-Scrape-Cache: miss and likewise ran no tier — exists only as an internal deploy-skew safeguard and is not reachable through this API. */
3984
+ /** @description The proxy tier that actually served this request's fetch, after any escalation — never the tier first attempted. One of datacenter, residential, mobile, lean, hosted_browser. Diagnostic only: it is never an input to routing, billing, caching or escalation. Present on sync fast-path responses. Omitted on a cache hit, which replayed stored bytes and ran no tier; and on responses the fast path did not serve. A third omission — a response replayed from stored bytes after this request's own cache lookup missed, which reports X-Scrape-Cache: miss and likewise ran no tier — exists only as an internal deploy-skew safeguard and is not reachable through this API. */
3684
3985
  "X-Scrape-Proxy-Tier-Label"?: string;
3685
3986
  /** @description WAF vendor detected on the target, if any (diagnostic). May be "suspected" when a low-confidence fail-open block marker was served. Omitted when no WAF is detected. */
3686
3987
  "X-Scrape-Waf"?: string;
@@ -3694,7 +3995,7 @@ export interface operations {
3694
3995
  "application/json": components["schemas"]["ScrapeSuccessEnvelope"] | components["schemas"]["ScrapeErrorEnvelope"];
3695
3996
  };
3696
3997
  };
3697
- /** @description Scrape accepted for background processing; the body is a receipt, not content. Returned when `async: true` was requested, or when a browser-path request's hold window expired before the render finished. Poll `GET /v1/scrape/{id}` for the result. */
3998
+ /** @description Scrape accepted for background processing; the body is a receipt, not content. Returned when `async: true` or `?async=true` was requested, or when a browser-path request's hold window expired before the render finished. Poll `GET /v1/scrape/{id}` for the result. */
3698
3999
  202: {
3699
4000
  headers: {
3700
4001
  /** @description Stable scrape identifier for the queued job. */
@@ -3730,8 +4031,12 @@ export interface operations {
3730
4031
  "application/json": components["schemas"]["Error"];
3731
4032
  };
3732
4033
  };
4034
+ 401: components["responses"]["Unauthorized"];
3733
4035
  402: components["responses"]["PaymentRequired"];
3734
- /** @description Validation error. */
4036
+ /**
4037
+ * @description Validation error. A `json` format entry whose `schema` the extractor cannot take is
4038
+ * refused with `schema_incompatible`, before anything is drawn.
4039
+ */
3735
4040
  422: {
3736
4041
  headers: {
3737
4042
  [name: string]: unknown;
@@ -3758,6 +4063,19 @@ export interface operations {
3758
4063
  "application/json": components["schemas"]["Error"];
3759
4064
  };
3760
4065
  };
4066
+ /**
4067
+ * @description The request carried a `json` format entry and JSON extraction is unavailable on this
4068
+ * deployment (`provider_unavailable`). It is refused before anything is drawn. A
4069
+ * terminal upstream failure is never a `503`: it is a `200` result, described above.
4070
+ */
4071
+ 503: {
4072
+ headers: {
4073
+ [name: string]: unknown;
4074
+ };
4075
+ content: {
4076
+ "application/json": components["schemas"]["Error"];
4077
+ };
4078
+ };
3761
4079
  };
3762
4080
  };
3763
4081
  getScrape: {
@@ -3774,12 +4092,47 @@ export interface operations {
3774
4092
  /** @description Scrape state (queued, success, or failed). */
3775
4093
  200: {
3776
4094
  headers: {
4095
+ /** @description Stable scrape identifier (also present on the envelope as `id`). Present on a completed or failed scrape; absent while it is still queued or processing. */
4096
+ "X-Scrape-ID"?: string;
4097
+ /** @description Envelope status discriminator, mirrored as a header for streaming consumers. Present on a completed or failed scrape; absent while it is still queued or processing. */
4098
+ "X-Scrape-Status"?: "success" | "failed" | "queued";
4099
+ /** @description The originally requested URL, before any redirects. Present on a completed or failed scrape; absent while it is still queued or processing. */
4100
+ "X-Scrape-URL"?: string;
4101
+ /** @description Content-Type of the scraped response body. Present on a completed or failed scrape; absent while it is still queued or processing. */
4102
+ "X-Scrape-Content-Type"?: string;
4103
+ /** @description Compressed wire bytes — the basis for bandwidth billing. Present on a completed or failed scrape; absent while it is still queued or processing. */
4104
+ "X-Scrape-Content-Length"?: number;
4105
+ /** @description Credits charged for this scrape (multiplier applied to base 1.0 per format). Present on a completed or failed scrape; absent while it is still queued or processing. */
4106
+ "X-Scrape-Credits-Charged"?: number;
4107
+ /** @description Handler elapsed time in milliseconds. X-Scrape-Elapsed-Ms emits the same value on gateway slow-path responses. Present on a completed or failed scrape; absent while it is still queued or processing. */
4108
+ "X-Scrape-Duration-Ms"?: number;
4109
+ /** @description End-to-end elapsed time in milliseconds. Alias for X-Scrape-Duration-Ms; both are emitted on gateway slow-path responses. Present on a completed or failed scrape; absent while it is still queued or processing. */
4110
+ "X-Scrape-Elapsed-Ms"?: number;
4111
+ /** @description Timestamp when the scrape row was created. Present on a completed or failed scrape; absent while it is still queued or processing. */
4112
+ "X-Scrape-Created-At"?: string;
4113
+ /** @description Timestamp when the scrape completed. Omitted if not yet completed. Present on a completed or failed scrape whose row records a completion time; absent while it is still queued or processing. */
4114
+ "X-Scrape-Completed-At"?: string;
4115
+ /** @description Expiry timestamp for the scrape artifact. Omitted if no retention applies. Present on a completed or failed scrape whose row records an expiry; absent while it is still queued or processing. */
4116
+ "X-Scrape-Expires-At"?: string;
4117
+ /** @description The URL after following redirects. Present on a completed or failed scrape whose row records a final URL; absent while it is still queued or processing. */
4118
+ "X-Scrape-Final-URL"?: string;
4119
+ /** @description HTTP status code returned by the target site. Present on a completed or failed scrape whose row records a target status code; absent while it is still queued or processing. */
4120
+ "X-Scrape-Status-Code"?: number;
4121
+ /** @description Cache outcome — `hit` = served from cache, `miss` = freshly fetched, `bypass` = `cache_ttl=0` requested. On GET present only on a failed scrape whose stored cache disposition is hit, miss or bypass; a completed scrape does not carry it, nor does a queued or processing one. */
4122
+ "X-Scrape-Cache"?: "hit" | "miss" | "bypass";
4123
+ /** @description Compressed wire byte count of the body, measured before any billing multiplication. It is not the decompressed size. Present on a completed or failed scrape; absent while it is still queued or processing. */
4124
+ "X-Raw-Bytes"?: number;
4125
+ /** @description Chargeable bytes after applying the billing multiplier. Equals round(X-Raw-Bytes × X-Billing-Multiplier). Present on a completed or failed scrape; absent while it is still queued or processing. */
4126
+ "X-Billable-Bytes"?: number;
4127
+ /** @description Bandwidth cost multiplier (e.g. 1.0 for a `raw`-only scrape, 1.5 when `markdown` is also requested). Cache hits compose the endpoint format factor, which is a separate number from this one: 0.5 for an unprocessed-source scrape, 0.75 with markdown. Excludes the `clean_markdown` surcharge: when `clean_markdown: true` and the clean succeeded, the settled usage is 3× this header's value, so this header does not predict the amount you are billed. The response body's `billing` node is the authoritative surface — it DOES carry the `clean_markdown` factor, so its `multiplier` and `billed_bytes` are what you are charged. Where the two disagree, the node is correct. Present on a completed or failed scrape; absent while it is still queued or processing. */
4128
+ "X-Billing-Multiplier"?: number;
3777
4129
  [name: string]: unknown;
3778
4130
  };
3779
4131
  content: {
3780
4132
  "application/json": components["schemas"]["ScrapeEnvelope"];
3781
4133
  };
3782
4134
  };
4135
+ 401: components["responses"]["Unauthorized"];
3783
4136
  /** @description Resource not found. */
3784
4137
  404: {
3785
4138
  headers: {
@@ -3970,7 +4323,38 @@ export interface operations {
3970
4323
  "application/json": components["schemas"]["Error"];
3971
4324
  };
3972
4325
  };
4326
+ 401: components["responses"]["Unauthorized"];
3973
4327
  402: components["responses"]["PaymentRequired"];
4328
+ /**
4329
+ * @description One or more URLs in the request are on ByteKit's blocklist. The whole request is
4330
+ * rejected before anything is queued or billed. This body is NOT the unified `Error`
4331
+ * envelope: it carries no `status`, `http_status` or `failed_at`. `blocked` lists every
4332
+ * offending URL with the rule that matched (`domain`, `tld`, `port` or `path`) and the
4333
+ * code that rule maps to (`host_forbidden` for the first three, `path_forbidden` for
4334
+ * `path`).
4335
+ */
4336
+ 403: {
4337
+ headers: {
4338
+ [name: string]: unknown;
4339
+ };
4340
+ content: {
4341
+ "application/json": {
4342
+ error: {
4343
+ /** @enum {string} */
4344
+ code: "url_forbidden";
4345
+ /** @example One or more URLs in this bulk request are blocked. */
4346
+ message: string;
4347
+ };
4348
+ blocked: {
4349
+ url: string;
4350
+ /** @enum {string} */
4351
+ rule_type: "domain" | "tld" | "port" | "path";
4352
+ /** @enum {string} */
4353
+ error_code: "host_forbidden" | "path_forbidden";
4354
+ }[];
4355
+ };
4356
+ };
4357
+ };
3974
4358
  /**
3975
4359
  * @description Validation error. `bulk_too_large` is returned when the item count
3976
4360
  * exceeds the account plan's `max_bulk_size` cap (also surfaced as
@@ -4092,6 +4476,7 @@ export interface operations {
4092
4476
  };
4093
4477
  };
4094
4478
  };
4479
+ 401: components["responses"]["Unauthorized"];
4095
4480
  /** @description Resource not found. */
4096
4481
  404: {
4097
4482
  headers: {
@@ -4107,10 +4492,19 @@ export interface operations {
4107
4492
  parameters: {
4108
4493
  query: {
4109
4494
  url: components["parameters"]["FetchUrl"];
4495
+ /** @description Two-letter country code. Either case is accepted; the value is upper-cased. */
4110
4496
  country?: components["parameters"]["FetchCountry"];
4111
4497
  timeout_ms?: components["parameters"]["FetchTimeoutMs"];
4112
4498
  /** @description How long a freshly fetched URL may be served from cache. `0` skips the cache read; cache-eligible fresh results are still written with the default 7-day TTL so later non-zero-TTL callers can HIT. Safety-classified WAF husks remain live-only and are not written. Accepts `Nh` (hours, up to 168h), `Nd` (days, up to 7d), or the integer `0`. Examples: `0`, `48h`, `2d`. Invalid values receive a 422 validation_error with an actionable message. */
4113
4499
  cache_ttl?: components["parameters"]["FetchCacheTtl"];
4500
+ /**
4501
+ * @description A JSON-encoded object, URL-encoded in the query string. It is echoed back base64-encoded in
4502
+ * the `X-Fetch-Custom` response header so callers can correlate the response to caller-side
4503
+ * state. Capped at 4096 UTF-8 bytes after JSON serialization, and not part of the cache key.
4504
+ * A value that is not valid JSON answers `422 validation_error` ("custom must be a
4505
+ * JSON-encoded object"); valid JSON that is not an object is also rejected with `422`.
4506
+ */
4507
+ custom?: components["parameters"]["FetchCustom"];
4114
4508
  };
4115
4509
  header?: never;
4116
4510
  path?: never;
@@ -4136,7 +4530,7 @@ export interface operations {
4136
4530
  "X-Fetch-Waf-Vendor": components["headers"]["XFetchWafVendor"];
4137
4531
  "X-Fetch-Content-Type": components["headers"]["XFetchContentType"];
4138
4532
  "X-Fetch-Custom": components["headers"]["XFetchCustom"];
4139
- /** @description Uncompressed body byte count measured before any billing multiplication. */
4533
+ /** @description Compressed wire byte count of the body, measured before any billing multiplication. It is not the decompressed size. */
4140
4534
  "X-Raw-Bytes"?: number;
4141
4535
  /** @description Chargeable bytes after applying the billing multiplier. Equals round(X-Raw-Bytes × X-Billing-Multiplier). */
4142
4536
  "X-Billable-Bytes"?: number;
@@ -4163,6 +4557,7 @@ export interface operations {
4163
4557
  "application/json": components["schemas"]["Error"];
4164
4558
  };
4165
4559
  };
4560
+ 401: components["responses"]["Unauthorized"];
4166
4561
  402: components["responses"]["PaymentRequired"];
4167
4562
  /**
4168
4563
  * @description Validation error (e.g. slow-path-only field), or a fetch that failed for a
@@ -4177,9 +4572,10 @@ export interface operations {
4177
4572
  * failure, such as a host that does not resolve. This is a result about the URL,
4178
4573
  * not an outage of this API, so it is a `4xx` rather than `502` or `503`. No
4179
4574
  * upstream HTTP status was received, so `error.http_status` reports `422`,
4180
- * mirroring what was served — unlike the relayed `upstream_error` under `502`
4181
- * below, whose status is the target's own. The request transfers no billable
4182
- * bytes and is charged nothing (#4669).
4575
+ * mirroring what was served — unlike the relayed `upstream_error` under `503`
4576
+ * below, whose `error.http_status` is the target's own. A target `502` or `504`
4577
+ * ends here too whenever it does not meet the condition for `503` below. The
4578
+ * request transfers no billable bytes and is charged nothing (#4669).
4183
4579
  */
4184
4580
  422: {
4185
4581
  headers: {
@@ -4209,7 +4605,12 @@ export interface operations {
4209
4605
  * `error.http_status` reports. Read `error.code` to tell them apart.
4210
4606
  *
4211
4607
  * - **`upstream_error`** — the target returned HTTP `502` or `504`, relayed here as
4212
- * `503`. Cloudflare fronts this API and replaces a clean origin 502 or 504 with its
4608
+ * `503`. This happens only when the escalation ladder ended on that answer, or when a
4609
+ * cached copy of it is served. A `502` or `504` is not terminal, so ByteKit first
4610
+ * retries it through its proxy tiers and the browser fallback; if the ladder ends any
4611
+ * other way, or a bot-protection vendor was seen on the way, the request answers
4612
+ * `422` (`upstream_error` or `blocked`) instead.
4613
+ * Cloudflare fronts this API and replaces a clean origin 502 or 504 with its
4213
4614
  * own generic `text/plain` error page, discarding the envelope before it reaches
4214
4615
  * you, while a 503 is passed through unchanged. The body's `error.http_status`
4215
4616
  * still reports the **true upstream status**, `502` or `504` — not `503` — and is
@@ -4271,7 +4672,7 @@ export interface operations {
4271
4672
  "X-Fetch-Waf-Vendor": components["headers"]["XFetchWafVendor"];
4272
4673
  "X-Fetch-Content-Type": components["headers"]["XFetchContentType"];
4273
4674
  "X-Fetch-Custom": components["headers"]["XFetchCustom"];
4274
- /** @description Uncompressed body byte count measured before any billing multiplication. */
4675
+ /** @description Compressed wire byte count of the body, measured before any billing multiplication. It is not the decompressed size. */
4275
4676
  "X-Raw-Bytes"?: number;
4276
4677
  /** @description Chargeable bytes after applying the billing multiplier. Equals round(X-Raw-Bytes × X-Billing-Multiplier). */
4277
4678
  "X-Billable-Bytes"?: number;
@@ -4298,6 +4699,7 @@ export interface operations {
4298
4699
  "application/json": components["schemas"]["Error"];
4299
4700
  };
4300
4701
  };
4702
+ 401: components["responses"]["Unauthorized"];
4301
4703
  402: components["responses"]["PaymentRequired"];
4302
4704
  /**
4303
4705
  * @description Validation error (e.g. malformed JSON, unsupported fetch format, or slow-path-only
@@ -4312,9 +4714,10 @@ export interface operations {
4312
4714
  * failure, such as a host that does not resolve. This is a result about the URL,
4313
4715
  * not an outage of this API, so it is a `4xx` rather than `502` or `503`. No
4314
4716
  * upstream HTTP status was received, so `error.http_status` reports `422`,
4315
- * mirroring what was served — unlike the relayed `upstream_error` under `502`
4316
- * below, whose status is the target's own. The request transfers no billable
4317
- * bytes and is charged nothing (#4669).
4717
+ * mirroring what was served — unlike the relayed `upstream_error` under `503`
4718
+ * below, whose `error.http_status` is the target's own. A target `502` or `504`
4719
+ * ends here too whenever it does not meet the condition for `503` below. The
4720
+ * request transfers no billable bytes and is charged nothing (#4669).
4318
4721
  */
4319
4722
  422: {
4320
4723
  headers: {
@@ -4344,7 +4747,12 @@ export interface operations {
4344
4747
  * `error.http_status` reports. Read `error.code` to tell them apart.
4345
4748
  *
4346
4749
  * - **`upstream_error`** — the target returned HTTP `502` or `504`, relayed here as
4347
- * `503`. Cloudflare fronts this API and replaces a clean origin 502 or 504 with its
4750
+ * `503`. This happens only when the escalation ladder ended on that answer, or when a
4751
+ * cached copy of it is served. A `502` or `504` is not terminal, so ByteKit first
4752
+ * retries it through its proxy tiers and the browser fallback; if the ladder ends any
4753
+ * other way, or a bot-protection vendor was seen on the way, the request answers
4754
+ * `422` (`upstream_error` or `blocked`) instead.
4755
+ * Cloudflare fronts this API and replaces a clean origin 502 or 504 with its
4348
4756
  * own generic `text/plain` error page, discarding the envelope before it reaches
4349
4757
  * you, while a 503 is passed through unchanged. The body's `error.http_status`
4350
4758
  * still reports the **true upstream status**, `502` or `504` — not `503` — and is
@@ -4459,7 +4867,38 @@ export interface operations {
4459
4867
  "application/json": components["schemas"]["Error"];
4460
4868
  };
4461
4869
  };
4870
+ 401: components["responses"]["Unauthorized"];
4462
4871
  402: components["responses"]["PaymentRequired"];
4872
+ /**
4873
+ * @description One or more URLs in the request are on ByteKit's blocklist. The whole request is
4874
+ * rejected before anything is queued or billed. This body is NOT the unified `Error`
4875
+ * envelope: it carries no `status`, `http_status` or `failed_at`. `blocked` lists every
4876
+ * offending URL with the rule that matched (`domain`, `tld`, `port` or `path`) and the
4877
+ * code that rule maps to (`host_forbidden` for the first three, `path_forbidden` for
4878
+ * `path`).
4879
+ */
4880
+ 403: {
4881
+ headers: {
4882
+ [name: string]: unknown;
4883
+ };
4884
+ content: {
4885
+ "application/json": {
4886
+ error: {
4887
+ /** @enum {string} */
4888
+ code: "url_forbidden";
4889
+ /** @example One or more URLs in this bulk request are blocked. */
4890
+ message: string;
4891
+ };
4892
+ blocked: {
4893
+ url: string;
4894
+ /** @enum {string} */
4895
+ rule_type: "domain" | "tld" | "port" | "path";
4896
+ /** @enum {string} */
4897
+ error_code: "host_forbidden" | "path_forbidden";
4898
+ }[];
4899
+ };
4900
+ };
4901
+ };
4463
4902
  /**
4464
4903
  * @description Validation error. `bulk_too_large` is returned when the item count
4465
4904
  * exceeds the account plan's `max_bulk_size` cap (also surfaced as
@@ -4677,6 +5116,7 @@ export interface operations {
4677
5116
  };
4678
5117
  };
4679
5118
  };
5119
+ 401: components["responses"]["Unauthorized"];
4680
5120
  /** @description Resource not found. */
4681
5121
  404: {
4682
5122
  headers: {
@@ -4738,6 +5178,7 @@ export interface operations {
4738
5178
  };
4739
5179
  };
4740
5180
  };
5181
+ 401: components["responses"]["Unauthorized"];
4741
5182
  /** @description Validation error. Returned when `status` is not one of the documented values, or when `cursor` is not a cursor this endpoint issued. */
4742
5183
  422: {
4743
5184
  headers: {
@@ -4973,7 +5414,38 @@ export interface operations {
4973
5414
  "application/json": components["schemas"]["Error"];
4974
5415
  };
4975
5416
  };
5417
+ 401: components["responses"]["Unauthorized"];
4976
5418
  402: components["responses"]["PaymentRequired"];
5419
+ /**
5420
+ * @description One or more URLs in the request are on ByteKit's blocklist. The whole request is
5421
+ * rejected before anything is queued or billed. This body is NOT the unified `Error`
5422
+ * envelope: it carries no `status`, `http_status` or `failed_at`. `blocked` lists every
5423
+ * offending URL with the rule that matched (`domain`, `tld`, `port` or `path`) and the
5424
+ * code that rule maps to (`host_forbidden` for the first three, `path_forbidden` for
5425
+ * `path`).
5426
+ */
5427
+ 403: {
5428
+ headers: {
5429
+ [name: string]: unknown;
5430
+ };
5431
+ content: {
5432
+ "application/json": {
5433
+ error: {
5434
+ /** @enum {string} */
5435
+ code: "url_forbidden";
5436
+ /** @example One or more URLs in this bulk request are blocked. */
5437
+ message: string;
5438
+ };
5439
+ blocked: {
5440
+ url: string;
5441
+ /** @enum {string} */
5442
+ rule_type: "domain" | "tld" | "port" | "path";
5443
+ /** @enum {string} */
5444
+ error_code: "host_forbidden" | "path_forbidden";
5445
+ }[];
5446
+ };
5447
+ };
5448
+ };
4977
5449
  /**
4978
5450
  * @description Validation error. `bulk_too_large` is returned when the item count
4979
5451
  * exceeds the account plan's `max_bulk_size` cap (also surfaced as
@@ -5079,6 +5551,7 @@ export interface operations {
5079
5551
  };
5080
5552
  };
5081
5553
  };
5554
+ 401: components["responses"]["Unauthorized"];
5082
5555
  /** @description Resource not found. */
5083
5556
  404: {
5084
5557
  headers: {
@@ -5133,6 +5606,7 @@ export interface operations {
5133
5606
  };
5134
5607
  };
5135
5608
  };
5609
+ 401: components["responses"]["Unauthorized"];
5136
5610
  /** @description Resource not found. */
5137
5611
  404: {
5138
5612
  headers: {
@@ -5254,6 +5728,7 @@ export interface operations {
5254
5728
  };
5255
5729
  };
5256
5730
  };
5731
+ 401: components["responses"]["Unauthorized"];
5257
5732
  };
5258
5733
  };
5259
5734
  listMonitors: {
@@ -5283,6 +5758,7 @@ export interface operations {
5283
5758
  };
5284
5759
  };
5285
5760
  };
5761
+ 401: components["responses"]["Unauthorized"];
5286
5762
  };
5287
5763
  };
5288
5764
  createMonitor: {
@@ -5327,6 +5803,7 @@ export interface operations {
5327
5803
  "application/json": components["schemas"]["Error"];
5328
5804
  };
5329
5805
  };
5806
+ 401: components["responses"]["Unauthorized"];
5330
5807
  /** @description Duplicate monitor for this URL. */
5331
5808
  409: {
5332
5809
  headers: {
@@ -5367,6 +5844,7 @@ export interface operations {
5367
5844
  "application/json": components["schemas"]["MonitorResponse"];
5368
5845
  };
5369
5846
  };
5847
+ 401: components["responses"]["Unauthorized"];
5370
5848
  /** @description Resource not found. */
5371
5849
  404: {
5372
5850
  headers: {
@@ -5396,6 +5874,7 @@ export interface operations {
5396
5874
  };
5397
5875
  content?: never;
5398
5876
  };
5877
+ 401: components["responses"]["Unauthorized"];
5399
5878
  /** @description Resource not found. */
5400
5879
  404: {
5401
5880
  headers: {
@@ -5451,6 +5930,7 @@ export interface operations {
5451
5930
  "application/json": components["schemas"]["Error"];
5452
5931
  };
5453
5932
  };
5933
+ 401: components["responses"]["Unauthorized"];
5454
5934
  /** @description Resource not found. */
5455
5935
  404: {
5456
5936
  headers: {
@@ -5508,6 +5988,7 @@ export interface operations {
5508
5988
  };
5509
5989
  };
5510
5990
  };
5991
+ 401: components["responses"]["Unauthorized"];
5511
5992
  };
5512
5993
  };
5513
5994
  createSitemap: {
@@ -5551,7 +6032,25 @@ export interface operations {
5551
6032
  "application/json": components["schemas"]["Error"];
5552
6033
  };
5553
6034
  };
6035
+ 401: components["responses"]["Unauthorized"];
5554
6036
  402: components["responses"]["PaymentRequired"];
6037
+ /**
6038
+ * @description The target is on ByteKit's blocklist. Nothing is queued and nothing is billed.
6039
+ * The unified `Error` envelope carries one of two codes:
6040
+ *
6041
+ * - `host_forbidden` — a blocked domain, any `.gov` host, or a blocked port.
6042
+ * `details` is `{ host }`.
6043
+ * - `path_forbidden` — an authentication-style path such as a login page.
6044
+ * `details` is `{ path }`.
6045
+ */
6046
+ 403: {
6047
+ headers: {
6048
+ [name: string]: unknown;
6049
+ };
6050
+ content: {
6051
+ "application/json": components["schemas"]["Error"];
6052
+ };
6053
+ };
5555
6054
  /** @description Validation error. */
5556
6055
  422: {
5557
6056
  headers: {
@@ -5600,6 +6099,7 @@ export interface operations {
5600
6099
  "application/json": components["schemas"]["SitemapResponse"];
5601
6100
  };
5602
6101
  };
6102
+ 401: components["responses"]["Unauthorized"];
5603
6103
  /** @description Resource not found. */
5604
6104
  404: {
5605
6105
  headers: {
@@ -5639,7 +6139,7 @@ export interface operations {
5639
6139
  * }
5640
6140
  */
5641
6141
  "application/json": {
5642
- /** @description The search query. */
6142
+ /** @description The search query, up to 2048 characters. */
5643
6143
  query: string;
5644
6144
  /**
5645
6145
  * @description Which search index to query. `web` (default) returns ranked organic results; `news` returns news articles in the same `results` array, additionally populating `source` and `image` on each item; `images` returns image results, populating `source`, `domain`, and a fuller `image` object (full-image dimensions plus a thumbnail URL and dimensions) while omitting `snippet` and `date`. Billing is identical for all three.
@@ -5756,6 +6256,7 @@ export interface operations {
5756
6256
  "application/json": components["schemas"]["Error"];
5757
6257
  };
5758
6258
  };
6259
+ 401: components["responses"]["Unauthorized"];
5759
6260
  402: components["responses"]["PaymentRequired"];
5760
6261
  /** @description Rate limit exceeded (`rate_limited`). Carries the `X-RateLimit-Limit`/`X-RateLimit-Remaining`/`X-RateLimit-Reset` triplet and a `Retry-After` header. The window is per-second for a bearer API key, or the 60-request/60-second Clerk session window when authenticated via `resolveDualAuth` — `Retry-After` reflects whichever window applies to the request. */
5761
6262
  429: {
@@ -5780,25 +6281,28 @@ export interface operations {
5780
6281
  };
5781
6282
  };
5782
6283
  /**
5783
- * @description Upstream search provider error, answered at `503` rather than `502` because
5784
- * Cloudflare replaces an origin 502 body with its own page (#4891). The body is a fixed,
5785
- * vendor-masked shape — deliberately NOT the unified `Error`
5786
- * envelope. The upstream provider's identity and message are
5787
- * never surfaced, so the response carries only the constant
5788
- * `error` code `search_provider_error`.
6284
+ * @description Two different bodies travel under this status. Tell them apart by the
6285
+ * type of the top-level `error` key: a string is the first, an object
6286
+ * is the second.
6287
+ *
6288
+ * - **Upstream search provider error**, answered at `503` rather than
6289
+ * `502` because Cloudflare replaces an origin 502 body with its own
6290
+ * page (#4891). The body is a fixed, vendor-masked shape —
6291
+ * deliberately NOT the unified `Error` envelope. The upstream
6292
+ * provider's identity and message are never surfaced, so the
6293
+ * response carries only the constant `error` code
6294
+ * `search_provider_error`.
6295
+ * - **Billing entitlement unavailable** (`billing_entitlement_missing`),
6296
+ * raised before any search runs, when the account has a Stripe
6297
+ * subscription but its plan could not be resolved. This one is the
6298
+ * unified `Error` envelope. No search is run and nothing is charged.
5789
6299
  */
5790
6300
  503: {
5791
6301
  headers: {
5792
6302
  [name: string]: unknown;
5793
6303
  };
5794
6304
  content: {
5795
- "application/json": {
5796
- /**
5797
- * @description Fixed vendor-masked error code. Always `search_provider_error`; the upstream provider's identity and failure detail are withheld by design.
5798
- * @enum {string}
5799
- */
5800
- error: "search_provider_error";
5801
- };
6305
+ "application/json": components["schemas"]["CreateSearchResponse503"] | components["schemas"]["Error"];
5802
6306
  };
5803
6307
  };
5804
6308
  };
@@ -5836,7 +6340,7 @@ export interface operations {
5836
6340
  * @description Target page URL (HTTP/HTTPS, SSRF-blocked, fast-path only).
5837
6341
  */
5838
6342
  url: string;
5839
- /** @description JSON Schema (draft 2020-12) describing the desired output. Serialized size ≤ 50 KB, nesting depth ≤ 8, must compile under Ajv, and must be normalizable into Groq's strict-mode subset (root `type: object`; no `pattern`/`format`/`if`/`then`/`else`/ top-level `oneOf`/`anyOf`; `$ref` limited to `#/$defs`). A non-normalizable schema returns `422 schema_incompatible`. */
6343
+ /** @description JSON Schema (draft 2020-12) describing the desired output. Serialized size ≤ 50 KB, nesting depth ≤ 8, must compile under Ajv, and must be normalizable into Groq's strict-mode subset: root `type: object`, and only an allowlist of keywords at any depth — `type`, `properties`, `required`, `additionalProperties`, `items`, `enum`, `$defs`, `$ref`, `description`, `title` and `default` (`$ref` limited to `#/$defs`). Every other keyword, such as `pattern`, `format`, `minimum`, `maxLength`, `const`, `oneOf`, `anyOf`, `allOf` or `if`/`then`/`else`, returns `422 schema_incompatible`. */
5840
6344
  schema: Record<string, never>;
5841
6345
  /** @description Optional natural-language extraction hint. */
5842
6346
  prompt?: string;
@@ -5860,7 +6364,10 @@ export interface operations {
5860
6364
  * @default US
5861
6365
  */
5862
6366
  country?: string | null;
5863
- /** @default null */
6367
+ /**
6368
+ * @description Accepted and forwarded to the extraction service, which does not read it: it currently has no effect.
6369
+ * @default null
6370
+ */
5864
6371
  language?: string | null;
5865
6372
  };
5866
6373
  };
@@ -5893,7 +6400,7 @@ export interface operations {
5893
6400
  status_code: number | null;
5894
6401
  /** @description Upstream wire bytes — the bandwidth billing basis. */
5895
6402
  content_length: number;
5896
- /** @description True when markdown exceeded the LLM token budget and was tail-truncated. */
6403
+ /** @description True when the page sent to the LLM, the structured metadata (JSON-LD and meta tags) plus the markdown, exceeded the token budget and was cut to fit. */
5897
6404
  truncated: boolean;
5898
6405
  };
5899
6406
  /** @description Additive warning codes, e.g. `content_truncated`, `extract_validation_failed`, `exhausted_retries`, `model_refusal`, `empty_extraction`. */
@@ -5910,18 +6417,15 @@ export interface operations {
5910
6417
  "application/json": components["schemas"]["Error"];
5911
6418
  };
5912
6419
  };
5913
- /** @description Missing or invalid bearer key. */
5914
- 401: {
5915
- headers: {
5916
- [name: string]: unknown;
5917
- };
5918
- content: {
5919
- "application/json": components["schemas"]["Error"];
5920
- };
5921
- };
6420
+ 401: components["responses"]["Unauthorized"];
5922
6421
  402: components["responses"]["PaymentRequired"];
5923
- /** @description Endpoint not available (feature flag disabled). */
5924
- 404: {
6422
+ /**
6423
+ * @description Validation error (`validation_error`), non-normalizable schema (`schema_incompatible`),
6424
+ * or the fetched page's HTML could not be converted for extraction — over the size cap or
6425
+ * past the conversion deadline (`content_too_large`). On `content_too_large` the page's
6426
+ * bandwidth is billed and the credits are refunded.
6427
+ */
6428
+ 422: {
5925
6429
  headers: {
5926
6430
  [name: string]: unknown;
5927
6431
  };
@@ -5929,8 +6433,8 @@ export interface operations {
5929
6433
  "application/json": components["schemas"]["Error"];
5930
6434
  };
5931
6435
  };
5932
- /** @description Validation error (`validation_error`) or non-normalizable schema (`schema_incompatible`). */
5933
- 422: {
6436
+ /** @description Per-account rate limit (`rate_limited`) or upstream provider rate limit (`provider_rate_limited`); a `Retry-After` header may be present. */
6437
+ 429: {
5934
6438
  headers: {
5935
6439
  [name: string]: unknown;
5936
6440
  };
@@ -5938,8 +6442,11 @@ export interface operations {
5938
6442
  "application/json": components["schemas"]["Error"];
5939
6443
  };
5940
6444
  };
5941
- /** @description Per-account rate limit (`rate_limited`) or upstream provider rate limit (`provider_rate_limited`); a `Retry-After` header may be present. */
5942
- 429: {
6445
+ /**
6446
+ * @description Internal error (`internal_error`): the request could not be recorded, or its
6447
+ * bandwidth charge could not be reserved. The credits held for it are refunded.
6448
+ */
6449
+ 500: {
5943
6450
  headers: {
5944
6451
  [name: string]: unknown;
5945
6452
  };
@@ -6041,6 +6548,7 @@ export interface operations {
6041
6548
  };
6042
6549
  };
6043
6550
  };
6551
+ 401: components["responses"]["Unauthorized"];
6044
6552
  };
6045
6553
  };
6046
6554
  getUsageDaily: {
@@ -6109,6 +6617,7 @@ export interface operations {
6109
6617
  };
6110
6618
  };
6111
6619
  };
6620
+ 401: components["responses"]["Unauthorized"];
6112
6621
  };
6113
6622
  };
6114
6623
  getUsageByEndpoint: {
@@ -6156,6 +6665,7 @@ export interface operations {
6156
6665
  };
6157
6666
  };
6158
6667
  };
6668
+ 401: components["responses"]["Unauthorized"];
6159
6669
  };
6160
6670
  };
6161
6671
  getLogs: {
@@ -6239,6 +6749,7 @@ export interface operations {
6239
6749
  };
6240
6750
  };
6241
6751
  };
6752
+ 401: components["responses"]["Unauthorized"];
6242
6753
  };
6243
6754
  };
6244
6755
  createCheckout: {
@@ -6253,23 +6764,23 @@ export interface operations {
6253
6764
  "application/json": {
6254
6765
  /** @enum {string} */
6255
6766
  plan: "starter" | "growth" | "scale";
6256
- /** Format: uri */
6257
- success_url: string;
6258
- /** Format: uri */
6259
- cancel_url: string;
6767
+ /**
6768
+ * Format: uri
6769
+ * @description Where Stripe sends the user back if their bank requires leaving the page to authenticate the payment.
6770
+ */
6771
+ return_url: string;
6260
6772
  };
6261
6773
  };
6262
6774
  };
6263
6775
  responses: {
6264
- /** @description Successful response. */
6776
+ /** @description Checkout session created; pay it in-page with its client secret. */
6265
6777
  200: {
6266
6778
  headers: {
6267
6779
  [name: string]: unknown;
6268
6780
  };
6269
6781
  content: {
6270
6782
  "application/json": {
6271
- /** Format: uri */
6272
- checkout_url: string;
6783
+ client_secret: string;
6273
6784
  session_id: string;
6274
6785
  };
6275
6786
  };
@@ -6283,9 +6794,52 @@ export interface operations {
6283
6794
  "application/json": components["schemas"]["Error"];
6284
6795
  };
6285
6796
  };
6797
+ 401: components["responses"]["Unauthorized"];
6286
6798
  };
6287
6799
  };
6288
6800
  createPortal: {
6801
+ parameters: {
6802
+ query?: never;
6803
+ header?: never;
6804
+ path?: never;
6805
+ cookie?: never;
6806
+ };
6807
+ requestBody?: never;
6808
+ responses: {
6809
+ 401: components["responses"]["Unauthorized"];
6810
+ /** @description The portal is retired; manage billing at /settings/billing. */
6811
+ 410: {
6812
+ headers: {
6813
+ [name: string]: unknown;
6814
+ };
6815
+ content: {
6816
+ "application/json": components["schemas"]["Error"];
6817
+ };
6818
+ };
6819
+ };
6820
+ };
6821
+ registerPayg: {
6822
+ parameters: {
6823
+ query?: never;
6824
+ header?: never;
6825
+ path?: never;
6826
+ cookie?: never;
6827
+ };
6828
+ requestBody?: never;
6829
+ responses: {
6830
+ 401: components["responses"]["Unauthorized"];
6831
+ /** @description Card setup moved to POST /v1/billing/payment-methods/setup. */
6832
+ 410: {
6833
+ headers: {
6834
+ [name: string]: unknown;
6835
+ };
6836
+ content: {
6837
+ "application/json": components["schemas"]["Error"];
6838
+ };
6839
+ };
6840
+ };
6841
+ };
6842
+ createTopup: {
6289
6843
  parameters: {
6290
6844
  query?: never;
6291
6845
  header?: never;
@@ -6295,27 +6849,33 @@ export interface operations {
6295
6849
  requestBody: {
6296
6850
  content: {
6297
6851
  "application/json": {
6298
- /** @enum {string} */
6299
- purpose: "payment_method_update" | "invoice_history" | "subscription_cancel";
6300
- /** Format: uri */
6852
+ /**
6853
+ * @description Amount to deposit, in US cents. Allowed amounts — $10, $25, $50, $100, $500. Charged exactly; the plan rate prices usage, not the deposit.
6854
+ * @enum {integer}
6855
+ */
6856
+ amount_cents: 1000 | 2500 | 5000 | 10000 | 50000;
6857
+ /**
6858
+ * Format: uri
6859
+ * @description Where Stripe sends the user back if their bank requires leaving the page to authenticate the payment.
6860
+ */
6301
6861
  return_url: string;
6302
6862
  };
6303
6863
  };
6304
6864
  };
6305
6865
  responses: {
6306
- /** @description Successful response. */
6866
+ /** @description Checkout session created; pay it in-page with its client secret. */
6307
6867
  200: {
6308
6868
  headers: {
6309
6869
  [name: string]: unknown;
6310
6870
  };
6311
6871
  content: {
6312
6872
  "application/json": {
6313
- /** Format: uri */
6314
- portal_url: string;
6873
+ client_secret: string;
6874
+ session_id: string;
6315
6875
  };
6316
6876
  };
6317
6877
  };
6318
- /** @description No Stripe customer linked. */
6878
+ /** @description No customer or free plan. */
6319
6879
  400: {
6320
6880
  headers: {
6321
6881
  [name: string]: unknown;
@@ -6324,8 +6884,18 @@ export interface operations {
6324
6884
  "application/json": components["schemas"]["Error"];
6325
6885
  };
6326
6886
  };
6327
- /** @description Cancellation disclosure revision is absent or stale. */
6328
- 409: {
6887
+ 401: components["responses"]["Unauthorized"];
6888
+ /** @description Validation error (missing/invalid fields). */
6889
+ 422: {
6890
+ headers: {
6891
+ [name: string]: unknown;
6892
+ };
6893
+ content: {
6894
+ "application/json": components["schemas"]["Error"];
6895
+ };
6896
+ };
6897
+ /** @description Stripe error creating the Checkout session (`stripe_error`). Answered at `503`, not `502`, because Cloudflare replaces an origin 502 body with its own page (#4891). */
6898
+ 503: {
6329
6899
  headers: {
6330
6900
  [name: string]: unknown;
6331
6901
  };
@@ -6335,21 +6905,14 @@ export interface operations {
6335
6905
  };
6336
6906
  };
6337
6907
  };
6338
- registerPayg: {
6908
+ getCancellation: {
6339
6909
  parameters: {
6340
6910
  query?: never;
6341
6911
  header?: never;
6342
6912
  path?: never;
6343
6913
  cookie?: never;
6344
6914
  };
6345
- requestBody: {
6346
- content: {
6347
- "application/json": {
6348
- /** Format: uri */
6349
- return_url: string;
6350
- };
6351
- };
6352
- };
6915
+ requestBody?: never;
6353
6916
  responses: {
6354
6917
  /** @description Successful response. */
6355
6918
  200: {
@@ -6358,13 +6921,17 @@ export interface operations {
6358
6921
  };
6359
6922
  content: {
6360
6923
  "application/json": {
6361
- /** Format: uri */
6362
- checkout_url: string;
6363
- session_id: string;
6924
+ /** @description Whether the plan ends at the period end instead of renewing. */
6925
+ cancel_at_period_end: boolean;
6926
+ /**
6927
+ * Format: date-time
6928
+ * @description When the paid period ends, read from the plan's subscription item.
6929
+ */
6930
+ current_period_end: string | null;
6364
6931
  };
6365
6932
  };
6366
6933
  };
6367
- /** @description Already registered. */
6934
+ /** @description No subscription (`no_subscription`). */
6368
6935
  400: {
6369
6936
  headers: {
6370
6937
  [name: string]: unknown;
@@ -6373,51 +6940,54 @@ export interface operations {
6373
6940
  "application/json": components["schemas"]["Error"];
6374
6941
  };
6375
6942
  };
6943
+ 401: components["responses"]["Unauthorized"];
6944
+ /** @description The caller is not an account admin (`forbidden`). */
6945
+ 403: {
6946
+ headers: {
6947
+ [name: string]: unknown;
6948
+ };
6949
+ content: {
6950
+ "application/json": components["schemas"]["Error"];
6951
+ };
6952
+ };
6953
+ /** @description The Stripe subscription could not be read (`stripe_error`). Answered at `503`, not `502`, because Cloudflare replaces an origin 502 body with its own page (#4891). */
6954
+ 503: {
6955
+ headers: {
6956
+ [name: string]: unknown;
6957
+ };
6958
+ content: {
6959
+ "application/json": components["schemas"]["Error"];
6960
+ };
6961
+ };
6376
6962
  };
6377
6963
  };
6378
- createTopup: {
6964
+ cancelSubscription: {
6379
6965
  parameters: {
6380
6966
  query?: never;
6381
6967
  header?: never;
6382
6968
  path?: never;
6383
6969
  cookie?: never;
6384
6970
  };
6385
- requestBody: {
6386
- content: {
6387
- "application/json": {
6388
- /**
6389
- * @description Amount to deposit, in US cents. Allowed amounts — $10, $25, $50, $100, $500. Charged exactly; the plan rate prices usage, not the deposit.
6390
- * @enum {integer}
6391
- */
6392
- amount_cents: 1000 | 2500 | 5000 | 10000 | 50000;
6393
- /**
6394
- * Format: uri
6395
- * @description Redirect target after a completed Checkout.
6396
- */
6397
- success_url: string;
6398
- /**
6399
- * Format: uri
6400
- * @description Redirect target when the user abandons Checkout.
6401
- */
6402
- cancel_url: string;
6403
- };
6404
- };
6405
- };
6971
+ requestBody?: never;
6406
6972
  responses: {
6407
- /** @description Hosted Checkout session created. */
6973
+ /** @description The plan now ends at the period end. */
6408
6974
  200: {
6409
6975
  headers: {
6410
6976
  [name: string]: unknown;
6411
6977
  };
6412
6978
  content: {
6413
6979
  "application/json": {
6414
- /** Format: uri */
6415
- checkout_url: string;
6416
- session_id: string;
6980
+ /** @description Whether the plan ends at the period end instead of renewing. */
6981
+ cancel_at_period_end: boolean;
6982
+ /**
6983
+ * Format: date-time
6984
+ * @description When the paid period ends, read from the plan's subscription item.
6985
+ */
6986
+ current_period_end: string | null;
6417
6987
  };
6418
6988
  };
6419
6989
  };
6420
- /** @description No customer or free plan. */
6990
+ /** @description No subscription (`no_subscription`). */
6421
6991
  400: {
6422
6992
  headers: {
6423
6993
  [name: string]: unknown;
@@ -6426,8 +6996,9 @@ export interface operations {
6426
6996
  "application/json": components["schemas"]["Error"];
6427
6997
  };
6428
6998
  };
6429
- /** @description Validation error (missing/invalid fields). */
6430
- 422: {
6999
+ 401: components["responses"]["Unauthorized"];
7000
+ /** @description The caller is not an account admin (`forbidden`). */
7001
+ 403: {
6431
7002
  headers: {
6432
7003
  [name: string]: unknown;
6433
7004
  };
@@ -6435,7 +7006,16 @@ export interface operations {
6435
7006
  "application/json": components["schemas"]["Error"];
6436
7007
  };
6437
7008
  };
6438
- /** @description Stripe error creating the Checkout session (`stripe_error`). Answered at `503`, not `502`, because Cloudflare replaces an origin 502 body with its own page (#4891). */
7009
+ /** @description Cancellation disclosure revision is absent or stale (`billing_disclosure_stale`). The current revision is in the `Billing-Disclosure-Revision` response header. */
7010
+ 409: {
7011
+ headers: {
7012
+ [name: string]: unknown;
7013
+ };
7014
+ content: {
7015
+ "application/json": components["schemas"]["Error"];
7016
+ };
7017
+ };
7018
+ /** @description Stripe refused or failed the cancellation (`stripe_error`). Answered at `503`, not `502`, because Cloudflare replaces an origin 502 body with its own page (#4891). */
6439
7019
  503: {
6440
7020
  headers: {
6441
7021
  [name: string]: unknown;
@@ -6446,23 +7026,53 @@ export interface operations {
6446
7026
  };
6447
7027
  };
6448
7028
  };
6449
- cancelSubscription: {
7029
+ keepSubscription: {
6450
7030
  parameters: {
6451
7031
  query?: never;
6452
7032
  header?: never;
6453
7033
  path?: never;
6454
7034
  cookie?: never;
6455
7035
  };
6456
- requestBody: {
6457
- content: {
6458
- "application/json": {
6459
- reason?: string;
7036
+ requestBody?: never;
7037
+ responses: {
7038
+ /** @description The plan renews at the period end. */
7039
+ 200: {
7040
+ headers: {
7041
+ [name: string]: unknown;
7042
+ };
7043
+ content: {
7044
+ "application/json": {
7045
+ /** @description Whether the plan ends at the period end instead of renewing. */
7046
+ cancel_at_period_end: boolean;
7047
+ /**
7048
+ * Format: date-time
7049
+ * @description When the paid period ends, read from the plan's subscription item.
7050
+ */
7051
+ current_period_end: string | null;
7052
+ };
6460
7053
  };
6461
7054
  };
6462
- };
6463
- responses: {
6464
- /** @description Cancellation moved to hosted Billing Portal. */
6465
- 410: {
7055
+ /** @description No subscription (`no_subscription`). */
7056
+ 400: {
7057
+ headers: {
7058
+ [name: string]: unknown;
7059
+ };
7060
+ content: {
7061
+ "application/json": components["schemas"]["Error"];
7062
+ };
7063
+ };
7064
+ 401: components["responses"]["Unauthorized"];
7065
+ /** @description The caller is not an account admin (`forbidden`). */
7066
+ 403: {
7067
+ headers: {
7068
+ [name: string]: unknown;
7069
+ };
7070
+ content: {
7071
+ "application/json": components["schemas"]["Error"];
7072
+ };
7073
+ };
7074
+ /** @description Stripe refused or failed the change (`stripe_error`). Answered at `503`, not `502`, because Cloudflare replaces an origin 502 body with its own page (#4891). */
7075
+ 503: {
6466
7076
  headers: {
6467
7077
  [name: string]: unknown;
6468
7078
  };
@@ -6507,6 +7117,7 @@ export interface operations {
6507
7117
  "application/json": components["schemas"]["Error"];
6508
7118
  };
6509
7119
  };
7120
+ 401: components["responses"]["Unauthorized"];
6510
7121
  /** @description The Stripe subscription schedule could not be read (`stripe_error`). Answered at `503`, not `502`, because Cloudflare replaces an origin 502 body with its own page (#4891). */
6511
7122
  503: {
6512
7123
  headers: {
@@ -6567,6 +7178,7 @@ export interface operations {
6567
7178
  "application/json": components["schemas"]["Error"];
6568
7179
  };
6569
7180
  };
7181
+ 401: components["responses"]["Unauthorized"];
6570
7182
  };
6571
7183
  };
6572
7184
  revokePlanChange: {
@@ -6601,6 +7213,7 @@ export interface operations {
6601
7213
  "application/json": components["schemas"]["Error"];
6602
7214
  };
6603
7215
  };
7216
+ 401: components["responses"]["Unauthorized"];
6604
7217
  };
6605
7218
  };
6606
7219
  listInvoices: {
@@ -6635,6 +7248,7 @@ export interface operations {
6635
7248
  invoice_pdf: string | null;
6636
7249
  hosted_invoice_url: string | null;
6637
7250
  }[];
7251
+ /** @description True when older invoices exist after this page. */
6638
7252
  has_more: boolean;
6639
7253
  };
6640
7254
  };
@@ -6648,6 +7262,7 @@ export interface operations {
6648
7262
  "application/json": components["schemas"]["Error"];
6649
7263
  };
6650
7264
  };
7265
+ 401: components["responses"]["Unauthorized"];
6651
7266
  };
6652
7267
  };
6653
7268
  getTopupBalance: {
@@ -6703,6 +7318,7 @@ export interface operations {
6703
7318
  };
6704
7319
  };
6705
7320
  };
7321
+ 401: components["responses"]["Unauthorized"];
6706
7322
  };
6707
7323
  };
6708
7324
  updateAutoTopup: {
@@ -6749,6 +7365,7 @@ export interface operations {
6749
7365
  "application/json": components["schemas"]["Error"];
6750
7366
  };
6751
7367
  };
7368
+ 401: components["responses"]["Unauthorized"];
6752
7369
  };
6753
7370
  };
6754
7371
  createPaymentMethodSetup: {
@@ -6778,6 +7395,7 @@ export interface operations {
6778
7395
  "application/json": components["schemas"]["Error"];
6779
7396
  };
6780
7397
  };
7398
+ 401: components["responses"]["Unauthorized"];
6781
7399
  };
6782
7400
  };
6783
7401
  listPaymentMethods: {
@@ -6809,6 +7427,7 @@ export interface operations {
6809
7427
  "application/json": components["schemas"]["Error"];
6810
7428
  };
6811
7429
  };
7430
+ 401: components["responses"]["Unauthorized"];
6812
7431
  };
6813
7432
  };
6814
7433
  setDefaultPaymentMethod: {
@@ -6840,6 +7459,7 @@ export interface operations {
6840
7459
  "application/json": components["schemas"]["Error"];
6841
7460
  };
6842
7461
  };
7462
+ 401: components["responses"]["Unauthorized"];
6843
7463
  /** @description Payment method not found. */
6844
7464
  404: {
6845
7465
  headers: {
@@ -6889,6 +7509,7 @@ export interface operations {
6889
7509
  "application/json": components["schemas"]["Error"];
6890
7510
  };
6891
7511
  };
7512
+ 401: components["responses"]["Unauthorized"];
6892
7513
  /** @description Payment method not found. */
6893
7514
  404: {
6894
7515
  headers: {
@@ -6984,6 +7605,7 @@ export interface operations {
6984
7605
  };
6985
7606
  };
6986
7607
  };
7608
+ 401: components["responses"]["Unauthorized"];
6987
7609
  };
6988
7610
  };
6989
7611
  retryWebhookDelivery: {
@@ -7018,6 +7640,7 @@ export interface operations {
7018
7640
  "application/json": components["schemas"]["Error"];
7019
7641
  };
7020
7642
  };
7643
+ 401: components["responses"]["Unauthorized"];
7021
7644
  /** @description Delivery not found or not in a retryable state. */
7022
7645
  404: {
7023
7646
  headers: {
@@ -7110,11 +7733,11 @@ export interface operations {
7110
7733
  path?: never;
7111
7734
  cookie?: never;
7112
7735
  };
7113
- /** @description Optional clickwrap acceptance signal (issue #1025). When present, terms_version MUST equal the published current version or the request is rejected with 400 terms_version_mismatch. When absent, the server stamps the current version server-side (back-compatible). */
7736
+ /** @description Optional Terms version guard (issue #1025). When present, terms_version MUST equal the published current version or the request is rejected with 400 terms_version_mismatch. It is never recorded as acceptance: a new account starts with an empty terms_version, and acceptance is recorded only by POST /v1/account/accept-terms. When absent, the guard is skipped (back-compatible). */
7114
7737
  requestBody?: {
7115
7738
  content: {
7116
7739
  "application/json": {
7117
- /** @description The Terms of Service version the user is accepting. */
7740
+ /** @description The Terms of Service version the client was built against. Checked against the current version, never recorded as acceptance. */
7118
7741
  terms_version?: string;
7119
7742
  };
7120
7743
  };
@@ -7138,7 +7761,7 @@ export interface operations {
7138
7761
  "application/json": components["schemas"]["Account"];
7139
7762
  };
7140
7763
  };
7141
- /** @description terms_version does not match the published current version. */
7764
+ /** @description terms_version does not match the published current version (version guard only; acceptance is recorded by POST /v1/account/accept-terms). */
7142
7765
  400: {
7143
7766
  headers: {
7144
7767
  [name: string]: unknown;