Skip to main content
Glama

Server Details

Web data for AI agents. Spicrawl MCP lets agents fetch public web pages as clean Markdown, HTML, text, screenshots, PDFs, or structured JSON. It handles JavaScript-heavy pages and browser actions like clicking, filling forms, and scrolling.

Ownership verified
Status
Healthy
Uptime
99.8% over 21 days
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL

TDQS

A4/5.0

Scored across 25 tools

Disambiguation4/5

The batch group has several closely related tools (batch_results vs batch_task_content both return content; batch_status vs batch_list vs batch_results), and session_get vs session_context require careful reading, but the detailed descriptions clearly separate each. Scrape, docs, usage and request tools are all distinct. Mostly distinguishable with a couple of overlapping pairs.

Naming Consistency4/5

Uniform spicrawl_ prefix with snake_case throughout, and a predictable noun_verb scheme (batch_submit, session_create, docs_read). Minor deviations exist: singular/plural inconsistency (request_get vs requests_list), and some noun-first names (batch_task_content, browser_connect_url). Still largely readable and consistent.

Tool Count3/5

25 tools sits at the heavy end of the range and spans many sub-domains (batch, session, docs, usage, requests). Each earns some place, but the count is large for one server and includes one non-functional tool (browser_connect_url is 'coming soon'). Borderline heavy.

Completeness4/5

Strong lifecycle coverage: scraping (scrape), batch jobs (submit/add/status/results/task_content/cancel/close/retry), sessions (create/get/list/release/delete/context), usage, request logs, and docs. Minor gaps like no session update/rename and no project or key management, but core workflows are fully covered.

Available Tools

25 tools
spicrawl_batch_add_itemsAdd URLs to an open batch jobAInspect

Append URLs to a batch job that was submitted with open: true. Same item vocabulary as spicrawl_batch_submit (EITHER urls or items, not both, plus shared settings for these new items). Fails with CONFLICT if the job is closed or finished. Not idempotent: calling twice adds the URLs twice. Returns { job, items_added, items_dispatched }.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlsNoShorthand: URLs scraped with the shared settings and no per-item overrides. Mutually exclusive with `items`.
waitNoMilliseconds to wait after load (rendered scrapes).
itemsNoLong form: one /v1/scrape request object per item. Besides `url` and `external_id`, any /v1/scrape field (e.g. `js_render`, `wait_for`, `response_format`) overrides the shared setting for that item only. Mutually exclusive with `urls`.
formatNoOutput format for every item (`response_format`). spicrawl_batch_submit defaults to 'markdown', the same as spicrawl_scrape; an item's own `response_format` overrides it.
job_idYesThe batch job id returned by spicrawl_batch_submit or spicrawl_batch_list.
renderNoRender every URL with a browser (`js_render`).
max_costNoCeiling in credits for ONE item (not the whole job — see credit_budget).
wait_forNoCSS selector to wait for before capturing (rendered scrapes).
premium_proxyNoComing soon: not available yet, do not send. Use residential managed-pool exits for every URL.
proxy_countryNoComing soon: not available yet, do not send. ISO-3166 alpha-2 exit country; requires premium_proxy.
custom_headersNoExtra request headers sent with every URL.
block_resourcesNoResource types to block while rendering, e.g. ["image","font","media"].
main_content_onlyNoStrip each page to its main article.

Output Schema

ParametersJSON Schema
NameRequiredDescription
jobNoThe job as it stands after the call.
items_addedNoItems written to the job.
items_dispatchedNoOf those, how many reached the dispatch queue now; do not re-add the rest.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes beyond annotations by disclosing the non-idempotency ('calling twice adds the URLs twice'), the CONFLICT failure for closed/finished jobs, and the exact return shape. Annotations already cover idempotentHint=false and openWorldHint, so credit here is for the conflict semantics and return fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences with zero filler: purpose, vocabulary constraint, failure condition, idempotency warning, and return shape. The critical non-idempotency warning is front-loaded enough to be caught.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers the operation's key gotchas (mutual exclusivity, CONFLICT on closed jobs, non-idempotency) despite an output schema existing. An agent has everything needed to invoke correctly and interpret the response.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema carries the parameter burden. The description adds value by flagging the mutual exclusivity of `urls`/`items` and that shared settings apply to new items, but this largely restates what the schema already documents.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (append) and resource (URLs to a batch job), and scopes it precisely to jobs submitted with `open: true`, which distinguishes it from spicrawl_batch_submit and other batch siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the sibling it shares item vocabulary with (spicrawl_batch_submit) and states the precondition (job must be open) plus failure mode (CONFLICT). Lacks explicit 'when to use this vs spicrawl_batch_retry' guidance, but the open-job scoping is a clear routing signal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_batch_cancelCancel a batch jobA
DestructiveIdempotent
Inspect

Cancel a batch job: items not yet started are cancelled and will never run; items already finished keep their results; items already running finish first, so the job comes back cancelling and moves to cancelled when they drain. Cannot be undone — resubmit to run the URLs again. Returns the job object.

ParametersJSON Schema
NameRequiredDescriptionDefault
job_idYesThe batch job id returned by spicrawl_batch_submit or spicrawl_batch_list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesJob id. Pass it as `job_id` to the other spicrawl_batch_* tools.
nameNoThe label given at submission, if any.
openNoTrue while the job accepts appended items (it will not complete until closed).
paramsNoThe job-level scrape settings as stored.
statusNoLifecycle: queued, running, paused, cancelling, completed, failed or cancelled. Keep polling while queued/running/paused/cancelling; stop at completed, failed or cancelled.
priorityNoEffective scheduling priority.
progressNoLive item counters and the credits charged so far.
warningsNoDecisions made on the caller's behalf at submission (a clamped concurrency, items not yet queued).
error_codeNoMachine code of a job-level failure.
project_idNoProject the API key belongs to.
started_atNoISO-8601 time the first item started.
status_urlNoAPI path to poll for this job: /v1/batch/{id}.
concurrencyNoEffective per-job concurrency after the server's clamping.
finished_atNoISO-8601 time the job reached a terminal status.
results_urlNoAPI path of the job's results: /v1/batch/{id}/results.
total_itemsNoNumber of items in the job.
max_attemptsNoEffective attempts per item.
submitted_atNoISO-8601 time the job was accepted.
error_messageNoHuman-readable job-level failure reason.
estimated_creditsNoCredits reserved at submission (a hold, not a charge; compare with progress.credits_charged).
failure_thresholdNoFailed-item count that aborts the job, when set.
results_expire_atNoISO-8601 deadline after which results answer 410 Gone.
cancel_requested_atNoISO-8601 time a cancel was accepted.
estimated_credits_microNoSame as estimated_credits in micro-credits.

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (destructiveHint, idempotentHint, readOnlyHint=false) by specifying exactly what is destroyed (items not yet started), what is preserved (finished items keep results), and how in-flight items are handled. It also discloses irreversibility, the 'cancelling' -> 'cancelled' state transition, and the recovery path (resubmit), which annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core action and packed with high-value behavioral detail in a compact form; no filler sentences. The trailing 'Returns the job object' is mildly redundant given an output schema exists, a minor inefficiency rather than a flaw.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter mutation tool with full annotation coverage and an output schema, the description supplies everything else an agent needs: scope of destruction, state-machine behavior, irreversibility, and remediation. No meaningful gap remains.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only one parameter, job_id, and the schema documents it fully (100% coverage, including its provenance from spicrawl_batch_submit/spicrawl_batch_list). The description adds no format, constraint, or edge-case detail about the id, so baseline 3 is appropriate when the schema already carries the parameter contract.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Cancel a batch job') and immediately scopes the semantics to per-item lifecycle behavior, so an agent knows exactly what operation this is. It never names or contrasts the adjacent spicrawl_batch_close sibling, which is the one plausible confusion, so it falls short of full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: the description communicates that this stops a job and that running items must drain, which tells an agent the appropriate operational moment. However there is no explicit when-to-use/when-not, no prerequisites, and no mention of when spicrawl_batch_close or spicrawl_batch_retry would be preferred instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_batch_closeClose an open batch jobA
Idempotent
Inspect

Stop an open batch job accepting items, so it completes once its queued work drains. Idempotent (closing a closed job succeeds). Returns the job object.

ParametersJSON Schema
NameRequiredDescriptionDefault
job_idYesThe batch job id returned by spicrawl_batch_submit or spicrawl_batch_list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesJob id. Pass it as `job_id` to the other spicrawl_batch_* tools.
nameNoThe label given at submission, if any.
openNoTrue while the job accepts appended items (it will not complete until closed).
paramsNoThe job-level scrape settings as stored.
statusNoLifecycle: queued, running, paused, cancelling, completed, failed or cancelled. Keep polling while queued/running/paused/cancelling; stop at completed, failed or cancelled.
priorityNoEffective scheduling priority.
progressNoLive item counters and the credits charged so far.
warningsNoDecisions made on the caller's behalf at submission (a clamped concurrency, items not yet queued).
error_codeNoMachine code of a job-level failure.
project_idNoProject the API key belongs to.
started_atNoISO-8601 time the first item started.
status_urlNoAPI path to poll for this job: /v1/batch/{id}.
concurrencyNoEffective per-job concurrency after the server's clamping.
finished_atNoISO-8601 time the job reached a terminal status.
results_urlNoAPI path of the job's results: /v1/batch/{id}/results.
total_itemsNoNumber of items in the job.
max_attemptsNoEffective attempts per item.
submitted_atNoISO-8601 time the job was accepted.
error_messageNoHuman-readable job-level failure reason.
estimated_creditsNoCredits reserved at submission (a hold, not a charge; compare with progress.credits_charged).
failure_thresholdNoFailed-item count that aborts the job, when set.
results_expire_atNoISO-8601 deadline after which results answer 410 Gone.
cancel_requested_atNoISO-8601 time a cancel was accepted.
estimated_credits_microNoSame as estimated_credits in micro-credits.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false, and the description reinforces idempotency with a concrete case ('closing a closed job succeeds'). It also adds the non-obvious asynchronous semantic that the job does not stop immediately but drains its queue, which annotations do not convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, each carrying distinct information: the action, the idempotency guarantee, and the return value. Nothing is padded or restated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter mutation with full annotation coverage and an output schema, the description covers behavior, idempotency, and drain semantics adequately. The only gap is not routing the agent between this tool and spicrawl_batch_cancel.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single job_id parameter is documented with its origin ('returned by spicrawl_batch_submit or spicrawl_batch_list'). The description adds no further parameter meaning, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a precise verb and resource ('Stop an open batch job accepting items') plus the post-condition ('completes once its queued work drains'). This separates it from the sibling spicrawl_batch_cancel, which an agent would otherwise confuse for immediate termination.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The graceful-drain framing implies the when ('you want the job to finish its queued work rather than abort it'), but no alternative is named outright. The sibling spicrawl_batch_cancel is never mentioned, so the choice between graceful close and hard cancel is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_batch_listList batch jobsA
Read-onlyIdempotent
Inspect

List this API key's project's batch jobs, newest first, with status and progress. Returns { batches: [...], next_cursor? }; pass next_cursor back as cursor for the next page.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoPage size (default 50, max 200).
cursorNo`next_cursor` from a previous page, verbatim.
statusNoOnly jobs in this status.

Output Schema

ParametersJSON Schema
NameRequiredDescription
batchesYesJobs, newest first (empty when there are none).
next_cursorNoPass back as `cursor` for the next page; absent on the last page.

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safe-read profile (readOnly, idempotent, non-destructive), so the bar is lower. The description adds real context beyond them: project scoping, newest-first ordering, and the cursor-based pagination contract, which an agent needs to page correctly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, front-loaded with purpose and scope, then the return/pagination contract. No filler; every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so explaining return values is optional, yet the description still sketches the shape and pagination loop usefully. It is complete for calling the tool; the only gap is that sibling boundaries (vs batch_status) are not drawn.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all three parameters are already documented, including the status enum. The description reinforces the cursor linkage but adds no syntax or meaning beyond what the schema states, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('List ... batch jobs') with clear scope (this API key's project) and ordering (newest first). However, it does not differentiate itself from the sibling spicrawl_batch_status, which likely also surfaces job status, so an agent may hesitate between the two.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use versus alternatives is given. The pagination instruction ('pass next_cursor back as cursor') is procedural help, not guidance on selecting this tool over batch_status or batch_results.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_batch_resultsRead a batch job's resultsA
Read-onlyIdempotent
Inspect

Return a page of FINISHED items of a batch job (one record per item: seq, url, external_id, status, error, and content, or a result_url API path (GET /v1/batch/{id}/tasks/{seq}/content, same key) for large bodies). Unfinished items are not listed yet. Returns { results: [...], next_cursor? }; pass next_cursor back as cursor for the next page. Results expire after the job's retention window (410 Gone).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoPage size (default 500, max 5000).
cursorNo`next_cursor` from a previous page, verbatim.
job_idYesThe batch job id returned by spicrawl_batch_submit or spicrawl_batch_list.
statusNoOnly items that finished with this status.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultsYesFinished items of the job, in seq order.
next_cursorNoPass back as `cursor` for the next page; absent on the last page.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only cover the read-only/idempotent safety profile; the description goes well beyond them by disclosing that unfinished items are not yet listed, the exact paging contract, the expiry-and-410 behavior, and the large-body result_url fallback. This is exactly the behavioral context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose leads the sentence, followed by pagination and retention details in priority order. Dense but efficient, though the first sentence packs several concepts into a nested parenthetical that could be split for faster scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists, yet the description additionally explains the page shape and cursor handoff, plus what happens on expiry and where large bodies live. For a paginated read tool with three inputs, nothing an agent needs in order to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the description's parameter-level content (cursor round-trip, page size, status filtering via the job's items) is already stated in the schema. It restates the paging loop without adding new syntax or constraints, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Return) and resource (a page of FINISHED items of a batch job), and the scope word 'FINISHED' immediately distinguishes it from job-level status siblings and from per-task content fetches. An agent can identify the tool's role without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear operational context: results only appear once items finish, pages are walked by passing next_cursor back as cursor, and results expire (410 Gone). It also points at the result_url path for large bodies rather than the sibling spicrawl_batch_task_content. What's missing is an explicit when-to-use comparison against spicrawl_batch_status or spicrawl_batch_list.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_batch_retryRetry a batch job's failed itemsAInspect

Re-queue every FAILED item of a batch job so it runs again (succeeded items are untouched; a job with no failures is returned unchanged). Returns { job, items_reset, items_dispatched }.

ParametersJSON Schema
NameRequiredDescriptionDefault
job_idYesThe batch job id returned by spicrawl_batch_submit or spicrawl_batch_list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
jobNoThe job as it stands after the call.
items_resetNoFailed items reset to queued (0 means nothing had failed).
items_dispatchedNoOf those, how many reached the dispatch queue now; the rest are recovered automatically.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the mutation profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false), and the description adds real value on top: only failed items are re-queued, succeeded items are preserved, and a no-failure job is a no-op. It doesn't discuss re-dispatch semantics for a non-idempotent operation (e.g., duplicate side effects), which would have fully earned a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, front-loaded with the action and its scope, followed by the return shape. Every clause carries information and none is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the description needn't detail return values, yet it still names the return fields. The mutation behavior is well covered; only deeper operational detail (auth/session requirements, effect on a currently running job) is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single job_id parameter is already documented in the schema as coming from spicrawl_batch_submit or spicrawl_batch_list. The description adds nothing about the parameter beyond what the schema states, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Re-queue'), resource ('FAILED item of a batch job'), and scope ('every FAILED item', 'succeeded items untouched'). An agent can distinguish this from spicrawl_batch_submit, spicrawl_batch_cancel, and spicrawl_batch_results without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear selection condition implicitly by scoping the operation to jobs with failures and noting a job with no failures returns unchanged. It doesn't explicitly name alternative tools (e.g., resubmit vs cancel) for when retry isn't the right move, so it stops short of full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_batch_statusCheck a batch job's statusA
Read-onlyIdempotent
Inspect

Return one batch job with its status and progress (total/completed/succeeded/failed/remaining, credits charged). Poll this after spicrawl_batch_submit; once status is completed, failed or cancelled, read spicrawl_batch_results.

ParametersJSON Schema
NameRequiredDescriptionDefault
job_idYesThe batch job id returned by spicrawl_batch_submit or spicrawl_batch_list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesJob id. Pass it as `job_id` to the other spicrawl_batch_* tools.
nameNoThe label given at submission, if any.
openNoTrue while the job accepts appended items (it will not complete until closed).
paramsNoThe job-level scrape settings as stored.
statusNoLifecycle: queued, running, paused, cancelling, completed, failed or cancelled. Keep polling while queued/running/paused/cancelling; stop at completed, failed or cancelled.
priorityNoEffective scheduling priority.
progressNoLive item counters and the credits charged so far.
warningsNoDecisions made on the caller's behalf at submission (a clamped concurrency, items not yet queued).
error_codeNoMachine code of a job-level failure.
project_idNoProject the API key belongs to.
started_atNoISO-8601 time the first item started.
status_urlNoAPI path to poll for this job: /v1/batch/{id}.
concurrencyNoEffective per-job concurrency after the server's clamping.
finished_atNoISO-8601 time the job reached a terminal status.
results_urlNoAPI path of the job's results: /v1/batch/{id}/results.
total_itemsNoNumber of items in the job.
max_attemptsNoEffective attempts per item.
submitted_atNoISO-8601 time the job was accepted.
error_messageNoHuman-readable job-level failure reason.
estimated_creditsNoCredits reserved at submission (a hold, not a charge; compare with progress.credits_charged).
failure_thresholdNoFailed-item count that aborts the job, when set.
results_expire_atNoISO-8601 deadline after which results answer 410 Gone.
cancel_requested_atNoISO-8601 time a cancel was accepted.
estimated_credits_microNoSame as estimated_credits in micro-credits.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so safety is covered; the description adds genuine behavioral context by enumerating the progress counters and credit charging, and by defining which statuses are terminal. It stops short of stating polling cadence, rate limits, or behavior for an unknown/expired job_id.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler. The return shape is front-loaded and the lifecycle guidance follows immediately, so the agent gets the essential contract in the first clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not explain the payload, and the polling workflow is fully covered. The only unaddressed edge is failure handling for an invalid or expired job_id, which is minor given the read-only, idempotent annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single job_id parameter is fully documented in the schema, including its provenance. The description adds nothing about the parameter itself, so the baseline 3 for schema-carried semantics applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Return one batch job with its status and progress') and pins the scope to a single job, which cleanly separates it from the list-shaped sibling spicrawl_batch_list. An agent knows exactly what this returns without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit sequencing: poll this after spicrawl_batch_submit, and once status is completed/failed/cancelled, switch to spicrawl_batch_results. Both the when-to-use and the alternative are named with the condition that selects them.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_batch_submitSubmit a batch scrape jobAInspect

