@hunt-labs/bytekit-sdk 0.8.0 → 0.9.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.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,42 @@ today, see [README.md](./README.md), which remains the authoritative usage guide
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.9.0] - 2026-08-20
14
+
15
+ ### Removed
16
+
17
+ - **BREAKING: the `cookies` and `headers` request-body fields are gone from every capture
18
+ endpoint** (#3242) — `/v1/scrape`, `/v1/scrape/bulk`, `/v1/screenshots`, `/v1/recordings` and
19
+ `/v1/schema`. A request that carries either field is rejected with `400 validation_error`; it
20
+ is not ignored, and there is no deprecation window, feature flag, or compatibility header.
21
+ `ScrapeOpts.cookies`, `ScrapeOpts.headers` and the exported `ScrapeCookie` type are removed
22
+ from the SDK surface, so a call that still passes them no longer compiles.
23
+
24
+ ```ts
25
+ // before — compiled, and the values were forwarded to the target site
26
+ await client.scrape.create({ url, cookies: [{ name: 'session', value: 'abc' }] });
27
+ // after — does not compile; the same body over raw HTTP is a 400 validation_error
28
+ await client.scrape.create({ url });
29
+ ```
30
+
31
+ ByteKit continues to manage its own cookie jar and request headers internally; what was removed
32
+ is the caller's ability to inject or override them.
33
+
34
+ ### Changed
35
+
36
+ - **The generated types now declare the `503` response of `GET`/`POST /v1/fetch`** (#3372).
37
+ `/v1/fetch` answers `503` on two conditions and both carry the ordinary `Error` envelope, so
38
+ a typed consumer reading `operations['getFetch']['responses']` / `['postFetch']` can handle it
39
+ instead of meeting an undeclared status at runtime. Read `error.code` to tell the two apart,
40
+ because they disagree about `error.http_status`:
41
+ - `upstream_error` — the target returned HTTP `502`, relayed at `503` because Cloudflare
42
+ replaces a clean origin 502 with its own error page. `error.http_status` stays `502`, the
43
+ **true upstream status**, and is the only surviving record of what the target answered.
44
+ - `internal_error` (`Fetch service unavailable.`) — the fetch service was unreachable. There
45
+ is no upstream, so `error.http_status` reports `503`, matching what was served.
46
+
47
+ No runtime behaviour changes, and every other documented `/v1/fetch` status is unaffected.
48
+
13
49
  ## [0.8.0] - 2026-08-19
14
50
 
15
51
  ### Removed
@@ -272,8 +272,9 @@ export interface paths {
272
272
  };
273
273
  /**
274
274
  * Fetch a URL (GET)
275
- * @description Direct HTTP fetch. The response body IS the content; metadata is returned in X-Fetch-* headers.
276
- * Omit `format` for raw passthrough. Use `format=markdown` or `format=html` for conversion.
275
+ * @description Direct HTTP fetch. Successful responses return the upstream response bytes verbatim;
276
+ * metadata is returned in X-Fetch-* headers. Non-2xx upstream responses use the
277
+ * `upstream_error` JSON envelope with the upstream HTTP status.
277
278
  */
278
279
  get: operations["getFetch"];
279
280
  put?: never;
@@ -303,7 +304,7 @@ export interface paths {
303
304
  /**
304
305
  * Bulk fetch URLs
305
306
  * @description Enqueues multiple URLs for HTTP fetching. Results delivered via webhook.
306
- * Does not support options that require page rendering (cookies, wait_for_selector, etc.).
307
+ * Does not support options that require page rendering (wait_for_selector, etc.).
307
308
  *
308
309
  * **Limits:** request bodies are guarded in a two-tier shape. A streamed body
309
310
  * with no `Content-Length` header is capped at 2 MB before your API key
@@ -588,8 +589,8 @@ export interface paths {
588
589
  * Schema-driven structured extraction
589
590
  * @description Fetches `url` and extracts structured JSON conforming to the supplied
590
591
  * JSON Schema (draft 2020-12) using an LLM. Fast-path only — slow-path
591
- * rendering options (`wait_until=networkidle`, `cookies`, `delay_ms`,
592
- * custom `headers`, `wait_for_selector`) cause a `400 unsupported_url`.
592
+ * rendering options (`wait_until=networkidle`, `delay_ms`,
593
+ * `wait_for_selector`) cause a `400 unsupported_url`.
593
594
  *
594
595
  * Dual-axis billing: a fixed per-request credit charge **plus** the
595
596
  * underlying page's bandwidth, billed exactly like `/v1/scrape`. The
@@ -1041,7 +1042,7 @@ export interface paths {
1041
1042
  /**
1042
1043
  * Query scrape by URL (deprecated)
1043
1044
  * @deprecated
1044
- * @description Use GET /v1/fetch?url=...&format=markdown instead.
1045
+ * @description Use GET /v1/fetch?url=... instead.
1045
1046
  */
1046
1047
  get: operations["queryScrapeLegacy"];
1047
1048
  put?: never;
@@ -1404,14 +1405,6 @@ export interface components {
1404
1405
  details?: unknown;
1405
1406
  };
1406
1407
  };
1407
- Cookie: {
1408
- name: string;
1409
- value: string;
1410
- domain?: string;
1411
- path?: string;
1412
- secure?: boolean;
1413
- httpOnly?: boolean;
1414
- };
1415
1408
  Viewport: {
1416
1409
  width: number;
1417
1410
  height: number;
@@ -1534,12 +1527,6 @@ export interface components {
1534
1527
  formats: ("raw_html" | "html" | "markdown" | "links" | "images")[];
1535
1528
  /** @default US */
1536
1529
  country: string;
1537
- /** @default [] */
1538
- cookies: components["schemas"]["Cookie"][];
1539
- /** @default {} */
1540
- headers: {
1541
- [key: string]: string;
1542
- };
1543
1530
  /** @default 0 */
1544
1531
  delay_ms: number;
1545
1532
  /** @default 30000 */
@@ -1914,8 +1901,6 @@ export interface components {
1914
1901
  FetchRequest: {
1915
1902
  /** Format: uri */
1916
1903
  url: string;
1917
- /** @enum {string} */
1918
- format?: "markdown" | "html";
1919
1904
  /** @default US */
1920
1905
  country: string;
1921
1906
  /** @default 60000 */
@@ -1932,37 +1917,6 @@ export interface components {
1932
1917
  custom: {
1933
1918
  [key: string]: unknown;
1934
1919
  };
1935
- /**
1936
- * @description Markdown processing mode. Only used when format=markdown.
1937
- * @enum {string}
1938
- */
1939
- markdown_mode?: "article" | "raw" | "llm";
1940
- /** @description BM25 query string for relevance-ranked filtering. Only used when format=markdown. */
1941
- markdown_query?: string;
1942
- /**
1943
- * @description Link rendering style. Only used when format=markdown.
1944
- * @enum {string}
1945
- */
1946
- markdown_links?: "inline" | "references" | "none" | "text";
1947
- /**
1948
- * @description Image retention mode. Only used when format=markdown.
1949
- * @enum {string}
1950
- */
1951
- markdown_images?: "inline" | "references" | "none" | "text";
1952
- /** @description Append a Links footer to the markdown output. Only used when format=markdown. */
1953
- with_links_summary?: boolean;
1954
- /** @description Append an Images footer to the markdown output. Only used when format=markdown. */
1955
- with_images_summary?: boolean;
1956
- /** @description Compact whitespace output. Only used when format=markdown. */
1957
- markdown_compact?: boolean;
1958
- /** @description Filter low-signal images. Only used when format=markdown. */
1959
- markdown_filter_images?: boolean;
1960
- /** @description When true, `formats.links` and `formats.images` return `ScrapeScoredLink[]` / `ScrapeScoredImage[]` (rich objects) instead of `string[]`, and a top-level `tables` array is included. Only used when format=markdown. */
1961
- markdown_include_media?: boolean;
1962
- /** @description When true, enables markdown-pipeline and tag-filter warnings for affected html and markdown requests. Artifact availability warnings such as `artifact_unavailable` may appear independently of this flag. */
1963
- markdown_include_warnings?: boolean;
1964
- /** @description When true, includes a top-level `stats` object with `ScrapeStats` (chars, tokens, blocks). Only used when format=markdown. */
1965
- markdown_include_stats?: boolean;
1966
1920
  };
1967
1921
  ScreenshotRequest: {
1968
1922
  /** Format: uri */
@@ -2000,12 +1954,6 @@ export interface components {
2000
1954
  scroll: boolean;
2001
1955
  /** @default null */
2002
1956
  clip: components["schemas"]["Clip"] | null;
2003
- /** @default {} */
2004
- headers: {
2005
- [key: string]: string;
2006
- };
2007
- /** @default [] */
2008
- cookies: components["schemas"]["Cookie"][];
2009
1957
  /** @default false */
2010
1958
  dark_mode: boolean;
2011
1959
  /**
@@ -2125,12 +2073,6 @@ export interface components {
2125
2073
  /** @default 0 */
2126
2074
  delay_ms: number;
2127
2075
  scroll?: components["schemas"]["ScrollOptions"];
2128
- /** @default {} */
2129
- headers: {
2130
- [key: string]: string;
2131
- };
2132
- /** @default [] */
2133
- cookies: components["schemas"]["Cookie"][];
2134
2076
  /** @default false */
2135
2077
  dark_mode: boolean;
2136
2078
  /** @default US */
@@ -2699,7 +2641,6 @@ export interface components {
2699
2641
  */
2700
2642
  ClientSurfaceMarker: string;
2701
2643
  FetchUrl: string;
2702
- FetchFormat: "markdown" | "html";
2703
2644
  FetchCountry: string;
2704
2645
  FetchTimeoutMs: number;
2705
2646
  /** @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. */
@@ -2739,11 +2680,9 @@ export interface components {
2739
2680
  XFetchURL: string;
2740
2681
  /**
2741
2682
  * @description Byte length of the response body served on this request (integer as string) — NOT the
2742
- * billing basis. On a passthrough request (no `format`) the body is the relayed upstream
2743
- * payload, so this equals the upstream wire byte count. With `format=html` or
2744
- * `format=markdown` the body is the transformed document, so this is the transformed byte
2745
- * count and is typically far smaller than what is billed. Billing always reads the upstream
2746
- * compressed wire bytes from `X-Raw-Bytes` / `X-Billable-Bytes`, on every path.
2683
+ * billing basis. The body is always the upstream response bytes, so this equals the upstream wire byte
2684
+ * count. Billing always reads the upstream compressed wire bytes from `X-Raw-Bytes` /
2685
+ * `X-Billable-Bytes`, on every path.
2747
2686
  */
2748
2687
  XFetchContentLength: string;
2749
2688
  XFetchCreditsCharged: string;
@@ -3625,10 +3564,6 @@ export interface operations {
3625
3564
  url: string;
3626
3565
  formats?: ("raw_html" | "html" | "markdown" | "links" | "images")[];
3627
3566
  country?: string;
3628
- cookies?: components["schemas"]["Cookie"][];
3629
- headers?: {
3630
- [key: string]: string;
3631
- };
3632
3567
  delay_ms?: number;
3633
3568
  timeout_ms?: number;
3634
3569
  metadata?: components["schemas"]["Metadata"];
@@ -3663,10 +3598,6 @@ export interface operations {
3663
3598
  formats?: ("raw_html" | "html" | "markdown" | "links" | "images")[];
3664
3599
  /** @default US */
3665
3600
  country?: string;
3666
- cookies?: components["schemas"]["Cookie"][];
3667
- headers?: {
3668
- [key: string]: string;
3669
- };
3670
3601
  /** @default 0 */
3671
3602
  delay_ms?: number;
3672
3603
  /** @default 30000 */
@@ -3726,7 +3657,7 @@ export interface operations {
3726
3657
  completed_at: string | null;
3727
3658
  /** @description Always null on the create response — the job has not been billed yet (routes/scrape-bulk.ts builds the 202 body from a partial job row). Fractional when populated (credits are NUMERIC(10,2)); the numeric branch is unreachable on this path and exists only so the 202 and 200 bodies share one shape. */
3728
3659
  total_credits_charged: number | null;
3729
- /** @description Estimated credits at submission time. Null in GET responses. Fractional — markdown/html formats weigh 0.5 credits each (scrape-shared/src/credits.ts), so a one-item markdown job is 1.5. */
3660
+ /** @description Estimated credits at submission time. Null in GET responses. Fetch-bulk items use the raw fetch bandwidth billing factor. */
3730
3661
  estimated_credits: number | null;
3731
3662
  /** @description Webhook endpoint URL (HTTPS only; http:// rejected with 400 invalid_url, reason scheme_unsupported) */
3732
3663
  webhook_url: string;
@@ -3826,7 +3757,6 @@ export interface operations {
3826
3757
  parameters: {
3827
3758
  query: {
3828
3759
  url: components["parameters"]["FetchUrl"];
3829
- format?: components["parameters"]["FetchFormat"];
3830
3760
  country?: components["parameters"]["FetchCountry"];
3831
3761
  timeout_ms?: components["parameters"]["FetchTimeoutMs"];
3832
3762
  /** @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. */
@@ -3860,16 +3790,14 @@ export interface operations {
3860
3790
  "X-Raw-Bytes"?: number;
3861
3791
  /** @description Chargeable bytes after applying the billing multiplier. Equals round(X-Raw-Bytes × X-Billing-Multiplier). */
3862
3792
  "X-Billable-Bytes"?: number;
3863
- /** @description Bandwidth cost multiplier applied to X-Raw-Bytes. A markdown fetch bills as fetch_md (miss 1.5, hit 0.75); a raw fetch bills 1.0 on a miss, 0.5 on a cache hit. Single `/v1/fetch` returns the fetched bytes as the body, so it carries no `billing` node — this header trio is the ONLY billing surface here. Items under `GET /v1/fetch/bulk/{id}` do carry the node. */
3793
+ /** @description Bandwidth cost multiplier applied to X-Raw-Bytes. Single `/v1/fetch` returns the fetched bytes as the body, so it carries no `billing` node — this header trio is the ONLY billing surface here. Items under `GET /v1/fetch/bulk/{id}` do carry the node. */
3864
3794
  "X-Billing-Multiplier"?: number;
3865
3795
  /** @description Back-compat duplicate of `X-Billing-Multiplier` — identical value on every path. Prefer `X-Billing-Multiplier`; this alias is retained for clients that read the `X-Fetch-*` header family. */
3866
3796
  "X-Fetch-Billing-Multiplier"?: number;
3867
3797
  [name: string]: unknown;
3868
3798
  };
3869
3799
  content: {
3870
- "*/*": string;
3871
- "text/markdown": string;
3872
- "text/html": string;
3800
+ "text/plain": string;
3873
3801
  };
3874
3802
  };
3875
3803
  /** @description Invalid URL (`invalid_url`) or oversized request. */
@@ -3881,7 +3809,7 @@ export interface operations {
3881
3809
  "application/json": components["schemas"]["Error"];
3882
3810
  };
3883
3811
  };
3884
- /** @description Validation error (e.g. unsupported `format`, slow-path-only field, or `format=html` against a non-HTML content type). */
3812
+ /** @description Validation error (e.g. slow-path-only field). */
3885
3813
  422: {
3886
3814
  headers: {
3887
3815
  [name: string]: unknown;
@@ -3900,10 +3828,14 @@ export interface operations {
3900
3828
  };
3901
3829
  };
3902
3830
  /**
3903
- * @description Fetch service unavailable, content transform failed, or a non-2xx upstream
3904
- * response relayed as the unified Error envelope. On an upstream relay the HTTP
3905
- * status equals the upstream status (code `upstream_error`), so any 4xx/5xx the
3906
- * target returns surfaces here as an Error envelope rather than a raw body (#1462).
3831
+ * @description Content transform failed, or a non-2xx upstream response relayed as the unified
3832
+ * Error envelope. On an upstream relay the HTTP status equals the upstream status
3833
+ * (code `upstream_error`), so any 4xx/5xx the target returns surfaces here as an
3834
+ * Error envelope rather than a raw body (#1462).
3835
+ *
3836
+ * **One divergence.** An upstream `502` is relayed at HTTP `503`, not `502` — see
3837
+ * the `503` response below. A fetch service that cannot be reached also answers
3838
+ * `503`, not `502` (#3373); this status no longer covers that condition.
3907
3839
  */
3908
3840
  502: {
3909
3841
  headers: {
@@ -3913,6 +3845,30 @@ export interface operations {
3913
3845
  "application/json": components["schemas"]["Error"];
3914
3846
  };
3915
3847
  };
3848
+ /**
3849
+ * @description Two distinct conditions answer `503`, and they disagree about what the body's
3850
+ * `error.http_status` reports. Read `error.code` to tell them apart.
3851
+ *
3852
+ * - **`upstream_error`** — the target returned HTTP `502`, relayed here as `503`.
3853
+ * Cloudflare fronts this API and replaces a clean origin 502 with its own generic
3854
+ * `text/plain` error page, discarding the envelope before it reaches you, while a
3855
+ * 503 is passed through unchanged. The body's `error.http_status` still reports
3856
+ * the **true upstream status**, `502` — not `503` — and is the only surviving
3857
+ * record of what the target answered, so the body rather than the HTTP status is
3858
+ * authoritative here (#3355).
3859
+ * - **`internal_error`** (message `Fetch service unavailable.`) — the fetch service
3860
+ * could not be reached at all. There is no upstream status to preserve: the `503`
3861
+ * is this API's own choice of wire status, so the body's `error.http_status`
3862
+ * reports `503`, mirroring what was served (#3373).
3863
+ */
3864
+ 503: {
3865
+ headers: {
3866
+ [name: string]: unknown;
3867
+ };
3868
+ content: {
3869
+ "application/json": components["schemas"]["Error"];
3870
+ };
3871
+ };
3916
3872
  };
3917
3873
  };
3918
3874
  postFetch: {
@@ -3926,10 +3882,7 @@ export interface operations {
3926
3882
  content: {
3927
3883
  /**
3928
3884
  * @example {
3929
- * "url": "https://example.com",
3930
- * "format": "markdown",
3931
- * "markdown_mode": "article",
3932
- * "markdown_links": "inline"
3885
+ * "url": "https://example.com"
3933
3886
  * }
3934
3887
  */
3935
3888
  "application/json": components["schemas"]["FetchRequest"];
@@ -3958,16 +3911,14 @@ export interface operations {
3958
3911
  "X-Raw-Bytes"?: number;
3959
3912
  /** @description Chargeable bytes after applying the billing multiplier. Equals round(X-Raw-Bytes × X-Billing-Multiplier). */
3960
3913
  "X-Billable-Bytes"?: number;
3961
- /** @description Bandwidth cost multiplier applied to X-Raw-Bytes. A markdown fetch bills as fetch_md (miss 1.5, hit 0.75); a raw fetch bills 1.0 on a miss, 0.5 on a cache hit. Single `/v1/fetch` returns the fetched bytes as the body, so it carries no `billing` node — this header trio is the ONLY billing surface here. Items under `GET /v1/fetch/bulk/{id}` do carry the node. */
3914
+ /** @description Bandwidth cost multiplier applied to X-Raw-Bytes. Single `/v1/fetch` returns the fetched bytes as the body, so it carries no `billing` node — this header trio is the ONLY billing surface here. Items under `GET /v1/fetch/bulk/{id}` do carry the node. */
3962
3915
  "X-Billing-Multiplier"?: number;
3963
3916
  /** @description Back-compat duplicate of `X-Billing-Multiplier` — identical value on every path. Prefer `X-Billing-Multiplier`; this alias is retained for clients that read the `X-Fetch-*` header family. */
3964
3917
  "X-Fetch-Billing-Multiplier"?: number;
3965
3918
  [name: string]: unknown;
3966
3919
  };
3967
3920
  content: {
3968
- "*/*": string;
3969
- "text/markdown": string;
3970
- "text/html": string;
3921
+ "text/plain": string;
3971
3922
  };
3972
3923
  };
3973
3924
  /** @description Invalid URL (`invalid_url`) or oversized request body. */
@@ -3979,7 +3930,7 @@ export interface operations {
3979
3930
  "application/json": components["schemas"]["Error"];
3980
3931
  };
3981
3932
  };
3982
- /** @description Validation error (e.g. malformed JSON, unsupported `format`, slow-path-only field, or `format=html` against a non-HTML content type). */
3933
+ /** @description Validation error (e.g. malformed JSON, unsupported fetch format, or slow-path-only field). */
3983
3934
  422: {
3984
3935
  headers: {
3985
3936
  [name: string]: unknown;
@@ -3998,10 +3949,14 @@ export interface operations {
3998
3949
  };
3999
3950
  };
4000
3951
  /**
4001
- * @description Fetch service unavailable, content transform failed, or a non-2xx upstream
4002
- * response relayed as the unified Error envelope. On an upstream relay the HTTP
4003
- * status equals the upstream status (code `upstream_error`), so any 4xx/5xx the
4004
- * target returns surfaces here as an Error envelope rather than a raw body (#1462).
3952
+ * @description Content transform failed, or a non-2xx upstream response relayed as the unified
3953
+ * Error envelope. On an upstream relay the HTTP status equals the upstream status
3954
+ * (code `upstream_error`), so any 4xx/5xx the target returns surfaces here as an
3955
+ * Error envelope rather than a raw body (#1462).
3956
+ *
3957
+ * **One divergence.** An upstream `502` is relayed at HTTP `503`, not `502` — see
3958
+ * the `503` response below. A fetch service that cannot be reached also answers
3959
+ * `503`, not `502` (#3373); this status no longer covers that condition.
4005
3960
  */
4006
3961
  502: {
4007
3962
  headers: {
@@ -4011,6 +3966,30 @@ export interface operations {
4011
3966
  "application/json": components["schemas"]["Error"];
4012
3967
  };
4013
3968
  };
3969
+ /**
3970
+ * @description Two distinct conditions answer `503`, and they disagree about what the body's
3971
+ * `error.http_status` reports. Read `error.code` to tell them apart.
3972
+ *
3973
+ * - **`upstream_error`** — the target returned HTTP `502`, relayed here as `503`.
3974
+ * Cloudflare fronts this API and replaces a clean origin 502 with its own generic
3975
+ * `text/plain` error page, discarding the envelope before it reaches you, while a
3976
+ * 503 is passed through unchanged. The body's `error.http_status` still reports
3977
+ * the **true upstream status**, `502` — not `503` — and is the only surviving
3978
+ * record of what the target answered, so the body rather than the HTTP status is
3979
+ * authoritative here (#3355).
3980
+ * - **`internal_error`** (message `Fetch service unavailable.`) — the fetch service
3981
+ * could not be reached at all. There is no upstream status to preserve: the `503`
3982
+ * is this API's own choice of wire status, so the body's `error.http_status`
3983
+ * reports `503`, mirroring what was served (#3373).
3984
+ */
3985
+ 503: {
3986
+ headers: {
3987
+ [name: string]: unknown;
3988
+ };
3989
+ content: {
3990
+ "application/json": components["schemas"]["Error"];
3991
+ };
3992
+ };
4014
3993
  };
4015
3994
  };
4016
3995
  createFetchBulk: {
@@ -4026,14 +4005,10 @@ export interface operations {
4026
4005
  urls: (string | {
4027
4006
  /** Format: uri */
4028
4007
  url: string;
4029
- /** @enum {string} */
4030
- format?: "markdown" | "html";
4031
4008
  country?: string;
4032
4009
  cache_ttl?: string;
4033
4010
  })[];
4034
4011
  defaults?: {
4035
- /** @enum {string} */
4036
- format?: "markdown" | "html";
4037
4012
  /** @default US */
4038
4013
  country?: string;
4039
4014
  /** @default 48h */
@@ -4070,7 +4045,7 @@ export interface operations {
4070
4045
  completed_at: string | null;
4071
4046
  /** @description Always null on the create response — the job has not been billed yet (routes/fetch-bulk.ts builds the 202 body from a partial job row). Fractional when populated (credits are NUMERIC(10,2)); the numeric branch is unreachable on this path and exists only so the 202 and 200 bodies share one shape. */
4072
4047
  total_credits_charged: number | null;
4073
- /** @description Estimated credits at submission time. Null in GET responses. Fractional — markdown/html formats weigh 0.5 credits each (scrape-shared/src/credits.ts), so a one-item markdown job is 1.5. */
4048
+ /** @description Estimated credits at submission time. Null in GET responses. Fetch items are raw passthrough requests and use the raw fetch bandwidth billing factor. */
4074
4049
  estimated_credits: number | null;
4075
4050
  /** @description Webhook endpoint URL (HTTPS only; http:// rejected with 400 invalid_url, reason scheme_unsupported) */
4076
4051
  webhook_url: string;
@@ -4427,7 +4402,7 @@ export interface operations {
4427
4402
  completed_at: string | null;
4428
4403
  /** @description Always null on the create response — the job has not been billed yet (routes/bulk.ts builds the 202 body from a partial job row). Fractional when populated (credits are NUMERIC(10,2)); the numeric branch is unreachable on this path and exists only so the 202 and 200 bodies share one shape. */
4429
4404
  total_credits_charged: number | null;
4430
- /** @description Estimated credits at submission time. Null in GET responses. Fractional — markdown/html formats weigh 0.5 credits each (scrape-shared/src/credits.ts), so a one-item markdown job is 1.5. */
4405
+ /** @description Estimated credits at submission time. Null in GET responses. Fetch-bulk items use the raw fetch bandwidth billing factor. */
4431
4406
  estimated_credits: number | null;
4432
4407
  /** @description Webhook endpoint URL (HTTPS only; http:// rejected with 400 invalid_url, reason scheme_unsupported) */
4433
4408
  webhook_url: string;
@@ -5248,18 +5223,8 @@ export interface operations {
5248
5223
  * @enum {string}
5249
5224
  */
5250
5225
  wait_until?: "load" | "domcontentloaded" | "networkidle";
5251
- /** @default [] */
5252
- cookies?: {
5253
- name: string;
5254
- value: string;
5255
- domain: string;
5256
- }[];
5257
5226
  /** @default 0 */
5258
5227
  delay_ms?: number;
5259
- /** @default {} */
5260
- headers?: {
5261
- [key: string]: string;
5262
- };
5263
5228
  /**
5264
5229
  * @description Two-letter country code, upper-cased. `null` is coerced to `US`.
5265
5230
  * @default US
@@ -5624,9 +5589,9 @@ export interface operations {
5624
5589
  status_code?: number | null;
5625
5590
  /** @description Raw upstream bytes the request carried (the billing base before the multiplier). null while pending/failed. */
5626
5591
  raw_bytes?: number | null;
5627
- /** @description Billable bytes — raw_bytes × billing_multiplier, rounded. Mirrors the X-Billable-Bytes response header. null while pending/failed. */
5592
+ /** @description The bytes this request was BILLED — the same amount its own response reported in `X-Billable-Bytes`. For a scrape or fetch request this is the settled decomposition replayed as it was recorded at completion, so it already carries every factor that applied: the endpoint factor (`scrape` 1.0, `scrape_md` 1.5, `fetch` 1.0, `fetch_md` 1.5, a monitor run 1.0), the cache-hit ×0.5, and the clean-markdown ×3. Screenshots and recordings are `raw_bytes` × the fixed 1.5 Phase-1 render factor whatever capture options they carried — capture billing composes no discount factor, so that product is exact. It is NOT `raw_bytes` × `billing_multiplier`: that field reports a CREDIT count, a different quantity from the byte factors above, and on a recordings row their product is not bytes at all. One residual: a scrape or fetch row completed before the decomposition was recorded is reconstructed from its endpoint and cache-hit factors, which leaves a markdown `/v1/fetch` request of that vintage reported at 1.0 rather than 1.5 — nothing on such a row distinguishes it. That population ages out of this feed's retention window and is not backfilled. null while pending/failed (the row has no byte basis yet). */
5628
5593
  billable_bytes?: number | null;
5629
- /** @description BASE billing multiplier persisted for this request — the settled `credits_charged` factor, and the same factor `billable_bytes` above is derived from. Its scale is not uniform and is not a rate you can carry from one row to another: each endpoint persists its own credit unit, and the single and bulk paths of the same endpoint may persist different factors for identical options. Read this as the factor this one row settled at, and see that endpoint's own pricing for what it charges. This is a LOGS ROW field and is NOT the scrape response envelope field — the envelope carries no flat `billing_multiplier` at all; its billing surface is the `billing` node (see BillingNode). This row reports only the base settled factor, so it can differ from `billing.multiplier` and from the X-Billing-Multiplier response header, both of which report the composed real-endpoint value. null while pending/failed. */
5594
+ /** @description BASE billing multiplier persisted for this request — the settled `credits_charged` factor. It is NOT what `billable_bytes` above is derived from: that field reports settled BYTES, and multiplying `raw_bytes` by this credit count does not give the amount billed. Its scale is not uniform and is not a rate you can carry from one row to another: each endpoint persists its own credit unit, and the single and bulk paths of the same endpoint may persist different factors for identical options. Read this as the factor this one row settled at, and see https://bytekit.com/docs/billing/credits for what each endpoint charges. This is a LOGS ROW field and is NOT the scrape response envelope field — the envelope carries no flat `billing_multiplier` at all; its billing surface is the `billing` node (see BillingNode). This row reports only the base settled factor, so it can differ from `billing.multiplier` and from the X-Billing-Multiplier response header, both of which report the composed real-endpoint value. null while pending/failed. */
5630
5595
  billing_multiplier?: number | null;
5631
5596
  duration_ms?: number | null;
5632
5597
  /** @description How the request originated (single/bulk/monitor). */
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export type { ByteKitOptions, RequestOptions, ApiResponse, ConnectionErrorCode,
3
3
  export { V01_METHODS } from './allowlist.js';
4
4
  export type { V01Method } from './allowlist.js';
5
5
  export type { ScrapeId, ScreenshotId, BulkId, MonitorId, SitemapId, ApiKeyId, WebhookDeliveryId, SearchType, SearchDateRange, SearchOpts, SearchResult, SearchResultImage, SearchResponse, } from './types.js';
6
- export type { ScrapeCookie, ScrapeOpts, MarkdownMode, MarkdownLinks, MarkdownImages, TokenEncoding, ScrapeCreateResponse, ScrapeGetResponse, ScrapeBulkCreateRequest, ScrapeBulkCreateResponse, ScrapeBulkGetResponse, } from './resources/scrape.js';
6
+ export type { ScrapeOpts, MarkdownMode, MarkdownLinks, MarkdownImages, TokenEncoding, ScrapeCreateResponse, ScrapeGetResponse, ScrapeBulkCreateRequest, ScrapeBulkCreateResponse, ScrapeBulkGetResponse, } from './resources/scrape.js';
7
7
  export type { ScreenshotCreateRequest, ScreenshotCreateResponse, ScreenshotGetResponse, } from './resources/screenshots.js';
8
8
  export type { FetchOpts, FetchGetOpts, FetchResult, FetchCacheStatus, FetchBulkCreateRequest, FetchBulkCreateResponse, FetchBulkGetResponse, } from './resources/fetch.js';
9
9
  export type { MonitorCreateRequest, MonitorCreateResponse, ListMonitorsParams, MonitorStatus, ListMonitorsResponse, MonitorResponse, MonitorUpdateRequest, UpdateMonitorResponse, ListMonitorCapturesResponse, } from './resources/monitors.js';
@@ -15,32 +15,8 @@ export type FetchBulkGetResponse = operations['getFetchBulk']['responses'][200][
15
15
  */
16
16
  export interface FetchOpts {
17
17
  url: string;
18
- /** Output format. `'markdown'` runs the HTML→markdown pipeline; `'html'` returns raw HTML. Narrowed to the spec union — off-spec values (e.g. `'pdf'`) are rejected at compile time. */
19
- format?: 'markdown' | 'html';
20
18
  country?: string;
21
19
  timeout_ms?: number;
22
- /** Markdown processing mode. Only used when `format=markdown`. article/raw/llm. */
23
- markdown_mode?: 'article' | 'raw' | 'llm';
24
- /** BM25 query string for relevance-ranked filtering. Only used when `format=markdown`. */
25
- markdown_query?: string;
26
- /** Link rendering style. Only used when `format=markdown`. */
27
- markdown_links?: 'inline' | 'references' | 'none' | 'text';
28
- /** Image retention mode. Only used when `format=markdown`. */
29
- markdown_images?: 'inline' | 'references' | 'none' | 'text';
30
- /** Append a `Links:` footer to the markdown output. Only used when `format=markdown`. */
31
- with_links_summary?: boolean;
32
- /** Append an `Images:` footer to the markdown output. Only used when `format=markdown`. */
33
- with_images_summary?: boolean;
34
- /** Compact whitespace output. Only used when `format=markdown`. */
35
- markdown_compact?: boolean;
36
- /** Filter low-signal images. Only used when `format=markdown`. */
37
- markdown_filter_images?: boolean;
38
- /** When true, `formats.links`/`formats.images` return rich objects and a top-level `tables` array is included. Only used when `format=markdown`. */
39
- markdown_include_media?: boolean;
40
- /** When true, enables markdown-pipeline and tag-filter warnings for affected html/markdown requests. */
41
- markdown_include_warnings?: boolean;
42
- /** When true, includes a top-level `stats` object (chars, tokens, blocks). Only used when `format=markdown`. */
43
- markdown_include_stats?: boolean;
44
20
  /**
45
21
  * How long a freshly fetched URL may be served from cache. Matches the
46
22
  * OpenAPI `FetchRequest.cache_ttl` schema: a duration string (`"48h"`,
@@ -66,17 +42,15 @@ export interface FetchOpts {
66
42
  * the generated `getFetch` query type by `_AssertFetchGetQueryKeysCoverSpec`
67
43
  * below, so it cannot drift away from the spec silently.
68
44
  */
69
- declare const FETCH_GET_QUERY_KEYS: readonly ["url", "format", "country", "timeout_ms", "cache_ttl"];
45
+ declare const FETCH_GET_QUERY_KEYS: readonly ["url", "country", "timeout_ms", "cache_ttl"];
70
46
  type FetchGetQueryKey = (typeof FETCH_GET_QUERY_KEYS)[number];
71
47
  /**
72
48
  * Options accepted by `fetch.get` (GET /v1/fetch).
73
49
  *
74
- * A strict subset of {@link FetchOpts}: only the five params the spec's
50
+ * A strict subset of {@link FetchOpts}: only the four params the spec's
75
51
  * `GET /v1/fetch` actually declares. Everything else on the POST body —
76
- * `custom` (#2481) and the eleven `markdown_*` / `with_*` tuning fields (#2539) —
77
- * has no GET query param and was silently dropped by the query builder, so it is
78
- * excluded here and passing it is a compile error. Use `create()` (POST) for
79
- * those.
52
+ * `custom` has no GET query param and is excluded here; passing it is a compile
53
+ * error. Use `create()` (POST) for custom metadata.
80
54
  */
81
55
  export type FetchGetOpts = Pick<FetchOpts, FetchGetQueryKey>;
82
56
  /** Cache-lookup outcome reported in the `X-Fetch-Cache` response header. */
@@ -84,8 +58,8 @@ export type FetchCacheStatus = 'hit' | 'miss' | 'bypass';
84
58
  /**
85
59
  * The result of `fetch.create` / `fetch.get`.
86
60
  *
87
- * `/v1/fetch` returns the fetched content AS the response body (text/html,
88
- * text/markdown, or raw binary passthrough) with metadata carried in `X-Fetch-*`
61
+ * `/v1/fetch` returns the fetched content AS the response body, including its
62
+ * original media type and raw bytes, with metadata carried in `X-Fetch-*`
89
63
  * headers on the response — it is NOT a JSON envelope. `body` is therefore the raw
90
64
  * content string, never a parsed object, and the named fields decode the
91
65
  * headers the docs call out. Anything not surfaced here is available on
@@ -144,10 +118,8 @@ export declare class FetchResource {
144
118
  *
145
119
  * Resolves a `FetchResult` — the raw content body plus `X-Fetch-*` metadata.
146
120
  *
147
- * Accepts only the five params the spec declares for this endpoint. `custom`
148
- * (#2481) and the `markdown_*` / `with_*` tuning fields (#2539) are POST-body
149
- * options with no GET query param — they were silently dropped by this builder,
150
- * so they are now compile errors instead. Use `create()` (POST) for those.
121
+ * Accepts only the four params the spec declares for this endpoint. `custom`
122
+ * is a POST-body option with no GET query param; use `create()` for custom metadata.
151
123
  *
152
124
  * The query string is built by iterating `FETCH_GET_QUERY_KEYS`, the same list
153
125
  * `FetchGetOpts` is derived from, so every accepted option is necessarily
@@ -9,7 +9,7 @@ import { buildPath } from '../client.js';
9
9
  * the generated `getFetch` query type by `_AssertFetchGetQueryKeysCoverSpec`
10
10
  * below, so it cannot drift away from the spec silently.
11
11
  */
12
- const FETCH_GET_QUERY_KEYS = ['url', 'format', 'country', 'timeout_ms', 'cache_ttl'];
12
+ const FETCH_GET_QUERY_KEYS = ['url', 'country', 'timeout_ms', 'cache_ttl'];
13
13
  const CACHE_STATUSES = ['hit', 'miss', 'bypass'];
14
14
  /** Build a typed {@link FetchResult} from a raw body + its header set. */
15
15
  function toFetchResult(raw) {
@@ -60,10 +60,8 @@ export class FetchResource {
60
60
  *
61
61
  * Resolves a `FetchResult` — the raw content body plus `X-Fetch-*` metadata.
62
62
  *
63
- * Accepts only the five params the spec declares for this endpoint. `custom`
64
- * (#2481) and the `markdown_*` / `with_*` tuning fields (#2539) are POST-body
65
- * options with no GET query param — they were silently dropped by this builder,
66
- * so they are now compile errors instead. Use `create()` (POST) for those.
63
+ * Accepts only the four params the spec declares for this endpoint. `custom`
64
+ * is a POST-body option with no GET query param; use `create()` for custom metadata.
67
65
  *
68
66
  * The query string is built by iterating `FETCH_GET_QUERY_KEYS`, the same list
69
67
  * `FetchGetOpts` is derived from, so every accepted option is necessarily
@@ -1,5 +1,5 @@
1
1
  import type { ByteKit, RequestOptions } from '../client.js';
2
- import type { components, operations } from '../generated/api.js';
2
+ import type { operations } from '../generated/api.js';
3
3
  import type { ScrapeId, BulkId } from '../types.js';
4
4
  /**
5
5
  * Response of POST /v1/scrape — a 200 sync success envelope or a 202 queued
@@ -26,23 +26,11 @@ export type MarkdownLinks = 'inline' | 'references' | 'none' | 'text';
26
26
  export type MarkdownImages = 'inline' | 'references' | 'none' | 'text';
27
27
  /** Tokenizer encoding hint for `token_budget`. */
28
28
  export type TokenEncoding = 'cl100k_base' | 'o200k_base';
29
- /**
30
- * A cookie to set before loading the page — the spec's `Cookie` schema verbatim
31
- * (`name` and `value` required; `domain`, `path`, `secure`, `httpOnly` optional).
32
- *
33
- * DERIVED from the generated schema (#2547), never hand-authored: `cookies` was
34
- * previously an open bag of untyped records, so a nameless cookie compiled and only
35
- * failed as a 422 on the wire.
36
- */
37
- export type ScrapeCookie = components['schemas']['Cookie'];
38
29
  /** Options for POST /v1/scrape. */
39
30
  export interface ScrapeOpts {
40
31
  url: string;
41
32
  formats?: Array<'raw_html' | 'html' | 'markdown' | 'links' | 'images'>;
42
33
  country?: string;
43
- /** Cookies to set before loading the page. `name` and `value` are required (spec `Cookie` schema). */
44
- cookies?: ScrapeCookie[];
45
- headers?: Record<string, string>;
46
34
  delay_ms?: number;
47
35
  /** SERVER-side scrape budget in ms — how long the gateway may spend on the scrape itself. For the CLIENT-side abort budget (when this SDK gives up on the wire), see `RequestOptions.requestTimeoutMs`. */
48
36
  timeout_ms?: number;
package/dist/version.d.ts CHANGED
@@ -5,4 +5,4 @@
5
5
  * outbound request carries — see the emit site in `client.ts`. The header name is spelled
6
6
  * only there, so issue #2905's pre-merge gate 1 counts exactly one occurrence in `src/`.
7
7
  */
8
- export declare const SDK_VERSION = "0.8.0";
8
+ export declare const SDK_VERSION = "0.9.0";
package/dist/version.js CHANGED
@@ -9,4 +9,4 @@
9
9
  * outbound request carries — see the emit site in `client.ts`. The header name is spelled
10
10
  * only there, so issue #2905's pre-merge gate 1 counts exactly one occurrence in `src/`.
11
11
  */
12
- export const SDK_VERSION = '0.8.0';
12
+ export const SDK_VERSION = '0.9.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hunt-labs/bytekit-sdk",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Official TypeScript SDK for the ByteKit API",
5
5
  "license": "MIT",
6
6
  "type": "module",