Mercury · Cited Validate
GET /buy/validate
What it does
URL (a JSON/API endpoint) + a JSON Schema in → a deterministic pass/fail with per-field errors (missing/wrong-type/enum/range/pattern), plus a signed provenance receipt binding the verdict to the exact response bytes AND the exact schema. Deterministic, keyless, no LLM — x402, USDC on Base mainnet.
The goal it serves: produce audit-grade evidence: a deterministic verdict bound to exact bytes, signed by the pinned key, so anyone can check it offline, forever — no callback to Mercury required.
Schemas & output preview
Input schema — the exact request shape the route validates.
{
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 2048,
"description": "the JSON/API endpoint to fetch + validate (http/https)"
},
"schema": {
"type": "string",
"maxLength": 16384,
"description": "the JSON Schema to validate against. THREE accepted forms: (1) COMPACT URL-native comma list of field[:type] (type in string|number|integer|boolean|array|object|null; default string), e.g. id:integer,name,price:number,inStock:boolean — every field becomes a REQUIRED typed property; (2) a JSON-Schema string (Draft-07 core subset: type/required/properties/items/enum/const/min*/max*/pattern/format/additionalProperties/nullable/anyOf/oneOf/allOf/not); (3) a shorthand-map string {\"id\":\"integer\",\"name\":\"string\"}."
},
"pointer": {
"type": "string",
"maxLength": 256,
"description": "optional JSON-Pointer (e.g. /data or /result/0) to validate a SUB-DOCUMENT of the response instead of the whole body (for APIs that wrap the payload)."
}
},
"required": [
"url",
"schema"
],
"additionalProperties": false
}Output schema — the exact response shape the handler returns.
{
"type": "object",
"properties": {
"ok": {
"type": "boolean",
"description": "true when the validation RAN (delivered); false on an honest undeliverable (503-before-charge)"
},
"url": {
"type": "string",
"description": "final URL after redirects"
},
"status": {
"type": "integer",
"description": "upstream HTTP status of the fetched JSON"
},
"text": {
"type": "string",
"description": "the canonical signed string: JSON.stringify(report, sorted-keys) — the exact bytes the provenance receipt covers (embeds documentHash + schemaHash + verdict)"
},
"fetchedAt": {
"type": "string",
"description": "ISO timestamp of the fetch (also in the signed attestation)"
},
"data": {
"type": "object",
"description": "the validation report the buyer consumes",
"properties": {
"valid": {
"type": "boolean",
"description": "true iff the fetched JSON conforms to the schema with zero errors"
},
"errorCount": {
"type": "integer",
"description": "number of validation errors found"
},
"errors": {
"type": "array",
"description": "per-field errors in document order (empty when valid)",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "JSON-Pointer path to the offending value"
},
"keyword": {
"type": "string",
"description": "the schema keyword that failed (type, required, enum, minimum, pattern, …)"
},
"message": {
"type": "string",
"description": "human-readable reason"
}
}
}
},
"truncated": {
"type": "boolean",
"description": "true if the error cap clipped the list (still honest about more existing)"
},
"documentHash": {
"type": "string",
"description": "0x… sha256 of the canonical JSON document that was validated"
},
"schemaHash": {
"type": "string",
"description": "0x… sha256 of the canonical (normalised) schema that was applied"
},
"schemaForm": {
"type": "string",
"description": "which input form was used: compact | json-schema | shorthand"
},
"pointer": {
"type": "string",
"description": "the JSON-Pointer applied (empty for whole-body validation)"
},
"validatedType": {
"type": "string",
"description": "the JSON type of the validated (sub-)document"
}
}
},
"attestation": {
"type": "object",
"description": "EIP-191 provenance receipt over `text` (the canonical sorted-key JSON of the report, which embeds documentHash + schemaHash + verdict), ecrecoverable OFFLINE (key at /.well-known/mercury-attestation). Proves: which schema was checked, which bytes were checked, and the verdict — all at fetchedAt.",
"properties": {
"keyId": {
"type": "string"
},
"alg": {
"type": "string"
},
"address": {
"type": "string"
},
"contentHash": {
"type": "string"
},
"nonce": {
"type": "string"
},
"signedAt": {
"type": "string"
},
"signature": {
"type": "string"
},
"verify": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"howTo": {
"type": "string"
}
}
}
}
},
"error": {
"type": "string",
"description": "present only when ok:false (undeliverable, not charged)"
}
},
"required": [
"ok",
"url"
],
"additionalProperties": true
}Output preview — a real example response, shown free (you only pay when you call the route).
{
"ok": true,
"url": "https://api.example.com/item/42",
"status": 200,
"text": "{\"errorCount\":1,\"errors\":[{\"keyword\":\"required\",\"message\":\"missing required property \\\"name\\\"\",\"path\":\"/\"}],\"valid\":false,\"validatedType\":\"object\",\"documentHash\":\"0x<sha256 of canonical document>\",\"pointer\":\"\",\"schemaForm\":\"compact\",\"schemaHash\":\"0x<sha256 of canonical schema>\",\"truncated\":false}",
"fetchedAt": "2026-06-04T00:00:00.000Z",
"data": {
"valid": false,
"errorCount": 1,
"errors": [
{
"path": "/",
"keyword": "required",
"message": "missing required property \"name\""
}
],
"truncated": false,
"documentHash": "0x<sha256 of canonical document>",
"schemaHash": "0x<sha256 of canonical schema>",
"schemaForm": "compact",
"pointer": "",
"validatedType": "object"
},
"attestation": {
"keyId": "mercury-x402-attestation-v1:0x<signer>",
"alg": "EIP-191-personal_sign",
"address": "0x<signer-from-/.well-known/mercury-attestation>",
"contentHash": "0x<sha256 of text>",
"nonce": "0x<16-random-bytes>",
"signedAt": "2026-06-04T00:00:00.000Z",
"signature": "0x<65-byte EIP-191 signature>",
"verify": {
"message": "mercury-x402:fetch-attestation:v1\nurl=https://api.example.com/item/42\nstatus=200\nsha256=0x…\nfetchedAt=2026-06-04T00:00:00.000Z\nnonce=0x…",
"howTo": "EIP-191 ecrecover this message; signer must equal address. Recompute sha256(text)==contentHash."
}
}
}Pay & call
Your agent calls the route; the 402 challenge carries the exact price ($0.005, USDC on Base mainnet); the x402 client settles via the CDP facilitator and retries. No key, no signup.
import { wrapFetchWithPayment } from "x402-fetch";
const pay = wrapFetchWithPayment(fetch, account); // viem account holding a little USDC on Base
const res = await pay("https://network.mercury-hq.com/buy/validate?url=https://example.com&schema=id:integer,name,price:number");
const out = await res.json(); // the result + `attestation` (the signed receipt)Prepaid alternative — the same route accepts an API key:
# Same route, prepaid API-key rail (Bearer mk_live_…) — get a key at https://network.mercury-hq.com/developers
curl -H "Authorization: Bearer mk_live_YOURKEY" "https://network.mercury-hq.com/buy/validate?url=https://example.com&schema=id:integer,name,price:number"Verify the receipt
Recover the EIP-191 signature over sha256(content)‖url‖status‖fetchedAt‖nonce and confirm the signer equals the pinned attestation key 0xACB40253BD71Bb9a5d491b2c6EFF755F2A33Fc75 (published at /.well-known/mercury-attestation). No callback to Mercury — the receipt verifies offline, forever. Verification is always free: POST the receipt to /x402/verify or run ecrecover yourself.
| Fact | Value |
|---|---|
| Attestation signer (pinned) | 0xACB40253BD71Bb9a5d491b2c6EFF755F2A33Fc75 |
| Key published at | /.well-known/mercury-attestation |
| Live verifier (free) | /x402/verify |
| Settlement | real USDC on Base mainnet (eip155:8453) via CDP — auditable on BaseScan |
Related
Cited Diff
$0.006Cited Notarize
$0.008More: all services · /catalog · the headline web-fetch · agent twin of this page: GET /university/docs/cited-validate?format=md