Submit many URLs to be scraped as one asynchronous job, with shared settings applied to every URL. Give EITHER urls or items, not both (at least one URL, unless open is true). Returns the job object (id, status, estimated_credits, progress). Poll with spicrawl_batch_status, read with spicrawl_batch_results or spicrawl_batch_task_content. Use this instead of many spicrawl_scrape calls when you have tens or thousands of URLs. Set open: true to keep the job accepting more URLs via spicrawl_batch_add_items; an open job never finishes until you call spicrawl_batch_close.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoA human label for the job.
openNoKeep the job accepting items after submission (append with spicrawl_batch_add_items, finish with spicrawl_batch_close).
urlsNoShorthand: URLs scraped with the shared settings and no per-item overrides. Mutually exclusive with `items`.
waitNoMilliseconds to wait after load (rendered scrapes).
itemsNoLong form: one /v1/scrape request object per item. Besides `url` and `external_id`, any /v1/scrape field (e.g. `js_render`, `wait_for`, `response_format`) overrides the shared setting for that item only. Mutually exclusive with `urls`.
formatNoOutput format for every item (`response_format`). spicrawl_batch_submit defaults to 'markdown', the same as spicrawl_scrape; an item's own `response_format` overrides it.
renderNoRender every URL with a browser (`js_render`).
max_costNoCeiling in credits for ONE item (not the whole job — see credit_budget).
priorityNoScheduling priority of the job relative to your other jobs.
wait_forNoCSS selector to wait for before capturing (rendered scrapes).
concurrencyNoMax items in flight at once for this job (may be capped by the server; see warnings).
max_attemptsNoPer-item retry attempts on failure.
credit_budgetNoCeiling on the WHOLE job, in credits; the run aborts when it would exceed this.
premium_proxyNoComing soon: not available yet, do not send. Use residential managed-pool exits for every URL.
proxy_countryNoComing soon: not available yet, do not send. ISO-3166 alpha-2 exit country; requires premium_proxy.
custom_headersNoExtra request headers sent with every URL.
block_resourcesNoResource types to block while rendering, e.g. ["image","font","media"].
failure_thresholdNoAbort the job once this many items have failed.
main_content_onlyNoStrip each page to its main article.
webhook_endpoint_idNoId of a registered webhook endpoint notified (with the job object) when the job completes.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesJob id. Pass it as `job_id` to the other spicrawl_batch_* tools.
nameNoThe label given at submission, if any.
openNoTrue while the job accepts appended items (it will not complete until closed).
paramsNoThe job-level scrape settings as stored.
statusNoLifecycle: queued, running, paused, cancelling, completed, failed or cancelled. Keep polling while queued/running/paused/cancelling; stop at completed, failed or cancelled.
priorityNoEffective scheduling priority.
progressNoLive item counters and the credits charged so far.
warningsNoDecisions made on the caller's behalf at submission (a clamped concurrency, items not yet queued).
error_codeNoMachine code of a job-level failure.
project_idNoProject the API key belongs to.
started_atNoISO-8601 time the first item started.
status_urlNoAPI path to poll for this job: /v1/batch/{id}.
concurrencyNoEffective per-job concurrency after the server's clamping.
finished_atNoISO-8601 time the job reached a terminal status.
results_urlNoAPI path of the job's results: /v1/batch/{id}/results.
total_itemsNoNumber of items in the job.
max_attemptsNoEffective attempts per item.
submitted_atNoISO-8601 time the job was accepted.
error_messageNoHuman-readable job-level failure reason.
estimated_creditsNoCredits reserved at submission (a hold, not a charge; compare with progress.credits_charged).
failure_thresholdNoFailed-item count that aborts the job, when set.
results_expire_atNoISO-8601 deadline after which results answer 410 Gone.
cancel_requested_atNoISO-8601 time a cancel was accepted.
estimated_credits_microNoSame as estimated_credits in micro-credits.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare non-read-only, non-idempotent, non-destructive behavior. The description adds genuine context beyond that: the job is asynchronous, it returns a job object, and an open job 'never finishes until you call spicrawl_batch_close' — a lifecycle trap the annotations do not convey. It stops short of stating credit/auth side effects or that concurrent submission of the same URLs will duplicate work.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first clause, followed by constraints, return shape, routing, and the alternative-tool guidance. Six sentences, each carrying distinct information, with no restatement of the name or title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 20-parameter, nested-object, async submission tool with a full output schema and 100% schema coverage, the description supplies exactly the missing layer: mutual exclusivity, open-job lifecycle, and the sibling tools to poll/read/extend with. No essential calling information is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3. The description adds real meaning beyond the schema by stating the mutual exclusion of `urls` and `items` ('not both') and the minimum-content rule ('at least one URL, unless `open` is true'), which the schema does not express as a constraint.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource (submit many URLs as one asynchronous job) and immediately scopes it with 'shared settings applied to every URL'. It explicitly distinguishes itself from the scrape sibling and from batch_add_items/batch_close, so an agent can identify it without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States the selection condition outright: 'Use this instead of many spicrawl_scrape calls when you have tens or thousands of URLs.' It also names the downstream lifecycle tools (batch_status to poll, batch_results/batch_task_content to read, batch_add_items/batch_close for open jobs) and the exclusive condition for urls vs items.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_batch_task_contentRead one batch item's contentA
Read-onlyIdempotent
Inspect

Return the full payload one item of a batch job produced, by its seq (items are numbered from 0 in submission order). Cheaper than paging results when you need one URL's output. A CONFLICT error means either the item has not finished yet (poll spicrawl_batch_status and ask again) or it finished as failed (it will never produce content; the message says which). NOT_FOUND means no such seq.

ParametersJSON Schema
NameRequiredDescriptionDefault
seqYesThe item's sequence number (0-based, submission order).
job_idYesThe batch job id returned by spicrawl_batch_submit or spicrawl_batch_list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
contentNoThe item's document when it is text (markdown, text or html) or any non-object JSON value. An item whose payload is a JSON object is returned as that object's own fields instead.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, and the description adds a genuinely new layer: the error contract. It explains that CONFLICT is ambiguous between 'not finished yet' and 'finished as failed, will never produce content', and that the message disambiguates — this is behavior an agent cannot infer from the schema or annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, front-loaded with the primary purpose, then the cost/routing rationale, then the failure semantics. No filler, and each sentence carries distinct information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be described, and the description instead covers the two non-obvious gaps — cost trade-off versus paging and the ambiguous CONFLICT failure mode. Nothing an agent needs to call and interpret this tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both `seq` and `job_id` are already documented in the schema, including the 0-based submission-order semantics that the description restates. The description adds no syntax or format detail beyond the structured fields, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (return), resource (one batch item's full payload), and the addressing key (`seq`), and explicitly contrasts itself with the sibling that pages results. An agent can identify the tool and its scope without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit selection rule ('Cheaper than paging results when you need one URL's output') that routes against spicrawl_batch_results, and additionally routes on failure states by telling the agent to poll spicrawl_batch_status on CONFLICT. When-to-use and the recovery alternative are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_browser_connect_urlBrowser (CDP) connect URLAInspect

Coming soon: remote browsers are not available yet, so minting fails; do not rely on this tool. For scripted page interaction today use actions on spicrawl_scrape. Mints a single-use connect URL for Spicrawl's remote browser (GET /v1/browser, a DevTools Protocol (CDP) WebSocket) so YOUR code can drive it with any CDP client, using the URL as the browser WebSocket endpoint. It calls POST /v1/browser/token and returns a ws:// or wss:// URL carrying a short-lived token, never the API key: the URL works ONCE, within 60 seconds, and only with the options given here (editing them in the URL is refused), so call this right before connecting and again for every new session. Prefer sending the key as an Authorization header when the client supports headers on the WebSocket upgrade: then connect to the plain /v1/browser URL with 'Authorization: Bearer ' and no token is needed. The endpoint exists only when the deployment was installed with --with-cdp, and the key must carry the browser scope; otherwise minting fails (404 or 403). Parameter errors are reported when minting.

ParametersJSON Schema
NameRequiredDescriptionDefault
proxyNoYour own proxy, as http://user:pass@host:port. Replaces our pool, so proxy_country, proxy_region and sticky_key cannot be combined with it. Kept out of the returned URL.
engineNoRendering tier of the remote browser: `browser` (full browser, full protocol; the default) or `js` (lighter JavaScript rendering with a smaller protocol surface). A tier your plan does not include is refused.
sticky_keyNoKeep one exit IP for the session under this key (2-64 letters, digits, hyphens). Omit to rotate (the default).
session_ttlNoSession lifetime in seconds, 60-900. Default 180.
proxy_regionNoBroader exit region/pool name; 'global' means no constraint. Mutually exclusive with proxy_country.
proxy_countryNoExit country, ISO-3166 alpha-2 lowercase (e.g. 'de'). Mutually exclusive with proxy_region.

Output Schema

ParametersJSON Schema
NameRequiredDescription
urlYesws:// or wss:// connect URL carrying a single-use token (never the API key); use it as the CDP browser WebSocket endpoint.
notesNoUsage notes for the connect URL.
expires_atNoWhen the token expires, RFC 3339 UTC (60 s after minting).
single_useYesAlways true: the URL works for one connection.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite annotations covering safety hints, the description adds substantial behavior beyond them: single-use URL, 60-second window, options locked into the token (URL edits refused), token never exposes the API key, endpoint requires --with-cdp, key needs `browser` scope, and 404/403 failure modes. This is unusually rich disclosure for a token-minting tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the critical 'coming soon, do not rely' warning, which is the most important thing an agent can read. The body is dense and every clause carries operational detail, though it is long and could be tightened slightly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description needn't explain return values, and it still covers auth, scope requirements, deployment prerequisite, token lifetime, single-use constraint, and failure codes. Nothing an agent needs to call or avoid this tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all six parameters including enums, patterns, ranges, and mutual exclusions. The description only echoes this at a high level ('only with the options given here') without adding syntax or semantics beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Mints a single-use connect URL for Spicrawl's remote browser'), names the underlying endpoint, and distinguishes itself from the sibling alternative ('use `actions` on spicrawl_scrape'). An agent immediately knows what it does and that it is currently non-functional.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when NOT to use it ('Coming soon... do not rely on this tool') and routes to the working alternative for scripted page interaction today. It also gives the timing rule (call right before connecting, again per session) and the Authorization-header variant.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_docs_indexList the Spicrawl docsA
Read-onlyIdempotent
Inspect

The docs' llms.txt: every Spicrawl documentation page with its title, a one-line description and its Markdown URL. Use it to find the right page when a search does not, or to get an overview of what is documented; read a page with spicrawl_docs_read. No parameters.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
urlYesWhere the document lives on the docs site.
contentYesThe index (llms.txt): one line per page with its title, description and Markdown URL.
truncatedYesTrue when the content was cut at the size cap; the content says so at its end.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, openWorld and non-destructive, so the safety profile is covered. The description adds useful context beyond them: the content is a static llms.txt index and what each entry carries, which tells the agent this is a cheap catalog lookup rather than a live query.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the resource and its contents, followed by when-to-use and the read follow-up. No filler and nothing repeated from the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A zero-parameter catalog tool with an output schema, so return-value details need not be spelled out; the description still summarizes the entry shape. Nothing needed to select or invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so the schema carries nothing to misinterpret and the baseline is 4. The description explicitly confirms 'No parameters', which matches the empty schema and removes any doubt about required input.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource (the Spicrawl docs llms.txt index) and exactly what it contains: every page with title, one-line description and Markdown URL. It names spicrawl_docs_read as the follow-up and implies spicrawl_docs_search, so an agent can distinguish it from its siblings without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit conditions: use it to find the right page when a search fails, or to get an overview. It names spicrawl_docs_read as the alternative for actually reading a page, though the search tool it complements (spicrawl_docs_search) is referenced only as 'a search' rather than by name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_docs_readRead a Spicrawl docs pageA
Read-onlyIdempotent
Inspect

Fetches one Spicrawl documentation page as Markdown. path may be a page path (guides/anti-bot), a docs URL from spicrawl_docs_search (url or md_url), or either with a #anchor (the whole page is returned; the anchor names the section to look at). Only pages on the Spicrawl docs (https://docs.spicrawl.com/docs) can be read. Pages over 60000 characters are truncated, and the text says so. Don't know the path? Use spicrawl_docs_search, or spicrawl_docs_index (llms.txt) for the list of every page.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPage path (`guides/anti-bot`, `errors#AUTH_INVALID_KEY`) or a full docs URL, as returned by spicrawl_docs_search.

Output Schema

ParametersJSON Schema
NameRequiredDescription
urlYesWhere the document lives on the docs site.
titleNoThe page's first heading, when it has one.
md_urlNoThe Markdown source it was read from.
contentYesThe document as Markdown.
sectionNoThe #anchor that was asked for, without the #. The whole page is returned.
truncatedYesTrue when the content was cut at the size cap; the content says so at its end.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, openWorld and non-destructive, so the safety profile is covered. The description adds real behavioral context beyond that: pages over 60000 characters are truncated and the text says so, and only pages under https://docs.spicrawl.com/docs can be read.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tight sentences, all front-loaded with the core action first, then accepted input forms, then the domain limit, then routing to alternatives. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists so return values need no explanation; what remains an agent needs (accepted path formats, anchor semantics, truncation behavior, domain restriction, fallback tools) is all present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description genuinely enriches the single `path` parameter: it accepts a page path, a docs URL from search (url or md_url), or either with a `#anchor`, and clarifies the anchor only names the section to look at while the whole page is returned.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetches one Spicrawl documentation page as Markdown') and scopes it to a single page, which cleanly separates it from siblings like spicrawl_docs_search and spicrawl_docs_index.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the alternatives and the condition for using them: 'Don't know the path? Use spicrawl_docs_search, or spicrawl_docs_index (llms.txt) for the list of every page.' It also states the domain restriction on which pages can be read.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_request_getGet one requestA
Read-onlyIdempotent
Inspect

