@hunt-labs/bytekit-sdk 0.9.3 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -194,7 +194,17 @@ export interface paths {
194
194
  put?: never;
195
195
  /**
196
196
  * Scrape a URL
197
- * @description Fetches and processes a URL, returning content in one or more formats wrapped in a ScrapeEnvelope. Most requests return synchronously in under a second; requests needing a full page render return HTTP 202 and complete asynchronously.
197
+ * @description Fetches and processes a URL, returning content in one or more formats wrapped in a ScrapeEnvelope.
198
+ *
199
+ * **The response shape is decided by your request, not by how we route it.** In precedence order:
200
+ *
201
+ * 1. `async: true` → **202** with a `ScrapeQueuedEnvelope` receipt, returned immediately. Poll `GET /v1/scrape/{id}` for the result.
202
+ * 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
+ * 3. Otherwise the request is served by the fast HTTP path and returns **200** with the content envelope, typically in under a second.
204
+ *
205
+ * **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 happens before any job row exists, so its envelope carries `id: 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
+ *
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.
198
208
  */
199
209
  post: operations["createScrape"];
200
210
  delete?: never;
@@ -235,9 +245,10 @@ export interface paths {
235
245
  /**
236
246
  * Bulk scrape URLs
237
247
  * @description Enqueues multiple URLs for scraping. Results delivered via webhook.
238
- * Webhook deliveries include `X-ByteKit-Event: scrape.completed` or
239
- * `X-ByteKit-Event: scrape.failed` so receivers can dispatch on the
240
- * header without parsing the body shape.
248
+ * Completion deliveries use `X-ByteKit-Event: bulk.completed` and the
249
+ * `BulkCompletedWebhook` contract: at most 500 complete items and 1 MiB,
250
+ * followed by cursor recovery through `GET /v1/scrape/bulk/{id}` whenever
251
+ * `recovery_required` is true.
241
252
  */
242
253
  post: operations["createScrapeBulk"];
243
254
  delete?: never;
@@ -253,7 +264,20 @@ export interface paths {
253
264
  path?: never;
254
265
  cookie?: never;
255
266
  };
256
- /** Get scrape bulk job status */
267
+ /**
268
+ * Get scrape bulk job status
269
+ * @description Returns the job envelope plus its rehydrated per-URL scrape envelopes.
270
+ *
271
+ * **Downloading item content.** A `raw` or `markdown` artifact within the
272
+ * 10-MiB inline cap is returned inline. An oversized one is replaced by a
273
+ * **pre-signed** URL, minted fresh on every read of this endpoint and valid
274
+ * for **86400 seconds (24 hours)**. The underlying objects are private, so an
275
+ * unsigned URL returns `401`: download the content inside that window, or
276
+ * re-poll this endpoint for a fresh signature. An artifact that was never
277
+ * stored, or whose object cannot be signed, is omitted from `formats` and
278
+ * reported as `artifact_unavailable` in `warnings`. The private unsigned
279
+ * storage URL is never returned.
280
+ */
257
281
  get: operations["getScrapeBulk"];
258
282
  put?: never;
259
283
  post?: never;
@@ -305,6 +329,10 @@ export interface paths {
305
329
  * Bulk fetch URLs
306
330
  * @description Enqueues multiple URLs for HTTP fetching. Results delivered via webhook.
307
331
  * Does not support options that require page rendering (wait_for_selector, etc.).
332
+ * Completion deliveries use `X-ByteKit-Event: bulk.completed` and the
333
+ * `BulkCompletedWebhook` contract: at most 500 complete items and 1 MiB,
334
+ * followed by cursor recovery through `GET /v1/fetch/bulk/{id}` whenever
335
+ * `recovery_required` is true.
308
336
  *
309
337
  * **Limits:** request bodies are guarded in a two-tier shape. A streamed body
310
338
  * with no `Content-Length` header is capped at 2 MB before your API key
@@ -342,7 +370,9 @@ export interface paths {
342
370
  * objects are private, so an unsigned URL returns `401`: download the
343
371
  * content inside that window, or re-poll this endpoint for a fresh
344
372
  * signature. Items that are not `completed`, and completed items with no
345
- * stored object, carry `null` or the unsigned stored URL instead.
373
+ * stored object, or completed items whose object cannot be signed, carry
374
+ * `null`; the latter report `artifact_unavailable`. The private unsigned
375
+ * storage URL is never returned.
346
376
  */
347
377
  get: operations["getFetchBulk"];
348
378
  put?: never;
@@ -373,6 +403,9 @@ export interface paths {
373
403
  * Provide `urls` (simple list) or `items` (per-item config), not both.
374
404
  * Webhook deliveries include `X-ByteKit-Event: bulk.completed` so
375
405
  * receivers can dispatch on the header without parsing the body shape.
406
+ * The body follows `BulkCompletedWebhook`: at most 500 complete items and
407
+ * 1 MiB, followed by cursor recovery through the existing mixed-item route
408
+ * whenever `recovery_required` is true.
376
409
  *
377
410
  * **Limits:** request bodies are guarded in a two-tier shape. A streamed body
378
411
  * with no `Content-Length` header is capped at 4 MB before your API key
@@ -424,15 +457,25 @@ export interface paths {
424
457
  * List bulk job items
425
458
  * @description Returns the bulk job's items, discriminated by `type`.
426
459
  *
427
- * **Downloading item artifacts.** `image_url` (`type: screenshot`) and both
428
- * `content_url` and `markdown_url` (`type: scrape`) are **pre-signed** URLs,
429
- * minted fresh on every read of this endpoint and valid for **600 seconds
430
- * (10 minutes)** —
460
+ * **Downloading item artifacts.** For a `completed` item with a storage key,
461
+ * `image_url` (`type: screenshot`) and both `content_url` and `markdown_url`
462
+ * (`type: scrape`) are **pre-signed** URLs, minted fresh on every read of
463
+ * this endpoint and valid for **600 seconds (10 minutes)** —
431
464
  * the same signing lifetime as `content_url` on `GET /v1/fetch/bulk/{id}`.
432
- * The underlying objects are private, so an unsigned URL returns `401`:
433
- * download inside that window, or re-poll this endpoint for a fresh
434
- * signature. Items that are not `completed`, and completed items with no
435
- * stored object, carry `null` or the unsigned stored URL instead.
465
+ * Download inside that window, or re-poll this endpoint for a fresh
466
+ * signature.
467
+ *
468
+ * **When no signature is minted.** Three cases mint none: an item that is not
469
+ * `completed`, a `completed` item with no storage key, and a `completed` item
470
+ * whose object could not be signed — during an object-storage outage, for
471
+ * instance. In all three the item's stored value is returned unchanged: `null`
472
+ * while nothing has been stored, and otherwise a **private, unsigned**
473
+ * object-storage URL that answers `401`. These fields are neither nulled nor
474
+ * flagged in that case, so treat an artifact URL as usable only once you have
475
+ * downloaded it, and re-poll for a fresh signature otherwise.
476
+ * `artifact_warnings` and its `artifact_unavailable` code describe the sibling
477
+ * `artifacts` object on `type: scrape` items only — they say nothing about
478
+ * `image_url`, `content_url`, or `markdown_url`.
436
479
  */
437
480
  get: operations["listBulkScreenshots"];
438
481
  put?: never;
@@ -882,7 +925,8 @@ export interface paths {
882
925
  /**
883
926
  * Configure auto-topup
884
927
  * @description Enable or disable automatic bandwidth top-ups. When enabling,
885
- * threshold_bytes, amount_bytes, and monthly_cap_cents are all required.
928
+ * threshold_bytes, amount_bytes, and monthly_cap_cents must all be present;
929
+ * monthly_cap_cents may be null, which means no monthly cap.
886
930
  */
887
931
  put: operations["updateAutoTopup"];
888
932
  post?: never;
@@ -1413,6 +1457,95 @@ export interface components {
1413
1457
  details?: unknown;
1414
1458
  };
1415
1459
  };
1460
+ /**
1461
+ * @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`.
1462
+ *
1463
+ * REFERENCE DOCUMENTATION ONLY (#4340). No operation `$ref`s this schema and no response ever carries an object of this shape, so no client model is generated from it and no SDK re-exports it. On the wire the value appears as the FLAT `error_code` / `error_message` fields on a bulk list item — `GET /v1/fetch/bulk/{id}`, `GET /v1/bulk/{id}/screenshots` — and on the `items[]` entries of the `bulk.completed` webhook body, never as a nested `{ code, message }` object. This schema names the `artifact_unavailable` code and the contract that goes with it; the two properties below describe that code and message, not a wire envelope.
1464
+ */
1465
+ BulkArtifactUnavailableError: {
1466
+ /** @enum {string} */
1467
+ code: "artifact_unavailable";
1468
+ message: string;
1469
+ };
1470
+ /** @description Mandatory bounded scrape record emitted when the ordinary rehydrated envelope cannot fit within the 16-MiB page bound. The stable item identity and terminal outcome always remain available; bounded signed references and failure detail are included when they fit. */
1471
+ BulkMandatoryScrapeItem: {
1472
+ id: string;
1473
+ /** @enum {string} */
1474
+ type: "scrape";
1475
+ /** @enum {string} */
1476
+ terminal_outcome: "pending" | "processing" | "completed" | "failed" | "cancelled";
1477
+ /** Format: uri */
1478
+ url: string;
1479
+ /** @description Bounded signed references retained from the ordinary scrape envelope. Only the formats the job requested are present; the key set is the `/v1/scrape` format vocabulary. */
1480
+ formats?: {
1481
+ raw?: string | null;
1482
+ markdown?: string | null;
1483
+ links?: null | (string | components["schemas"]["ScrapeScoredLink"])[];
1484
+ images?: null | (string | components["schemas"]["ScrapeScoredImage"])[];
1485
+ };
1486
+ error?: {
1487
+ code: string;
1488
+ message: string | null;
1489
+ /** Format: date-time */
1490
+ failed_at: string | null;
1491
+ };
1492
+ };
1493
+ /** @description Whole-job counters. These do not reset or shrink with the current page. */
1494
+ BulkJobCounters: {
1495
+ total: number;
1496
+ completed: number;
1497
+ failed: number;
1498
+ };
1499
+ /**
1500
+ * @description Customer body for `X-ByteKit-Event: bulk.completed`. Delivery is bounded to
1501
+ * 500 complete items and 1 MiB of customer-visible JSON, stopping only between
1502
+ * items. When either item coverage or artifact coverage is incomplete, follow
1503
+ * `recovery_url` with cursor pagination; stable `bulk_id` plus each item `id`
1504
+ * supports idempotent processing after duplicate, delayed, or retried delivery.
1505
+ */
1506
+ BulkCompletedWebhook: {
1507
+ bulk_id: string;
1508
+ /** @enum {string} */
1509
+ status: "completed";
1510
+ total: number;
1511
+ completed: number;
1512
+ failed: number;
1513
+ total_credits_charged: number;
1514
+ /** Format: uri */
1515
+ webhook_url: string;
1516
+ /** @description Complete item records included before the 500-item or 1-MiB manifest bound. Every record carries a stable `id`, a `type`, and a terminal `status`. */
1517
+ items: ({
1518
+ /** @description Stable prefixed item id; deduplicate with `bulk_id` plus this id. */
1519
+ id: string;
1520
+ /** @enum {string} */
1521
+ type: "fetch" | "scrape" | "screenshot" | "recording";
1522
+ /** @enum {string} */
1523
+ status: "success" | "completed" | "failed" | "cancelled";
1524
+ /** @description May be `artifact_unavailable` when no usable result reference exists. */
1525
+ error_code?: string | null;
1526
+ error_message?: string | null;
1527
+ /** @description Present and true when the manifest bounded a long error message. */
1528
+ error_message_truncated?: boolean;
1529
+ } & {
1530
+ [key: string]: unknown;
1531
+ })[];
1532
+ /** @enum {string} */
1533
+ recovery_api: "fetch" | "scrape" | "mixed";
1534
+ /**
1535
+ * @description Existing paginated result-recovery path for this job.
1536
+ * @example /v1/fetch/bulk/bulk_01j9abc123
1537
+ */
1538
+ recovery_url: string;
1539
+ manifest_item_count: number;
1540
+ /** @description True when every terminal job item is present in this webhook body. */
1541
+ manifest_items_complete: boolean;
1542
+ /** @description True when every included completed item has a usable artifact or reference. */
1543
+ manifest_artifacts_complete: boolean;
1544
+ /** @description True only when both item and artifact coverage are complete. */
1545
+ manifest_complete: boolean;
1546
+ /** @description Inverse of `manifest_complete`; follow `recovery_url` when true. */
1547
+ recovery_required: boolean;
1548
+ };
1416
1549
  Viewport: {
1417
1550
  width: number;
1418
1551
  height: number;
@@ -1535,11 +1668,17 @@ export interface components {
1535
1668
  formats: ("raw" | "markdown" | "links" | "images")[];
1536
1669
  /** @default US */
1537
1670
  country: string;
1538
- /** @default 0 */
1671
+ /**
1672
+ * @description Milliseconds to wait after page load before capturing, for content that renders late. Any value above 0 puts the request on the full browser render path. Unless `async: true` is also set, the request is then HELD until the render finishes and returns 200 with the content envelope, or returns the 202 receipt if the hold window expires first. `0` (the default) keeps the request on the fast HTTP path, which returns 200 in one round trip.
1673
+ * @default 0
1674
+ */
1539
1675
  delay_ms: number;
1540
1676
  /** @default 30000 */
1541
1677
  timeout_ms: number;
1542
- /** @default false */
1678
+ /**
1679
+ * @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.
1680
+ * @default false
1681
+ */
1543
1682
  async: boolean;
1544
1683
  /**
1545
1684
  * Format: uri
@@ -1829,17 +1968,19 @@ export interface components {
1829
1968
  * from a prior cache entry (billed at 0.5×). `miss` — no reusable entry was
1830
1969
  * found, so the result was freshly fetched. `bypass` — `cache_ttl: '0'`
1831
1970
  * skipped the read. Cache-eligible fresh results are written through;
1832
- * safety-classified WAF husks remain live-only. Present on the async success
1833
- * envelope (synchronous and webhook delivery); omitted by paths with no cache
1834
- * verdict (e.g. bulk results).
1971
+ * safety-classified WAF husks remain live-only. Present on the synchronous
1972
+ * response, on webhook delivery, and on `GET /v1/scrape/{id}` for a row whose
1973
+ * terminal write recorded a disposition; omitted by paths with no cache verdict
1974
+ * (e.g. bulk results) and for a stored row that recorded none, where absent
1975
+ * means unknown rather than `miss`.
1835
1976
  * @enum {string}
1836
1977
  */
1837
1978
  cache?: "miss" | "hit" | "bypass";
1838
- /** @description Age in whole seconds of the cache entry replayed on a `hit`. Clamped to ≥ 0 to absorb clock skew. Present only on `cache: hit`. */
1979
+ /** @description Age in whole seconds of the cache entry replayed on a `hit`. Clamped to ≥ 0 to absorb clock skew. Present only on `cache: hit`. `GET /v1/scrape/{id}` reports `cache: hit` without this field: the age is a property of the replay that happened at completion time, is not persisted on the row, and cannot be derived honestly afterwards. */
1839
1980
  cache_age_s?: number;
1840
1981
  };
1841
1982
  /**
1842
- * @description Terminal asynchronous scrape failures are delivered to subscribers of `failed` as this payload with `X-ByteKit-Event: scrape.failed`.
1983
+ * @description The canonical terminal failure payload. It is returned inline on a `POST /v1/scrape` that fails upstream (HTTP 200, `id: null`), by `GET /v1/scrape/{id}` once a queued job has failed, and delivered to subscribers of `failed` with `X-ByteKit-Event: scrape.failed`.
1843
1984
  * @example {
1844
1985
  * "schema_version": 1,
1845
1986
  * "status": "failed",
@@ -2166,7 +2307,7 @@ export interface components {
2166
2307
  options?: {
2167
2308
  [key: string]: unknown;
2168
2309
  };
2169
- /** @description Scrape monitor options (formats, country, headers, etc.). Only for type=scrape. */
2310
+ /** @description Scrape monitor options (formats, country, wait_for_selector, wait_until, delay_ms). Only for type=scrape. */
2170
2311
  scrape_options?: {
2171
2312
  [key: string]: unknown;
2172
2313
  };
@@ -2544,7 +2685,7 @@ export interface components {
2544
2685
  /** Format: date-time */
2545
2686
  created_at: string;
2546
2687
  };
2547
- /** @description Minimal account shape returned by GET /v1/account when authenticated with a Clerk session JWT. Omits api_key, subscription, and auto_topup. */
2688
+ /** @description Minimal account shape returned by GET /v1/account when authenticated with a Clerk session JWT. Omits api_key, subscription, and auto_topup; the single boolean `has_subscription` stands in for the bearer path's `subscription` object. */
2548
2689
  AccountSessionResponse: {
2549
2690
  id: string;
2550
2691
  email: string;
@@ -2577,6 +2718,42 @@ export interface components {
2577
2718
  created_at: string;
2578
2719
  /** @description True once the account has SUCCESSFULLY COMPLETED at least one billable request (a scrape/screenshot/fetch/… that settled and was charged credits), regardless of whether it was authenticated with a Clerk session or an API key. All-time — never windowed. A request that failed does not flip it, even when its bandwidth was billed: the monitor terminal-preflight-failure path records bytes without credits, and only the credited settlement counts here. Powers the dashboard onboarding gate — the app shows the guided onboarding flow until this is true, then the dashboard. Lags by up to one usage rollup: the completion service writes the row after the response is returned, so a just-completed first request may still read false for a moment. Treat that as "not visible yet", never as "this account has never made a request". */
2579
2720
  has_activity: boolean;
2721
+ /** @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. */
2722
+ has_subscription: boolean;
2723
+ };
2724
+ /** @description Account shape returned by PATCH /v1/account. Identical to AccountSessionResponse except that it omits `has_activity`: the PATCH handler returns the shared session-account body unchanged and does not run the extra activity lookup that GET /v1/account layers on top of it (issue #4187). */
2725
+ AccountPatchResponse: {
2726
+ id: string;
2727
+ email: string;
2728
+ name: string | null;
2729
+ plan: {
2730
+ id: string;
2731
+ slug: string;
2732
+ name: string;
2733
+ included_screenshots: number;
2734
+ has_overage: boolean;
2735
+ overage_price_cents: number | null;
2736
+ max_concurrency: number;
2737
+ rate_limit_per_sec: number;
2738
+ max_bulk_size: number;
2739
+ max_monitors: number;
2740
+ retention_days: number;
2741
+ };
2742
+ /** @description Prefixed user id of the calling admin user. Null for non-admin members. */
2743
+ owner_user_id: string | null;
2744
+ /** @description Account notification preferences (bandwidth alerts). */
2745
+ notifications: {
2746
+ /** @description Whether the account admin wants an email when bandwidth reaches 80 % of the plan limit. */
2747
+ bandwidth_80_enabled: boolean;
2748
+ /** @description Whether the account admin wants an email when bandwidth reaches 100 % of the plan limit. */
2749
+ bandwidth_100_enabled: boolean;
2750
+ };
2751
+ /** @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. */
2752
+ terms_version: string;
2753
+ /** @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. */
2754
+ has_subscription: boolean;
2755
+ /** Format: date-time */
2756
+ created_at: string;
2580
2757
  };
2581
2758
  /** @description Partial update payload for PATCH /v1/account. All fields are optional; at least one of name, email, or notifications must be provided. */
2582
2759
  PatchAccountRequest: {
@@ -2906,7 +3083,7 @@ export interface operations {
2906
3083
  [name: string]: unknown;
2907
3084
  };
2908
3085
  content: {
2909
- "application/json": components["schemas"]["Account"];
3086
+ "application/json": components["schemas"]["AccountPatchResponse"];
2910
3087
  };
2911
3088
  };
2912
3089
  /** @description Missing or invalid Clerk JWT. */
@@ -3423,7 +3600,7 @@ export interface operations {
3423
3600
  };
3424
3601
  };
3425
3602
  responses: {
3426
- /** @description Scrape completed synchronously. */
3603
+ /** @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 ends before any job row exists, so its envelope carries `id: null` and there is nothing to poll; `error.http_status` is present only when a real upstream HTTP status is known. */
3427
3604
  200: {
3428
3605
  headers: {
3429
3606
  /** @description Stable scrape identifier (also present on the envelope as `id`). */
@@ -3476,7 +3653,7 @@ export interface operations {
3476
3653
  "X-Scrape-Markdown-Length"?: number;
3477
3654
  /** @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. */
3478
3655
  "X-Scrape-Proxy-Tier"?: number;
3479
- /** @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. */
3656
+ /** @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. */
3480
3657
  "X-Scrape-Proxy-Tier-Label"?: string;
3481
3658
  /** @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. */
3482
3659
  "X-Scrape-Waf"?: string;
@@ -3487,10 +3664,10 @@ export interface operations {
3487
3664
  [name: string]: unknown;
3488
3665
  };
3489
3666
  content: {
3490
- "application/json": components["schemas"]["ScrapeSuccessEnvelope"];
3667
+ "application/json": components["schemas"]["ScrapeSuccessEnvelope"] | components["schemas"]["ScrapeErrorEnvelope"];
3491
3668
  };
3492
3669
  };
3493
- /** @description Scrape accepted for async processing. */
3670
+ /** @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. */
3494
3671
  202: {
3495
3672
  headers: {
3496
3673
  /** @description Stable scrape identifier for the queued job. */
@@ -3779,7 +3956,14 @@ export interface operations {
3779
3956
  };
3780
3957
  getScrapeBulk: {
3781
3958
  parameters: {
3782
- query?: never;
3959
+ query?: {
3960
+ /** @description Opaque cursor returned by the preceding page. It is bound to this bulk id, this recovery route, and the exact status filter; cross-scope cursors return 422. */
3961
+ cursor?: string;
3962
+ /** @description Maximum result rows considered for this page; the 16-MiB response bound may stop sooner. */
3963
+ limit?: number;
3964
+ /** @description Optional item-status filter. A cursor may be reused only with the same filter. */
3965
+ status?: "pending" | "processing" | "completed" | "failed" | "cancelled";
3966
+ };
3783
3967
  header?: never;
3784
3968
  path: {
3785
3969
  id: string;
@@ -3818,8 +4002,12 @@ export interface operations {
3818
4002
  estimated_credits: number | null;
3819
4003
  /** @description Webhook endpoint URL (HTTPS only; http:// rejected with 400 invalid_url, reason scheme_unsupported) */
3820
4004
  webhook_url: string;
3821
- /** @description Rehydrated per-URL scrape envelopes — the terminal page of results (default 100 rows, `?limit=` up to 500). `routes/scrape-bulk.ts` spreads this key into the SAME body on both status branches, so it is present here exactly as it is on the 202; on the 200 the entries carry their final success or error envelopes (issue #3632). */
3822
- items: components["schemas"]["ScrapeEnvelope"][];
4005
+ /** @description Opaque cursor for the next stable page; null when traversal is complete. */
4006
+ next_cursor: string | null;
4007
+ /** @description True when another page is available through `next_cursor`. */
4008
+ has_more: boolean;
4009
+ /** @description Rehydrated per-URL scrape envelopes — the terminal page of results (default 500 rows, `?limit=` up to 500). `routes/scrape-bulk.ts` spreads this key into the SAME body on both status branches, so it is present here exactly as it is on the 202; on the 200 the entries carry their final success or error envelopes (issue #3632). */
4010
+ items: (components["schemas"]["ScrapeEnvelope"] | components["schemas"]["BulkMandatoryScrapeItem"])[];
3823
4011
  };
3824
4012
  };
3825
4013
  };
@@ -3853,8 +4041,12 @@ export interface operations {
3853
4041
  estimated_credits: number | null;
3854
4042
  /** @description Webhook endpoint URL (HTTPS only; http:// rejected with 400 invalid_url, reason scheme_unsupported) */
3855
4043
  webhook_url: string;
3856
- /** @description Rehydrated per-URL scrape envelopes — the same page the 200 returns (default 100 rows, `?limit=` up to 500). While the job is non-terminal most entries carry the `queued` envelope. */
3857
- items: components["schemas"]["ScrapeEnvelope"][];
4044
+ /** @description Opaque cursor for the next stable page; null when traversal is complete. */
4045
+ next_cursor: string | null;
4046
+ /** @description True when another page is available through `next_cursor`. */
4047
+ has_more: boolean;
4048
+ /** @description Rehydrated per-URL scrape envelopes — the same page the 200 returns (default 500 rows, `?limit=` up to 500). While the job is non-terminal most entries carry the `queued` envelope. */
4049
+ items: (components["schemas"]["ScrapeEnvelope"] | components["schemas"]["BulkMandatoryScrapeItem"])[];
3858
4050
  };
3859
4051
  };
3860
4052
  };
@@ -4220,7 +4412,14 @@ export interface operations {
4220
4412
  };
4221
4413
  getFetchBulk: {
4222
4414
  parameters: {
4223
- query?: never;
4415
+ query?: {
4416
+ /** @description Opaque cursor returned by the preceding page. It is bound to this bulk id, this recovery route, and the exact status filter; cross-scope cursors return 422. */
4417
+ cursor?: string;
4418
+ /** @description Maximum result rows considered for this page; the 16-MiB response bound may stop sooner. */
4419
+ limit?: number;
4420
+ /** @description Optional item-status filter. A cursor may be reused only with the same filter. */
4421
+ status?: "pending" | "processing" | "completed" | "failed" | "cancelled";
4422
+ };
4224
4423
  header?: never;
4225
4424
  path: {
4226
4425
  id: string;
@@ -4253,8 +4452,12 @@ export interface operations {
4253
4452
  estimated_credits: number | null;
4254
4453
  /** @description Webhook endpoint URL (HTTPS only; http:// rejected with 400 invalid_url, reason scheme_unsupported) */
4255
4454
  webhook_url: string;
4256
- /** @description Per-URL fetch items, oldest first, capped at 500 (listBulkFetchItemsWithLatestAttempt). */
4257
- items: {
4455
+ /** @description Opaque cursor for the next stable page; null when traversal is complete. */
4456
+ next_cursor: string | null;
4457
+ /** @description True when another page is available through `next_cursor`. */
4458
+ has_more: boolean;
4459
+ /** @description Stable per-URL fetch items, oldest first. Follow `next_cursor` while `has_more` is true to enumerate the complete filtered job; each page considers at most 500 rows and is bounded to 16 MiB. */
4460
+ items: ({
4258
4461
  /**
4259
4462
  * @description Scrape-row id, `sc_`-prefixed. Fetch-bulk items are rows of the same resource sync `/v1/scrape` returns, so they share its prefix. Not to be confused with the `ft_`-prefixed `X-Fetch-ID` correlation header on sync `/v1/fetch`, which identifies a request rather than a stored item.
4260
4463
  * @example sc_01j9abc123
@@ -4264,25 +4467,46 @@ export interface operations {
4264
4467
  url: string;
4265
4468
  /** @enum {string} */
4266
4469
  status: "pending" | "processing" | "completed" | "failed" | "cancelled";
4267
- content_type: string | null;
4268
- content_length: number | null;
4269
- /** @description Pre-signed download URL for the fetched body, valid for 600 seconds (10 minutes) from the moment this response was generated — matching the signing TTL of `image_url` on `GET /v1/bulk/{id}/screenshots`. A new signature is minted on every poll. Null for items with no stored body; a completed item whose object cannot be signed falls back to the unsigned stored URL, which returns 401 on download. */
4470
+ content_type?: string | null;
4471
+ content_length?: number | null;
4472
+ /** @description Pre-signed download URL for the fetched body, valid for 600 seconds (10 minutes) from the moment this response was generated — matching the signing TTL of `image_url` on `GET /v1/bulk/{id}/screenshots`. A new signature is minted on every poll. Null for items with no stored body or whose object cannot be signed. In the latter case `error_code` is `artifact_unavailable`; the private unsigned storage URL is never returned. */
4270
4473
  content_url: string | null;
4271
- waf_vendor: string | null;
4272
- cache_hit: boolean;
4474
+ waf_vendor?: string | null;
4475
+ cache_hit?: boolean;
4273
4476
  /**
4274
4477
  * @description Itemised account of this item's charge — the basis, the named factors
4275
4478
  * that composed the multiplier, and the resulting billed bytes. Omitted
4276
4479
  * for rows that completed before the billing node was persisted.
4277
4480
  */
4278
4481
  billing?: components["schemas"]["BillingNode"];
4482
+ /** @description Stable item-local error code. `artifact_unavailable` means the stored result or a usable signed reference could not be produced. */
4279
4483
  error_code: string | null;
4280
4484
  error_message: string | null;
4281
4485
  /** Format: date-time */
4282
- created_at: string;
4486
+ created_at?: string;
4283
4487
  /** Format: date-time */
4284
- completed_at: string | null;
4285
- }[];
4488
+ completed_at?: string | null;
4489
+ } | {
4490
+ /**
4491
+ * @description Scrape-row id, `sc_`-prefixed — the same stable identity the ordinary item carries, so recovery pagination is unaffected.
4492
+ * @example sc_01j9abc123
4493
+ */
4494
+ id: string;
4495
+ /** @enum {string} */
4496
+ type: "fetch";
4497
+ /**
4498
+ * @description Terminal state of the item. This is the contract's terminal signal and outranks the ordinary item's legacy `status` spelling.
4499
+ * @enum {string}
4500
+ */
4501
+ terminal_outcome: "pending" | "processing" | "completed" | "failed" | "cancelled";
4502
+ /** Format: uri */
4503
+ url: string;
4504
+ /** @description Bounded pre-signed download URL retained from the ordinary item, or `null` when the reference did not fit or could not be produced. */
4505
+ content_url: string | null;
4506
+ error_code: string | null;
4507
+ /** @description Bounded failure detail; a long message is truncated. */
4508
+ error_message: string | null;
4509
+ })[];
4286
4510
  };
4287
4511
  };
4288
4512
  };
@@ -4319,8 +4543,12 @@ export interface operations {
4319
4543
  estimated_credits: number | null;
4320
4544
  /** @description Webhook endpoint URL (HTTPS only; http:// rejected with 400 invalid_url, reason scheme_unsupported) */
4321
4545
  webhook_url: string;
4322
- /** @description Per-URL fetch items, oldest first, capped at 500 (listBulkFetchItemsWithLatestAttempt). */
4323
- items: {
4546
+ /** @description Opaque cursor for the next stable page; null when traversal is complete. */
4547
+ next_cursor: string | null;
4548
+ /** @description True when another page is available through `next_cursor`. */
4549
+ has_more: boolean;
4550
+ /** @description Stable per-URL fetch items, oldest first. Follow `next_cursor` while `has_more` is true to enumerate the complete filtered job; each page considers at most 500 rows and is bounded to 16 MiB. */
4551
+ items: ({
4324
4552
  /**
4325
4553
  * @description Scrape-row id, `sc_`-prefixed. Fetch-bulk items are rows of the same resource sync `/v1/scrape` returns, so they share its prefix. Not to be confused with the `ft_`-prefixed `X-Fetch-ID` correlation header on sync `/v1/fetch`, which identifies a request rather than a stored item.
4326
4554
  * @example sc_01j9abc123
@@ -4330,25 +4558,46 @@ export interface operations {
4330
4558
  url: string;
4331
4559
  /** @enum {string} */
4332
4560
  status: "pending" | "processing" | "completed" | "failed" | "cancelled";
4333
- content_type: string | null;
4334
- content_length: number | null;
4335
- /** @description Pre-signed download URL for the fetched body, valid for 600 seconds (10 minutes) from the moment this response was generated — matching the signing TTL of `image_url` on `GET /v1/bulk/{id}/screenshots`. A new signature is minted on every poll. Null for items with no stored body; a completed item whose object cannot be signed falls back to the unsigned stored URL, which returns 401 on download. */
4561
+ content_type?: string | null;
4562
+ content_length?: number | null;
4563
+ /** @description Pre-signed download URL for the fetched body, valid for 600 seconds (10 minutes) from the moment this response was generated — matching the signing TTL of `image_url` on `GET /v1/bulk/{id}/screenshots`. A new signature is minted on every poll. Null for items with no stored body or whose object cannot be signed. In the latter case `error_code` is `artifact_unavailable`; the private unsigned storage URL is never returned. */
4336
4564
  content_url: string | null;
4337
- waf_vendor: string | null;
4338
- cache_hit: boolean;
4565
+ waf_vendor?: string | null;
4566
+ cache_hit?: boolean;
4339
4567
  /**
4340
4568
  * @description Itemised account of this item's charge — the basis, the named factors
4341
4569
  * that composed the multiplier, and the resulting billed bytes. Omitted
4342
4570
  * for rows that completed before the billing node was persisted.
4343
4571
  */
4344
4572
  billing?: components["schemas"]["BillingNode"];
4573
+ /** @description Stable item-local error code. `artifact_unavailable` means the stored result or a usable signed reference could not be produced. */
4345
4574
  error_code: string | null;
4346
4575
  error_message: string | null;
4347
4576
  /** Format: date-time */
4348
- created_at: string;
4577
+ created_at?: string;
4349
4578
  /** Format: date-time */
4350
- completed_at: string | null;
4351
- }[];
4579
+ completed_at?: string | null;
4580
+ } | {
4581
+ /**
4582
+ * @description Scrape-row id, `sc_`-prefixed — the same stable identity the ordinary item carries, so recovery pagination is unaffected.
4583
+ * @example sc_01j9abc123
4584
+ */
4585
+ id: string;
4586
+ /** @enum {string} */
4587
+ type: "fetch";
4588
+ /**
4589
+ * @description Terminal state of the item. This is the contract's terminal signal and outranks the ordinary item's legacy `status` spelling.
4590
+ * @enum {string}
4591
+ */
4592
+ terminal_outcome: "pending" | "processing" | "completed" | "failed" | "cancelled";
4593
+ /** Format: uri */
4594
+ url: string;
4595
+ /** @description Bounded pre-signed download URL retained from the ordinary item, or `null` when the reference did not fit or could not be produced. */
4596
+ content_url: string | null;
4597
+ error_code: string | null;
4598
+ /** @description Bounded failure detail; a long message is truncated. */
4599
+ error_message: string | null;
4600
+ })[];
4352
4601
  };
4353
4602
  };
4354
4603
  };
@@ -4789,7 +5038,14 @@ export interface operations {
4789
5038
  };
4790
5039
  listBulkScreenshots: {
4791
5040
  parameters: {
4792
- query?: never;
5041
+ query?: {
5042
+ /** @description Opaque per-type seek cursor returned by the preceding page. It is bound to this bulk id, this mixed recovery route, and the exact status filter; cross-scope cursors return 422. */
5043
+ cursor?: string;
5044
+ /** @description Maximum rows selected per requested item type; the 16-MiB response bound may stop sooner. */
5045
+ limit?: number;
5046
+ /** @description Optional item-status filter. A cursor may be reused only with the same filter. */
5047
+ status?: "pending" | "processing" | "completed" | "failed" | "cancelled";
5048
+ };
4793
5049
  header?: never;
4794
5050
  path: {
4795
5051
  id: string;
@@ -4809,8 +5065,13 @@ export interface operations {
4809
5065
  bulk_id: string;
4810
5066
  /** @description Number of items in `items` (page size, not the job total). */
4811
5067
  total: number;
5068
+ /** @description Opaque per-type cursor for the next stable page; null when every selected item type is exhausted. Never advances past an item omitted by the byte bound. */
5069
+ next_cursor: string | null;
5070
+ /** @description True when another page is available through `next_cursor`. */
5071
+ has_more: boolean;
5072
+ job_counters: components["schemas"]["BulkJobCounters"];
4812
5073
  /** @description Heterogeneous capture items discriminated by `type`. Fields outside the common set are present only for the matching `type`. */
4813
- items: {
5074
+ items: ({
4814
5075
  /** @enum {string} */
4815
5076
  type: "screenshot" | "recording" | "scrape";
4816
5077
  /** @description Prefixed id — `ss_` / `rec_` / `sc_` per `type`. */
@@ -4819,7 +5080,7 @@ export interface operations {
4819
5080
  status: "pending" | "processing" | "completed" | "failed" | "cancelled";
4820
5081
  /** Format: uri */
4821
5082
  url: string;
4822
- credits_charged: number | null;
5083
+ credits_charged?: number | null;
4823
5084
  /**
4824
5085
  * @description Itemised account of this item's charge — the basis, the named factors
4825
5086
  * that composed the multiplier, and the resulting billed bytes. Omitted
@@ -4827,12 +5088,13 @@ export interface operations {
4827
5088
  */
4828
5089
  billing?: components["schemas"]["BillingNode"];
4829
5090
  error_code: string | null;
5091
+ /** @description Bounded human-readable failure detail. */
4830
5092
  error_message: string | null;
4831
5093
  /** Format: date-time */
4832
- created_at: string;
5094
+ created_at?: string;
4833
5095
  /** Format: date-time */
4834
- completed_at: string | null;
4835
- /** @description `type: screenshot` only. Presigned for completed rows with a storage key; raw image_url otherwise. */
5096
+ completed_at?: string | null;
5097
+ /** @description `type: screenshot` only. Pre-signed download URL for the image, minted fresh for completed rows with a storage key and valid for 600 seconds (10 minutes). For every other row the stored value is returned unchanged — `null` while no image has been stored, and otherwise a private, unsigned storage URL that returns 401 on download. That covers non-completed rows, completed rows with no storage key, and completed rows whose object could not be signed; none of them raise an `artifact_warnings` entry. */
4836
5098
  image_url?: string | null;
4837
5099
  /** @description `type: screenshot` and `type: scrape` only. */
4838
5100
  page_title?: string | null;
@@ -4840,7 +5102,7 @@ export interface operations {
4840
5102
  format?: string;
4841
5103
  /** @description `type: recording` only. */
4842
5104
  video_url?: string | null;
4843
- /** @description `type: scrape` only. Pre-signed download URL for the scraped body, valid for 600 seconds (10 minutes) from the moment this response was generated — matching the signing TTL of `image_url` above and of `content_url` on `GET /v1/fetch/bulk/{id}`. A new signature is minted on every poll. Null for items with no stored body; a completed item whose object cannot be signed falls back to the unsigned stored URL, which returns 401 on download. */
5105
+ /** @description `type: scrape` only. Pre-signed download URL for the scraped body, valid for 600 seconds (10 minutes) from the moment this response was generated — matching the signing TTL of `image_url` above and of `content_url` on `GET /v1/fetch/bulk/{id}`. A new signature is minted on every poll for a completed item with a storage key. For every other item the stored value is returned unchanged — `null` while no body has been stored, and otherwise a private, unsigned storage URL that returns 401 on download. No `artifact_warnings` entry is raised for this field; unlike `GET /v1/fetch/bulk/{id}`, this endpoint reports no `artifact_unavailable` when signing fails. */
4844
5106
  content_url?: string | null;
4845
5107
  /** @description `type: scrape` only. */
4846
5108
  content_type?: string | null;
@@ -4848,9 +5110,33 @@ export interface operations {
4848
5110
  content_length?: number | null;
4849
5111
  /** @description `type: scrape` only. Always null in bulk listings — fetch the body via `markdown_url`. */
4850
5112
  markdown?: string | null;
4851
- /** @description `type: scrape` only. Pre-signed download URL for the markdown rendering of the page, valid for 600 seconds (10 minutes) from the moment this response was generated — the same signing TTL as `content_url` and `image_url` above. A new signature is minted on every poll. Null for items with no stored markdown; a completed item whose object cannot be signed falls back to the unsigned stored URL, which returns 401 on download. */
5113
+ /** @description `type: scrape` only. Pre-signed download URL for the markdown rendering of the page, valid for 600 seconds (10 minutes) from the moment this response was generated — the same signing TTL as `content_url` and `image_url` above. A new signature is minted on every poll for a completed item with a markdown key. For every other item the stored value is returned unchanged — `null` while no markdown has been stored, and otherwise a private, unsigned storage URL that returns 401 on download. No `artifact_warnings` entry is raised for this field; unlike `GET /v1/fetch/bulk/{id}`, this endpoint reports no `artifact_unavailable` when signing fails. */
4852
5114
  markdown_url?: string | null;
4853
- }[];
5115
+ /** @description `type: scrape` only. Exact requested artifact values or signed references. Every key is present; unrequested or unavailable values are null, with nonfatal reference failures in `artifact_warnings`. */
5116
+ artifacts?: {
5117
+ raw: string | null;
5118
+ markdown: string | null;
5119
+ links: null | (string | components["schemas"]["ScrapeScoredLink"])[];
5120
+ images: null | (string | components["schemas"]["ScrapeScoredImage"])[];
5121
+ };
5122
+ /** @description Nonfatal artifact reference failures for this scrape item. */
5123
+ artifact_warnings?: components["schemas"]["ScrapeWarning"][];
5124
+ } | {
5125
+ /** @description Prefixed id — `ss_` / `rec_` / `sc_` per `type`. The same stable identity the ordinary item carries. */
5126
+ id: string;
5127
+ /** @enum {string} */
5128
+ type: "screenshot" | "recording" | "scrape";
5129
+ /**
5130
+ * @description Terminal state of the item. This is the contract's terminal signal and outranks the ordinary item's legacy `status` spelling.
5131
+ * @enum {string}
5132
+ */
5133
+ terminal_outcome: "pending" | "processing" | "completed" | "failed" | "cancelled";
5134
+ /** Format: uri */
5135
+ url: string;
5136
+ error_code: string | null;
5137
+ /** @description Bounded failure detail; a long message is truncated. */
5138
+ error_message: string | null;
5139
+ })[];
4854
5140
  };
4855
5141
  };
4856
5142
  };
@@ -5619,7 +5905,7 @@ export interface operations {
5619
5905
  plan_type: "payg" | "subscription";
5620
5906
  /** @description Total top-up spend in cents for this billing period. Present only in dual/bytes billing mode. */
5621
5907
  topup_spent_cents?: number;
5622
- /** @description Remaining purchased top-up bytes, already net of any overage consumed against them. Equal to topup_bytes. Present only in dual/bytes billing mode. */
5908
+ /** @description Remaining top-up bytes across purchased top-up lots and the one-time starter grant, already net of any overage consumed against them. Equal to topup_bytes. Present only in dual/bytes billing mode. */
5623
5909
  topup_balance_bytes?: number;
5624
5910
  /** @description Days elapsed since period_start. */
5625
5911
  period_days_elapsed: number;
@@ -5825,7 +6111,7 @@ export interface operations {
5825
6111
  error_message?: string | null;
5826
6112
  /** @description Prefixed key id (ak_) that issued the request. */
5827
6113
  api_key_id?: string | null;
5828
- /** @description Stored content, image or video URL — null when the row has no stored object. For a `completed` row with a stored object this is a **pre-signed** download URL, minted fresh on every read of this endpoint and valid for **600 seconds (10 minutes)** — the same signing lifetime as `content_url` on `GET /v1/fetch/bulk/{id}` and `image_url` on `GET /v1/bulk/{id}/screenshots`. The underlying objects are private, so an unsigned URL returns 401: download inside that window, or re-poll this endpoint for a fresh signature. Rows that are not `completed`, and completed rows whose object cannot be signed, fall back to the unsigned stored URL, which returns 401 on download. */
6114
+ /** @description Stored content, image or video URL. For a `completed` row with a non-empty storage key this is a **pre-signed** download URL, minted fresh on every read of this endpoint and valid for **600 seconds (10 minutes)** — the same signing lifetime as `content_url` on `GET /v1/fetch/bulk/{id}` and `image_url` on `GET /v1/bulk/{id}/screenshots`. Download inside that window, or re-poll this endpoint for a fresh signature. For every other row the stored value is returned unchanged — `null` while no object has been stored, and otherwise a private, unsigned storage URL that returns 401 on download. That covers rows that are not `completed`, completed rows with no storage key, and completed rows whose object could not be signed; this endpoint raises no `artifact_unavailable` signal for any of them. */
5829
6115
  artifact_url?: string | null;
5830
6116
  /** @description The original request options. */
5831
6117
  options?: {
@@ -6337,7 +6623,10 @@ export interface operations {
6337
6623
  };
6338
6624
  content: {
6339
6625
  "application/json": {
6340
- bandwidth: components["schemas"]["BandwidthBalance"];
6626
+ bandwidth: components["schemas"]["BandwidthBalance"] & {
6627
+ /** @description Remaining balance of your subscription allowance: bytes still unspent across all allowance lots, the current period's and any rolled over from earlier periods alike, after active refund reservations. This is a remaining balance and falls to zero as the allowance is drawn down. It is not `included_bytes`, which is the plan's configured grant for a period and does not move as it is spent; do not subtract one from the other. `rollover_bytes` is a subset of this figure. */
6628
+ remaining_allowance_bytes: number;
6629
+ };
6341
6630
  credits: components["schemas"]["CreditBalance"];
6342
6631
  rates: {
6343
6632
  /** @description Bandwidth top-up price in cents per MB. When the authenticated account is on a plan that does not explicitly configure a top-up price (e.g. free, payg, or a custom plan without an explicit value), the API falls back to the rack rate — the highest `topup_price_per_mb_cents` configured across all plans — so the UI never advertises `$0.00/GB`. */
@@ -6382,8 +6671,8 @@ export interface operations {
6382
6671
  * @enum {integer}
6383
6672
  */
6384
6673
  amount_bytes?: 5000000000 | 25000000000 | 50000000000 | 75000000000 | 100000000000;
6385
- /** @description $1-$1000. Required when enabled. */
6386
- monthly_cap_cents?: number;
6674
+ /** @description $1-$1000, or null for no monthly cap. Required when enabled — send an explicit null to remove the cap; omitting the key is rejected. */
6675
+ monthly_cap_cents?: number | null;
6387
6676
  };
6388
6677
  };
6389
6678
  };