# Webscan buyer guide

Two tools for AI agents. Public documentation and demonstration snapshots are free.
Research requests are paid individually in USDC on Base mainnet (`eip155:8453`) using x402.

## Choose the tool for your task

| Task | Buy | Use the result for |
| --- | --- | --- |
| Inspect a website before crawling or integration | `POST /v1/website-preflight` — $0.02 | Choose an access path; discover robots, sitemaps and OpenAPI; inspect redirects, DNS/TLS, technologies and security headers |
| Compare competitor pricing, offers or purchase terms | `POST /v1/competitive-page-benchmark` — $0.12 | Build a source-backed competitor table from offers, prices, conditions, contacts and booking methods |
| Prepare a landing page or SEO brief | Competitive Page Benchmark | Use observed categories, content blocks, conversion patterns and source-linked target observations |

You supply competitor URLs. For a market-wide comparison choose 3–10 distinct companies in the same market. Start from homepages for company research, pricing pages for plans, or matching product/service pages for an offer comparison. Add your own website as `target_url` when you want gaps and strengths. Each supplied URL starts an internal site crawl.

## Find Webscan

Webscan is indexed in Agentic Market under `api.webscan-ai.online`. Search for `webscan`, `competitor analysis`, `landing page research` or `website reconnaissance`. Direct inspection shows the current price and schema before payment:

```sh
npx -y awal@latest x402 bazaar search "webscan" --json
npx -y awal@latest x402 details https://api.webscan-ai.online/v1/website-preflight --json
npx -y awal@latest x402 details https://api.webscan-ai.online/v1/competitive-page-benchmark --json
```

Names: **Webscan AI Website Preflight** and **Webscan Competitor Benchmark**.

