From 63b89645bfe4a82faeee952478ff7fe8f33e1c59 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 22:16:36 +0000 Subject: [PATCH 1/4] feat(api): api update --- .stats.yml | 4 +- api.md | 6 +- src/context/dev/resources/batch.py | 8 +- src/context/dev/types/__init__.py | 6 +- .../dev/types/batch_cancel_response.py | 97 ++++++++++-------- src/context/dev/types/batch_list_response.py | 96 ++++++++++-------- .../dev/types/batch_retrieve_response.py | 99 ++++++++++--------- src/context/dev/types/crawl_controls.py | 54 ++++++++++ src/context/dev/types/error.py | 15 --- src/context/dev/types/failure.py | 17 ++++ src/context/dev/types/intake.py | 46 +++++++++ .../{error_count.py => page_error_count.py} | 4 +- 12 files changed, 296 insertions(+), 156 deletions(-) create mode 100644 src/context/dev/types/crawl_controls.py delete mode 100644 src/context/dev/types/error.py create mode 100644 src/context/dev/types/failure.py create mode 100644 src/context/dev/types/intake.py rename src/context/dev/types/{error_count.py => page_error_count.py} (82%) diff --git a/.stats.yml b/.stats.yml index 33b7080..963533f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 37 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-960cb623c7ec84bf4dc0f5945cbc19eec9cca48271071f400d96066eaa55dbd6.yml -openapi_spec_hash: 84fd39e3f4dc964bf0c32d4e95da1b34 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-838f03b1c3584485eeded993459e6bbae058da9f6df16b7967980fbba98cc748.yml +openapi_spec_hash: 4a9db9cd9eac4ae4e2694b3d835a772f config_hash: 2bea1743c84d63bd61f8501a6ea63065 diff --git a/api.md b/api.md index d95bf72..7040315 100644 --- a/api.md +++ b/api.md @@ -140,8 +140,10 @@ Types: ```python from context.dev.types import ( - ErrorCount, - Error, + PageErrorCount, + Failure, + CrawlControls, + Intake, BatchRetrieveResponse, BatchListResponse, BatchCancelResponse, diff --git a/src/context/dev/resources/batch.py b/src/context/dev/resources/batch.py index 50e9ded..ee9f176 100644 --- a/src/context/dev/resources/batch.py +++ b/src/context/dev/resources/batch.py @@ -61,8 +61,8 @@ def retrieve( """Check progress and get download links when the batch finishes. Also returns the - rejected-URL list and webhook signing secret from submission, so nothing is lost - if the submit response was dropped. + rejected-URL list from submission. The webhook signing secret is not repeated + here — it is returned once, by the submit response. Args: batch_id: ID of the batch to retrieve or cancel. @@ -326,8 +326,8 @@ async def retrieve( """Check progress and get download links when the batch finishes. Also returns the - rejected-URL list and webhook signing secret from submission, so nothing is lost - if the submit response was dropped. + rejected-URL list from submission. The webhook signing secret is not repeated + here — it is returned once, by the submit response. Args: batch_id: ID of the batch to retrieve or cancel. diff --git a/src/context/dev/types/__init__.py b/src/context/dev/types/__init__.py index c49ba0d..efea4d2 100644 --- a/src/context/dev/types/__init__.py +++ b/src/context/dev/types/__init__.py @@ -2,8 +2,10 @@ from __future__ import annotations -from .error import Error as Error -from .error_count import ErrorCount as ErrorCount +from .intake import Intake as Intake +from .failure import Failure as Failure +from .crawl_controls import CrawlControls as CrawlControls +from .page_error_count import PageErrorCount as PageErrorCount from .webhook_delivery import WebhookDelivery as WebhookDelivery from .batch_list_params import BatchListParams as BatchListParams from .web_search_params import WebSearchParams as WebSearchParams diff --git a/src/context/dev/types/batch_cancel_response.py b/src/context/dev/types/batch_cancel_response.py index 9ac6ff5..cb012e0 100644 --- a/src/context/dev/types/batch_cancel_response.py +++ b/src/context/dev/types/batch_cancel_response.py @@ -3,50 +3,49 @@ from typing import List, Optional from typing_extensions import Literal -from .error import Error +from .intake import Intake +from .failure import Failure from .._models import BaseModel -from .error_count import ErrorCount +from .crawl_controls import CrawlControls +from .page_error_count import PageErrorCount -__all__ = ["BatchCancelResponse", "Credits", "Input", "Progress", "Results", "ResultsFile", "Timing", "KeyMetadata"] +__all__ = ["BatchCancelResponse", "Credits", "Progress", "Results", "ResultsFile", "Timing", "KeyMetadata"] class Credits(BaseModel): - """Reserved and used credits.""" + """What this batch has done to your credit balance.""" - charged: int - """Credits used by successful pages.""" + net: int + """`reserved` minus `refunded` — what the batch has cost so far. - estimated: int - """Credits reserved when the batch was accepted.""" - - -class Input(BaseModel): - """Submission counts.""" + Equal to `reserved` until the batch settles. + """ - accepted: int - """Pages accepted, or the crawl page limit. Credits are reserved for this count.""" + refunded: int + """Credits returned for pages that did not succeed. - duplicates: int - """Duplicate URL and `itemId` pairs skipped. Always 0 for crawls.""" + Stays 0 until the batch reaches a final status, then settles in one movement. + """ - invalid: int - """Pages rejected during validation.""" + reserved: int + """Credits debited from your balance the moment the batch was accepted. - submitted: int - """Pages submitted before validation. For a crawl, the page limit.""" + This is a charge, not a forecast — the whole amount leaves the balance up front. + """ class Progress(BaseModel): - """Current processing counts. Use `status` to check completion.""" + """Pages attempted so far. Use `status` to check completion.""" failed: int """Pages that could not be scraped.""" pending: int - """Accepted pages not yet attempted. + """Reserved pages not yet attempted. - Always 0 once the batch completes; a crawl can finish under its page limit when - the site has no more reachable pages. + A cancelled batch keeps reporting the URLs it never reached; a crawl whose + `input.reserved_is_ceiling` is true reports 0 once final, because its unspent + budget was never real pages. """ succeeded: int @@ -65,9 +64,8 @@ class ResultsFile(BaseModel): class Results(BaseModel): - """Download links available when the batch finishes. - - GET /batch/{batch_id}/results serves the same records as paginated JSON. + """ + Download links, available once the batch reaches a final status and null before then. GET /batch/{batch_id}/results serves the same records as paginated JSON. """ expires_at: str @@ -102,28 +100,46 @@ class BatchCancelResponse(BaseModel): id: str """Batch ID used to retrieve or cancel the job.""" + crawl: Optional[CrawlControls] = None + """ + The crawl controls as submitted, so the limits requested can be compared against + what the crawl reached. + """ + credits: Credits - """Reserved and used credits.""" + """What this batch has done to your credit balance.""" - error: Optional[Error] = None - """Why the batch failed.""" + failure: Optional[Failure] = None + """ + A failure of the batch as a whole, distinct from the per-page failures in + `page_errors`. + """ - errors: List[ErrorCount] - """Page failures grouped by error code.""" + format: Literal["markdown", "html"] + """What each page is returned as. - input: Input - """Submission counts.""" + Matches `input.data.format` on the submit request. + """ + + input: Intake + """What submission took in, and what it charged for.""" mode: Literal["scrape", "crawl"] - """How pages are selected.""" + """How pages were selected. Matches `input.mode` on the submit request.""" + + page_errors: List[PageErrorCount] + """Individual page failures grouped by error code, sorted by count. + + Unrelated to `failure`, which is the batch itself failing. + """ progress: Progress - """Current processing counts. Use `status` to check completion.""" + """Pages attempted so far. Use `status` to check completion.""" results: Optional[Results] = None - """Download links available when the batch finishes. - - GET /batch/{batch_id}/results serves the same records as paginated JSON. + """ + Download links, available once the batch reaches a final status and null before + then. GET /batch/{batch_id}/results serves the same records as paginated JSON. """ status: Literal["queued", "running", "cancelling", "completed", "cancelled", "failed"] @@ -134,8 +150,5 @@ class BatchCancelResponse(BaseModel): timing: Timing - type: Literal["markdown", "html"] - """Output format.""" - key_metadata: Optional[KeyMetadata] = None """API key usage for this request.""" diff --git a/src/context/dev/types/batch_list_response.py b/src/context/dev/types/batch_list_response.py index c91eb07..1267839 100644 --- a/src/context/dev/types/batch_list_response.py +++ b/src/context/dev/types/batch_list_response.py @@ -3,15 +3,16 @@ from typing import List, Optional from typing_extensions import Literal -from .error import Error +from .intake import Intake +from .failure import Failure from .._models import BaseModel -from .error_count import ErrorCount +from .crawl_controls import CrawlControls +from .page_error_count import PageErrorCount __all__ = [ "BatchListResponse", "Data", "DataCredits", - "DataInput", "DataProgress", "DataResults", "DataResultsFile", @@ -21,42 +22,39 @@ class DataCredits(BaseModel): - """Reserved and used credits.""" + """What this batch has done to your credit balance.""" - charged: int - """Credits used by successful pages.""" + net: int + """`reserved` minus `refunded` — what the batch has cost so far. - estimated: int - """Credits reserved when the batch was accepted.""" - - -class DataInput(BaseModel): - """Submission counts.""" + Equal to `reserved` until the batch settles. + """ - accepted: int - """Pages accepted, or the crawl page limit. Credits are reserved for this count.""" + refunded: int + """Credits returned for pages that did not succeed. - duplicates: int - """Duplicate URL and `itemId` pairs skipped. Always 0 for crawls.""" + Stays 0 until the batch reaches a final status, then settles in one movement. + """ - invalid: int - """Pages rejected during validation.""" + reserved: int + """Credits debited from your balance the moment the batch was accepted. - submitted: int - """Pages submitted before validation. For a crawl, the page limit.""" + This is a charge, not a forecast — the whole amount leaves the balance up front. + """ class DataProgress(BaseModel): - """Current processing counts. Use `status` to check completion.""" + """Pages attempted so far. Use `status` to check completion.""" failed: int """Pages that could not be scraped.""" pending: int - """Accepted pages not yet attempted. + """Reserved pages not yet attempted. - Always 0 once the batch completes; a crawl can finish under its page limit when - the site has no more reachable pages. + A cancelled batch keeps reporting the URLs it never reached; a crawl whose + `input.reserved_is_ceiling` is true reports 0 once final, because its unspent + budget was never real pages. """ succeeded: int @@ -75,9 +73,8 @@ class DataResultsFile(BaseModel): class DataResults(BaseModel): - """Download links available when the batch finishes. - - GET /batch/{batch_id}/results serves the same records as paginated JSON. + """ + Download links, available once the batch reaches a final status and null before then. GET /batch/{batch_id}/results serves the same records as paginated JSON. """ expires_at: str @@ -104,28 +101,46 @@ class Data(BaseModel): id: str """Batch ID used to retrieve or cancel the job.""" + crawl: Optional[CrawlControls] = None + """ + The crawl controls as submitted, so the limits requested can be compared against + what the crawl reached. + """ + credits: DataCredits - """Reserved and used credits.""" + """What this batch has done to your credit balance.""" - error: Optional[Error] = None - """Why the batch failed.""" + failure: Optional[Failure] = None + """ + A failure of the batch as a whole, distinct from the per-page failures in + `page_errors`. + """ - errors: List[ErrorCount] - """Page failures grouped by error code.""" + format: Literal["markdown", "html"] + """What each page is returned as. - input: DataInput - """Submission counts.""" + Matches `input.data.format` on the submit request. + """ + + input: Intake + """What submission took in, and what it charged for.""" mode: Literal["scrape", "crawl"] - """How pages are selected.""" + """How pages were selected. Matches `input.mode` on the submit request.""" + + page_errors: List[PageErrorCount] + """Individual page failures grouped by error code, sorted by count. + + Unrelated to `failure`, which is the batch itself failing. + """ progress: DataProgress - """Current processing counts. Use `status` to check completion.""" + """Pages attempted so far. Use `status` to check completion.""" results: Optional[DataResults] = None - """Download links available when the batch finishes. - - GET /batch/{batch_id}/results serves the same records as paginated JSON. + """ + Download links, available once the batch reaches a final status and null before + then. GET /batch/{batch_id}/results serves the same records as paginated JSON. """ status: Literal["queued", "running", "cancelling", "completed", "cancelled", "failed"] @@ -136,9 +151,6 @@ class Data(BaseModel): timing: DataTiming - type: Literal["markdown", "html"] - """Output format.""" - class KeyMetadata(BaseModel): """Metadata about the API key used for the request. diff --git a/src/context/dev/types/batch_retrieve_response.py b/src/context/dev/types/batch_retrieve_response.py index d2ef3e4..a4cb4c6 100644 --- a/src/context/dev/types/batch_retrieve_response.py +++ b/src/context/dev/types/batch_retrieve_response.py @@ -3,14 +3,15 @@ from typing import List, Optional from typing_extensions import Literal -from .error import Error +from .intake import Intake +from .failure import Failure from .._models import BaseModel -from .error_count import ErrorCount +from .crawl_controls import CrawlControls +from .page_error_count import PageErrorCount __all__ = [ "BatchRetrieveResponse", "Credits", - "Input", "InvalidURL", "Progress", "Results", @@ -21,29 +22,25 @@ class Credits(BaseModel): - """Reserved and used credits.""" + """What this batch has done to your credit balance.""" - charged: int - """Credits used by successful pages.""" + net: int + """`reserved` minus `refunded` — what the batch has cost so far. - estimated: int - """Credits reserved when the batch was accepted.""" - - -class Input(BaseModel): - """Submission counts.""" + Equal to `reserved` until the batch settles. + """ - accepted: int - """Pages accepted, or the crawl page limit. Credits are reserved for this count.""" + refunded: int + """Credits returned for pages that did not succeed. - duplicates: int - """Duplicate URL and `itemId` pairs skipped. Always 0 for crawls.""" + Stays 0 until the batch reaches a final status, then settles in one movement. + """ - invalid: int - """Pages rejected during validation.""" + reserved: int + """Credits debited from your balance the moment the batch was accepted. - submitted: int - """Pages submitted before validation. For a crawl, the page limit.""" + This is a charge, not a forecast — the whole amount leaves the balance up front. + """ class InvalidURL(BaseModel): @@ -55,16 +52,17 @@ class InvalidURL(BaseModel): class Progress(BaseModel): - """Current processing counts. Use `status` to check completion.""" + """Pages attempted so far. Use `status` to check completion.""" failed: int """Pages that could not be scraped.""" pending: int - """Accepted pages not yet attempted. + """Reserved pages not yet attempted. - Always 0 once the batch completes; a crawl can finish under its page limit when - the site has no more reachable pages. + A cancelled batch keeps reporting the URLs it never reached; a crawl whose + `input.reserved_is_ceiling` is true reports 0 once final, because its unspent + budget was never real pages. """ succeeded: int @@ -83,9 +81,8 @@ class ResultsFile(BaseModel): class Results(BaseModel): - """Download links available when the batch finishes. - - GET /batch/{batch_id}/results serves the same records as paginated JSON. + """ + Download links, available once the batch reaches a final status and null before then. GET /batch/{batch_id}/results serves the same records as paginated JSON. """ expires_at: str @@ -120,31 +117,49 @@ class BatchRetrieveResponse(BaseModel): id: str """Batch ID used to retrieve or cancel the job.""" + crawl: Optional[CrawlControls] = None + """ + The crawl controls as submitted, so the limits requested can be compared against + what the crawl reached. + """ + credits: Credits - """Reserved and used credits.""" + """What this batch has done to your credit balance.""" - error: Optional[Error] = None - """Why the batch failed.""" + failure: Optional[Failure] = None + """ + A failure of the batch as a whole, distinct from the per-page failures in + `page_errors`. + """ + + format: Literal["markdown", "html"] + """What each page is returned as. - errors: List[ErrorCount] - """Page failures grouped by error code.""" + Matches `input.data.format` on the submit request. + """ - input: Input - """Submission counts.""" + input: Intake + """What submission took in, and what it charged for.""" invalid_urls: List[InvalidURL] """Rejected URLs, up to 100. These are not charged.""" mode: Literal["scrape", "crawl"] - """How pages are selected.""" + """How pages were selected. Matches `input.mode` on the submit request.""" + + page_errors: List[PageErrorCount] + """Individual page failures grouped by error code, sorted by count. + + Unrelated to `failure`, which is the batch itself failing. + """ progress: Progress - """Current processing counts. Use `status` to check completion.""" + """Pages attempted so far. Use `status` to check completion.""" results: Optional[Results] = None - """Download links available when the batch finishes. - - GET /batch/{batch_id}/results serves the same records as paginated JSON. + """ + Download links, available once the batch reaches a final status and null before + then. GET /batch/{batch_id}/results serves the same records as paginated JSON. """ status: Literal["queued", "running", "cancelling", "completed", "cancelled", "failed"] @@ -155,11 +170,5 @@ class BatchRetrieveResponse(BaseModel): timing: Timing - type: Literal["markdown", "html"] - """Output format.""" - key_metadata: Optional[KeyMetadata] = None """API key usage for this request.""" - - webhook_secret: Optional[str] = None - """Webhook signing secret. Also returned by GET /batch/{batch_id}.""" diff --git a/src/context/dev/types/crawl_controls.py b/src/context/dev/types/crawl_controls.py new file mode 100644 index 0000000..182a460 --- /dev/null +++ b/src/context/dev/types/crawl_controls.py @@ -0,0 +1,54 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union, Optional +from typing_extensions import Literal, TypeAlias + +from .._models import BaseModel + +__all__ = ["CrawlControls", "Source", "SourceUnionMember0", "SourceUnionMember1"] + + +class SourceUnionMember0(BaseModel): + type: Literal["start_url"] + + url: str + """Page the crawl started from.""" + + +class SourceUnionMember1(BaseModel): + domain: str + """Domain whose sitemap supplied the pages.""" + + type: Literal["sitemap"] + + +Source: TypeAlias = Union[SourceUnionMember0, SourceUnionMember1] + + +class CrawlControls(BaseModel): + """ + The crawl controls as submitted, so the limits requested can be compared against what the crawl reached. + """ + + follow_subdomains: bool + """Whether links to subdomains were followed. Always false for a sitemap crawl.""" + + max_depth: Optional[int] = None + """Link depth limit. + + Always 0 for a sitemap crawl, which never follows links off its URLs; null when + a `start_url` crawl set no limit. + """ + + max_pages: int + """The `maxUrls` submitted with the crawl. + + A sitemap crawl scrapes only the URLs its sitemap actually lists, up to this + many, so `input.reserved` is often lower. + """ + + source: Source + """Where the crawl started.""" + + url_pattern: Optional[str] = None + """RE2 pattern URLs had to match to be crawled. Null when the crawl set none.""" diff --git a/src/context/dev/types/error.py b/src/context/dev/types/error.py deleted file mode 100644 index c564450..0000000 --- a/src/context/dev/types/error.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .._models import BaseModel - -__all__ = ["Error"] - - -class Error(BaseModel): - """Why the batch failed.""" - - code: str - """Batch error code.""" - - message: str - """Batch error message.""" diff --git a/src/context/dev/types/failure.py b/src/context/dev/types/failure.py new file mode 100644 index 0000000..6736081 --- /dev/null +++ b/src/context/dev/types/failure.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel + +__all__ = ["Failure"] + + +class Failure(BaseModel): + """ + A failure of the batch as a whole, distinct from the per-page failures in `page_errors`. + """ + + code: str + """Why the batch itself stopped.""" + + message: str + """Human-readable explanation.""" diff --git a/src/context/dev/types/intake.py b/src/context/dev/types/intake.py new file mode 100644 index 0000000..c6f2b5b --- /dev/null +++ b/src/context/dev/types/intake.py @@ -0,0 +1,46 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from .._models import BaseModel + +__all__ = ["Intake"] + + +class Intake(BaseModel): + """What submission took in, and what it charged for.""" + + duplicates: int + """URLs dropped before reserving because another entry resolved to the same page. + + Non-zero for sitemap crawls too, whose sitemaps routinely list a page more than + once. + """ + + invalid: Optional[int] = None + """ + URLs from your list rejected as unusable; the same ones are itemised in + `invalid_urls` at submission. Null for a crawl — a crawl that resolves no usable + page is rejected outright with a 400 rather than accepted with an empty list. + """ + + reserved: int + """Pages credits were reserved for. + + Everything else — progress, the refund, the completion percentage — is measured + against this. + """ + + reserved_is_ceiling: bool + """Whether `reserved` is an upper bound the batch may finish under. + + True only for a crawl that follows links, whose reachable page count is + unknowable until it runs. False for a scrape and for a sitemap crawl, where + `reserved` is an exact page count. + """ + + submitted: Optional[int] = None + """URLs in the list you sent, before validation and de-duplication. + + Null for a crawl, which is given a source rather than a list. + """ diff --git a/src/context/dev/types/error_count.py b/src/context/dev/types/page_error_count.py similarity index 82% rename from src/context/dev/types/error_count.py rename to src/context/dev/types/page_error_count.py index 783906d..12c0e3f 100644 --- a/src/context/dev/types/error_count.py +++ b/src/context/dev/types/page_error_count.py @@ -2,10 +2,10 @@ from .._models import BaseModel -__all__ = ["ErrorCount"] +__all__ = ["PageErrorCount"] -class ErrorCount(BaseModel): +class PageErrorCount(BaseModel): """Page failures sharing one error code.""" code: str From 3688eab17dcc2546c3e9c7249d15be912354012c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 31 Jul 2026 22:45:46 +0000 Subject: [PATCH 2/4] feat(api): api update --- .stats.yml | 4 +- .../dev/types/batch_cancel_response.py | 99 +++++-------------- 2 files changed, 24 insertions(+), 79 deletions(-) diff --git a/.stats.yml b/.stats.yml index 963533f..06846fb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 37 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-838f03b1c3584485eeded993459e6bbae058da9f6df16b7967980fbba98cc748.yml -openapi_spec_hash: 4a9db9cd9eac4ae4e2694b3d835a772f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-21a0195dcea548066fd6c227d634217b897900a6732a688e41c83344c2e92c94.yml +openapi_spec_hash: 388f5780dc9bf205c04b6a6214e4fafc config_hash: 2bea1743c84d63bd61f8501a6ea63065 diff --git a/src/context/dev/types/batch_cancel_response.py b/src/context/dev/types/batch_cancel_response.py index cb012e0..de73f63 100644 --- a/src/context/dev/types/batch_cancel_response.py +++ b/src/context/dev/types/batch_cancel_response.py @@ -4,86 +4,45 @@ from typing_extensions import Literal from .intake import Intake -from .failure import Failure from .._models import BaseModel from .crawl_controls import CrawlControls from .page_error_count import PageErrorCount -__all__ = ["BatchCancelResponse", "Credits", "Progress", "Results", "ResultsFile", "Timing", "KeyMetadata"] +__all__ = ["BatchCancelResponse", "Credits", "Progress", "Timing", "KeyMetadata"] class Credits(BaseModel): - """What this batch has done to your credit balance.""" - - net: int - """`reserved` minus `refunded` — what the batch has cost so far. - - Equal to `reserved` until the batch settles. - """ - - refunded: int - """Credits returned for pages that did not succeed. - - Stays 0 until the batch reaches a final status, then settles in one movement. - """ + """What this batch cost so far.""" reserved: int - """Credits debited from your balance the moment the batch was accepted. + """Credits debited at submission. - This is a charge, not a forecast — the whole amount leaves the balance up front. + The unspent remainder is refunded once the batch settles — read + `credits.refunded` from GET /batch/{batch_id} then. """ class Progress(BaseModel): - """Pages attempted so far. Use `status` to check completion.""" + """How far the batch got before cancellation.""" failed: int - """Pages that could not be scraped.""" + """Pages that could not be scraped before the request landed.""" pending: int - """Reserved pages not yet attempted. - - A cancelled batch keeps reporting the URLs it never reached; a crawl whose - `input.reserved_is_ceiling` is true reports 0 once final, because its unspent - budget was never real pages. - """ + """Reserved pages that will now be skipped, and refunded when the batch settles.""" succeeded: int - """Pages scraped successfully.""" - - -class ResultsFile(BaseModel): - bytes: int - """Compressed file size in bytes.""" - - items: int - """Results in this file.""" - - url: str - """Temporary URL for a gzipped NDJSON file.""" - - -class Results(BaseModel): - """ - Download links, available once the batch reaches a final status and null before then. GET /batch/{batch_id}/results serves the same records as paginated JSON. - """ - - expires_at: str - """When the download URLs expire.""" - - files: List[ResultsFile] - """Result files. Order is not guaranteed.""" + """Pages scraped successfully before the request landed.""" class Timing(BaseModel): - completed_at: Optional[str] = None - """When processing finished. Null while active.""" + """There is no finish time yet — the batch is still winding down.""" created_at: str """When the batch was created.""" started_at: Optional[str] = None - """When processing started. Null while queued.""" + """When processing started. Null if it was cancelled while still queued.""" class KeyMetadata(BaseModel): @@ -98,7 +57,7 @@ class KeyMetadata(BaseModel): class BatchCancelResponse(BaseModel): id: str - """Batch ID used to retrieve or cancel the job.""" + """Batch ID.""" crawl: Optional[CrawlControls] = None """ @@ -107,48 +66,34 @@ class BatchCancelResponse(BaseModel): """ credits: Credits - """What this batch has done to your credit balance.""" - - failure: Optional[Failure] = None - """ - A failure of the batch as a whole, distinct from the per-page failures in - `page_errors`. - """ + """What this batch cost so far.""" format: Literal["markdown", "html"] - """What each page is returned as. - - Matches `input.data.format` on the submit request. - """ + """What each page is returned as.""" input: Intake """What submission took in, and what it charged for.""" mode: Literal["scrape", "crawl"] - """How pages were selected. Matches `input.mode` on the submit request.""" + """How pages were selected.""" page_errors: List[PageErrorCount] - """Individual page failures grouped by error code, sorted by count. - - Unrelated to `failure`, which is the batch itself failing. - """ + """Page failures so far, grouped by error code and sorted by count.""" progress: Progress - """Pages attempted so far. Use `status` to check completion.""" + """How far the batch got before cancellation.""" - results: Optional[Results] = None - """ - Download links, available once the batch reaches a final status and null before - then. GET /batch/{batch_id}/results serves the same records as paginated JSON. - """ + status: Literal["cancelling"] + """Always `cancelling`. - status: Literal["queued", "running", "cancelling", "completed", "cancelled", "failed"] - """Current state. `completed`, `cancelled`, and `failed` are final.""" + Work already in flight finishes; the batch reaches `cancelled` shortly after. + """ tags: List[str] """Tags stored on the batch at submission.""" timing: Timing + """There is no finish time yet — the batch is still winding down.""" key_metadata: Optional[KeyMetadata] = None """API key usage for this request.""" From da261be4676883e2a8e85ca0b4b7be887a24e85b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 1 Aug 2026 00:42:53 +0000 Subject: [PATCH 3/4] feat(api): api update --- .stats.yml | 4 +- src/context/dev/resources/batch.py | 24 ++++------- src/context/dev/resources/web.py | 40 ++++++++----------- .../dev/types/web_screenshot_params.py | 5 +-- .../dev/types/web_web_crawl_md_params.py | 5 +-- .../dev/types/web_web_scrape_html_params.py | 5 +-- .../dev/types/web_web_scrape_md_params.py | 5 +-- 7 files changed, 34 insertions(+), 54 deletions(-) diff --git a/.stats.yml b/.stats.yml index 06846fb..3b484e3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 37 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-21a0195dcea548066fd6c227d634217b897900a6732a688e41c83344c2e92c94.yml -openapi_spec_hash: 388f5780dc9bf205c04b6a6214e4fafc +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-758c3a2fbd5b7be61c8e6e0ad2e6a5ec30695747bb675960d888c497647d13d7.yml +openapi_spec_hash: 00002d90bde02f67e174368ae470c597 config_hash: 2bea1743c84d63bd61f8501a6ea63065 diff --git a/src/context/dev/resources/batch.py b/src/context/dev/resources/batch.py index ee9f176..0244b3e 100644 --- a/src/context/dev/resources/batch.py +++ b/src/context/dev/resources/batch.py @@ -58,11 +58,8 @@ def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BatchRetrieveResponse: - """Check progress and get download links when the batch finishes. - - Also returns the - rejected-URL list from submission. The webhook signing secret is not repeated - here — it is returned once, by the submit response. + """ + Check progress, and get download links once the batch finishes. Args: batch_id: ID of the batch to retrieve or cancel. @@ -202,9 +199,8 @@ def get_results( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BatchGetResultsResponse: """ - Page through the result records of a finished batch as JSON, in the same order - as the downloadable result files. Use this instead of downloading and parsing - the NDJSON files yourself. + Page through a finished batch's results as JSON instead of downloading the + NDJSON files. Args: batch_id: ID of the batch to retrieve or cancel. @@ -323,11 +319,8 @@ async def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BatchRetrieveResponse: - """Check progress and get download links when the batch finishes. - - Also returns the - rejected-URL list from submission. The webhook signing secret is not repeated - here — it is returned once, by the submit response. + """ + Check progress, and get download links once the batch finishes. Args: batch_id: ID of the batch to retrieve or cancel. @@ -467,9 +460,8 @@ async def get_results( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> BatchGetResultsResponse: """ - Page through the result records of a finished batch as JSON, in the same order - as the downloadable result files. Use this instead of downloading and parsing - the NDJSON files yourself. + Page through a finished batch's results as JSON instead of downloading the + NDJSON files. Args: batch_id: ID of the batch to retrieve or cancel. diff --git a/src/context/dev/resources/web.py b/src/context/dev/resources/web.py index 8d7aec7..889ed6d 100644 --- a/src/context/dev/resources/web.py +++ b/src/context/dev/resources/web.py @@ -620,9 +620,8 @@ def screenshot( color_scheme: Optional parameter to choose the site's visual theme in the screenshot. Use 'light' or 'dark' when the site offers both appearances. - country: Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). direct_url: A specific URL to screenshot directly, bypassing domain resolution (e.g., 'https://example.com/pricing'). When provided, the screenshot is taken of this @@ -1280,9 +1279,8 @@ def web_crawl_md( Args: url: The starting URL for the crawl (must include http:// or https:// protocol) - country: Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). exclude_selectors: CSS selectors to remove before each crawled page is converted to Markdown. Applied after includeSelectors. Exclusion takes precedence: an element matching @@ -1630,9 +1628,8 @@ def web_scrape_html( content is captured. Requires a paid plan. Send a JSON array in the query parameter. Maximum: 5 actions. - country: Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). exclude_selectors: CSS selectors to remove from the result. Applied after includeSelectors. Exclusion takes precedence: an element matching both is removed. Examples: @@ -2071,9 +2068,8 @@ def web_scrape_md( content is captured. Requires a paid plan. Send a JSON array in the query parameter. Maximum: 5 actions. - country: Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). exclude_selectors: CSS selectors to remove before conversion to Markdown. Applied after includeSelectors. Exclusion takes precedence: an element matching both is @@ -2824,9 +2820,8 @@ async def screenshot( color_scheme: Optional parameter to choose the site's visual theme in the screenshot. Use 'light' or 'dark' when the site offers both appearances. - country: Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). direct_url: A specific URL to screenshot directly, bypassing domain resolution (e.g., 'https://example.com/pricing'). When provided, the screenshot is taken of this @@ -3484,9 +3479,8 @@ async def web_crawl_md( Args: url: The starting URL for the crawl (must include http:// or https:// protocol) - country: Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). exclude_selectors: CSS selectors to remove before each crawled page is converted to Markdown. Applied after includeSelectors. Exclusion takes precedence: an element matching @@ -3834,9 +3828,8 @@ async def web_scrape_html( content is captured. Requires a paid plan. Send a JSON array in the query parameter. Maximum: 5 actions. - country: Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). exclude_selectors: CSS selectors to remove from the result. Applied after includeSelectors. Exclusion takes precedence: an element matching both is removed. Examples: @@ -4275,9 +4268,8 @@ async def web_scrape_md( content is captured. Requires a paid plan. Send a JSON array in the query parameter. Maximum: 5 actions. - country: Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + country: Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). exclude_selectors: CSS selectors to remove before conversion to Markdown. Applied after includeSelectors. Exclusion takes precedence: an element matching both is diff --git a/src/context/dev/types/web_screenshot_params.py b/src/context/dev/types/web_screenshot_params.py index 918b6c9..830e1a7 100644 --- a/src/context/dev/types/web_screenshot_params.py +++ b/src/context/dev/types/web_screenshot_params.py @@ -225,9 +225,8 @@ class WebScreenshotParams(TypedDict, total=False): "zw", ] """ - Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). """ direct_url: Annotated[str, PropertyInfo(alias="directUrl")] diff --git a/src/context/dev/types/web_web_crawl_md_params.py b/src/context/dev/types/web_web_crawl_md_params.py index 31eff91..aa455b3 100644 --- a/src/context/dev/types/web_web_crawl_md_params.py +++ b/src/context/dev/types/web_web_crawl_md_params.py @@ -221,9 +221,8 @@ class WebWebCrawlMdParams(TypedDict, total=False): "zw", ] """ - Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). """ exclude_selectors: Annotated[SequenceNotStr[str], PropertyInfo(alias="excludeSelectors")] diff --git a/src/context/dev/types/web_web_scrape_html_params.py b/src/context/dev/types/web_web_scrape_html_params.py index d47752c..4ddbb15 100644 --- a/src/context/dev/types/web_web_scrape_html_params.py +++ b/src/context/dev/types/web_web_scrape_html_params.py @@ -229,9 +229,8 @@ class WebWebScrapeHTMLParams(TypedDict, total=False): "zw", ] """ - Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). """ exclude_selectors: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="excludeSelectors")] diff --git a/src/context/dev/types/web_web_scrape_md_params.py b/src/context/dev/types/web_web_scrape_md_params.py index d18a710..7cc894e 100644 --- a/src/context/dev/types/web_web_scrape_md_params.py +++ b/src/context/dev/types/web_web_scrape_md_params.py @@ -232,9 +232,8 @@ class WebWebScrapeMdParams(TypedDict, total=False): "zw", ] """ - Two-letter ISO 3166-1 alpha-2 country code identifying a supported Context.dev - residential proxy exit location. Must be one of Context.dev's supported - countries. When provided, Context.dev fetches the target page from that country. + Fetch the target page through a residential proxy in this country (ISO 3166-1 + alpha-2). """ exclude_selectors: Annotated[Optional[SequenceNotStr[str]], PropertyInfo(alias="excludeSelectors")] From df3bf8e5f4106157de4a9218a9f72024810994eb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 1 Aug 2026 00:43:18 +0000 Subject: [PATCH 4/4] release: 2.7.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 10 ++++++++++ pyproject.toml | 2 +- src/context/dev/_version.py | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 511dd51..d1328ca 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.6.0" + ".": "2.7.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cebd96..574526f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 2.7.0 (2026-08-01) + +Full Changelog: [v2.6.0...v2.7.0](https://github.com/context-dot-dev/context-python-sdk/compare/v2.6.0...v2.7.0) + +### Features + +* **api:** api update ([da261be](https://github.com/context-dot-dev/context-python-sdk/commit/da261be4676883e2a8e85ca0b4b7be887a24e85b)) +* **api:** api update ([3688eab](https://github.com/context-dot-dev/context-python-sdk/commit/3688eab17dcc2546c3e9c7249d15be912354012c)) +* **api:** api update ([63b8964](https://github.com/context-dot-dev/context-python-sdk/commit/63b89645bfe4a82faeee952478ff7fe8f33e1c59)) + ## 2.6.0 (2026-07-31) Full Changelog: [v2.5.0...v2.6.0](https://github.com/context-dot-dev/context-python-sdk/compare/v2.5.0...v2.6.0) diff --git a/pyproject.toml b/pyproject.toml index 7493050..fb0dfb2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "context.dev" -version = "2.6.0" +version = "2.7.0" description = "The official Python library for the context.dev API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/context/dev/_version.py b/src/context/dev/_version.py index de35f16..31f9889 100644 --- a/src/context/dev/_version.py +++ b/src/context/dev/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "context.dev" -__version__ = "2.6.0" # x-release-please-version +__version__ = "2.7.0" # x-release-please-version