The full log record of one past API call by its request id. Every response carries its id in the X-Request-Id header (and error bodies carry it too), so this is the tool for debugging a failed or slow scrape: it shows status, error_code/error_detail, attempts, the engine and proxy (tier, country, provider, sticky) actually used, whether and how the target blocked it (vendor/signal/rule), per-stage latency spans and credits charged. Returns not_found both for unknown ids and for ones older than your retention window, and for another project's request unless your key has the read scope.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesThe request id (a ULID, from X-Request-Id or a spicrawl_requests_list row's `id`).

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesThe request id (X-Request-Id).
urlNoThe target URL as requested.
proxyNoWhat proxy was asked for versus what served. Never an exit IP or credentials.
spansNoLatency in milliseconds per stage; null means not measured. Stages do not sum to total_ms.
engineNoThe rendering tier that served it: fetch, js or browser. Absent when refused before a tier was chosen.
statusNoTerminal outcome: success, failed, timeout, blocked, rejected or cancelled. Only success is charged.
blockedNoPresent only when a bot challenge was detected.
attemptsNoDispatch attempts including retries.
bytes_inNo
featuresNoFeatures the request used; free-form.
url_hostNo
bytes_outNo
created_atNoWhen the request arrived, RFC 3339 UTC.
error_codeNoThe problem code the caller got, e.g. ERR::UPSTREAM::CHALLENGE. Absent on success.
project_idNo
http_statusNoThe target's HTTP status; absent when no response was received.
proxy_bytesNo
error_detailNo
credits_microNoCredits charged in micro-credits (1 credit = 1000000); 0 unless success.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnly/idempotent annotations by disclosing the auth requirement (needs `read` scope for other projects' requests) and precise failure semantics — not_found is returned both for unknown ids and for ids past the retention window. It also enumerates the content actually returned (status, error_code/detail, attempts, engine/proxy, block rules, latency spans, credits).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then the provenance of the id, the debugging use case, the record contents, and the failure conditions — every clause carries information, and the multi-item lists are compact rather than padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema already present, return shape needn't be explained, yet the description still completes the picture with auth prerequisites, retention-window behavior, and cross-project access rules. Nothing an agent needs to call and interpret this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single `id` parameter is already documented as a ULID from X-Request-Id or a list row. The description repeats rather than extends this (mentioning the X-Request-Id header), so it adds no meaning beyond the schema — baseline 3 for a fully-covered single param.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — 'The full log record of one past API call by its request id' — and the singular 'one ... by its request id' clearly contrasts with the plural spicrawl_requests_list sibling. An agent can distinguish this from the list tool and from session/batch tools without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly names the use case: 'this is the tool for debugging a failed or slow scrape.' It gives clear context for when to reach for it, but does not name an alternative or state an explicit when-not (e.g. preferring requests_list for scanning many).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_requests_listList recent requestsA
Read-onlyIdempotent
Inspect

Recent API calls in your key's project, newest first, each with project_id, status, engine, http_status, error_code/error_detail, attempts, URL, proxy used, latency spans (queue/engine/upstream/total ms), block detection and credits. Use it to find failing calls (only_errors=true) or to spot patterns across a target. all_projects=true lists every project in your organization instead (needs a key with the read scope; 403 ERR::AUTH::INSUFFICIENT_SCOPE otherwise). Records only exist within the retention window reported in page.retention_hours / page.retained_since; an empty page means nothing in that window. Paginate by passing page.next_before and page.next_before_id back as before and before_id while page.has_more is true, keeping all_projects the same. Not billing-grade: use spicrawl_usage for totals.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoRows per page, 1-200. Default 50.
beforeNoCursor: RFC 3339 timestamp, exactly as returned in page.next_before. Pass together with before_id.
statusNoOnly requests with this outcome.
before_idNoCursor: request id, exactly as returned in page.next_before_id.
only_errorsNoOnly requests whose status is anything other than 'success'.
all_projectsNoEvery project in your organization, not just the key's own. Needs the `read` scope. Keep it the same across pages.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNoRequest records, newest first. Can be shorter than limit while page.has_more is true.
pageNoPaging cursor and the retention window.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnlyHint/idempotentHint annotations by disclosing the retention window (page.retention_hours/retained_since), the meaning of an empty page, the exact 403 ERR::AUTH::INSUFFICIENT_SCOPE failure mode and required `read` scope, and the pagination contract. This is behavior an agent cannot infer from annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded: core purpose first, then filtering, scope, retention, pagination, and the billing caveat. Every sentence earns its place, though the enumeration of returned fields is dense enough to slightly slow the opening.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a paginated, retention-bounded, scope-sensitive list tool, the description covers pagination mechanics, retention semantics, scope requirements, error behavior, and the distinction from the totals tool. An output schema exists, so omission of return formatting is appropriate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description still adds value by tying parameters together (paginate via page.next_before/next_before_id into before/before_id, keep all_projects stable across pages, only_errors semantics) and reinforcing intent behind status filtering.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Starts with a precise verb+resource+ordering statement ('Recent API calls in your key's project, newest first') and enumerates the fields returned, so the agent knows exactly what this list yields. It also distinguishes itself from sibling spicrawl_request_get (single call) and spicrawl_usage (totals) by naming the latter explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit use cases ('find failing calls (only_errors=true)' and 'spot patterns across a target') plus a strong when-not directive ('Not billing-grade: use spicrawl_usage for totals'). Also names the alternative scope mode (all_projects=true) with its precondition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_scrapeScrape a URLAInspect

Retrieve a web page and return its content as markdown (default), text, HTML, a JSON envelope, or a printed PDF. Handles the fetch vs. browser decision, charset decoding, and PDF-to-text for you. Optionally extract structured data with CSS selectors (extract) or autoparse (a natural-language ai_extract is coming soon), return discovered links, take a screenshot, or scope the DOM with include_tags/exclude_tags. Each successful call is billed in credits (a failure costs 0). Results are cached by default, and a cache hit is billed like the fetch that stored it (the cache saves time, not credits); set cache=false for time-sensitive pages. With the defaults it only reads the page. A method other than GET, HEAD or OPTIONS, and the actions that click, fill or run scripts on the page, can change state on the target site: set them only when the user asks for that. For markdown, text and HTML it returns { content }. With format: "json", or when extract, ai_extract, autoparse, links, screenshot or network_capture is set, it returns the JSON envelope: content, the site's status, credits, engine (the rendering tier: fetch, js or browser), warnings and data for extraction. Screenshots come back as image content blocks; each screenshots entry in the JSON keeps its metadata and says which block holds it. A PDF comes back as a resource content block, with its size, the rendering tier and the credits in the JSON.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesThe absolute URL to retrieve.
modeNoRouting mode. `auto` lets the platform escalate fetch -> browser as needed, billing only the rung that worked.
waitNoMilliseconds to wait after load before capturing (render only).
cacheNoServe a recent cached result if fresh (on by default). A hit is billed at the same price as the fetch that stored it: the cache saves time, not credits. Set false only when you need live data.
linksNoAlso return the page's discovered links as an absolute, de-duplicated list.
proxyNoYour own proxy URL to egress through. Takes precedence over the pool; no surcharge.
formatNoOutput format. 'markdown' (default) is best for feeding to an LLM; 'html' returns the raw document; 'json' returns a structured envelope; 'pdf' prints the page in a full browser (routed there for you) and returns the file as a resource content block.markdown
methodNoHTTP method sent to the target (default GET; no request body can be sent). Anything but GET, HEAD or OPTIONS can change state on the target site: use it only when the user asks.
renderNoRender with a real browser (executes JavaScript). Use for single-page apps or pages whose content is painted client-side. Costs more than the default fetch tier.
actionsNoBrowser steps run in order before capture (render only). Each step is {type, ...fields}. Examples: [{"type":"click","selector":"#load-more"},{"type":"wait_for","selector":".item:nth-child(20)","timeout_ms":5000}] · infinite scroll: [{"type":"scroll","to_bottom":true},{"type":"wait_for","ms":1000}] · login: [{"type":"fill","selector":"#user","value":"me"},{"type":"fill","selector":"#pass","value":"…","secret":true},{"type":"click","selector":"button[type=submit]","wait_for_navigation":true}]. A screenshot step switches the response to the JSON envelope (a FORMAT_COERCED warning says so).
extractNoSelector-based extraction: a map of field -> CSS/XPath selector, e.g. {"title":"h1","price":".amount"}. Returns structured `data`. Precise and cheap when you know the page structure.
stealthNoComing soon: not available yet, do not send. Stealth mode: render in a full browser hardened against bot detection. Default false.
max_costNoRefuse (rather than run) a request that would cost more than this many credits.
wait_forNoCSS selector to wait for before capturing (render only).
autoparseNoReturn the structured data the page publishes about itself (JSON-LD, OpenGraph, Twitter Card, microdata). No selectors; survives redesigns.
cache_ttlNoMax age in seconds of a cached copy to accept (0 forces a fresh fetch; capped at 48h). Freshness only: a hit is billed like a fetch.
parse_pdfNoTurn a PDF target into text/markdown (default true). false refuses PDFs.
ai_extractNoComing soon: not available yet, do not send. Model-driven extraction: describe what you want and let a model find it, no selectors. Refused with ERR::INTERNAL::UNAVAILABLE until it launches; use `extract` or `autoparse`.
screenshotNoCapture a screenshot (requires render).
session_idNoRun inside a session from spicrawl_session_create: same exit IP and browser state (cookies, localStorage) across calls.
sticky_keyNoComing soon: not available yet, do not send. Reuse the same managed-pool exit for every request carrying this key, without a session.
impersonateNoFetch tier only: present a real browser's TLS/JA3 + HTTP/2 fingerprint to clear passive bot gates. On by default; set false to send a plain client handshake.
exclude_tagsNoCSS selectors to remove (e.g. ['nav','.ad','#cookie']).
include_tagsNoCSS selectors to KEEP (everything else is dropped).
proxy_verifyNoVerify `proxy` is reachable before using it.
premium_proxyNoComing soon: not available yet, do not send. Use a residential exit from Spicrawl's managed pool instead of datacenter. Until then, pass your own `proxy`.
proxy_countryNoComing soon: not available yet, do not send. ISO-3166 alpha-2 country for a managed-pool exit, lowercase (e.g. 'us', 'de').
custom_headersNoExtra request headers sent to the target, e.g. {"Accept-Language":"de"}.
extract_presetNoComing soon: not available yet, do not send. A named extraction preset instead of an inline `extract` map; any value fails today. Put the rules in `extract`.
block_resourcesNoResource types the browser should not load, e.g. ["fonts","media","images"] (render only). Faster and cheaper.
network_captureNoRecord the API responses the PAGE fetched while rendering — often cleaner JSON than the DOM. Render only.
original_statusNoReturn the target's own HTTP status instead of 200 for a successful scrape.
wait_for_timeoutNoMax milliseconds to wait for `wait_for`.
main_content_onlyNoStrip the page to its main article, dropping nav/footer/aside. Defaults on for markdown.
screenshot_formatNoScreenshot image format.
screenshot_qualityNoScreenshot quality 1-100 (lossy formats).
screenshot_fullpageNoCapture the whole page, not just the viewport.
screenshot_selectorNoCapture only the element matching this CSS selector.
allowed_status_codesNoTarget statuses to treat as success instead of an error (e.g. [404] to capture a not-found page).

Output Schema

ParametersJSON Schema
NameRequiredDescription
pdfNoPresent for format=pdf: the file itself is a resource content block.
urlNoThe requested URL.
dataNoOutput of `extract` or `autoparse`.
linksNoThe page's links, absolute and de-duplicated, when `links` was set.
engineNoRendering tier that produced the page: fetch, js or browser.
statusNoThe target site's HTTP status (not this call's). Anything but 200/404/410 is charged 0.
contentNoThe page in the requested format (markdown, text or html); absent for a PDF.
creditsNoCredits charged for this call.
headersNoThe target's response headers.
networkNoResponses the page fetched, when `network_capture` was set.
warningsNoAdvisories about the call, e.g. an ignored option.
final_urlNoURL after redirects; may be empty.
truncatedNoThe target body exceeded the size cap and was cut.
diagnosticsNoWhich rendering tiers were tried, after an escalation.
screenshotsNoMetadata of each screenshot; the images are separate image content blocks.
empty_fieldsNo`extract` rules that matched nothing: usually a broken selector.
proxy_sourceNoWhose exit carried the request: pool, custom or direct.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: credits billing per successful call with failures free, cache-hit billing parity (cache saves time, not credits), the warning that non-GET methods and click/fill/script actions can mutate the target site, and the tier escalation behavior. The annotations only say readOnly=false, openWorld=true, destructive=false, idempotent=false; the description explains why those are true and what the practical consequences are.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose, then options, then billing, then safety, then return shapes, so an agent can stop reading early. It is dense and long (heavy parentheticals), but with 39 parameters and several cross-cutting behaviors almost every clause carries non-redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a highly complex open-world tool, the description covers cost model, caching semantics, state-change risk, format-dependent return shapes, screenshot/PDF content blocks, and the JSON envelope fields. Even with an output schema present, nothing an agent needs to invoke it safely is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter semantics the schema does not state as a whole: 'With format: json, or when extract, ai_extract, autoparse, links, screenshot or network_capture is set, it returns the JSON envelope.' It also flags unavailable parameters (ai_extract) and clarifies defaults, which helps an agent pick among the 39 options.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource ('Retrieve a web page and return its content as markdown (default), text, HTML, a JSON envelope, or a printed PDF'), and the enumeration of output formats plus the fetch/browser handling makes it unmistakably the general-purpose single-URL scraper among its batch/session/usage siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete usage conditions: 'set `cache=false` for time-sensitive pages', 'set them only when the user asks for that' for state-changing methods and actions, and 'With the defaults it only reads the page.' It does not route the agent to siblings (e.g. batch_submit for multiple URLs), but within the tool the when-to-use guidance is explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_session_contextDump a session's stored contextA
Read-onlyIdempotent
Inspect

Return the full stored state of a LIVE session — cookies, localStorage and other credentials — plus its fingerprint and domain scores. The session_context object can be passed to spicrawl_session_create to clone the session. The result contains secrets (login cookies): do not echo it to the user or logs unless asked.

ParametersJSON Schema
NameRequiredDescriptionDefault
session_idYesThe session id returned by spicrawl_session_create or spicrawl_session_list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
retiredNoWhy the session was retired; absent while usable.
warningNoThe API's reminder that this state dies with the session.
created_atNoCreation time, RFC 3339 UTC.
expires_atNoCurrent expiry, RFC 3339 UTC.
session_idYesThe session id.
fingerprintNoStored browser fingerprint; null when none.
usage_countNo
last_used_atNoLast use, RFC 3339 UTC; null if never used.
domain_scoresNoPer-domain standing, keyed by domain. Omitted when empty.
schema_versionNo
session_contextNoCookies and storage: secrets. Pass it as `session_context` to spicrawl_session_create to clone the session.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive). The description adds genuinely new behavioral context: the result contains live login cookies and other secrets and must not be echoed to the user or logs unless asked. That is important disclosure beyond the structured fields, though the failure mode for a non-LIVE session is left unstated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences: payload contents first, downstream cloning use second, sensitivity warning last. Every sentence carries distinct information and nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need only light description, and the description still characterizes them (cookies, fingerprint, domain scores). The secrets-handling warning closes the main risk gap; only edge behavior for expired/non-live sessions is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

One parameter with 100% schema description coverage, and the schema already explains that session_id comes from spicrawl_session_create or spicrawl_session_list. The description adds no format, validity, or lifecycle detail beyond what the schema provides, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Return the full stored state of a LIVE session') and enumerates the payload (cookies, localStorage, credentials, fingerprint, domain scores), which is far richer than a tautology. It does not explicitly contrast itself with the near-named sibling spicrawl_session_get, so an agent must infer that this returns raw stored state rather than session metadata.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete downstream use case — passing the session_context object to spicrawl_session_create to clone the session — which tells the agent why and when to call it. It offers no explicit 'when not to use' or comparison against session_get/session_list, so the guidance is contextual rather than exclusionary.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_session_createCreate a browsing sessionAInspect

Create a session: a persistent browser identity (cookie jar, localStorage, a fixed rendering tier and, by default, a sticky exit IP) that survives across scrapes. Use it for multi-step flows — log in, then fetch pages behind the login — by passing the returned id as session_id to every spicrawl_scrape call that should share the state. The rendering tier is fixed for the session's lifetime and every scrape on the session runs on it. Leave engine out and one is chosen for you. Release the session with spicrawl_session_release when done. Returns the session object (id, engine, status, sticky_key, proxy, expires_at).