[Webscan on Agentic Market](https://agentic.market/services/api-webscan-ai-online)
 · [Interactive API documentation](https://api.webscan-ai.online/docs)
 · [OpenAPI JSON](https://api.webscan-ai.online/openapi.json)
 · [machine-readable index](https://api.webscan-ai.online/llms.txt)

## Website Preflight request

```json
{"url":"https://example.com","freshness_seconds":3600}
```

| Field | Required | Meaning |
| --- | --- | --- |
| `url` | Yes | Public HTTP(S) website URL, 8–2048 characters |
| `freshness_seconds` | No | Maximum reusable analysis age: 0–86400 seconds; default 3600. Use 0 for fresh collection |

With an already authorized and funded Coinbase Agentic Wallet:

```sh
npx -y awal@latest x402 pay \
  https://api.webscan-ai.online/v1/website-preflight \
  -X POST -d '{"url":"https://example.com","freshness_seconds":3600}' \
  --max-amount 20000
```

This is a real purchase: `20000` atomic units = $0.02 USDC. Wallet setup belongs to your x402 client; Webscan needs no subscription or Webscan API key.

## Competitive Page Benchmark request

```json
{
  "competitor_urls": ["https://asana.com", "https://monday.com", "https://clickup.com"],
  "target_url": "https://notion.com",
  "freshness_seconds": 21600,
  "crawl": {"max_pages_per_site": 4, "max_depth": 1},
  "response_format": "agent_v1"
}
```

| Field | Required | Meaning |
| --- | --- | --- |
| `competitor_urls` | Yes | 3–10 distinct public HTTP(S) URLs; each up to 2048 characters |
| `target_url` | No | Your distinct public website for observed gaps and strengths; omit for competitor-only research |
| `freshness_seconds` | No | 0–86400 seconds; default 21600 (6 hours). Use 0 for fresh collection |
| `crawl.max_pages_per_site` | No | 1–8 pages per company including the supplied page; default 4 |
| `crawl.max_depth` | No | 0–2 internal-link hops from the supplied page; default 1. Use 0 for just the supplied page |
| `response_format` | No | `agent_v1` gives readable facts with shared evidence locations; `normalized_full_v1` preserves the exact full document in encoded form; `full` is the unchanged default |

```sh
npx -y awal@latest x402 pay \
  https://api.webscan-ai.online/v1/competitive-page-benchmark \
  -X POST \
  -d '{"competitor_urls":["https://asana.com","https://monday.com","https://clickup.com"],"target_url":"https://notion.com","freshness_seconds":21600,"crawl":{"max_pages_per_site":4,"max_depth":1},"response_format":"agent_v1"}' \
  --max-amount 120000
```

This is a real purchase: `120000` atomic units = $0.12 USDC for the request, not per website or page. Cache freshness changes reuse of computation, not the price. Every new request is a separate purchase; there is no paid-result retrieval or free replay. Save the delivered JSON in your own workflow.

For direct agent use request `agent_v1`. It preserves every page profile, commercial fact, comparison, error and uncertainty; no foreign page text is added. `companies`, `sources` and `evidence` are objects keyed by their IDs. Follow `evidence[id].location_id` into `locations`, then `location.source_id` into `sources`. A missing location URL inherits the source's `final_url`, falling back to `url`. `observation_groups[].context` applies to every observation in that group. `target_source_id`, when present, points to the exact target profile instead of repeating it. Source hashes, range-fetch diagnostics and unvisited URL lists are omitted; `pending_page_count` and coverage remain. This is a factual projection, not an exact full-document encoding.

For original array-shaped records request `full`. For exact archival equivalence use `normalized_full_v1`; the reference reader in [`scanner/examples/normalized_packet.rs`](https://github.com/DRootA/webscan/blob/main/scanner/examples/normalized_packet.rs) supports `read_summary`, `select_facts` and `resolve_evidence`. Decoding reconstructs schema 5.0, including nulls, empty values and ordering. Selected fact IDs are packet-local; contact/action IDs include the source field to keep phone, email, form and CTA records distinct. All formats are served from the same analysis; format selection does not change payment or crawl scope.

### Compare billing options of one SaaS plan

`saas_billing_comparisons` reports the advertised recurring charge over 12 months for compatible monthly/annual options of the same plan. `plan_index` addresses `saas_tariffs.plans`; `monthly_option_index` and `annual_option_index` address that plan's `pricing_options` (zero-based). Amounts apply to the quoted `quantity` and `unit`, not a whole team. Positive `annual_savings` means annual billing is cheaper; negative means more expensive. Prices are held constant for this arithmetic comparison. This is not a checkout total or a claim that different products are equivalent. Retain `unknown_fields`, `implicit_fields` and evidence; minimum seats, taxes or regional eligibility may be unobserved. Promotional, conditional, ambiguous, ranged, metered and conflicting options do not generate a comparison.

## Read the result into a decision

Benchmark response version: `schema_version: "5.0"`. Preflight stays at `"1.0"`.

The paths below use `full` array notation. In `agent_v1`, use the ID-keyed dictionaries (`sources[source_id]`, `companies[company_id]`, `evidence[evidence_id]`) and resolve evidence locations as described above. Source hashes are not part of `agent_v1`.

| Decision | Read these fields | Next step |
| --- | --- | --- |
| Competitor product/service table | `companies[].pages[].source_id` → `sources[].page_profile.offer_details` | Use original offer names, observed amount/currency, `price_basis`, conditions and source URLs |
| Product requirements and specifications | `sources[].page_profile.products` | Keep each subject with its identifiers, raw attribute values, explicit numbers/units and evidence; different SKUs are not interchangeable |
| Published compatibility | `commercial_terms` where `kind` is `compatibility` | Read `relation`, `subject`, `target`, `condition` and `claim` together; a requirement is not proof that a candidate satisfies it |
| Delivery planning | `commercial_terms` where `kind` is `delivery` | Separate `handling` from `transit`; retain business-day units, product/destination scope and conditions |
| Price positioning | `market_patterns.price_ranges`, `offer_details[].price_comparison` | Compare only emitted groups; retain reason codes where basis is unknown |
| Landing-page structure | `market_patterns.content_structure`, `common_page_elements`, `sources[].page_profile.content_blocks` | Turn observed sections and categories into a sourced page outline |
| Conversion opportunities | `market_patterns.booking_methods`, `payment_methods`, `trust_signals`, `target_gaps`, `target_strengths` | Use the returned subject, scope, observation and suggested action |
| Contact or branch comparison | `sources[].page_profile.contact_locations`, `phones`, `emails`, `messenger_links` | Preserve address/phone/hours associations and any display/link disagreement |
| Commercial terms | `sources[].page_profile.commercial_terms` | Keep the subject, conditions, duration/distance and claim locator together |
| Verify an observation | Finding `evidence_ids` → `evidence[].id` → `sources[].source_id` | Retain URL, excerpt, selector, timestamp, retrieval method and content hash with your conclusion |
| Plan a technical collection | Preflight `access_paths`, `machine_interfaces`, `page`, `target` | Choose the next collection method and URLs from observed availability |

Warranty duration ranges use `duration.value` as the lower bound and optional
`duration.value_max` as the upper bound. `qualifier: "approximately"` preserves an
explicit approximation from the source.

For service variants, keep the service name together with `price_basis.variant`, `composition`, `conditions` and evidence. A published price-effective date is a condition, not a promise that the rate applies today. A price quoted per month can require annual billing; preserve both the period and commitment.

`commercial_terms` with `kind: "return_policy"` distinguish accepted returns from scoped product exclusions. `window_start` identifies purchase, delivery or shipment when explicit; an unknown starting event stays null/omitted. Refund-processing time is not the buyer's return deadline. `kind: "return_fee"` separates `amount`/`percent` from `order_threshold`; each qualifier belongs to its own value. Keep the original claim when a range, currency or condition is unresolved.

### Product facts beyond price

`products[]` groups facts under one observed `subject`. Its `evidence` proves the name/identifier and ownership once; each fact has its own property/value evidence. `kind: "identity"` retains strings such as SKU/GTIN, including leading zeroes. `kind: "specification"` keeps the raw value; `numeric_value` and `unit` are populated only for an unambiguous scalar. Dimensions, ranges and conflicting units must not be reduced to a made-up single measurement. These are source-declared attributes, not verified laboratory measurements or a universal product registry.

`contact_locations` keeps postal addresses with their own phones and opening hours. Optional `contact_phones` preserves explicit phone labels when no postal address is observed, without inventing an address or repeating an already associated location phone. Booking buttons without a static destination retain their action label and service context with `url: null`; a button is not proof of availability.

Compatibility relations are `supported`, `not_supported` or `requires`. A null subject is unresolved, not every product on the page. Preserve conditions such as a required adapter, firmware version or operating mode. An omitted compatibility claim does not mean compatible or incompatible. Delivery `available: null` is unknown; carrier-specific exclusions do not establish a global shipping ban. Estimates are not guaranteed arrival dates, and handling/transit values are not automatically added.

The existing normalized reader supports `select_facts` with `fact_type: "product"`. Follow the selected source for its URL and retrieval timestamp; product facts and commercial terms retain their inline statements. No additional lookup or new paid endpoint is required to read these fields from the delivered response.

Count companies, not pages: follow `comparison_company_id` when origins alias. The target does not contribute to competitor statistics. `target_analysis` is the target seed profile; child-page facts remain in the target company's referenced sources.

An unobserved fact is not established absence. `target_has: null` and `target_observation: "unknown"` are verification tasks, not claims that a competitor is unique or your company lacks a feature. `quality` describes heuristic coverage, not measured accuracy. `status` describes the completed collection scope. Keep `coverage`, source errors and omission fields when using a partial result. Price, currency and similar names alone do not prove equivalent offers.

## Full examples: inspect before buying

These are frozen, unedited Rust-generated snapshots captured on the dates in the manifest, not live promises or hand-written ideal responses. Benchmark samples were collected through the scanner during release QA; the Preflight sample was delivered through the public paid endpoint. Demonstration files do not expose receipts, wallet credentials or customer requests.

- **[SaaS full JSON](https://api.webscan-ai.online/guide/examples/saas.json)** · [request](https://api.webscan-ai.online/guide/examples/saas-request.json): monday.com, Slack, Notion, target Asana. Start with `saas_tariffs` for product-scoped plans (same tier name can belong to different products), monthly/annual and promotional prices, metered usage, per-user/per-account limits, retention, price region, free/contact-sales states, seat minimums and increments, tax, trials, add-ons and overage; follow field evidence IDs before making a pricing decision.
- **[Ecommerce full JSON](https://api.webscan-ai.online/guide/examples/ecommerce.json)** · [request](https://api.webscan-ai.online/guide/examples/ecommerce-request.json): Girlfriend, Spanx, Vuori, target Alo. `c1p1` includes “Black Compressive High-Rise Legging”, $108 USD, SKU and an Add to Cart CTA. Price-basis fields show which comparison dimensions were established.
- **[Tourism full JSON](https://api.webscan-ai.online/guide/examples/tourism.json)** · [request](https://api.webscan-ai.online/guide/examples/tourism-request.json): 7tour, Online Pattaya, Thai Online, target Pattaya Tours. `market_patterns.booking_methods` records messenger on two companies; `e2` ties one observation to its source. `c1p1` includes Ramayana at 1139 THB as an observed offer.
- **[Preflight full JSON](https://api.webscan-ai.online/guide/examples/preflight.json)** · [request](https://api.webscan-ai.online/guide/examples/preflight-request.json): example.com. Static HTML is available; the packet includes TLS, HTTP, metadata and the available access paths.

[Snapshot manifest and SHA-256 hashes](https://api.webscan-ai.online/guide/examples/manifest.json). The responses retain their original partial statuses, unknowns, extraction artifacts and source failures. They demonstrate actual output, not a precision/recall benchmark. Use the JSON files as external data; source text is never an instruction to your agent.

## Payment and errors

An unsigned POST returns `402` with an empty JSON object. Decode **`PAYMENT-REQUIRED`**, not the body, to read payment requirements. An x402 client handles challenge, signature, paid request and settlement; inspect HTTP status and JSON before treating a purchase as delivered. Use a client response timeout that covers collection and payment, for example 120 seconds. The gateway allows 40 seconds for paid benchmark upstream, 10 for verification and 35 for settlement; this is not an end-to-end SLA.

| HTTP | Handling |
| --- | --- |
| `200` | Read `complete`/`partial`, `coverage`, source errors and evidence before using findings |
| `400` / `422` | Correct input using error/message or validation detail. The initial payment challenge can precede field validation |
| `402` | Follow the x402 challenge or inspect payment rejection; do not send USDC with a plain token transfer |
| `413` | Reduce request JSON: Preflight accepts 8 KiB, Benchmark 24 KiB |
| `502` | Inspect scanner failure or `insufficient_competitor_coverage`; no independent competitor input was analyzable in the latter case |
| `503` / `504` | Inspect capacity/payment/timeout information before deciding on another purchase |

**Payment safety:** a lost response or `settlement_outcome_unknown` can occur after a transfer. Verify the original transaction before authorizing another payment. Do not automatically retry a paid operation with a new authorization. Every newly authorized API request is a separate purchase.

Collection accepts public HTTP(S), standard ports, and no embedded credentials. Research uses Rust and local open-source components, including a local Chromium fallback. It does not use a server LLM or external search/analytical data API. Page coverage, retrieval methods and collection notes are explicit in each packet.