ParametersJSON Schema
NameRequiredDescriptionDefault
engineNoRendering tier fixed for the session's lifetime. Optional: leave it out and one is chosen for you. `fetch` is plain HTTP; `js` is JavaScript rendering and refuses `actions`, `block_resources`, screenshots and PDFs; `browser` is a full browser.
rotate_ipNoComing soon: not available yet, do not send. Keep the cookie jar stable but rotate the managed-pool exit IP per request. Cannot combine with sticky_key.
sticky_keyNoComing soon: not available yet, do not send. Pin the managed-pool exit IP to this key; sessions sharing a key share an exit. Cannot combine with rotate_ip.
fingerprintNoComing soon: not available yet, do not send. Browser fingerprint pin, stored verbatim. Needs a full-browser session (`engine: "browser"`).
region_poolNoComing soon: not available yet, do not send. Managed-pool region to draw the exit from.
ttl_secondsNoIdle lifetime in seconds (min 30, default 1800; the organization's maximum is enforced, not clamped).
domain_scoresNoSeed per-domain error scores (usually copied from a spicrawl_session_context dump).
premium_proxyNoComing soon: not available yet, do not send. Use a residential managed-pool exit, exactly as on spicrawl_scrape.
proxy_countryNoComing soon: not available yet, do not send. ISO-3166 alpha-2 exit country; requires premium_proxy.
session_contextNoSeed the session's state (cookies, storage) — e.g. the `session_context` object from spicrawl_session_context, to clone a session.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesSession id; pass it as `session_id` to spicrawl_scrape.
leaseNoPresent only while a scrape holds the session; release and delete are refused until it lapses unless `force`.
proxyNoThe session's exit intent (never an IP or endpoint).
engineNoRendering tier the session is bound to: fetch, js or browser.
statusNoactive, released or expired; derived from the clock, and only `active` sessions can be used.
contextNoSize summary of the stored context (counts only, no secrets); null once the session is not active.
retiredNoWhy the session was taken out of service (expired, usage_exhausted, explicit); absent while usable.
warningsNoDecisions made on your behalf at creation, e.g. a TTL reduced to the organization maximum.
created_atNoCreation time, RFC 3339 UTC.
expires_atNoCurrent expiry (slides on use), RFC 3339 UTC.
project_idNoProject the session belongs to.
sticky_keyNoExit pin in use (empty when rotate_ip was set).
fingerprintNoBrowser fingerprint, as stored.
released_atNoRelease time, on released sessions, RFC 3339 UTC.
usage_countNoSuccessful scrapes that used the session.
last_used_atNoLast successful scrape, RFC 3339 UTC; null if never used.
domain_scoresNoPer-domain standing, keyed by domain. Omitted when empty.
hard_expires_atNoFixed ceiling the expiry never passes, RFC 3339 UTC.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are sparse (readOnlyHint=false, openWorldHint=false, idempotentHint=false, destructiveHint=false). The description adds that the rendering tier is fixed for the session's lifetime, that sessions survive across scrapes, and that they must be released with spicrawl_session_release, which is meaningful for resource management. However, it doesn't disclose default TTL or expiration behavior beyond what the schema already shows.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense paragraph with no wasted sentences and is front-loaded with the essential definition. It is slightly long, but every clause (persistent identity, multi-step flow, engine fixed, release step) earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that an output schema exists, the description doesn't need to enumerate return values, though it helpfully mentions key fields. It covers the critical lifecycle (create → use via session_id → release), which is exactly what an agent needs for this stateful resource.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents every parameter thoroughly. The description adds a small amount of guidance (leave `engine` out and one is chosen) but not enough to go beyond the baseline 3 when the schema does all the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Create) and resource (a session/browsing identity), and elaborates exactly what a session is: a persistent state container (cookie jar, localStorage, fixed rendering tier, sticky exit IP). It distinguishes itself from siblings by naming spicrawl_session_release and spicrawl_scrape and describing their relationship.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use it (multi-step flows—log in then fetch pages behind the login) and how to use it with a sibling (pass the returned `id` as `session_id` to spicrawl_scrape calls that should share state). It also names a related lifecycle tool, spicrawl_session_release, for cleanup.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_session_deleteDelete a sessionA
DestructiveIdempotent
Inspect

Permanently delete a session and its stored state, including the record itself (prefer spicrawl_session_release if you only want to stop using it). Idempotent: deleting an already-deleted session succeeds. Refused while a scrape holds the session's lease unless force is true.

ParametersJSON Schema
NameRequiredDescriptionDefault
forceNoBreak an active lease (a scrape currently using the session). Only set when you know it is safe.
session_idYesThe session id returned by spicrawl_session_create or spicrawl_session_list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
deletedYesAlways true on success (deleting an already-deleted session succeeds).
session_idYesThe id that was deleted.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructive=true and idempotent=true, but the description adds real behavioral context beyond them: what gets destroyed (the record and stored state), that repeat deletes succeed, and that deletion is refused while a scrape holds the lease unless force is set.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with zero waste; the destructive scope is front-loaded, followed by the alternative and then edge-case behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema covering return values and annotations covering safety, the description supplies everything else an agent needs: destruction scope, idempotency, lease precondition, and escape hatch.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already documented in the schema. The description reinforces the force semantics ('unless force is true') but adds no syntax or format detail beyond what the schema provides; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Permanently delete a session and its stored state') and explicitly scopes it against the sibling spicrawl_session_release, so an agent can differentiate without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the alternative explicitly ('prefer spicrawl_session_release if you only want to stop using it') and states the selection condition, plus the refusal precondition involving an active lease. When-to-use and when-not-to-use are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_session_getGet a sessionA
Read-onlyIdempotent
Inspect

Return one session's metadata: status, engine (its rendering tier), proxy/exit, usage count, expiry, lease holder, and a summary of its stored context. Never returns the credentials themselves (use spicrawl_session_context for that).

ParametersJSON Schema
NameRequiredDescriptionDefault
session_idYesThe session id returned by spicrawl_session_create or spicrawl_session_list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesSession id; pass it as `session_id` to spicrawl_scrape.
leaseNoPresent only while a scrape holds the session; release and delete are refused until it lapses unless `force`.
proxyNoThe session's exit intent (never an IP or endpoint).
engineNoRendering tier the session is bound to: fetch, js or browser.
statusNoactive, released or expired; derived from the clock, and only `active` sessions can be used.
contextNoSize summary of the stored context (counts only, no secrets); null once the session is not active.
retiredNoWhy the session was taken out of service (expired, usage_exhausted, explicit); absent while usable.
warningsNoDecisions made on your behalf at creation, e.g. a TTL reduced to the organization maximum.
created_atNoCreation time, RFC 3339 UTC.
expires_atNoCurrent expiry (slides on use), RFC 3339 UTC.
project_idNoProject the session belongs to.
sticky_keyNoExit pin in use (empty when rotate_ip was set).
fingerprintNoBrowser fingerprint, as stored.
released_atNoRelease time, on released sessions, RFC 3339 UTC.
usage_countNoSuccessful scrapes that used the session.
last_used_atNoLast successful scrape, RFC 3339 UTC; null if never used.
domain_scoresNoPer-domain standing, keyed by domain. Omitted when empty.
hard_expires_atNoFixed ceiling the expiry never passes, RFC 3339 UTC.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds valuable non-obvious behavior: it never returns credentials and points to the sibling tool that does, plus it lists the metadata fields exposed. It does not cover error behavior or lease semantics in depth.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly written sentences with no wasted words. The returned fields are front-loaded, and the credential limitation and alternative are appended as the key exception, making the structure easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with an output schema and rich annotations, the description is complete enough. It clarifies the return contents and the credential boundary, and the output schema handles the detailed response structure, leaving no critical gap for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the session_id parameter is already fully documented in the schema, including where it comes from. The description adds no additional syntax, format, or constraint details for the parameter, so the baseline score of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (Return) and resource (one session's metadata) and enumerates the exact fields returned. It also explicitly distinguishes itself from the sibling spicrawl_session_context by noting it never returns credentials, so an agent can tell the two apart without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear context for use (fetch a session's metadata) and an explicit alternative for the credential case ('use spicrawl_session_context for that'). However, it does not state when to prefer this over spicrawl_session_list or describe prerequisites for calling it, so it falls short of full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_session_listList sessionsA
Read-onlyIdempotent
Inspect

List this API key's project's sessions, newest first. Returns { sessions: [...], next_cursor? }; pass next_cursor back as cursor for the next page. Never includes the stored credentials.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoPage size (default 50, max 200).
cursorNo`next_cursor` from a previous page, verbatim.
engineNoOnly sessions on this rendering tier.
statusNoOnly sessions in this state.

Output Schema

ParametersJSON Schema
NameRequiredDescription
sessionsYesSessions on this page, newest first; may be short or empty under a `status` filter.
next_cursorNoPass back as `cursor` for the next page; absent on the last page.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the bar is lower, and the description still adds a security-relevant trait: "Never includes the stored credentials." It also discloses the return envelope shape and that next_cursor is the pagination handle, going beyond structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, front-loaded with scope and ordering, then return shape and pagination, then the credential caveat. No filler and every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values needn't be fully explained, and the description covers scope, ordering, pagination, and the credential exclusion. It stops short of noting how the engine/status filters interact, but those are documented in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all four params are self-documented, making 3 the baseline. The description's note that next_cursor is passed back as cursor largely restates the cursor param's own schema text, adding little beyond it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource+scope ("List this API key's project's sessions") and adds ordering semantics ("newest first"). An agent can tell this is a paginated list apart from the singular session_get / session_context siblings, though it doesn't explicitly name an alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the verb (list = enumerate sessions) and it explains the pagination loop, but there is no explicit when-to-use/when-not guidance or routing against siblings like requests_list or session_get. Adequate but with clear gaps.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_session_releaseRelease a sessionA
DestructiveIdempotent
Inspect

End a session when you are done with it: frees its exit IP and browser state; it can no longer be used with spicrawl_scrape. Its stored cookies and storage are purged and cannot be recovered; start a new session and log in again to continue. The record stays visible (status released) so its history can still be inspected. Refused while a scrape holds the session's lease unless force is true. Returns the session object.

ParametersJSON Schema
NameRequiredDescriptionDefault
forceNoBreak an active lease (a scrape currently using the session). Only set when you know it is safe.
session_idYesThe session id returned by spicrawl_session_create or spicrawl_session_list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesSession id; pass it as `session_id` to spicrawl_scrape.
leaseNoPresent only while a scrape holds the session; release and delete are refused until it lapses unless `force`.
proxyNoThe session's exit intent (never an IP or endpoint).
engineNoRendering tier the session is bound to: fetch, js or browser.
statusNoactive, released or expired; derived from the clock, and only `active` sessions can be used.
contextNoSize summary of the stored context (counts only, no secrets); null once the session is not active.
retiredNoWhy the session was taken out of service (expired, usage_exhausted, explicit); absent while usable.
warningsNoDecisions made on your behalf at creation, e.g. a TTL reduced to the organization maximum.
created_atNoCreation time, RFC 3339 UTC.
expires_atNoCurrent expiry (slides on use), RFC 3339 UTC.
project_idNoProject the session belongs to.
sticky_keyNoExit pin in use (empty when rotate_ip was set).
fingerprintNoBrowser fingerprint, as stored.
released_atNoRelease time, on released sessions, RFC 3339 UTC.
usage_countNoSuccessful scrapes that used the session.
last_used_atNoLast successful scrape, RFC 3339 UTC; null if never used.
domain_scoresNoPer-domain standing, keyed by domain. Omitted when empty.
hard_expires_atNoFixed ceiling the expiry never passes, RFC 3339 UTC.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say destructive/idempotent/not-read-only; the description goes well beyond them by disclosing exactly what is destroyed (exit IP, browser state, cookies and storage, irrecoverably), what survives (the record, status `released`, history inspectable), the lease-refusal behavior, and the `force` override. This is the richest part of the definition.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four tight clauses in two sentences, front-loaded with the action and its consequences, then the refusal rule and return. No filler and no repetition of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, idempotent session-ending tool with an output schema already present, the description covers everything an agent needs: scope, irreversibility, downstream effects on spicrawl_scrape, retained record, and the lease conflict path. Return-value explanation is correctly omitted since the output schema carries it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds the missing trigger condition for `force` — refusal happens while a scrape holds the session's lease — which the schema only describes as 'break an active lease'. That contextual 'when is force needed' detail is genuine added value over the field-level text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb + resource ('End a session') with the consequences spelled out: frees exit IP and browser state, purges cookies/storage, record remains as status `released`. This distinguishes it from the sibling spicrawl_session_delete, which would imply record removal, without the agent having to open either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States the trigger clearly ('when you are done with it'), names the blocked follow-on ('can no longer be used with spicrawl_scrape'), and gives the recovery path ('start a new session and log in again'). It also documents the refusal condition and the escape hatch (`force` true). It never explicitly routes the agent to spicrawl_session_delete as the alternative, which keeps it just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_usageUsage breakdownA
Read-onlyIdempotent
Inspect

Billing-grade usage for your org over a date window, from the daily rollup (usage_daily), grouped by day, project, engine, feature or key. group_by=key returns per API key (key_id, name, prefix, project_id) counters per metric per day, from usage_key_daily; keyless (dashboard) usage is not in it, and a project-scoped key sees only its own project's keys. Use it to answer 'how many requests/credits did I use, and where'. The window defaults to the last 30 days including today; to is EXCLUSIVE (a single day 2026-08-01 is from=2026-08-01, to=2026-08-02) and the window may not exceed 400 days. The response carries stale_seconds (age of the newest rollup row; null when the window is empty). Requires the key to have the read scope.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoEXCLUSIVE end date, YYYY-MM-DD (UTC). Default: tomorrow, so today is included.
fromNoInclusive start date, YYYY-MM-DD (UTC). Default: 29 days before today.
metricsNoMetrics to return. Omit for all of them.
group_byNoHow to group the rows. Default 'day'.
project_idNoRestrict to one project id (must be a valid Spicrawl identifier).

Output Schema

ParametersJSON Schema
NameRequiredDescription
keysNogroup_by=key only: one entry per API key, with its counters per UTC day.
groupsNoThe buckets, sorted by key. Empty (or missing for group_by=key) does not mean no usage: read totals.
periodNoThe window, as a half-open range of UTC days.
totalsNoBilled quantities for the whole window. Authoritative; use these, not the sum of groups.
group_byNoThe dimension used: day, project, engine, feature or key.
warningsNoCaveats the numbers would otherwise hide.
usage_as_ofNoWhen the newest rollup row in the window was written; null when the window is empty.
unattributedNoThe part of each total the groups do not explain.
stale_secondsNoAge of usage_as_of in seconds; null when the window is empty. A large value means the rollup is behind.

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover only the safety profile (readOnly/idempotent/non-destructive), and the description adds substantial context beyond them: the default 30-day window, the EXCLUSIVE end date with a worked example, a hard 400-day window cap, the stale_seconds freshness field, the requirement for the `read` scope, and the blind spot for keyless usage. That is a rich, non-obvious behavioral disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is a single dense paragraph rather than a bulleted spec, which hurts scannability slightly, but the most important facts (what it returns, what it excludes, then window/date semantics, then auth) are front-loaded and each sentence carries non-redundant information. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the description rightly does not enumerate return fields; it still flags the one response property worth knowing (stale_seconds). Combined with window bounds, exclusivity, grouping caveats and the required scope, an agent has everything needed to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is already 100%, so the baseline is 3, but the description goes further by explaining semantics the schema only gestures at: `to` is exclusive with a single-day example, the default window is last 30 days including today, and group_by=key changes both the source table and the returned counter shape. Minor gaps remain around how metrics interact with grouping, but the added meaning is real.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource: billing-grade org usage over a date window, drawn from the usage_daily rollup and groupable by day/project/engine/feature/key. It even names the alternate source table (usage_key_daily) for key grouping. It never names its obvious siblings (spicrawl_usage_summary, spicrawl_usage_reconciliation), so the agent gets no explicit differentiation within the usage family.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a concrete usage condition: "Use it to answer 'how many requests/credits did I use, and where'", and supplies negative scoping for group_by=key (keyless dashboard usage is absent; a project-scoped key only sees its own project). It stops short of stating when to prefer this over spicrawl_usage_summary or spicrawl_usage_reconciliation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_usage_reconciliationUsage reconciliationA
Read-onlyIdempotent
Inspect

Drift report for ONE day: re-derives usage from that day's request log and compares it with the billed daily rollup, so you can see whether the rollup missed or double-counted anything. Defaults to yesterday (UTC); today is still accumulating and would always show drift. Requires the read scope.

ParametersJSON Schema
NameRequiredDescriptionDefault
dayNoThe UTC day to reconcile, YYYY-MM-DD. Default: yesterday.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dayNoThe UTC day reconciled.
driftNoDisagreements; empty means no drift.
warningsNoCaveats the numbers would otherwise hide.
repairableNoAlways false; nothing is repaired.
interpretationNoWhat the drift can and cannot prove. Read it before acting on drift.
request_log_rowsNoRows in the request log for the day; 0 means there was nothing to compare against.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so safety is covered. The description adds genuinely non-derivable context: the required `read` scope and the reason for the yesterday default (today's rollup is still accumulating), which is exactly the kind of behavioral detail annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler. The core behavior is front-loaded and the operational caveats (default, today's instability, required scope) follow in a single compact clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and the description covers scope, defaulting and auth. The only gap is operational cost: re-deriving a full day from the request log may be expensive or slow, and nothing here warns about that.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single `day` parameter is fully documented there, so the baseline is 3. The description goes slightly beyond by justifying the default (yesterday, because today always shows drift), which helps an agent decide whether to pass the parameter at all.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource ('re-derives usage from that day's request log and compares it with the billed daily rollup') and scopes it to ONE day, which separates it in an agent's mind from the raw-usage siblings spicrawl_usage and spicrawl_usage_summary. The 'drift report' framing makes the output intent unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States when the tool applies (a settled UTC day) and effectively excludes one case: 'today is still accumulating and would always show drift.' It never names the sibling alternatives (spicrawl_usage, spicrawl_usage_summary) that an agent might reach for instead, so routing is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

spicrawl_usage_summaryUsage summaryA
Read-onlyIdempotent
Inspect

A compact current-period summary of your org's usage (totals as of now, from the daily rollup). No parameters. Use for a quick 'how much have I used so far'; use spicrawl_usage for a windowed breakdown. Requires the read scope.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
planNo
periodNoThe window, as a half-open range of UTC days.
creditsNoMetered usage against the plan's included credits. Micro-credits: 1 credit = 1000000.
metricsNoEvery billed metric for the period.
warningsNoCaveats the numbers would otherwise hide.
allowanceNoThe monthly allowance the API enforces. Omitted when it cannot be read (warnings says so).
usage_as_ofNoWhen the newest rollup row in the window was written; null when the window is empty.
unattributedNoMetric name -> quantity. credits are micro-credits (1 credit = 1000000), engine_ms milliseconds, bytes_* bytes, the rest counts.
stale_secondsNoAge of usage_as_of in seconds; null when the window is empty. A large value means the rollup is behind.
period_elapsed_daysNoWhole days of the period elapsed; use it to pace consumption.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only, idempotent, non-destructive, and closed-world behavior. The description adds two things annotations cannot: the auth requirement ('Requires the `read` scope') and the data-freshness caveat implied by 'from the daily rollup' (totals are rolled-up, not real-time). Missing only a note on lag magnitude or pagination, so not a full 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with what the tool returns, followed by the routing guidance and the auth prerequisite. No filler; every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no prose. With annotations covering safety and the description covering scope, freshness source, alternative routing, and auth scope, an agent has everything needed to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so the baseline is 4. The description explicitly confirms 'No parameters', which matches the empty schema and prevents an agent from hunting for filter options.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource+scope: a current-period, org-level usage summary sourced from the daily rollup. It explicitly distinguishes itself from the sibling spicrawl_usage by naming it and the axis of difference (compact current totals vs. windowed breakdown).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-to-use ('quick how much have I used so far') and names the alternative tool plus the condition that selects it ('use spicrawl_usage for a windowed breakdown'). No inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 25 tool updates
    • Changedspicrawl_batch_add_items1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "items_added": {
        +      "description": "Items written to the job.",
        +      "type": "number"
        +    },
        +    "items_dispatched": {
        +      "description": "Of those, how many reached the dispatch queue now; do not re-add the rest.",
        +      "type": "number"
        +    },
        +    "job": {
        +      "additionalProperties": true,
        +      "description": "The job as it stands after the call.",
        +      "properties": {
        +        "cancel_requested_at": {
        +          "description": "ISO-8601 time a cancel was accepted.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "concurrency": {
        +          "description": "Effective per-job concurrency after the server's clamping.",
        +          "type": "number"
        +        },
        +        "error_code": {
        +          "description": "Machine code of a job-level failure.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "error_message": {
        +          "description": "Human-readable job-level failure reason.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "estimated_credits": {
        +          "description": "Credits reserved at submission (a hold, not a charge; compare with progress.credits_charged).",
        +          "type": "number"
        +        },
        +        "estimated_credits_micro": {
        +          "description": "Same as estimated_credits in micro-credits.",
        +          "type": "number"
        +        },
        +        "failure_threshold": {
        +          "description": "Failed-item count that aborts the job, when set.",
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "finished_at": {
        +          "description": "ISO-8601 time the job reached a terminal status.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "id": {
        +          "description": "Job id. Pass it as `job_id` to the other spicrawl_batch_* tools.",
        +          "type": "string"
        +        },
        +        "max_attempts": {
        +          "description": "Effective attempts per item.",
        +          "type": "number"
        +        },
        +        "name": {
        +          "description": "The label given at submission, if any.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "open": {
        +          "description": "True while the job accepts appended items (it will not complete until closed).",
        +          "type": [
        +            "boolean",
        +            "null"
        +          ]
        +        },
        +        "params": {
        +          "anyOf": [
        +            {
        +              "additionalProperties": {},
        +              "type": "object"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "description": "The job-level scrape settings as stored."
        +        },
        +        "priority": {
        +          "description": "Effective scheduling priority.",
        +          "type": "number"
        +        },
        +        "progress": {
        +          "additionalProperties": true,
        +          "description": "Live item counters and the credits charged so far.",
        +          "properties": {
        +            "bytes": {
        +              "description": "Total response bytes of finished items.",
        +              "type": "number"
        +            },
        +            "cancelled": {
        +              "description": "Items not run because the job was cancelled.",
        +              "type": "number"
        +            },
        +            "completed": {
        +              "description": "Items in any terminal status (succeeded + failed + cancelled + skipped).",
        +              "type": "number"
        +            },
        +            "credits_charged": {
        +              "description": "Credits actually charged so far (whole credits, rounded down).",
        +              "type": "number"
        +            },
        +            "credits_charged_micro": {
        +              "description": "Same as credits_charged in micro-credits (1 credit = 1,000,000).",
        +              "type": "number"
        +            },
        +            "failed": {
        +              "description": "Items that failed after all attempts; re-run them with spicrawl_batch_retry.",
        +              "type": "number"
        +            },
        +            "percent_complete": {
        +              "description": "completed / total x 100.",
        +              "type": "number"
        +            },
        +            "remaining": {
        +              "description": "Items not yet finished (total - completed).",
        +              "type": "number"
        +            },
        +            "skipped": {
        +              "description": "Items skipped (for example after failure_threshold or credit_budget stopped the run).",
        +              "type": "number"
        +            },
        +            "succeeded": {
        +              "description": "Items that succeeded. Only these are charged.",
        +              "type": "number"
        +            },
        +            "total": {
        +              "description": "Items in the job (grows when items are appended to an open job).",
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "project_id": {
        +          "description": "Project the API key belongs to.",
        +          "type": "string"
        +        },
        +        "results_expire_at": {
        +          "description": "ISO-8601 deadline after which results answer 410 Gone.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "results_url": {
        +          "description": "API path of the job's results: /v1/batch/{id}/results.",
        +          "type": "string"
        +        },
        +        "started_at": {
        +          "description": "ISO-8601 time the first item started.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "status": {
        +          "description": "Lifecycle: queued, running, paused, cancelling, completed, failed or cancelled. Keep polling while queued/running/paused/cancelling; stop at completed, failed or cancelled.",
        +          "type": "string"
        +        },
        +        "status_url": {
        +          "description": "API path to poll for this job: /v1/batch/{id}.",
        +          "type": "string"
        +        },
        +        "submitted_at": {
        +          "description": "ISO-8601 time the job was accepted.",
        +          "type": "string"
        +        },
        +        "total_items": {
        +          "description": "Number of items in the job.",
        +          "type": "number"
        +        },
        +        "warnings": {
        +          "anyOf": [
        +            {
        +              "items": {
        +                "type": "string"
        +              },
        +              "type": "array"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "description": "Decisions made on the caller's behalf at submission (a clamped concurrency, items not yet queued)."
        +        }
        +      },
        +      "required": [
        +        "id"
        +      ],
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedspicrawl_batch_cancel1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "cancel_requested_at": {
        +      "description": "ISO-8601 time a cancel was accepted.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "concurrency": {
        +      "description": "Effective per-job concurrency after the server's clamping.",
        +      "type": "number"
        +    },
        +    "error_code": {
        +      "description": "Machine code of a job-level failure.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "error_message": {
        +      "description": "Human-readable job-level failure reason.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "estimated_credits": {
        +      "description": "Credits reserved at submission (a hold, not a charge; compare with progress.credits_charged).",
        +      "type": "number"
        +    },
        +    "estimated_credits_micro": {
        +      "description": "Same as estimated_credits in micro-credits.",
        +      "type": "number"
        +    },
        +    "failure_threshold": {
        +      "description": "Failed-item count that aborts the job, when set.",
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "finished_at": {
        +      "description": "ISO-8601 time the job reached a terminal status.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "id": {
        +      "description": "Job id. Pass it as `job_id` to the other spicrawl_batch_* tools.",
        +      "type": "string"
        +    },
        +    "max_attempts": {
        +      "description": "Effective attempts per item.",
        +      "type": "number"
        +    },
        +    "name": {
        +      "description": "The label given at submission, if any.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "open": {
        +      "description": "True while the job accepts appended items (it will not complete until closed).",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "params": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "The job-level scrape settings as stored."
        +    },
        +    "priority": {
        +      "description": "Effective scheduling priority.",
        +      "type": "number"
        +    },
        +    "progress": {
        +      "additionalProperties": true,
        +      "description": "Live item counters and the credits charged so far.",
        +      "properties": {
        +        "bytes": {
        +          "description": "Total response bytes of finished items.",
        +          "type": "number"
        +        },
        +        "cancelled": {
        +          "description": "Items not run because the job was cancelled.",
        +          "type": "number"
        +        },
        +        "completed": {
        +          "description": "Items in any terminal status (succeeded + failed + cancelled + skipped).",
        +          "type": "number"
        +        },
        +        "credits_charged": {
        +          "description": "Credits actually charged so far (whole credits, rounded down).",
        +          "type": "number"
        +        },
        +        "credits_charged_micro": {
        +          "description": "Same as credits_charged in micro-credits (1 credit = 1,000,000).",
        +          "type": "number"
        +        },
        +        "failed": {
        +          "description": "Items that failed after all attempts; re-run them with spicrawl_batch_retry.",
        +          "type": "number"
        +        },
        +        "percent_complete": {
        +          "description": "completed / total x 100.",
        +          "type": "number"
        +        },
        +        "remaining": {
        +          "description": "Items not yet finished (total - completed).",
        +          "type": "number"
        +        },
        +        "skipped": {
        +          "description": "Items skipped (for example after failure_threshold or credit_budget stopped the run).",
        +          "type": "number"
        +        },
        +        "succeeded": {
        +          "description": "Items that succeeded. Only these are charged.",
        +          "type": "number"
        +        },
        +        "total": {
        +          "description": "Items in the job (grows when items are appended to an open job).",
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "project_id": {
        +      "description": "Project the API key belongs to.",
        +      "type": "string"
        +    },
        +    "results_expire_at": {
        +      "description": "ISO-8601 deadline after which results answer 410 Gone.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "results_url": {
        +      "description": "API path of the job's results: /v1/batch/{id}/results.",
        +      "type": "string"
        +    },
        +    "started_at": {
        +      "description": "ISO-8601 time the first item started.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "status": {
        +      "description": "Lifecycle: queued, running, paused, cancelling, completed, failed or cancelled. Keep polling while queued/running/paused/cancelling; stop at completed, failed or cancelled.",
        +      "type": "string"
        +    },
        +    "status_url": {
        +      "description": "API path to poll for this job: /v1/batch/{id}.",
        +      "type": "string"
        +    },
        +    "submitted_at": {
        +      "description": "ISO-8601 time the job was accepted.",
        +      "type": "string"
        +    },
        +    "total_items": {
        +      "description": "Number of items in the job.",
        +      "type": "number"
        +    },
        +    "warnings": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Decisions made on the caller's behalf at submission (a clamped concurrency, items not yet queued)."
        +    }
        +  },
        +  "required": [
        +    "id"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_batch_close1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "cancel_requested_at": {
        +      "description": "ISO-8601 time a cancel was accepted.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "concurrency": {
        +      "description": "Effective per-job concurrency after the server's clamping.",
        +      "type": "number"
        +    },
        +    "error_code": {
        +      "description": "Machine code of a job-level failure.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "error_message": {
        +      "description": "Human-readable job-level failure reason.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "estimated_credits": {
        +      "description": "Credits reserved at submission (a hold, not a charge; compare with progress.credits_charged).",
        +      "type": "number"
        +    },
        +    "estimated_credits_micro": {
        +      "description": "Same as estimated_credits in micro-credits.",
        +      "type": "number"
        +    },
        +    "failure_threshold": {
        +      "description": "Failed-item count that aborts the job, when set.",
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "finished_at": {
        +      "description": "ISO-8601 time the job reached a terminal status.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "id": {
        +      "description": "Job id. Pass it as `job_id` to the other spicrawl_batch_* tools.",
        +      "type": "string"
        +    },
        +    "max_attempts": {
        +      "description": "Effective attempts per item.",
        +      "type": "number"
        +    },
        +    "name": {
        +      "description": "The label given at submission, if any.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "open": {
        +      "description": "True while the job accepts appended items (it will not complete until closed).",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "params": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "The job-level scrape settings as stored."
        +    },
        +    "priority": {
        +      "description": "Effective scheduling priority.",
        +      "type": "number"
        +    },
        +    "progress": {
        +      "additionalProperties": true,
        +      "description": "Live item counters and the credits charged so far.",
        +      "properties": {
        +        "bytes": {
        +          "description": "Total response bytes of finished items.",
        +          "type": "number"
        +        },
        +        "cancelled": {
        +          "description": "Items not run because the job was cancelled.",
        +          "type": "number"
        +        },
        +        "completed": {
        +          "description": "Items in any terminal status (succeeded + failed + cancelled + skipped).",
        +          "type": "number"
        +        },
        +        "credits_charged": {
        +          "description": "Credits actually charged so far (whole credits, rounded down).",
        +          "type": "number"
        +        },
        +        "credits_charged_micro": {
        +          "description": "Same as credits_charged in micro-credits (1 credit = 1,000,000).",
        +          "type": "number"
        +        },
        +        "failed": {
        +          "description": "Items that failed after all attempts; re-run them with spicrawl_batch_retry.",
        +          "type": "number"
        +        },
        +        "percent_complete": {
        +          "description": "completed / total x 100.",
        +          "type": "number"
        +        },
        +        "remaining": {
        +          "description": "Items not yet finished (total - completed).",
        +          "type": "number"
        +        },
        +        "skipped": {
        +          "description": "Items skipped (for example after failure_threshold or credit_budget stopped the run).",
        +          "type": "number"
        +        },
        +        "succeeded": {
        +          "description": "Items that succeeded. Only these are charged.",
        +          "type": "number"
        +        },
        +        "total": {
        +          "description": "Items in the job (grows when items are appended to an open job).",
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "project_id": {
        +      "description": "Project the API key belongs to.",
        +      "type": "string"
        +    },
        +    "results_expire_at": {
        +      "description": "ISO-8601 deadline after which results answer 410 Gone.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "results_url": {
        +      "description": "API path of the job's results: /v1/batch/{id}/results.",
        +      "type": "string"
        +    },
        +    "started_at": {
        +      "description": "ISO-8601 time the first item started.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "status": {
        +      "description": "Lifecycle: queued, running, paused, cancelling, completed, failed or cancelled. Keep polling while queued/running/paused/cancelling; stop at completed, failed or cancelled.",
        +      "type": "string"
        +    },
        +    "status_url": {
        +      "description": "API path to poll for this job: /v1/batch/{id}.",
        +      "type": "string"
        +    },
        +    "submitted_at": {
        +      "description": "ISO-8601 time the job was accepted.",
        +      "type": "string"
        +    },
        +    "total_items": {
        +      "description": "Number of items in the job.",
        +      "type": "number"
        +    },
        +    "warnings": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Decisions made on the caller's behalf at submission (a clamped concurrency, items not yet queued)."
        +    }
        +  },
        +  "required": [
        +    "id"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_batch_list1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "batches": {
        +      "description": "Jobs, newest first (empty when there are none).",
        +      "items": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "cancel_requested_at": {
        +            "description": "ISO-8601 time a cancel was accepted.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "concurrency": {
        +            "description": "Effective per-job concurrency after the server's clamping.",
        +            "type": "number"
        +          },
        +          "error_code": {
        +            "description": "Machine code of a job-level failure.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "error_message": {
        +            "description": "Human-readable job-level failure reason.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "estimated_credits": {
        +            "description": "Credits reserved at submission (a hold, not a charge; compare with progress.credits_charged).",
        +            "type": "number"
        +          },
        +          "estimated_credits_micro": {
        +            "description": "Same as estimated_credits in micro-credits.",
        +            "type": "number"
        +          },
        +          "failure_threshold": {
        +            "description": "Failed-item count that aborts the job, when set.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "finished_at": {
        +            "description": "ISO-8601 time the job reached a terminal status.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "id": {
        +            "description": "Job id. Pass it as `job_id` to the other spicrawl_batch_* tools.",
        +            "type": "string"
        +          },
        +          "max_attempts": {
        +            "description": "Effective attempts per item.",
        +            "type": "number"
        +          },
        +          "name": {
        +            "description": "The label given at submission, if any.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "open": {
        +            "description": "True while the job accepts appended items (it will not complete until closed).",
        +            "type": [
        +              "boolean",
        +              "null"
        +            ]
        +          },
        +          "params": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": {},
        +                "type": "object"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "description": "The job-level scrape settings as stored."
        +          },
        +          "priority": {
        +            "description": "Effective scheduling priority.",
        +            "type": "number"
        +          },
        +          "progress": {
        +            "additionalProperties": true,
        +            "description": "Live item counters and the credits charged so far.",
        +            "properties": {
        +              "bytes": {
        +                "description": "Total response bytes of finished items.",
        +                "type": "number"
        +              },
        +              "cancelled": {
        +                "description": "Items not run because the job was cancelled.",
        +                "type": "number"
        +              },
        +              "completed": {
        +                "description": "Items in any terminal status (succeeded + failed + cancelled + skipped).",
        +                "type": "number"
        +              },
        +              "credits_charged": {
        +                "description": "Credits actually charged so far (whole credits, rounded down).",
        +                "type": "number"
        +              },
        +              "credits_charged_micro": {
        +                "description": "Same as credits_charged in micro-credits (1 credit = 1,000,000).",
        +                "type": "number"
        +              },
        +              "failed": {
        +                "description": "Items that failed after all attempts; re-run them with spicrawl_batch_retry.",
        +                "type": "number"
        +              },
        +              "percent_complete": {
        +                "description": "completed / total x 100.",
        +                "type": "number"
        +              },
        +              "remaining": {
        +                "description": "Items not yet finished (total - completed).",
        +                "type": "number"
        +              },
        +              "skipped": {
        +                "description": "Items skipped (for example after failure_threshold or credit_budget stopped the run).",
        +                "type": "number"
        +              },
        +              "succeeded": {
        +                "description": "Items that succeeded. Only these are charged.",
        +                "type": "number"
        +              },
        +              "total": {
        +                "description": "Items in the job (grows when items are appended to an open job).",
        +                "type": "number"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "project_id": {
        +            "description": "Project the API key belongs to.",
        +            "type": "string"
        +          },
        +          "results_expire_at": {
        +            "description": "ISO-8601 deadline after which results answer 410 Gone.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "results_url": {
        +            "description": "API path of the job's results: /v1/batch/{id}/results.",
        +            "type": "string"
        +          },
        +          "started_at": {
        +            "description": "ISO-8601 time the first item started.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "status": {
        +            "description": "Lifecycle: queued, running, paused, cancelling, completed, failed or cancelled. Keep polling while queued/running/paused/cancelling; stop at completed, failed or cancelled.",
        +            "type": "string"
        +          },
        +          "status_url": {
        +            "description": "API path to poll for this job: /v1/batch/{id}.",
        +            "type": "string"
        +          },
        +          "submitted_at": {
        +            "description": "ISO-8601 time the job was accepted.",
        +            "type": "string"
        +          },
        +          "total_items": {
        +            "description": "Number of items in the job.",
        +            "type": "number"
        +          },
        +          "warnings": {
        +            "anyOf": [
        +              {
        +                "items": {
        +                  "type": "string"
        +                },
        +                "type": "array"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "description": "Decisions made on the caller's behalf at submission (a clamped concurrency, items not yet queued)."
        +          }
        +        },
        +        "required": [
        +          "id"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "next_cursor": {
        +      "description": "Pass back as `cursor` for the next page; absent on the last page.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "batches"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_batch_results1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "next_cursor": {
        +      "description": "Pass back as `cursor` for the next page; absent on the last page.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "results": {
        +      "description": "Finished items of the job, in seq order.",
        +      "items": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "attempts": {
        +            "description": "How many times the item was tried.",
        +            "type": "number"
        +          },
        +          "bytes": {
        +            "description": "Response size recorded for this item.",
        +            "type": "number"
        +          },
        +          "credits_micro": {
        +            "description": "Micro-credits charged for this item (0 unless succeeded).",
        +            "type": "number"
        +          },
        +          "duration_ms": {
        +            "description": "Time spent on the item's final attempt, in milliseconds.",
        +            "type": "number"
        +          },
        +          "error": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": true,
        +                "properties": {
        +                  "code": {
        +                    "description": "Stable machine error code; switch on this, not on text.",
        +                    "type": "string"
        +                  },
        +                  "retryable": {
        +                    "description": "True when running the item again may succeed.",
        +                    "type": "boolean"
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "description": "Why the item failed. Absent on success."
        +          },
        +          "external_id": {
        +            "description": "The external_id supplied for this item, if any.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "finished_at": {
        +            "description": "ISO-8601 time the item reached its terminal status.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "http_status": {
        +            "description": "The target site's HTTP status (absent when no response was received).",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "request_id": {
        +            "description": "Id of the underlying request, for request history.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "result": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": true,
        +                "properties": {
        +                  "bytes": {
        +                    "description": "Full size of the stored payload in bytes.",
        +                    "type": "number"
        +                  },
        +                  "content": {
        +                    "description": "The item's document as raw JSON text (JSON-decode once to get the markdown, text or html). A prefix when truncated.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  },
        +                  "omitted": {
        +                    "description": "True when no content was included because the page's size budget was spent; use a smaller `limit`.",
        +                    "type": [
        +                      "boolean",
        +                      "null"
        +                    ]
        +                  },
        +                  "truncated": {
        +                    "description": "True when `content` is only a prefix.",
        +                    "type": [
        +                      "boolean",
        +                      "null"
        +                    ]
        +                  },
        +                  "unavailable": {
        +                    "description": "Why the payload could not be read at all.",
        +                    "type": [
        +                      "string",
        +                      "null"
        +                    ]
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "description": "The payload inline. Absent while the job is running or when the item has none."
        +          },
        +          "result_url": {
        +            "description": "API path to fetch this item's content on its own.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "seq": {
        +            "description": "0-based position in submission order; use it with spicrawl_batch_task_content.",
        +            "type": "number"
        +          },
        +          "status": {
        +            "description": "Terminal item status: succeeded, failed, cancelled or skipped.",
        +            "type": "string"
        +          },
        +          "url": {
        +            "description": "The target URL as submitted.",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "seq"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "results"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_batch_retry1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "items_dispatched": {
        +      "description": "Of those, how many reached the dispatch queue now; the rest are recovered automatically.",
        +      "type": "number"
        +    },
        +    "items_reset": {
        +      "description": "Failed items reset to queued (0 means nothing had failed).",
        +      "type": "number"
        +    },
        +    "job": {
        +      "additionalProperties": true,
        +      "description": "The job as it stands after the call.",
        +      "properties": {
        +        "cancel_requested_at": {
        +          "description": "ISO-8601 time a cancel was accepted.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "concurrency": {
        +          "description": "Effective per-job concurrency after the server's clamping.",
        +          "type": "number"
        +        },
        +        "error_code": {
        +          "description": "Machine code of a job-level failure.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "error_message": {
        +          "description": "Human-readable job-level failure reason.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "estimated_credits": {
        +          "description": "Credits reserved at submission (a hold, not a charge; compare with progress.credits_charged).",
        +          "type": "number"
        +        },
        +        "estimated_credits_micro": {
        +          "description": "Same as estimated_credits in micro-credits.",
        +          "type": "number"
        +        },
        +        "failure_threshold": {
        +          "description": "Failed-item count that aborts the job, when set.",
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "finished_at": {
        +          "description": "ISO-8601 time the job reached a terminal status.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "id": {
        +          "description": "Job id. Pass it as `job_id` to the other spicrawl_batch_* tools.",
        +          "type": "string"
        +        },
        +        "max_attempts": {
        +          "description": "Effective attempts per item.",
        +          "type": "number"
        +        },
        +        "name": {
        +          "description": "The label given at submission, if any.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "open": {
        +          "description": "True while the job accepts appended items (it will not complete until closed).",
        +          "type": [
        +            "boolean",
        +            "null"
        +          ]
        +        },
        +        "params": {
        +          "anyOf": [
        +            {
        +              "additionalProperties": {},
        +              "type": "object"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "description": "The job-level scrape settings as stored."
        +        },
        +        "priority": {
        +          "description": "Effective scheduling priority.",
        +          "type": "number"
        +        },
        +        "progress": {
        +          "additionalProperties": true,
        +          "description": "Live item counters and the credits charged so far.",
        +          "properties": {
        +            "bytes": {
        +              "description": "Total response bytes of finished items.",
        +              "type": "number"
        +            },
        +            "cancelled": {
        +              "description": "Items not run because the job was cancelled.",
        +              "type": "number"
        +            },
        +            "completed": {
        +              "description": "Items in any terminal status (succeeded + failed + cancelled + skipped).",
        +              "type": "number"
        +            },
        +            "credits_charged": {
        +              "description": "Credits actually charged so far (whole credits, rounded down).",
        +              "type": "number"
        +            },
        +            "credits_charged_micro": {
        +              "description": "Same as credits_charged in micro-credits (1 credit = 1,000,000).",
        +              "type": "number"
        +            },
        +            "failed": {
        +              "description": "Items that failed after all attempts; re-run them with spicrawl_batch_retry.",
        +              "type": "number"
        +            },
        +            "percent_complete": {
        +              "description": "completed / total x 100.",
        +              "type": "number"
        +            },
        +            "remaining": {
        +              "description": "Items not yet finished (total - completed).",
        +              "type": "number"
        +            },
        +            "skipped": {
        +              "description": "Items skipped (for example after failure_threshold or credit_budget stopped the run).",
        +              "type": "number"
        +            },
        +            "succeeded": {
        +              "description": "Items that succeeded. Only these are charged.",
        +              "type": "number"
        +            },
        +            "total": {
        +              "description": "Items in the job (grows when items are appended to an open job).",
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        "project_id": {
        +          "description": "Project the API key belongs to.",
        +          "type": "string"
        +        },
        +        "results_expire_at": {
        +          "description": "ISO-8601 deadline after which results answer 410 Gone.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "results_url": {
        +          "description": "API path of the job's results: /v1/batch/{id}/results.",
        +          "type": "string"
        +        },
        +        "started_at": {
        +          "description": "ISO-8601 time the first item started.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "status": {
        +          "description": "Lifecycle: queued, running, paused, cancelling, completed, failed or cancelled. Keep polling while queued/running/paused/cancelling; stop at completed, failed or cancelled.",
        +          "type": "string"
        +        },
        +        "status_url": {
        +          "description": "API path to poll for this job: /v1/batch/{id}.",
        +          "type": "string"
        +        },
        +        "submitted_at": {
        +          "description": "ISO-8601 time the job was accepted.",
        +          "type": "string"
        +        },
        +        "total_items": {
        +          "description": "Number of items in the job.",
        +          "type": "number"
        +        },
        +        "warnings": {
        +          "anyOf": [
        +            {
        +              "items": {
        +                "type": "string"
        +              },
        +              "type": "array"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "description": "Decisions made on the caller's behalf at submission (a clamped concurrency, items not yet queued)."
        +        }
        +      },
        +      "required": [
        +        "id"
        +      ],
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedspicrawl_batch_status1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "cancel_requested_at": {
        +      "description": "ISO-8601 time a cancel was accepted.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "concurrency": {
        +      "description": "Effective per-job concurrency after the server's clamping.",
        +      "type": "number"
        +    },
        +    "error_code": {
        +      "description": "Machine code of a job-level failure.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "error_message": {
        +      "description": "Human-readable job-level failure reason.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "estimated_credits": {
        +      "description": "Credits reserved at submission (a hold, not a charge; compare with progress.credits_charged).",
        +      "type": "number"
        +    },
        +    "estimated_credits_micro": {
        +      "description": "Same as estimated_credits in micro-credits.",
        +      "type": "number"
        +    },
        +    "failure_threshold": {
        +      "description": "Failed-item count that aborts the job, when set.",
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "finished_at": {
        +      "description": "ISO-8601 time the job reached a terminal status.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "id": {
        +      "description": "Job id. Pass it as `job_id` to the other spicrawl_batch_* tools.",
        +      "type": "string"
        +    },
        +    "max_attempts": {
        +      "description": "Effective attempts per item.",
        +      "type": "number"
        +    },
        +    "name": {
        +      "description": "The label given at submission, if any.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "open": {
        +      "description": "True while the job accepts appended items (it will not complete until closed).",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "params": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "The job-level scrape settings as stored."
        +    },
        +    "priority": {
        +      "description": "Effective scheduling priority.",
        +      "type": "number"
        +    },
        +    "progress": {
        +      "additionalProperties": true,
        +      "description": "Live item counters and the credits charged so far.",
        +      "properties": {
        +        "bytes": {
        +          "description": "Total response bytes of finished items.",
        +          "type": "number"
        +        },
        +        "cancelled": {
        +          "description": "Items not run because the job was cancelled.",
        +          "type": "number"
        +        },
        +        "completed": {
        +          "description": "Items in any terminal status (succeeded + failed + cancelled + skipped).",
        +          "type": "number"
        +        },
        +        "credits_charged": {
        +          "description": "Credits actually charged so far (whole credits, rounded down).",
        +          "type": "number"
        +        },
        +        "credits_charged_micro": {
        +          "description": "Same as credits_charged in micro-credits (1 credit = 1,000,000).",
        +          "type": "number"
        +        },
        +        "failed": {
        +          "description": "Items that failed after all attempts; re-run them with spicrawl_batch_retry.",
        +          "type": "number"
        +        },
        +        "percent_complete": {
        +          "description": "completed / total x 100.",
        +          "type": "number"
        +        },
        +        "remaining": {
        +          "description": "Items not yet finished (total - completed).",
        +          "type": "number"
        +        },
        +        "skipped": {
        +          "description": "Items skipped (for example after failure_threshold or credit_budget stopped the run).",
        +          "type": "number"
        +        },
        +        "succeeded": {
        +          "description": "Items that succeeded. Only these are charged.",
        +          "type": "number"
        +        },
        +        "total": {
        +          "description": "Items in the job (grows when items are appended to an open job).",
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "project_id": {
        +      "description": "Project the API key belongs to.",
        +      "type": "string"
        +    },
        +    "results_expire_at": {
        +      "description": "ISO-8601 deadline after which results answer 410 Gone.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "results_url": {
        +      "description": "API path of the job's results: /v1/batch/{id}/results.",
        +      "type": "string"
        +    },
        +    "started_at": {
        +      "description": "ISO-8601 time the first item started.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "status": {
        +      "description": "Lifecycle: queued, running, paused, cancelling, completed, failed or cancelled. Keep polling while queued/running/paused/cancelling; stop at completed, failed or cancelled.",
        +      "type": "string"
        +    },
        +    "status_url": {
        +      "description": "API path to poll for this job: /v1/batch/{id}.",
        +      "type": "string"
        +    },
        +    "submitted_at": {
        +      "description": "ISO-8601 time the job was accepted.",
        +      "type": "string"
        +    },
        +    "total_items": {
        +      "description": "Number of items in the job.",
        +      "type": "number"
        +    },
        +    "warnings": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Decisions made on the caller's behalf at submission (a clamped concurrency, items not yet queued)."
        +    }
        +  },
        +  "required": [
        +    "id"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_batch_submit1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "cancel_requested_at": {
        +      "description": "ISO-8601 time a cancel was accepted.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "concurrency": {
        +      "description": "Effective per-job concurrency after the server's clamping.",
        +      "type": "number"
        +    },
        +    "error_code": {
        +      "description": "Machine code of a job-level failure.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "error_message": {
        +      "description": "Human-readable job-level failure reason.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "estimated_credits": {
        +      "description": "Credits reserved at submission (a hold, not a charge; compare with progress.credits_charged).",
        +      "type": "number"
        +    },
        +    "estimated_credits_micro": {
        +      "description": "Same as estimated_credits in micro-credits.",
        +      "type": "number"
        +    },
        +    "failure_threshold": {
        +      "description": "Failed-item count that aborts the job, when set.",
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "finished_at": {
        +      "description": "ISO-8601 time the job reached a terminal status.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "id": {
        +      "description": "Job id. Pass it as `job_id` to the other spicrawl_batch_* tools.",
        +      "type": "string"
        +    },
        +    "max_attempts": {
        +      "description": "Effective attempts per item.",
        +      "type": "number"
        +    },
        +    "name": {
        +      "description": "The label given at submission, if any.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "open": {
        +      "description": "True while the job accepts appended items (it will not complete until closed).",
        +      "type": [
        +        "boolean",
        +        "null"
        +      ]
        +    },
        +    "params": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "The job-level scrape settings as stored."
        +    },
        +    "priority": {
        +      "description": "Effective scheduling priority.",
        +      "type": "number"
        +    },
        +    "progress": {
        +      "additionalProperties": true,
        +      "description": "Live item counters and the credits charged so far.",
        +      "properties": {
        +        "bytes": {
        +          "description": "Total response bytes of finished items.",
        +          "type": "number"
        +        },
        +        "cancelled": {
        +          "description": "Items not run because the job was cancelled.",
        +          "type": "number"
        +        },
        +        "completed": {
        +          "description": "Items in any terminal status (succeeded + failed + cancelled + skipped).",
        +          "type": "number"
        +        },
        +        "credits_charged": {
        +          "description": "Credits actually charged so far (whole credits, rounded down).",
        +          "type": "number"
        +        },
        +        "credits_charged_micro": {
        +          "description": "Same as credits_charged in micro-credits (1 credit = 1,000,000).",
        +          "type": "number"
        +        },
        +        "failed": {
        +          "description": "Items that failed after all attempts; re-run them with spicrawl_batch_retry.",
        +          "type": "number"
        +        },
        +        "percent_complete": {
        +          "description": "completed / total x 100.",
        +          "type": "number"
        +        },
        +        "remaining": {
        +          "description": "Items not yet finished (total - completed).",
        +          "type": "number"
        +        },
        +        "skipped": {
        +          "description": "Items skipped (for example after failure_threshold or credit_budget stopped the run).",
        +          "type": "number"
        +        },
        +        "succeeded": {
        +          "description": "Items that succeeded. Only these are charged.",
        +          "type": "number"
        +        },
        +        "total": {
        +          "description": "Items in the job (grows when items are appended to an open job).",
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "project_id": {
        +      "description": "Project the API key belongs to.",
        +      "type": "string"
        +    },
        +    "results_expire_at": {
        +      "description": "ISO-8601 deadline after which results answer 410 Gone.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "results_url": {
        +      "description": "API path of the job's results: /v1/batch/{id}/results.",
        +      "type": "string"
        +    },
        +    "started_at": {
        +      "description": "ISO-8601 time the first item started.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "status": {
        +      "description": "Lifecycle: queued, running, paused, cancelling, completed, failed or cancelled. Keep polling while queued/running/paused/cancelling; stop at completed, failed or cancelled.",
        +      "type": "string"
        +    },
        +    "status_url": {
        +      "description": "API path to poll for this job: /v1/batch/{id}.",
        +      "type": "string"
        +    },
        +    "submitted_at": {
        +      "description": "ISO-8601 time the job was accepted.",
        +      "type": "string"
        +    },
        +    "total_items": {
        +      "description": "Number of items in the job.",
        +      "type": "number"
        +    },
        +    "warnings": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Decisions made on the caller's behalf at submission (a clamped concurrency, items not yet queued)."
        +    }
        +  },
        +  "required": [
        +    "id"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_batch_task_content1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "content": {
        +      "description": "The item's document when it is text (markdown, text or html) or any non-object JSON value. An item whose payload is a JSON object is returned as that object's own fields instead."
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedspicrawl_browser_connect_url1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "expires_at": {
        +      "description": "When the token expires, RFC 3339 UTC (60 s after minting).",
        +      "type": "string"
        +    },
        +    "notes": {
        +      "description": "Usage notes for the connect URL.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "single_use": {
        +      "description": "Always true: the URL works for one connection.",
        +      "type": "boolean"
        +    },
        +    "url": {
        +      "description": "ws:// or wss:// connect URL carrying a single-use token (never the API key); use it as the CDP browser WebSocket endpoint.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "url",
        +    "single_use"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_docs_index1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "content": {
        +      "description": "The index (llms.txt): one line per page with its title, description and Markdown URL.",
        +      "type": "string"
        +    },
        +    "truncated": {
        +      "description": "True when the content was cut at the size cap; the content says so at its end.",
        +      "type": "boolean"
        +    },
        +    "url": {
        +      "description": "Where the document lives on the docs site.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "url",
        +    "truncated",
        +    "content"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_docs_read1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "content": {
        +      "description": "The document as Markdown.",
        +      "type": "string"
        +    },
        +    "md_url": {
        +      "description": "The Markdown source it was read from.",
        +      "type": "string"
        +    },
        +    "section": {
        +      "description": "The #anchor that was asked for, without the #. The whole page is returned.",
        +      "type": "string"
        +    },
        +    "title": {
        +      "description": "The page's first heading, when it has one.",
        +      "type": "string"
        +    },
        +    "truncated": {
        +      "description": "True when the content was cut at the size cap; the content says so at its end.",
        +      "type": "boolean"
        +    },
        +    "url": {
        +      "description": "Where the document lives on the docs site.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "url",
        +    "truncated",
        +    "content"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_docs_search1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "error_code": {
        +      "additionalProperties": true,
        +      "description": "Present when the query is an error code (ERR::AREA::NAME).",
        +      "properties": {
        +        "code": {
        +          "type": "string"
        +        },
        +        "md_url": {
        +          "description": "The errors page as Markdown; read it with spicrawl_docs_read.",
        +          "type": "string"
        +        },
        +        "note": {
        +          "type": "string"
        +        },
        +        "url": {
        +          "description": "The code's entry on the errors page.",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "code",
        +        "url",
        +        "md_url"
        +      ],
        +      "type": "object"
        +    },
        +    "hint": {
        +      "description": "What to try when there are no results.",
        +      "type": "string"
        +    },
        +    "query": {
        +      "description": "The search text, as sent.",
        +      "type": "string"
        +    },
        +    "results": {
        +      "description": "Matching pages, most relevant first. Empty when nothing matched.",
        +      "items": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "breadcrumbs": {
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          },
        +          "matches": {
        +            "items": {
        +              "additionalProperties": true,
        +              "properties": {
        +                "heading": {
        +                  "description": "The section the match is in.",
        +                  "type": "string"
        +                },
        +                "snippet": {
        +                  "description": "A short plain-text excerpt around the match.",
        +                  "type": "string"
        +                },
        +                "url": {
        +                  "description": "Link to the section, with its #anchor.",
        +                  "type": "string"
        +                }
        +              },
        +              "required": [
        +                "url"
        +              ],
        +              "type": "object"
        +            },
        +            "type": "array"
        +          },
        +          "md_url": {
        +            "description": "The page as Markdown; pass it to spicrawl_docs_read.",
        +            "type": "string"
        +          },
        +          "title": {
        +            "type": "string"
        +          },
        +          "url": {
        +            "description": "The page on the docs site.",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "title",
        +          "url",
        +          "md_url",
        +          "matches"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "query",
        +    "results"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_request_get1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "attempts": {
        +      "description": "Dispatch attempts including retries.",
        +      "type": "number"
        +    },
        +    "blocked": {
        +      "additionalProperties": true,
        +      "description": "Present only when a bot challenge was detected.",
        +      "properties": {
        +        "rule": {
        +          "type": "string"
        +        },
        +        "signal": {
        +          "type": "string"
        +        },
        +        "vendor": {
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "bytes_in": {
        +      "type": "number"
        +    },
        +    "bytes_out": {
        +      "type": "number"
        +    },
        +    "created_at": {
        +      "description": "When the request arrived, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "credits_micro": {
        +      "description": "Credits charged in micro-credits (1 credit = 1000000); 0 unless success.",
        +      "type": "number"
        +    },
        +    "engine": {
        +      "description": "The rendering tier that served it: fetch, js or browser. Absent when refused before a tier was chosen.",
        +      "type": "string"
        +    },
        +    "error_code": {
        +      "description": "The problem code the caller got, e.g. ERR::UPSTREAM::CHALLENGE. Absent on success.",
        +      "type": "string"
        +    },
        +    "error_detail": {
        +      "type": "string"
        +    },
        +    "features": {
        +      "additionalProperties": {},
        +      "description": "Features the request used; free-form.",
        +      "type": "object"
        +    },
        +    "http_status": {
        +      "description": "The target's HTTP status; absent when no response was received.",
        +      "type": "number"
        +    },
        +    "id": {
        +      "description": "The request id (X-Request-Id).",
        +      "type": "string"
        +    },
        +    "project_id": {
        +      "type": "string"
        +    },
        +    "proxy": {
        +      "additionalProperties": true,
        +      "description": "What proxy was asked for versus what served. Never an exit IP or credentials.",
        +      "properties": {
        +        "country": {
        +          "description": "Where the exit actually served from; compare with requested_country.",
        +          "type": "string"
        +        },
        +        "endpoint_id": {
        +          "type": "string"
        +        },
        +        "endpoints": {
        +          "anyOf": [
        +            {
        +              "items": {
        +                "type": "string"
        +              },
        +              "type": "array"
        +            },
        +            {
        +              "type": "null"
        +            }
        +          ],
        +          "description": "Every exit touched, in attempt order."
        +        },
        +        "provider": {
        +          "type": "string"
        +        },
        +        "reason": {
        +          "type": "string"
        +        },
        +        "requested_country": {
        +          "type": "string"
        +        },
        +        "requested_tier": {
        +          "type": "string"
        +        },
        +        "source": {
        +          "description": "pool, custom or direct.",
        +          "type": "string"
        +        },
        +        "sticky": {
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "proxy_bytes": {
        +      "type": "number"
        +    },
        +    "spans": {
        +      "additionalProperties": true,
        +      "description": "Latency in milliseconds per stage; null means not measured. Stages do not sum to total_ms.",
        +      "properties": {
        +        "admission_ms": {
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "dispatch_ms": {
        +          "$ref": "#/properties/spans/properties/admission_ms"
        +        },
        +        "engine_ms": {
        +          "$ref": "#/properties/spans/properties/admission_ms"
        +        },
        +        "extract_ms": {
        +          "$ref": "#/properties/spans/properties/admission_ms"
        +        },
        +        "queue_ms": {
        +          "$ref": "#/properties/spans/properties/admission_ms",
        +          "description": "Wait for a slot; high means capacity shortage, not a slow page."
        +        },
        +        "total_ms": {
        +          "$ref": "#/properties/spans/properties/admission_ms"
        +        },
        +        "upstream_ms": {
        +          "$ref": "#/properties/spans/properties/admission_ms"
        +        },
        +        "worker_ms": {
        +          "$ref": "#/properties/spans/properties/admission_ms"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "status": {
        +      "description": "Terminal outcome: success, failed, timeout, blocked, rejected or cancelled. Only success is charged.",
        +      "type": "string"
        +    },
        +    "url": {
        +      "description": "The target URL as requested.",
        +      "type": "string"
        +    },
        +    "url_host": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "id"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_requests_list1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "data": {
        +      "description": "Request records, newest first. Can be shorter than limit while page.has_more is true.",
        +      "items": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "attempts": {
        +            "description": "Dispatch attempts including retries.",
        +            "type": "number"
        +          },
        +          "blocked": {
        +            "additionalProperties": true,
        +            "description": "Present only when a bot challenge was detected.",
        +            "properties": {
        +              "rule": {
        +                "type": "string"
        +              },
        +              "signal": {
        +                "type": "string"
        +              },
        +              "vendor": {
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "bytes_in": {
        +            "type": "number"
        +          },
        +          "bytes_out": {
        +            "type": "number"
        +          },
        +          "created_at": {
        +            "description": "When the request arrived, RFC 3339 UTC.",
        +            "type": "string"
        +          },
        +          "credits_micro": {
        +            "description": "Credits charged in micro-credits (1 credit = 1000000); 0 unless success.",
        +            "type": "number"
        +          },
        +          "engine": {
        +            "description": "The rendering tier that served it: fetch, js or browser. Absent when refused before a tier was chosen.",
        +            "type": "string"
        +          },
        +          "error_code": {
        +            "description": "The problem code the caller got, e.g. ERR::UPSTREAM::CHALLENGE. Absent on success.",
        +            "type": "string"
        +          },
        +          "error_detail": {
        +            "type": "string"
        +          },
        +          "features": {
        +            "additionalProperties": {},
        +            "description": "Features the request used; free-form.",
        +            "type": "object"
        +          },
        +          "http_status": {
        +            "description": "The target's HTTP status; absent when no response was received.",
        +            "type": "number"
        +          },
        +          "id": {
        +            "description": "The request id (X-Request-Id).",
        +            "type": "string"
        +          },
        +          "project_id": {
        +            "type": "string"
        +          },
        +          "proxy": {
        +            "additionalProperties": true,
        +            "description": "What proxy was asked for versus what served. Never an exit IP or credentials.",
        +            "properties": {
        +              "country": {
        +                "description": "Where the exit actually served from; compare with requested_country.",
        +                "type": "string"
        +              },
        +              "endpoint_id": {
        +                "type": "string"
        +              },
        +              "endpoints": {
        +                "anyOf": [
        +                  {
        +                    "items": {
        +                      "type": "string"
        +                    },
        +                    "type": "array"
        +                  },
        +                  {
        +                    "type": "null"
        +                  }
        +                ],
        +                "description": "Every exit touched, in attempt order."
        +              },
        +              "provider": {
        +                "type": "string"
        +              },
        +              "reason": {
        +                "type": "string"
        +              },
        +              "requested_country": {
        +                "type": "string"
        +              },
        +              "requested_tier": {
        +                "type": "string"
        +              },
        +              "source": {
        +                "description": "pool, custom or direct.",
        +                "type": "string"
        +              },
        +              "sticky": {
        +                "type": "boolean"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "proxy_bytes": {
        +            "type": "number"
        +          },
        +          "spans": {
        +            "additionalProperties": true,
        +            "description": "Latency in milliseconds per stage; null means not measured. Stages do not sum to total_ms.",
        +            "properties": {
        +              "admission_ms": {
        +                "type": [
        +                  "number",
        +                  "null"
        +                ]
        +              },
        +              "dispatch_ms": {
        +                "$ref": "#/properties/data/items/properties/spans/properties/admission_ms"
        +              },
        +              "engine_ms": {
        +                "$ref": "#/properties/data/items/properties/spans/properties/admission_ms"
        +              },
        +              "extract_ms": {
        +                "$ref": "#/properties/data/items/properties/spans/properties/admission_ms"
        +              },
        +              "queue_ms": {
        +                "$ref": "#/properties/data/items/properties/spans/properties/admission_ms",
        +                "description": "Wait for a slot; high means capacity shortage, not a slow page."
        +              },
        +              "total_ms": {
        +                "$ref": "#/properties/data/items/properties/spans/properties/admission_ms"
        +              },
        +              "upstream_ms": {
        +                "$ref": "#/properties/data/items/properties/spans/properties/admission_ms"
        +              },
        +              "worker_ms": {
        +                "$ref": "#/properties/data/items/properties/spans/properties/admission_ms"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "status": {
        +            "description": "Terminal outcome: success, failed, timeout, blocked, rejected or cancelled. Only success is charged.",
        +            "type": "string"
        +          },
        +          "url": {
        +            "description": "The target URL as requested.",
        +            "type": "string"
        +          },
        +          "url_host": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "id"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "page": {
        +      "additionalProperties": true,
        +      "description": "Paging cursor and the retention window.",
        +      "properties": {
        +        "has_more": {
        +          "description": "True when more records may exist; continue with next_before and next_before_id.",
        +          "type": "boolean"
        +        },
        +        "next_before": {
        +          "description": "Send back as before. Present only when has_more.",
        +          "type": "string"
        +        },
        +        "next_before_id": {
        +          "description": "Send back as before_id. Present only when has_more.",
        +          "type": "string"
        +        },
        +        "retained_since": {
        +          "description": "The oldest instant still readable.",
        +          "type": "string"
        +        },
        +        "retention_hours": {
        +          "description": "How long records are kept; an empty data means nothing in this window.",
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedspicrawl_scrape1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "content": {
        +      "description": "The page in the requested format (markdown, text or html); absent for a PDF.",
        +      "type": "string"
        +    },
        +    "credits": {
        +      "description": "Credits charged for this call.",
        +      "type": "number"
        +    },
        +    "data": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Output of `extract` or `autoparse`."
        +    },
        +    "diagnostics": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Which rendering tiers were tried, after an escalation."
        +    },
        +    "empty_fields": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "`extract` rules that matched nothing: usually a broken selector."
        +    },
        +    "engine": {
        +      "description": "Rendering tier that produced the page: fetch, js or browser.",
        +      "type": "string"
        +    },
        +    "final_url": {
        +      "description": "URL after redirects; may be empty.",
        +      "type": "string"
        +    },
        +    "headers": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {
        +            "type": "string"
        +          },
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "The target's response headers."
        +    },
        +    "links": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "The page's links, absolute and de-duplicated, when `links` was set."
        +    },
        +    "network": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "additionalProperties": {},
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Responses the page fetched, when `network_capture` was set."
        +    },
        +    "pdf": {
        +      "additionalProperties": true,
        +      "description": "Present for format=pdf: the file itself is a resource content block.",
        +      "properties": {
        +        "attached_as": {
        +          "description": "Which resource content block holds the PDF.",
        +          "type": "string"
        +        },
        +        "content_type": {
        +          "type": "string"
        +        },
        +        "not_attached": {
        +          "description": "Why the PDF is not attached, and how to get it.",
        +          "type": "string"
        +        },
        +        "size_bytes": {
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "proxy_source": {
        +      "description": "Whose exit carried the request: pool, custom or direct.",
        +      "type": "string"
        +    },
        +    "screenshots": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "additionalProperties": true,
        +            "properties": {
        +              "attached_as": {
        +                "description": "Which image content block holds this screenshot.",
        +                "type": "string"
        +              },
        +              "format": {
        +                "type": "string"
        +              },
        +              "height": {
        +                "type": "number"
        +              },
        +              "label": {
        +                "type": "string"
        +              },
        +              "not_attached": {
        +                "description": "Why the image is not attached, and how to get it.",
        +                "type": "string"
        +              },
        +              "size_bytes": {
        +                "type": "number"
        +              },
        +              "width": {
        +                "type": "number"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Metadata of each screenshot; the images are separate image content blocks."
        +    },
        +    "status": {
        +      "description": "The target site's HTTP status (not this call's). Anything but 200/404/410 is charged 0.",
        +      "type": "number"
        +    },
        +    "truncated": {
        +      "description": "The target body exceeded the size cap and was cut.",
        +      "type": "boolean"
        +    },
        +    "url": {
        +      "description": "The requested URL.",
        +      "type": "string"
        +    },
        +    "warnings": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Advisories about the call, e.g. an ignored option."
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedspicrawl_session_context1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "created_at": {
        +      "description": "Creation time, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "domain_scores": {
        +      "additionalProperties": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "bad": {
        +            "description": "Failed requests counted.",
        +            "type": "integer"
        +          },
        +          "good": {
        +            "description": "Successful requests counted.",
        +            "type": "integer"
        +          },
        +          "last_updated": {
        +            "description": "Last update, Unix milliseconds.",
        +            "type": "number"
        +          },
        +          "retired": {
        +            "description": "Hard block for this domain; use a new session for it.",
        +            "type": "boolean"
        +          },
        +          "score": {
        +            "description": "Error score; rises on failures, decays on successes. Blocked at 3.",
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "description": "Per-domain standing, keyed by domain. Omitted when empty.",
        +      "type": "object"
        +    },
        +    "expires_at": {
        +      "description": "Current expiry, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "fingerprint": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {},
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Stored browser fingerprint; null when none."
        +    },
        +    "last_used_at": {
        +      "description": "Last use, RFC 3339 UTC; null if never used.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "retired": {
        +      "description": "Why the session was retired; absent while usable.",
        +      "type": "string"
        +    },
        +    "schema_version": {
        +      "type": "integer"
        +    },
        +    "session_context": {
        +      "additionalProperties": true,
        +      "description": "Cookies and storage: secrets. Pass it as `session_context` to spicrawl_session_create to clone the session.",
        +      "properties": {
        +        "cookies": {
        +          "items": {
        +            "additionalProperties": true,
        +            "properties": {
        +              "domain": {
        +                "type": "string"
        +              },
        +              "name": {
        +                "type": "string"
        +              },
        +              "value": {
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        "indexed_db": {
        +          "additionalProperties": {},
        +          "description": "Origin to databases; opaque.",
        +          "type": "object"
        +        },
        +        "local_storage": {
        +          "additionalProperties": {},
        +          "description": "Origin to key/value map.",
        +          "type": "object"
        +        },
        +        "session_storage": {
        +          "additionalProperties": {},
        +          "description": "Origin to key/value map.",
        +          "type": "object"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "session_id": {
        +      "description": "The session id.",
        +      "type": "string"
        +    },
        +    "usage_count": {
        +      "type": "integer"
        +    },
        +    "warning": {
        +      "description": "The API's reminder that this state dies with the session.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "session_id"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_session_create1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "context": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": true,
        +          "properties": {
        +            "bytes": {
        +              "description": "Serialised size of the stored context.",
        +              "type": "integer"
        +            },
        +            "cookies": {
        +              "description": "Cookies stored.",
        +              "type": "integer"
        +            },
        +            "origins": {
        +              "description": "Distinct origins with stored web storage.",
        +              "type": "integer"
        +            },
        +            "schema_version": {
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Size summary of the stored context (counts only, no secrets); null once the session is not active."
        +    },
        +    "created_at": {
        +      "description": "Creation time, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "domain_scores": {
        +      "additionalProperties": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "bad": {
        +            "description": "Failed requests counted.",
        +            "type": "integer"
        +          },
        +          "good": {
        +            "description": "Successful requests counted.",
        +            "type": "integer"
        +          },
        +          "last_updated": {
        +            "description": "Last update, Unix milliseconds.",
        +            "type": "number"
        +          },
        +          "retired": {
        +            "description": "Hard block for this domain; use a new session for it.",
        +            "type": "boolean"
        +          },
        +          "score": {
        +            "description": "Error score; rises on failures, decays on successes. Blocked at 3.",
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "description": "Per-domain standing, keyed by domain. Omitted when empty.",
        +      "type": "object"
        +    },
        +    "engine": {
        +      "description": "Rendering tier the session is bound to: fetch, js or browser.",
        +      "type": "string"
        +    },
        +    "expires_at": {
        +      "description": "Current expiry (slides on use), RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "fingerprint": {
        +      "additionalProperties": {},
        +      "description": "Browser fingerprint, as stored.",
        +      "type": "object"
        +    },
        +    "hard_expires_at": {
        +      "description": "Fixed ceiling the expiry never passes, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "id": {
        +      "description": "Session id; pass it as `session_id` to spicrawl_scrape.",
        +      "type": "string"
        +    },
        +    "last_used_at": {
        +      "description": "Last successful scrape, RFC 3339 UTC; null if never used.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "lease": {
        +      "additionalProperties": true,
        +      "description": "Present only while a scrape holds the session; release and delete are refused until it lapses unless `force`.",
        +      "properties": {
        +        "expires_at": {
        +          "description": "When the lease lapses at the latest, RFC 3339 UTC.",
        +          "type": "string"
        +        },
        +        "holder": {
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "project_id": {
        +      "description": "Project the session belongs to.",
        +      "type": "string"
        +    },
        +    "proxy": {
        +      "additionalProperties": true,
        +      "description": "The session's exit intent (never an IP or endpoint).",
        +      "properties": {
        +        "country": {
        +          "description": "Lowercase alpha-2 exit country, when one was requested.",
        +          "type": "string"
        +        },
        +        "region_pool": {
        +          "description": "Regional pool requested at creation.",
        +          "type": "string"
        +        },
        +        "tier": {
        +          "description": "Exit tier: datacenter or residential.",
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "released_at": {
        +      "description": "Release time, on released sessions, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "retired": {
        +      "description": "Why the session was taken out of service (expired, usage_exhausted, explicit); absent while usable.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "active, released or expired; derived from the clock, and only `active` sessions can be used.",
        +      "type": "string"
        +    },
        +    "sticky_key": {
        +      "description": "Exit pin in use (empty when rotate_ip was set).",
        +      "type": "string"
        +    },
        +    "usage_count": {
        +      "description": "Successful scrapes that used the session.",
        +      "type": "integer"
        +    },
        +    "warnings": {
        +      "description": "Decisions made on your behalf at creation, e.g. a TTL reduced to the organization maximum.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "id"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_session_delete1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "deleted": {
        +      "description": "Always true on success (deleting an already-deleted session succeeds).",
        +      "type": "boolean"
        +    },
        +    "session_id": {
        +      "description": "The id that was deleted.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "deleted",
        +    "session_id"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_session_get1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "context": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": true,
        +          "properties": {
        +            "bytes": {
        +              "description": "Serialised size of the stored context.",
        +              "type": "integer"
        +            },
        +            "cookies": {
        +              "description": "Cookies stored.",
        +              "type": "integer"
        +            },
        +            "origins": {
        +              "description": "Distinct origins with stored web storage.",
        +              "type": "integer"
        +            },
        +            "schema_version": {
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Size summary of the stored context (counts only, no secrets); null once the session is not active."
        +    },
        +    "created_at": {
        +      "description": "Creation time, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "domain_scores": {
        +      "additionalProperties": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "bad": {
        +            "description": "Failed requests counted.",
        +            "type": "integer"
        +          },
        +          "good": {
        +            "description": "Successful requests counted.",
        +            "type": "integer"
        +          },
        +          "last_updated": {
        +            "description": "Last update, Unix milliseconds.",
        +            "type": "number"
        +          },
        +          "retired": {
        +            "description": "Hard block for this domain; use a new session for it.",
        +            "type": "boolean"
        +          },
        +          "score": {
        +            "description": "Error score; rises on failures, decays on successes. Blocked at 3.",
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "description": "Per-domain standing, keyed by domain. Omitted when empty.",
        +      "type": "object"
        +    },
        +    "engine": {
        +      "description": "Rendering tier the session is bound to: fetch, js or browser.",
        +      "type": "string"
        +    },
        +    "expires_at": {
        +      "description": "Current expiry (slides on use), RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "fingerprint": {
        +      "additionalProperties": {},
        +      "description": "Browser fingerprint, as stored.",
        +      "type": "object"
        +    },
        +    "hard_expires_at": {
        +      "description": "Fixed ceiling the expiry never passes, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "id": {
        +      "description": "Session id; pass it as `session_id` to spicrawl_scrape.",
        +      "type": "string"
        +    },
        +    "last_used_at": {
        +      "description": "Last successful scrape, RFC 3339 UTC; null if never used.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "lease": {
        +      "additionalProperties": true,
        +      "description": "Present only while a scrape holds the session; release and delete are refused until it lapses unless `force`.",
        +      "properties": {
        +        "expires_at": {
        +          "description": "When the lease lapses at the latest, RFC 3339 UTC.",
        +          "type": "string"
        +        },
        +        "holder": {
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "project_id": {
        +      "description": "Project the session belongs to.",
        +      "type": "string"
        +    },
        +    "proxy": {
        +      "additionalProperties": true,
        +      "description": "The session's exit intent (never an IP or endpoint).",
        +      "properties": {
        +        "country": {
        +          "description": "Lowercase alpha-2 exit country, when one was requested.",
        +          "type": "string"
        +        },
        +        "region_pool": {
        +          "description": "Regional pool requested at creation.",
        +          "type": "string"
        +        },
        +        "tier": {
        +          "description": "Exit tier: datacenter or residential.",
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "released_at": {
        +      "description": "Release time, on released sessions, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "retired": {
        +      "description": "Why the session was taken out of service (expired, usage_exhausted, explicit); absent while usable.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "active, released or expired; derived from the clock, and only `active` sessions can be used.",
        +      "type": "string"
        +    },
        +    "sticky_key": {
        +      "description": "Exit pin in use (empty when rotate_ip was set).",
        +      "type": "string"
        +    },
        +    "usage_count": {
        +      "description": "Successful scrapes that used the session.",
        +      "type": "integer"
        +    },
        +    "warnings": {
        +      "description": "Decisions made on your behalf at creation, e.g. a TTL reduced to the organization maximum.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "id"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_session_list1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "next_cursor": {
        +      "description": "Pass back as `cursor` for the next page; absent on the last page.",
        +      "type": "string"
        +    },
        +    "sessions": {
        +      "description": "Sessions on this page, newest first; may be short or empty under a `status` filter.",
        +      "items": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "context": {
        +            "anyOf": [
        +              {
        +                "additionalProperties": true,
        +                "properties": {
        +                  "bytes": {
        +                    "description": "Serialised size of the stored context.",
        +                    "type": "integer"
        +                  },
        +                  "cookies": {
        +                    "description": "Cookies stored.",
        +                    "type": "integer"
        +                  },
        +                  "origins": {
        +                    "description": "Distinct origins with stored web storage.",
        +                    "type": "integer"
        +                  },
        +                  "schema_version": {
        +                    "type": "integer"
        +                  }
        +                },
        +                "type": "object"
        +              },
        +              {
        +                "type": "null"
        +              }
        +            ],
        +            "description": "Size summary of the stored context (counts only, no secrets); null once the session is not active."
        +          },
        +          "created_at": {
        +            "description": "Creation time, RFC 3339 UTC.",
        +            "type": "string"
        +          },
        +          "domain_scores": {
        +            "additionalProperties": {
        +              "additionalProperties": true,
        +              "properties": {
        +                "bad": {
        +                  "description": "Failed requests counted.",
        +                  "type": "integer"
        +                },
        +                "good": {
        +                  "description": "Successful requests counted.",
        +                  "type": "integer"
        +                },
        +                "last_updated": {
        +                  "description": "Last update, Unix milliseconds.",
        +                  "type": "number"
        +                },
        +                "retired": {
        +                  "description": "Hard block for this domain; use a new session for it.",
        +                  "type": "boolean"
        +                },
        +                "score": {
        +                  "description": "Error score; rises on failures, decays on successes. Blocked at 3.",
        +                  "type": "number"
        +                }
        +              },
        +              "type": "object"
        +            },
        +            "description": "Per-domain standing, keyed by domain. Omitted when empty.",
        +            "type": "object"
        +          },
        +          "engine": {
        +            "description": "Rendering tier the session is bound to: fetch, js or browser.",
        +            "type": "string"
        +          },
        +          "expires_at": {
        +            "description": "Current expiry (slides on use), RFC 3339 UTC.",
        +            "type": "string"
        +          },
        +          "fingerprint": {
        +            "additionalProperties": {},
        +            "description": "Browser fingerprint, as stored.",
        +            "type": "object"
        +          },
        +          "hard_expires_at": {
        +            "description": "Fixed ceiling the expiry never passes, RFC 3339 UTC.",
        +            "type": "string"
        +          },
        +          "id": {
        +            "description": "Session id; pass it as `session_id` to spicrawl_scrape.",
        +            "type": "string"
        +          },
        +          "last_used_at": {
        +            "description": "Last successful scrape, RFC 3339 UTC; null if never used.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "lease": {
        +            "additionalProperties": true,
        +            "description": "Present only while a scrape holds the session; release and delete are refused until it lapses unless `force`.",
        +            "properties": {
        +              "expires_at": {
        +                "description": "When the lease lapses at the latest, RFC 3339 UTC.",
        +                "type": "string"
        +              },
        +              "holder": {
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "project_id": {
        +            "description": "Project the session belongs to.",
        +            "type": "string"
        +          },
        +          "proxy": {
        +            "additionalProperties": true,
        +            "description": "The session's exit intent (never an IP or endpoint).",
        +            "properties": {
        +              "country": {
        +                "description": "Lowercase alpha-2 exit country, when one was requested.",
        +                "type": "string"
        +              },
        +              "region_pool": {
        +                "description": "Regional pool requested at creation.",
        +                "type": "string"
        +              },
        +              "tier": {
        +                "description": "Exit tier: datacenter or residential.",
        +                "type": "string"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "released_at": {
        +            "description": "Release time, on released sessions, RFC 3339 UTC.",
        +            "type": "string"
        +          },
        +          "retired": {
        +            "description": "Why the session was taken out of service (expired, usage_exhausted, explicit); absent while usable.",
        +            "type": "string"
        +          },
        +          "status": {
        +            "description": "active, released or expired; derived from the clock, and only `active` sessions can be used.",
        +            "type": "string"
        +          },
        +          "sticky_key": {
        +            "description": "Exit pin in use (empty when rotate_ip was set).",
        +            "type": "string"
        +          },
        +          "usage_count": {
        +            "description": "Successful scrapes that used the session.",
        +            "type": "integer"
        +          },
        +          "warnings": {
        +            "description": "Decisions made on your behalf at creation, e.g. a TTL reduced to the organization maximum.",
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          }
        +        },
        +        "required": [
        +          "id"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "sessions"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_session_release1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "context": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": true,
        +          "properties": {
        +            "bytes": {
        +              "description": "Serialised size of the stored context.",
        +              "type": "integer"
        +            },
        +            "cookies": {
        +              "description": "Cookies stored.",
        +              "type": "integer"
        +            },
        +            "origins": {
        +              "description": "Distinct origins with stored web storage.",
        +              "type": "integer"
        +            },
        +            "schema_version": {
        +              "type": "integer"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Size summary of the stored context (counts only, no secrets); null once the session is not active."
        +    },
        +    "created_at": {
        +      "description": "Creation time, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "domain_scores": {
        +      "additionalProperties": {
        +        "additionalProperties": true,
        +        "properties": {
        +          "bad": {
        +            "description": "Failed requests counted.",
        +            "type": "integer"
        +          },
        +          "good": {
        +            "description": "Successful requests counted.",
        +            "type": "integer"
        +          },
        +          "last_updated": {
        +            "description": "Last update, Unix milliseconds.",
        +            "type": "number"
        +          },
        +          "retired": {
        +            "description": "Hard block for this domain; use a new session for it.",
        +            "type": "boolean"
        +          },
        +          "score": {
        +            "description": "Error score; rises on failures, decays on successes. Blocked at 3.",
        +            "type": "number"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "description": "Per-domain standing, keyed by domain. Omitted when empty.",
        +      "type": "object"
        +    },
        +    "engine": {
        +      "description": "Rendering tier the session is bound to: fetch, js or browser.",
        +      "type": "string"
        +    },
        +    "expires_at": {
        +      "description": "Current expiry (slides on use), RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "fingerprint": {
        +      "additionalProperties": {},
        +      "description": "Browser fingerprint, as stored.",
        +      "type": "object"
        +    },
        +    "hard_expires_at": {
        +      "description": "Fixed ceiling the expiry never passes, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "id": {
        +      "description": "Session id; pass it as `session_id` to spicrawl_scrape.",
        +      "type": "string"
        +    },
        +    "last_used_at": {
        +      "description": "Last successful scrape, RFC 3339 UTC; null if never used.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "lease": {
        +      "additionalProperties": true,
        +      "description": "Present only while a scrape holds the session; release and delete are refused until it lapses unless `force`.",
        +      "properties": {
        +        "expires_at": {
        +          "description": "When the lease lapses at the latest, RFC 3339 UTC.",
        +          "type": "string"
        +        },
        +        "holder": {
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "project_id": {
        +      "description": "Project the session belongs to.",
        +      "type": "string"
        +    },
        +    "proxy": {
        +      "additionalProperties": true,
        +      "description": "The session's exit intent (never an IP or endpoint).",
        +      "properties": {
        +        "country": {
        +          "description": "Lowercase alpha-2 exit country, when one was requested.",
        +          "type": "string"
        +        },
        +        "region_pool": {
        +          "description": "Regional pool requested at creation.",
        +          "type": "string"
        +        },
        +        "tier": {
        +          "description": "Exit tier: datacenter or residential.",
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "released_at": {
        +      "description": "Release time, on released sessions, RFC 3339 UTC.",
        +      "type": "string"
        +    },
        +    "retired": {
        +      "description": "Why the session was taken out of service (expired, usage_exhausted, explicit); absent while usable.",
        +      "type": "string"
        +    },
        +    "status": {
        +      "description": "active, released or expired; derived from the clock, and only `active` sessions can be used.",
        +      "type": "string"
        +    },
        +    "sticky_key": {
        +      "description": "Exit pin in use (empty when rotate_ip was set).",
        +      "type": "string"
        +    },
        +    "usage_count": {
        +      "description": "Successful scrapes that used the session.",
        +      "type": "integer"
        +    },
        +    "warnings": {
        +      "description": "Decisions made on your behalf at creation, e.g. a TTL reduced to the organization maximum.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "id"
        +  ],
        +  "type": "object"
        +}
    • Changedspicrawl_usage1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "group_by": {
        +      "description": "The dimension used: day, project, engine, feature or key.",
        +      "type": "string"
        +    },
        +    "groups": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "additionalProperties": true,
        +            "properties": {
        +              "key": {
        +                "description": "The bucket: a YYYY-MM-DD day, a project id, an engine tier (fetch, js or browser) or a feature (extract, ai_extract, proxy_datacenter, proxy_residential, batch).",
        +                "type": "string"
        +              },
        +              "label": {
        +                "description": "Human label for an engine tier.",
        +                "type": "string"
        +              },
        +              "metrics": {
        +                "anyOf": [
        +                  {
        +                    "additionalProperties": {
        +                      "type": "number"
        +                    },
        +                    "type": "object"
        +                  },
        +                  {
        +                    "type": "null"
        +                  }
        +                ],
        +                "description": "Metric name -> quantity. credits are micro-credits (1 credit = 1000000), engine_ms milliseconds, bytes_* bytes, the rest counts."
        +              }
        +            },
        +            "required": [
        +              "key"
        +            ],
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "The buckets, sorted by key. Empty (or missing for group_by=key) does not mean no usage: read totals."
        +    },
        +    "keys": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "additionalProperties": true,
        +            "properties": {
        +              "days": {
        +                "anyOf": [
        +                  {
        +                    "items": {
        +                      "additionalProperties": true,
        +                      "properties": {
        +                        "day": {
        +                          "type": "string"
        +                        },
        +                        "metrics": {
        +                          "$ref": "#/properties/groups/anyOf/0/items/properties/metrics"
        +                        }
        +                      },
        +                      "required": [
        +                        "day"
        +                      ],
        +                      "type": "object"
        +                    },
        +                    "type": "array"
        +                  },
        +                  {
        +                    "type": "null"
        +                  }
        +                ]
        +              },
        +              "key_id": {
        +                "type": "string"
        +              },
        +              "name": {
        +                "type": "string"
        +              },
        +              "prefix": {
        +                "description": "Display prefix of the API key, never the secret.",
        +                "type": "string"
        +              },
        +              "project_id": {
        +                "type": "string"
        +              },
        +              "revoked": {
        +                "type": "boolean"
        +              },
        +              "totals": {
        +                "$ref": "#/properties/groups/anyOf/0/items/properties/metrics",
        +                "description": "Metric name -> quantity. credits are micro-credits (1 credit = 1000000), engine_ms milliseconds, bytes_* bytes, the rest counts."
        +              }
        +            },
        +            "required": [
        +              "key_id"
        +            ],
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "group_by=key only: one entry per API key, with its counters per UTC day."
        +    },
        +    "period": {
        +      "additionalProperties": true,
        +      "description": "The window, as a half-open range of UTC days.",
        +      "properties": {
        +        "bounds": {
        +          "description": "Always '[start, end)'.",
        +          "type": "string"
        +        },
        +        "days": {
        +          "type": "number"
        +        },
        +        "end": {
        +          "description": "End UTC day, EXCLUSIVE (YYYY-MM-DD).",
        +          "type": "string"
        +        },
        +        "start": {
        +          "description": "First UTC day, inclusive (YYYY-MM-DD).",
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "stale_seconds": {
        +      "description": "Age of usage_as_of in seconds; null when the window is empty. A large value means the rollup is behind.",
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "totals": {
        +      "$ref": "#/properties/groups/anyOf/0/items/properties/metrics",
        +      "description": "Billed quantities for the whole window. Authoritative; use these, not the sum of groups."
        +    },
        +    "unattributed": {
        +      "$ref": "#/properties/groups/anyOf/0/items/properties/metrics",
        +      "description": "The part of each total the groups do not explain."
        +    },
        +    "usage_as_of": {
        +      "description": "When the newest rollup row in the window was written; null when the window is empty.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "warnings": {
        +      "description": "Caveats the numbers would otherwise hide.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedspicrawl_usage_reconciliation1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "day": {
        +      "description": "The UTC day reconciled.",
        +      "type": "string"
        +    },
        +    "drift": {
        +      "anyOf": [
        +        {
        +          "items": {
        +            "additionalProperties": true,
        +            "properties": {
        +              "action": {
        +                "description": "The verdict: missing_in_usage_daily, absent_from_request_log, undercounted or overcounted.",
        +                "type": "string"
        +              },
        +              "delta": {
        +                "type": "number"
        +              },
        +              "metric": {
        +                "type": "string"
        +              },
        +              "observed_qty": {
        +                "description": "The quantity re-derived from the request log.",
        +                "type": "number"
        +              },
        +              "project_id": {
        +                "type": "string"
        +              },
        +              "stored_qty": {
        +                "description": "The billed quantity.",
        +                "type": "number"
        +              }
        +            },
        +            "type": "object"
        +          },
        +          "type": "array"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Disagreements; empty means no drift."
        +    },
        +    "interpretation": {
        +      "description": "What the drift can and cannot prove. Read it before acting on drift.",
        +      "type": "string"
        +    },
        +    "repairable": {
        +      "description": "Always false; nothing is repaired.",
        +      "type": "boolean"
        +    },
        +    "request_log_rows": {
        +      "description": "Rows in the request log for the day; 0 means there was nothing to compare against.",
        +      "type": "number"
        +    },
        +    "warnings": {
        +      "description": "Caveats the numbers would otherwise hide.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedspicrawl_usage_summary1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": true,
        +  "properties": {
        +    "allowance": {
        +      "additionalProperties": true,
        +      "description": "The monthly allowance the API enforces. Omitted when it cannot be read (warnings says so).",
        +      "properties": {
        +        "limit_credits": {
        +          "type": "number"
        +        },
        +        "limit_micro": {
        +          "type": "number"
        +        },
        +        "limit_source": {
        +          "description": "'default' or 'override'.",
        +          "type": "string"
        +        },
        +        "remaining_micro": {
        +          "description": "Credits left under the monthly limit: the number to show.",
        +          "type": "number"
        +        },
        +        "resets_at": {
        +          "description": "When the allowance is restored in full.",
        +          "type": "string"
        +        },
        +        "unlimited": {
        +          "type": "boolean"
        +        },
        +        "used_micro": {
        +          "description": "Spent plus credits held for in-flight work.",
        +          "type": "number"
        +        },
        +        "window_start": {
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "credits": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": true,
        +          "properties": {
        +            "included_micro": {
        +              "type": "number"
        +            },
        +            "overage_micro": {
        +              "type": "number"
        +            },
        +            "overage_micro_cents_per_credit": {
        +              "type": "number"
        +            },
        +            "remaining_micro": {
        +              "type": "number"
        +            },
        +            "used_basis_points": {
        +              "description": "Used / included in basis points (10000 = 100%); null when nothing is included.",
        +              "type": [
        +                "number",
        +                "null"
        +              ]
        +            },
        +            "used_micro": {
        +              "description": "Credits spent so far, from the usage rollup; excludes credits held for in-flight work.",
        +              "type": "number"
        +            }
        +          },
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Metered usage against the plan's included credits. Micro-credits: 1 credit = 1000000."
        +    },
        +    "metrics": {
        +      "anyOf": [
        +        {
        +          "additionalProperties": {
        +            "type": "number"
        +          },
        +          "type": "object"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "description": "Every billed metric for the period."
        +    },
        +    "period": {
        +      "additionalProperties": true,
        +      "description": "The window, as a half-open range of UTC days.",
        +      "properties": {
        +        "bounds": {
        +          "description": "Always '[start, end)'.",
        +          "type": "string"
        +        },
        +        "days": {
        +          "type": "number"
        +        },
        +        "end": {
        +          "description": "End UTC day, EXCLUSIVE (YYYY-MM-DD).",
        +          "type": "string"
        +        },
        +        "start": {
        +          "description": "First UTC day, inclusive (YYYY-MM-DD).",
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "period_elapsed_days": {
        +      "description": "Whole days of the period elapsed; use it to pace consumption.",
        +      "type": "number"
        +    },
        +    "plan": {
        +      "additionalProperties": true,
        +      "properties": {
        +        "code": {
        +          "type": "string"
        +        },
        +        "name": {
        +          "type": "string"
        +        },
        +        "period_source": {
        +          "description": "'subscription' (billing period) or 'allowance_month'.",
        +          "type": "string"
        +        },
        +        "subscription_status": {
        +          "description": "'none' when no subscription covers now (the free plan).",
        +          "type": "string"
        +        },
        +        "version": {
        +          "type": "number"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "stale_seconds": {
        +      "description": "Age of usage_as_of in seconds; null when the window is empty. A large value means the rollup is behind.",
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "unattributed": {
        +      "$ref": "#/properties/metrics",
        +      "description": "Metric name -> quantity. credits are micro-credits (1 credit = 1000000), engine_ms milliseconds, bytes_* bytes, the rest counts."
        +    },
        +    "usage_as_of": {
        +      "description": "When the newest rollup row in the window was written; null when the window is empty.",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "warnings": {
        +      "description": "Caveats the numbers would otherwise hide.",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
  2. 6 tool updates
    • Changedspicrawl_batch_add_items1 field changed
      • removedInput schema / properties / engine
        Removed value: -{
        -  "description": "Pin the scrape engine for every item: `fetch` or `obscura` (must be allowed by the plan and served by the deployment); `camoufox` is coming soon, do not pin it yet. `chromium` cannot be pinned in a batch — use `render: true`, or spicrawl_scrape.",
        -  "enum": [
        -    "fetch",
        -    "obscura",
        -    "camoufox"
        -  ],
        -  "type": "string"
        -}
    • Changedspicrawl_batch_submit1 field changed
      • removedInput schema / properties / engine
        Removed value: -{
        -  "description": "Pin the scrape engine for every item: `fetch` or `obscura` (must be allowed by the plan and served by the deployment); `camoufox` is coming soon, do not pin it yet. `chromium` cannot be pinned in a batch — use `render: true`, or spicrawl_scrape.",
        -  "enum": [
        -    "fetch",
        -    "obscura",
        -    "camoufox"
        -  ],
        -  "type": "string"
        -}
    • Changedspicrawl_browser_connect_url3 fields changed
      • changedInput schema / properties / engine / description
        Previous value: -"Browser engine. Default: the deployment's default (chromium). 'obscura' cannot run headful."New value: +"Rendering tier of the remote browser: `browser` (full browser, full protocol; the default) or `js` (lighter JavaScript rendering with a smaller protocol surface). A tier your plan does not include is refused."
      • changedInput schema / properties / engine / enum
        Previous value: -[
        -  "chromium",
        -  "obscura"
        -]New value: +[
        +  "browser",
        +  "js"
        +]
      • removedInput schema / properties / headless
        Removed value: -{
        -  "description": "false = headful browser with a display (desktop-sized screen). Omit for the deployment default.",
        -  "type": "boolean"
        -}
    • Changedspicrawl_scrape4 fields changed
      • removedInput schema / properties / engine
        Removed value: -{
        -  "description": "Pin the execution engine instead of letting the router choose. A pinned engine the deployment does not run is refused (ERR::ENGINE::UNAVAILABLE), never substituted. `camoufox` is coming soon: do not pin it yet.",
        -  "enum": [
        -    "fetch",
        -    "obscura",
        -    "chromium",
        -    "camoufox"
        -  ],
        -  "type": "string"
        -}
      • changedInput schema / properties / format / description
        Previous value: -"Output format. 'markdown' (default) is best for feeding to an LLM; 'html' returns the raw document; 'json' returns a structured envelope; 'pdf' prints the page in a browser and returns the file as a resource content block (needs `render` or `engine: \"chromium\"`)."New value: +"Output format. 'markdown' (default) is best for feeding to an LLM; 'html' returns the raw document; 'json' returns a structured envelope; 'pdf' prints the page in a full browser (routed there for you) and returns the file as a resource content block."
      • removedInput schema / properties / headless
        Removed value: -{
        -  "description": "false runs Chromium on a real display (1920x1080 screen). chromium engine only.",
        -  "type": "boolean"
        -}
      • changedInput schema / properties / stealth / description
        Previous value: -"Coming soon: not available yet, do not send. Stealth mode: render in the hardened Camoufox browser. Default false."New value: +"Coming soon: not available yet, do not send. Stealth mode: render in a full browser hardened against bot detection. Default false."
    • Changedspicrawl_session_create3 fields changed
      • changedInput schema / properties / engine / description
        Previous value: -"Engine pinned for the session's lifetime. Default: `obscura` if deployed, else `chromium`, else `fetch`. `camoufox` is coming soon: do not pin it yet."New value: +"Rendering tier fixed for the session's lifetime. Optional: leave it out and one is chosen for you. `fetch` is plain HTTP; `js` is JavaScript rendering and refuses `actions`, `block_resources`, screenshots and PDFs; `browser` is a full browser."
      • changedInput schema / properties / engine / enum
        Previous value: -[
        -  "fetch",
        -  "obscura",
        -  "chromium",
        -  "camoufox"
        -]New value: +[
        +  "fetch",
        +  "js",
        +  "browser"
        +]
      • changedInput schema / properties / fingerprint / description
        Previous value: -"Coming soon: not available yet, do not send. Camoufox fingerprint pin, stored verbatim. Only valid with engine `camoufox`."New value: +"Coming soon: not available yet, do not send. Browser fingerprint pin, stored verbatim. Needs a full-browser session (`engine: \"browser\"`)."
    • Changedspicrawl_session_list2 fields changed
      • changedInput schema / properties / engine / description
        Previous value: -"Only sessions pinned to this engine."New value: +"Only sessions on this rendering tier."
      • changedInput schema / properties / engine / enum
        Previous value: -[
        -  "fetch",
        -  "obscura",
        -  "chromium",
        -  "camoufox"
        -]New value: +[
        +  "fetch",
        +  "js",
        +  "browser"
        +]
  3. 25 tool updates
    • First observedspicrawl_batch_add_items
    • First observedspicrawl_batch_cancel
    • First observedspicrawl_batch_close
    • First observedspicrawl_batch_list
    • First observedspicrawl_batch_results
    • First observedspicrawl_batch_retry
    • First observedspicrawl_batch_status
    • First observedspicrawl_batch_submit
    • First observedspicrawl_batch_task_content
    • First observedspicrawl_browser_connect_url
    • First observedspicrawl_docs_index
    • First observedspicrawl_docs_read
    • First observedspicrawl_docs_search
    • First observedspicrawl_request_get
    • First observedspicrawl_requests_list
    • First observedspicrawl_scrape
    • First observedspicrawl_session_context
    • First observedspicrawl_session_create
    • First observedspicrawl_session_delete
    • First observedspicrawl_session_get
    • First observedspicrawl_session_list
    • First observedspicrawl_session_release
    • First observedspicrawl_usage
    • First observedspicrawl_usage_reconciliation
    • First observedspicrawl_usage_summary

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Perplexity for social: ask what competitors are running across social and get answers grounded in real ad and creative data, not guesses.
    2
    Apache 2.0
  • A
    license
    A
    quality
    C
    maintenance
    Enables brand visibility monitoring across major AI platforms like ChatGPT, Claude, Gemini, and Perplexity. It allows users to track visibility scores, analyze competitor data, and receive actionable insights to improve AI-generated brand recommendations.
    16
    4 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Browse IndustryLens's published competitive-intelligence reports and head-to-head competitor comparisons from any AI agent — real, source-backed data.
    MIT
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources