{"x402Version":2,"services":[{"resource":{"url":"https://api.cospel.dev/v1/extract","description":"Turn any text, HTML or URL into JSON that validates against your own JSON Schema. POST the source plus a draft 2020-12 schema and get back the typed object, plus per-field provenance: the exact source span each value came from, with a confidence score, and the offset of that span in UTF-16 code units, which is how JavaScript counts. If your language counts code points, match on the span rather than the offset. Failed extractions are not settled. Fields that are not present come back null rather than erroring, so you can iterate a list safely. Limits: 2 MB raw input, 200,000 characters after HTML cleaning (you are charged on the cleaned size, not the raw one). No account, no API key.","mimeType":"application/json","serviceName":"Structured Extraction by Schema","tags":["extraction","json-schema","structured-data","parsing","agent"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/extract/batch","description":"Extract structured JSON from up to 20 documents in one paid call, against your own JSON Schema. Priced per document on the cleaned size, and one bad document does not fail the rest: you are only charged for the ones that validate. Each result carries per-field provenance with the source span and offset. No account, no API key.","mimeType":"application/json","serviceName":"Structured Extraction, Batch","tags":["extraction","batch","json-schema","structured-data","agent"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/ens/resolve","description":"Resolve an ENS name to its Ethereum address, plus the resolver contract and optional text records (avatar, url, description, com.twitter, com.github, org.telegram, email). Reads the ENS registry on Ethereum mainnet directly, no third party index, so the answer is whatever the chain says right now. Names with no resolver or no address come back null rather than erroring, so you can iterate a list safely. Flat $0.002 per call, no account, no API key. e.g. POST with {name:\"vitalik.eth\"}. Returns JSON.","mimeType":"application/json","serviceName":"ENS Name Resolution","tags":["ens","ethereum","resolve","name","address"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/ens/reverse","description":"Resolve an Ethereum address to its ENS name, and tell you whether that name actually resolves back to the same address. A reverse record is a claim made by the address owner, not a proof: anyone can point their reverse record at any name. This endpoint does the forward check and returns `verified: true|false` so you never display an identity the address chose for itself. Addresses with no reverse record come back null rather than erroring. Flat $0.002 per call, no account, no API key. e.g. POST with {address:\"0xd8dA...\"}. Returns JSON.","mimeType":"application/json","serviceName":"ENS Reverse Resolution, Verified","tags":["ens","ethereum","reverse","name","address"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/token/metadata","description":"Read an ERC-20 token name, symbol, decimals and total supply straight from the chain, with the supply already divided by decimals so you do not have to. Tokens that only implement part of the standard return what could be read and null for the rest instead of failing the whole call. Addresses with no code come back with isContract false. Chains: ethereum, base, arbitrum, optimism, polygon. Defaults to base. Flat $0.0015 per call, no account, no API key. e.g. POST with {address:\"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\", chain:\"base\"}. Returns JSON.","mimeType":"application/json","serviceName":"ERC-20 Token Metadata","tags":["erc20","token","metadata","supply","decimals"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/address/profile","description":"Tell a contract from a wallet, and get the native balance, transaction count and code size for any EVM address, in one call. The balance comes back both raw and formatted. EIP-7702 aware: an account that delegated code is still reported as an EOA, with the delegation target in delegatedTo, instead of being misreported as a contract the way a plain has-code check does. Chains: ethereum, base, arbitrum, optimism, polygon. Defaults to base. Flat $0.0015 per call, no account, no API key. e.g. POST with {address:\"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\", chain:\"ethereum\"}. Returns JSON.","mimeType":"application/json","serviceName":"EVM Address Profile","tags":["address","wallet","contract","balance","nonce"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/token/balance","description":"Get an ERC-20 balance for a holder, returned raw and formatted with the token decimals and symbol resolved in the same call, so you do not need a second lookup to display it. Chains: ethereum, base, arbitrum, optimism, polygon. Defaults to base. Flat $0.0015 per call, no account, no API key. e.g. POST with {token:\"0x833589...\", holder:\"0xd8dA...\", chain:\"base\"}. Returns JSON.","mimeType":"application/json","serviceName":"ERC-20 Balance","tags":["erc20","balance","token","holder","evm"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/token/safety","description":"Structural risk signals for an ERC-20 contract: whether it is a proxy (logic can change without the address changing), whether an owner still holds privileges, whether it exposes standard metadata, and how large the bytecode is. Returns the individual checks, a list of findings in plain language, and a 0-100 score. This is signals, not a verdict: a legitimate project often keeps its owner for upgrades, and a low score guarantees nothing. Use it to decide what to look at, not what to trust. Proxy detection covers the standard slots, EIP-1967, zeppelinos, beacon and EIP-1822, and names which one answered. A negative comes back as not-detected rather than as proof: a proxy keeping its implementation in a storage variable of its own reads as an ordinary contract here. Chains: ethereum, base, arbitrum, optimism, polygon. Defaults to base. Flat $0.003 per call, no account, no API key. Returns JSON.","mimeType":"application/json","serviceName":"Token Risk Signals","tags":["token","safety","risk","proxy","security"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/contract/source","description":"Fetch the verified Solidity source of a deployed contract, trying Etherscan, Sourcify and Blockscout in turn so one explorer being down or missing the contract does not end the request. Proxies are followed to their implementation and the source you get back is the logic that actually runs, not the proxy shell. The response says which address was read and how the proxy was resolved. Only verified contracts can be returned: measured on a random sample of 200 contracts in active use, about two thirds have published source, so expect roughly one in three addresses to come back unavailable. Those are never charged: you get a 422 with charged 0.000000 and a reason, and a 400 if the address has no bytecode at all. Chains: ethereum, base, arbitrum, optimism, polygon. Defaults to base. Flat $0.005 per call, no account, no API key. e.g. POST with {address:\"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\", chain:\"base\"}. Returns JSON with every source file, the compiler version and the proxy chain.","mimeType":"application/json","serviceName":"Verified Contract Source","tags":["solidity","source-code","verified","contract","proxy"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/contract/audit","description":"Audit a deployed contract for security and gas issues. Fetches the verified source (following proxies to the implementation), then runs four analysers over it: SWC Registry and project detectors, gas patterns, structural gas heuristics, and AST checks on a real Solidity parse. Returns every finding with severity, file, line, the source line itself, and how to fix it, plus a risk level and per-analyser status. The status matters: if an analyser did not finish inside the time budget the report says so and never claims the contract is clean. Each finding carries vendored true when it sits in a dependency (OpenZeppelin, Solmate, anything under node_modules or a Foundry lib) rather than in code the deployer wrote, and summary.vendored counts them, on a typical token about a third. The risk level still counts them: a bug in a library ships in the deployed bytecode like any other, so the flag says who can fix a finding, not whether it matters. Only verified contracts can be audited. Measured on a random sample of 200 contracts in active use, about two thirds have published source, so roughly one address in three comes back unavailable. Those are never charged: a 422 with charged 0.000000 and a reason, or a 400 if the address holds no bytecode, or holds only an EIP-7702 delegation, in which case the delegate address comes back as delegatedTo so you can audit that instead. A contract whose source is too large to fetch is not charged either: it comes back with sourceOmitted true and risk \"unknown\", never a clean verdict on code nobody read. Chains: ethereum, base, arbitrum, optimism, polygon. Defaults to base. Flat $0.05 per call, no account, no API key. e.g. POST with {address:\"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\", chain:\"base\"}. Returns JSON.","mimeType":"application/json","serviceName":"Smart Contract Audit","tags":["audit","security","solidity","vulnerability","gas"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/gas","description":"Current gas price across several EVM chains in one call, in wei and gwei. Ask for the chains you care about and get them together, so an agent deciding where to execute does not need five round trips. Chains that fail to answer come back with an error field instead of failing the whole call. Available: ethereum, base, arbitrum, optimism, polygon. Flat $0.001 per call, no account, no API key. e.g. POST with {chains:[\"base\",\"arbitrum\"]}. Returns JSON.","mimeType":"application/json","serviceName":"Multichain Gas Price","tags":["gas","price","evm","multichain","onchain"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/tx/status","description":"Whether a transaction succeeded or reverted, with block number, sender, recipient, gas used, deployed contract address and log count. A transaction still in the mempool comes back with status pending and found true; one that was never broadcast comes back not-found with found false. Those used to be the same answer, and telling them apart is the whole point of polling, because it decides whether to keep waiting or to resubmit, and resubmitting something that is actually pending is how a nonce gets stuck. Chains: ethereum, base, arbitrum, optimism, polygon. Defaults to base. Flat $0.0015 per call, no account, no API key. e.g. POST with {hash:\"0x...\", chain:\"base\"}. Returns JSON.","mimeType":"application/json","serviceName":"Transaction Status","tags":["transaction","receipt","status","reverted","evm"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/inventory/ens/availability","description":"Registration status for up to 20 .eth names in one call: available, registered, in the 90 day grace period, or inside the 21 day premium auction. Returns the expiry, when the grace and premium windows end, the current dutch auction premium in dollars, and how many seconds until the status changes so you know when to ask again. A name in its premium window reprices every block, so this is a quote with a short shelf life rather than a stable price. Read straight from the ENS registrar on Ethereum, no third party index. Priced at $0.001 per distinct name, so the cost matches the work and repeating a name in one request is only charged once. No account, no API key. e.g. POST with {names:[\"vitalik\",\"foo.eth\"]}. Returns JSON.","mimeType":"application/json","serviceName":"ENS Availability and Premium","tags":["ens","domain","availability","expiry","premium"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/inventory/ens/appraise","description":"Desirability signals for up to 20 .eth names: length tier, numeric only, letters only, palindrome, repeating characters, separators, and non ASCII characters that render inconsistently and are a known phishing vector. Returns the individual signals, notes in plain language, and a 0-100 score. These are signals, not a valuation: nobody can price a name from its characters alone, and a number presented as a price would be one we cannot stand behind. Use it to rank a list, not to decide what to pay. Pure computation, no chain calls, answers in milliseconds. Flat $0.001 per call regardless of how many names you send. No account, no API key. e.g. POST with {names:[\"abc\",\"0007\",\"my-name\"]}. Returns JSON.","mimeType":"application/json","serviceName":"ENS Name Trait Signals","tags":["ens","domain","appraisal","signals","inventory"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/token/allowance","description":"How much a spender is allowed to move on an owner behalf for a given ERC-20, returned raw and formatted with the symbol and decimals resolved in the same call. Flags unlimited approvals explicitly with isUnlimited instead of making you compare against 2^256-1. An unlimited approval is the most common way funds are drained long after the transaction that granted it, and no wallet surfaces it until it is used. Chains: ethereum, base, arbitrum, optimism, polygon. Defaults to base. Flat $0.0015 per call, no account, no API key. e.g. POST with {token:\"0x8335...\", owner:\"0xd8dA...\", spender:\"0x0000...22D4\"}. Returns JSON.","mimeType":"application/json","serviceName":"ERC-20 Allowance and Approvals","tags":["erc20","allowance","approval","unlimited","security"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/address/balances","description":"Native token balance for one address on several EVM chains in a single call, raw and formatted, with the native symbol per chain. An agent deciding where it can afford to act needs them together; this removes the five round trips and the stitching. Chains that fail to answer come back with an error field instead of failing the whole call, and a response where every chain failed is not charged. Available: ethereum, base, arbitrum, optimism, polygon. Defaults to all five. Flat $0.002 per call, no account, no API key. e.g. POST with {address:\"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\"}. Returns JSON.","mimeType":"application/json","serviceName":"Native Balance Across Chains","tags":["balance","native","multichain","wallet","evm"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/oracle/price","description":"Read a Chainlink price feed directly from the chain and get the price along with how old it is. Pass a well-known pair like ETH/USD, BTC/USD, USDC/USD, DAI/USD or LINK/USD, or any feed address on Ethereum, Base, Arbitrum, Optimism or Polygon. Returns the scaled price, the raw answer and decimals, the feed description read from the contract itself, the round id, updatedAt, ageSeconds and a stale flag. The age is the point: feeds update on a deviation threshold or a heartbeat, so a quiet market means a price that has not been written for hours, and that is what turns into a bad decision when nobody checks. Measured live: ETH/USD comes back seconds to minutes old while USDC/USD ran over 17 hours old and was perfectly healthy, so pass staleAfterSeconds for your pair rather than trusting one threshold for all of them. This is the number on-chain contracts actually use, which is not always the exchange price. No account, no API key. e.g. POST with {pair:\"ETH/USD\",chain:\"ethereum\"}. Returns JSON.","mimeType":"application/json","serviceName":"Chainlink Price Feed Reader","tags":["chainlink","oracle","price","defi","feed"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/signature/verify","description":"Check whether an address signed a message, covering both plain accounts and smart contract wallets. Pass a message for EIP-191 personal_sign, or a precomputed 32 byte digest for EIP-712 typed data. For a normal account the signature is recovered and compared; for an address holding code the contract is asked through EIP-1271, which is what Safe and account abstraction wallets use and what an ecrecover-only check gets wrong, telling a legitimate user their signature is fake. The response says which path answered, the address actually recovered, whether the address is a contract, and a malleable flag for high-s signatures that have a valid twin. Failures come back with a reason instead of a bare false, so a typo is distinguishable from an attack. Works on Ethereum, Base, Arbitrum, Optimism and Polygon. No account, no API key. e.g. POST with {address,signature,message}. Returns JSON.","mimeType":"application/json","serviceName":"EOA and Smart Wallet Signatures","tags":["signature","verify","siwe","eip1271","eip712"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/block/info","description":"Read a block from Ethereum, Base, Arbitrum, Optimism or Polygon by number, or the latest one. Returns the hash, parent hash, timestamp, transaction count, gas used and limit, the base fee in both wei and gwei, the miner and the size. Two derived fields are included because they are what the raw numbers are usually for: ageSeconds, which tells you at a glance whether the chain is producing blocks or has stalled, and gasUsedRatio, which is congestion as a fraction of the limit rather than two large integers to divide yourself. A block that does not exist yet comes back null instead of erroring, so you can poll for one safely. Flat $0.001 per call, no account, no API key. e.g. POST with {chain:\"base\"} for the latest block. Returns JSON.","mimeType":"application/json","serviceName":"Block Info","tags":["block","ethereum","base","gas","basefee"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/tx/decode","description":"Decode the calldata of a transaction into a readable method and arguments, with no RPC and no chain needed: pass the hex and get the four byte selector, the matched signature, the decoded static arguments and the raw 32 byte words. It flags unlimitedApproval when the call grants an effectively infinite ERC-20 allowance or a blanket setApprovalForAll, which is how funds get drained long after the transaction that granted it and which nothing in the raw hex makes look unusual. The signature table is short and curated on purpose rather than scraped from a public registry, because those accept submissions and colliding selectors have been planted to make an approval read as something harmless. Dynamic arguments are reported as offsets instead of being guessed at, and the raw words are always returned so nothing is hidden. Flat $0.001 per call, no account, no API key. e.g. POST with {data:\"0xa9059cbb...\"}. Returns JSON.","mimeType":"application/json","serviceName":"Transaction Calldata Decoder","tags":["calldata","decode","abi","selector","approval"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/search/metadata","description":"Give it a URL and get everything the page declares about itself: title, description, canonical URL, language, site name, preview image, favicon, author, published date, all Open Graph and Twitter card tags, parsed JSON-LD blocks and RSS or Atom feeds. No model is involved, so the answer is parsed rather than inferred: it cannot hallucinate a title and it is the same every time. Relative URLs are resolved against the final URL after redirects, not the requested one, which is what makes preview images point at the right host. Invalid JSON-LD blocks are skipped instead of failing the call, and og tags published under the wrong attribute are still picked up. Requests are made through an egress policy that refuses private and internal addresses. Flat $0.002 per call, no account, no API key. e.g. POST with {url:\"https://stripe.com\"}. Returns JSON.","mimeType":"application/json","serviceName":"Page Metadata and Link Preview","tags":["metadata","opengraph","preview","unfurl","jsonld"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/research/claims","description":"Pull the checkable claims out of a document and get each one back with the exact span of the text it came from. Send text, HTML or a URL. Every claim carries its subject, who the document attributes it to, and a kind: fact, statistic, quote, prediction or opinion, because a measured number and a forecast about next year warrant completely different treatment and collapsing them is how a prediction ends up cited as a fact. The per-field provenance is the point: a claim with no source span is model output wearing a citation, and anything produced rather than copied is listed in ungrounded so you can see it. Useful for fact checking, diligence, monitoring what a company says about itself, and feeding a verification pipeline that needs to cite. Priced on the cleaned page size, not the raw one, and a response that does not validate is not charged. No account, no API key. e.g. POST with {source:{type:\"url\",value:\"https://...\"}}. Returns JSON.","mimeType":"application/json","serviceName":"Claims with Source Spans","tags":["claims","factcheck","research","provenance","citations"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/research/timeline","description":"Turn a document into a sorted timeline of dated events. Send text, HTML or a URL and get each event with the date exactly as printed, an ISO 8601 normalisation when the date is unambiguous, a description, the actors involved, and the span of the source it was read from. Events that carry a normalised date are sorted; the ones too vague to place keep their original wording and are returned separately rather than being given an invented date, because a guessed date sorts confidently into the wrong place and nothing downstream can tell. Useful for company histories, incident reconstruction, regulatory filings, litigation chronologies and changelogs. Priced on the cleaned page size, not the raw one. No account, no API key. e.g. POST with {source:{type:\"url\",value:\"https://...\"}}. Returns JSON.","mimeType":"application/json","serviceName":"Document Timeline Extraction","tags":["timeline","events","chronology","research","dates"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/research/compare","description":"Ask the same questions of several documents and get the answers side by side. Send two to twenty sources as text, HTML or URLs plus one JSON Schema, and every source is extracted against it and pivoted into a per-field comparison table. The disagreements list is the point: it names the fields where sources report different values, which is the finding, as opposed to a pile of JSON that happens to differ. The comparison is textual, not semantic, so \"$20 per month\" and \"$20/month\" are reported as a disagreement: it is a shortlist of what to look at, not a verdict. Every value keeps the span of the document it came from, so a disagreement can be traced back to the sentence on each side. Useful for vendor and pricing comparisons, competitive research, spec sheets, and reconciling numbers across filings or reports. One source failing does not sink the rest and only the ones that validated are charged. Priced on cleaned size, no account, no API key. Returns JSON.","mimeType":"application/json","serviceName":"Compare Sources on One Schema","tags":["compare","research","competitive","pricing","vendors"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/inventory/domain/availability","description":"Check whether a domain is registered and get its full registration record: registrar, creation, update and expiry dates, days to expiry, EPP status codes, nameservers and DNSSEC. Read from the authoritative RDAP registry for the TLD, with DNS as corroboration. The important part is what it refuses to guess: the common shortcut of asking a bootstrap redirector and treating 404 as available reports every .io and .co domain as free, because those TLDs publish no RDAP service and the 404 means \"I do not know where to ask\". Here the IANA bootstrap is resolved first, so a TLD with no RDAP service returns status unknown with authoritative false rather than a confident wrong answer about whether a name can be bought. DNS can prove a domain is in use but never that it is free, and that asymmetry is reflected in the result. No account, no API key. e.g. POST with {domain:\"example.com\"}. Returns JSON.","mimeType":"application/json","serviceName":"Domain Availability and Whois","tags":["domain","availability","rdap","whois","dns"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/inventory/domain/bulk","description":"Check up to 25 domains in one request and get the registration status of each. Built for the actual job: running a naming shortlist, or the same name across many TLDs, without sending 25 requests. Every domain is checked against the authoritative RDAP registry for its TLD with DNS as corroboration, and any TLD that publishes no RDAP service comes back as unknown with authoritative false rather than being reported as free, which is what the usual 404 shortcut does to every .io and .co name. The response groups results into available, registered and unknown so a shortlist can be acted on directly, and it is priced per domain rather than flat, so the cost matches the work. One domain failing does not sink the rest. No account, no API key. e.g. POST with {domains:[\"a.com\",\"b.dev\"]}. Returns JSON.","mimeType":"application/json","serviceName":"Bulk Domain Availability","tags":["domain","bulk","availability","rdap","naming"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/social/company/tech","description":"Give it a domain and get what the site is built with: framework, CMS, ecommerce platform, hosting, CDN, analytics, payments, support and marketing tools. Detected from literal markers in the HTML and from HTTP response headers, with no model involved, so it cannot invent a technology and the answer is identical on every call. Every detection carries the evidence that produced it, so a weak signal can be judged instead of trusted. Absence is never reported as \"they do not use it\": a tool can leave no trace on a home page, so this is evidence rather than an inventory. Useful for prospecting, competitive research, partner and integration discovery, and qualifying a lead list before spending on it. Requests go through an egress policy that refuses private and internal addresses. Flat $0.002 per call, no account, no API key. e.g. POST with {domain:\"stripe.com\"}. Returns JSON.","mimeType":"application/json","serviceName":"Website Technology Stack","tags":["techstack","builtwith","prospecting","enrichment","competitive"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/social/company/email","description":"Everything a domain publishes about its email: whether it can receive mail at all, its MX records, which provider hosts them, and its SPF and DMARC records parsed rather than returned raw. Reports the SPF policy from the qualifier on all, the DMARC policy and the percentage it applies to, and a spoofingProtection score from 0 to 100 that says how hard it is to send mail pretending to be this domain. Notes call out the cases that look like protection and are not, such as an SPF record ending in +all, which authorises the entire internet to send as the domain, or DMARC at p=none, which only asks for reports and blocks nothing. It deliberately does not verify individual mailboxes: that means probing a stranger SMTP server, most providers answer the same for every address, and the result would be noise sold as a fact. Useful for lead qualification, deliverability audits, security review and vendor diligence. Flat $0.001 per call, no account, no API key. e.g. POST with {domain:\"stripe.com\"}. Returns JSON.","mimeType":"application/json","serviceName":"Domain Email and Anti-Spoofing","tags":["email","dns","mx","spf","dmarc"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/tx/simulate","description":"Dry-run a transaction before sending it and find out whether it would succeed, and if not, why. Send the target, the calldata, optionally a sender, a value and a block, and get back success, the return data and a gas estimate, or a decoded revert. The decoding is the point: a raw eth_call returns an ABI-encoded blob on failure, so a missing allowance and a slippage check look identical, and the only way left to tell them apart is to send the transaction and pay gas to find out. This decodes the three shapes a revert arrives in, Error(string) from require, Panic(uint256) with the compiler code named in words rather than left as 0x11, and custom errors, whose selector is returned rather than a guessed name because the name lives in an ABI we do not have. The raw revert data always comes back so you can decode what we did not. Works on Ethereum, Base, Arbitrum, Optimism and Polygon, against latest or any historical block. No account, no API key. e.g. POST with {chain,to,data}. Returns JSON.","mimeType":"application/json","serviceName":"Simulation with Decoded Reverts","tags":["simulate","transaction","revert","ethcall","gas"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/signing/explain","description":"Find out what a transaction actually does to your balances before you sign it. Send the chain, the sender, the target and the calldata, and get back the net balance change per asset with symbols and decimals applied, every allowance the call grants with its spender and whether it is unlimited, any change of contract ownership, and every contract the call touched. The amounts come from simulating the transaction and netting the resulting transfer events, not from reading the calldata, which is the difference that matters: decoding tells you a router was called, simulating tells you four tokens moved through three contracts and which of them were yours. It works on calls nobody published an ABI for, because the events are emitted either way. Native value is tracked alongside tokens. It reports facts and never a verdict: there is no safe flag, because whether a transfer is theft depends on intent, which no trace contains. A transaction that would revert is reported as such with the reason. Works on Ethereum, Base, Arbitrum, Optimism and Polygon. No account, no API key. e.g. POST with {chain,from,to,data}. Returns JSON.","mimeType":"application/json","serviceName":"Transaction Clear Signing","tags":["signing","simulate","approval","transaction","wallet"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/search/readable","description":"Give it a URL and get the article text with the navigation, cookie banners, sidebars and footers removed, ready to feed into something else. No model is involved, so it costs no inference, cannot invent a sentence and returns the same text every time. Comes back with the title, the word and character counts, an estimated reading time, the cleaning strategy that produced it and how much of the raw page survived, so you can judge the quality rather than trust it. Measured on real pages, readability-based cleaning produces 38 percent fewer tokens than a regex strip at the same accuracy, which is what makes this worth doing before you pay a model somewhere else. Use the extraction service instead when you want a schema filled rather than the prose. Requests go through an egress policy that refuses private and internal addresses. Flat $0.002 per call, no account, no API key. e.g. POST with {url:\"https://example.com/post\"}. Returns JSON.","mimeType":"application/json","serviceName":"Readable Article Text","tags":["readable","article","text","extract","boilerplate"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/search/links","description":"Every link on a page, resolved to absolute URLs and classified as internal, external, social, file, mailto or tel, with the anchor text, the rel attribute and a nofollow flag that covers sponsored and ugc too. Also returns the outbound hosts ranked by how often they are linked, which is the actual question behind most link extraction: who does this site point at. Internal links are excluded from that ranking, because every page links itself dozens of times and including it would put the site at the top of its own outbound footprint. Links are deduplicated by resolved URL, so a home page linked from the logo, the nav and the footer counts once rather than three times. Relative URLs resolve against the final URL after redirects, not the requested one, which is what keeps them pointing at the right host. No model involved, so it is exact and identical on every call. Flat $0.002 per call, no account, no API key. e.g. POST with {url:\"https://example.com\"}. Returns JSON.","mimeType":"application/json","serviceName":"Page Links, Classified","tags":["links","crawl","outbound","backlinks","seo"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/eip712/hash","description":"Compute the EIP-712 digest a wallet would sign for a piece of typed data, along with the domain separator, the struct hash and the canonical type string. Doing this by hand is a pile of exacting detail: referenced structs must be listed alphabetically in the type string, dynamic fields are hashed rather than encoded in place, arrays are the hash of their concatenated members, fixed bytes pad left while numbers pad right, and the domain is a struct of only the fields actually present. Get any of it wrong and nothing errors, you get a well-formed 32 byte value that verifies against nothing. This implementation is checked against the reference vector in EIP-712 itself. Pairs with the signature verification service, which takes a digest as input: compute it here, verify a signature against it there. No private key is accepted, sent or held, and nothing is signed. No account, no API key. e.g. POST with {types,primaryType,domain,message}. Returns JSON.","mimeType":"application/json","serviceName":"EIP-712 Typed Data Hash","tags":["eip712","typeddata","hash","signature","permit"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/social/company/security","description":"Audit the security headers a site sends and get a graded report rather than a dump. Covers Content-Security-Policy, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy and Permissions-Policy, each with what that specific configuration actually achieves. The part a checklist misses is headers that are present and doing nothing: a CSP containing unsafe-inline is close to no policy at all against XSS, and a Referrer-Policy of unsafe-url still leaks query string tokens cross-origin, yet both pass any test that only asks whether the header exists. CSP frame-ancestors is recognised as superseding X-Frame-Options, so a modern site is not marked down for omitting the old header. Also reports headers that disclose the server stack, which is free reconnaissance rather than a vulnerability. Over plain http the grade is capped, because every transport protection is one a network attacker can simply remove. No account, no API key. e.g. POST with {domain:\"stripe.com\"}. Returns JSON.","mimeType":"application/json","serviceName":"Security Headers Audit","tags":["security","headers","csp","hsts","audit"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/social/company/dns","description":"Every DNS record a domain publishes in one call: A, AAAA, NS, MX, TXT and CAA, run in parallel with an absent record reported as absent rather than as an error, which is what makes it safe to run over a list. Identifies the DNS provider from the nameservers, and classifies the TXT records, which is where the interesting things hide: domain verification tokens name the SaaS vendors a company uses, and that is a signal no other single lookup gives. The token values themselves are not returned, only the vendor, because a verification token is a secret whose only purpose is to be possessed. Notes call out an IPv6-only domain, which IPv4 clients cannot reach, and the absence of CAA, which means any certificate authority may issue. No account, no API key. e.g. POST with {domain:\"stripe.com\"}. Returns JSON.","mimeType":"application/json","serviceName":"Full DNS Record Profile","tags":["dns","records","nameservers","caa","txt"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/search/feed","description":"Parse an RSS, Atom or RDF feed into one normalised JSON shape. The three standards answer the same question with different tag names, and the differences are exactly the kind that return null instead of erroring: Atom puts an item URL in a link attribute while RSS puts it in the element text, and the publication date hides behind published, pubDate, updated or date depending on the feed. Every item comes back with title, link resolved to an absolute URL, the date as published and an ISO 8601 normalisation, author, a trimmed summary, id and categories. lastPublished is computed from the newest item rather than the first, because plenty of feeds are ordered oldest first and reading position as recency reports a live feed as abandoned. No model is involved, so it is exact and identical every call. Up to 200 items per request. No account, no API key. e.g. POST with {url:\"https://github.blog/feed/\"}. Returns JSON.","mimeType":"application/json","serviceName":"RSS and Atom Feed Parser","tags":["rss","atom","feed","syndication","monitoring"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/search/sitemap","description":"Parse a sitemap into a URL list, or a robots.txt into the sitemaps it declares. Point it at either: a robots.txt returns the Sitemap lines, which is the only place a site says where its sitemap actually is, and a sitemap returns its entries with lastmod, changefreq and priority. A sitemap index is reported as an index with its child sitemaps listed and NOT followed, because an index can point at hundreds of sitemaps of fifty thousand URLs each and expanding it silently would turn one paid call into a crawl you did not ask for or price. Up to 200 entries per request. Useful for discovering what a site publishes, monitoring what changed by lastmod, and seeding a crawl. No model involved. No account, no API key. e.g. POST with {url:\"https://example.com/robots.txt\"}. Returns JSON.","mimeType":"application/json","serviceName":"Sitemap and robots.txt Parser","tags":["sitemap","robots","crawl","seo","discovery"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/multicall","description":"Send up to 25 eth_call reads in one request, across chains if you like, and get each result back independently. This is the escape hatch for contracts whose interface nobody standardised: pass the target, the calldata and optionally a decode hint of uint, int, bool, address or string, and the raw return data always comes back alongside anything decoded. Nothing is inferred, because 32 bytes of zeros is a valid uint256, a valid bool and a valid address at the same time, so guessing would mean presenting one reading as the truth. One call reverting is reported as that call error rather than failing the request, so a bad address does not cost you the other 24. Results echo the target and calldata, so you can match them without relying on order. Priced per call rather than flat, so the cost matches the work. No account, no API key. Returns JSON.","mimeType":"application/json","serviceName":"Batched Contract Reads","tags":["multicall","batch","ethcall","contract","reads"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/contract/storage","description":"Read raw storage slots from a contract, up to 20 at a time. This is the escape hatch for values that exist in storage and are exposed by no getter, which is the normal situation for anything a contract author did not intend to publish. Named slots are accepted so you do not have to carry the hex: eip1967.implementation, eip1967.admin, eip1967.beacon and eip1822.proxiable, which are fixed by standard and therefore mean the same in every contract that uses them. Each slot comes back as the raw 32 bytes plus readings as an address and as an unsigned integer, and a zero flag, because the same 32 bytes are a valid address and a valid number at once and only you know which it is. Works on Ethereum, Base, Arbitrum, Optimism and Polygon. No account, no API key. e.g. POST with {address,slots:[\"eip1967.implementation\"]}. Returns JSON.","mimeType":"application/json","serviceName":"Raw Contract Storage","tags":["storage","slot","proxy","eip1967","audit"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/abi/encode","description":"Turn a function signature and its arguments into the calldata you send. Closes the loop with the batched reads and simulation services, which both take calldata: without an encoder an agent has to hardcode hex it cannot adapt. Returns the canonical signature, the four byte selector, the full data and each argument as its own 32 byte word so you can check the encoding. The canonicalisation matters: transfer(address, uint256) with a space, or uint instead of uint256, hashes to a different and entirely valid-looking selector that no contract implements. Only fixed-size types are encoded, which is address, bool, intN, uintN and bytesN. Dynamic types are refused rather than half encoded, because a wrong head and tail layout produces calldata a node will happily execute against the wrong arguments. No account, no API key. e.g. POST with {signature:\"balanceOf(address)\",args:[\"0x…\"]}. Returns JSON.","mimeType":"application/json","serviceName":"ABI Calldata Encoder","tags":["abi","encode","calldata","selector","contract"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/chain/status","description":"The state of every chain side by side: latest block, how many seconds since it was produced, the gas price and the base fee, both in gwei. Defaults to all five of Ethereum, Base, Arbitrum, Optimism and Polygon, or pass the ones you care about. blockAgeSeconds is the field that matters: it is how you tell a chain that is producing blocks from one that has stalled, and it is the check most callers skip because it needs a timestamp compared against your own clock. A chain that cannot be reached is reported as ok false with its error, next to the ones that answered, rather than failing the request, because an agent deciding where it can afford to act needs the ones that did answer. Flat price whatever the number of chains, since it is one read each and they run in parallel. No account, no API key. e.g. POST with {} for all five. Returns JSON.","mimeType":"application/json","serviceName":"Multichain Health and Gas","tags":["chain","status","health","gas","basefee"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/contract/logs","description":"Read the events a contract emitted over a recent block range. Pass the address and optionally a block range and topic filters, where topics[0] is the event signature hash and the rest are indexed arguments, with null as a wildcard in any position. The range is capped at 2000 blocks and the cap is in the response, so you page by moving fromBlock yourself. That is deliberate: eth_getLogs is the one method that costs a provider real money, and every public endpoint bounds it differently, some by range, some by result count, some by timing out. An unbounded range would make this fail unpredictably depending on which endpoint answered, which is worse than failing consistently. Logs removed by a reorg are reported with a removed flag rather than filtered out, so state reconciliation can tell the two cases apart. A busy contract that exceeds the provider result limit is retried automatically at the smaller range the provider itself names, and narrowedTo reports the window that was actually covered, so you get data instead of an error and still know the window moved. Works on Ethereum, Base, Arbitrum, Optimism and Polygon. No account, no API key. e.g. POST with {chain,address}. Returns JSON.","mimeType":"application/json","serviceName":"Recent Contract Event Logs","tags":["logs","events","getlogs","topics","contract"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/search/diff","description":"Diff two versions of a page or two pieces of text and get what was added and removed. Send URLs, HTML or text for before and after. Both sides are cleaned before comparing, which is what makes this usable for monitoring: an HTML diff of two fetches of the same unchanged page is enormous, because build hashes, CSRF tokens, timestamps and rotating ad slots all change on every request, so a monitor would fire every time. Cleaning removes exactly that layer and leaves the change a person would have noticed. The trade is that a change only in markup is invisible, which is the right way round here. Whitespace is collapsed before comparing for the same reason. Returns a changed flag, a similarity score, the added and removed lines with their positions, and counts. No model is involved. Up to 100 changes of each kind are listed and the rest are counted in truncated, so nothing is silently dropped. No account, no API key. e.g. POST with {before,after}. Returns JSON.","mimeType":"application/json","serviceName":"Compare Two Pages or Documents","tags":["diff","compare","monitoring","changes","versions"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/search/classify","description":"Sort a document into labels you define. Send text, HTML or a URL plus your list of up to 20 labels, and get back which ones apply, with a confidence and the reasoning. Set multi to allow more than one. The labels are yours on purpose: the job is routing a document into categories that exist in someone else system, a support queue, a lead status, a content type, and nobody wants a fixed taxonomy for that. The important part is that none is always an allowed answer. A classifier forced to choose from a list always chooses, so a document that fits nothing gets assigned confidently to whichever label is least wrong, and that failure is invisible downstream because a wrong label looks exactly like a right one. Useful for triage, routing, tagging a corpus and filtering a crawl. Priced on the cleaned page size, not the raw one, and a response that does not validate is not charged. No account, no API key. e.g. POST with {labels,source}. Returns JSON.","mimeType":"application/json","serviceName":"Classify into Your Own Labels","tags":["classify","labels","routing","triage","tagging"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/research/entities","description":"Pull the people, organisations, locations, products, amounts and dates out of a document, each with the exact span of the text it came from. Send text, HTML or a URL. Every entity carries its kind, the role it plays in the document in the document own terms rather than a fixed taxonomy, and the other surface forms it appears under so you can deduplicate \"Acme Corp\" and \"Acme\" without guessing. The provenance is the point: an entity with no source span is a name the model produced, and there is no way to tell that apart after the fact. Fields the model judged rather than quoted are reported separately in derived, so ungrounded keeps meaning content that should have been quoted and was not. Useful for building a knowledge graph, screening documents for parties, and feeding a pipeline that has to cite. Priced on the cleaned page size, and a response that does not validate is not charged. No account, no API key. e.g. POST with {source:{type:\"url\",value:\"https://...\"}}. Returns JSON.","mimeType":"application/json","serviceName":"Named Entities with Source Spans","tags":["entities","ner","research","provenance","knowledge"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/research/summarize","description":"Turn a document into a structured summary rather than a paragraph: a one sentence headline, standalone key points, the takeaway when the document implies one, its topics and who it is written for. Send text, HTML or a URL. The key points are phrased to stand alone, because a bullet that only makes sense next to the one above it is useless in a digest, which is where these end up. Provenance comes back for every field, and every field is reported as derived rather than ungrounded: a summary is written, not quoted, so flagging it as unsourced on every call would be a warning that carries no information. Useful for digests, triage over a reading list, and putting a readable label on a corpus before deciding what to read. Priced on the cleaned page size, not the raw one, and a response that does not validate is not charged. No account, no API key. e.g. POST with {source:{type:\"url\",value:\"https://...\"}}. Returns JSON.","mimeType":"application/json","serviceName":"Structured Document Summary","tags":["summary","digest","research","triage","keypoints"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/research/qa","description":"Ask a question about a document and get the answer along with the sentence it came from. Send text, HTML or a URL plus your question. The difference from pasting a page into a model yourself is the check: the answer must name the sentence it used, and that quote is then located in the source and scored, so an invented one does not pass as sourced. There is also an answered flag, because a model asked about something a page does not cover will answer anyway, confidently, from its own knowledge, and that response is otherwise indistinguishable from a real one. When answered is false the answer says so instead of guessing. Useful for document triage, diligence, compliance checks and any pipeline that has to show where a fact came from. Priced on the cleaned page size, not the raw one, and a response that does not validate is not charged. No account, no API key. e.g. POST with {question,source}. Returns JSON.","mimeType":"application/json","serviceName":"Answer a Question with the Quote","tags":["qa","question","answer","citation","research"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/inventory/domain/variants","description":"Give it a name and get where that name is available. Checks up to 25 TLDs, defaulting to com, net, org, io, dev, app, ai, co, xyz and sh, or pass your own list. Every combination is checked against the authoritative RDAP registry for that TLD with DNS as corroboration, and any TLD publishing no RDAP service comes back as unknown with authoritative false rather than being reported as free. That distinction matters more here than anywhere: io and co are both in the usual shortlist and both absent from the IANA bootstrap, so the naive version of this endpoint would tell you your brand is available on the two TLDs people most want it on. Results are grouped into available, registered and unknown so the shortlist can be acted on directly. Priced per domain checked rather than flat. No account, no API key. e.g. POST with {name:\"acme\"}. Returns JSON.","mimeType":"application/json","serviceName":"One Name Across Many TLDs","tags":["domain","naming","availability","tld","brand"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/social/company/profile","description":"One call for everything this catalogue knows about a domain: the technology stack detected from HTML and header markers, the mail posture from MX, SPF and DMARC with a spoofing score, the full DNS profile including which SaaS vendors the domain is verified with, and a graded security headers audit. Built because these four are almost always wanted together, and asking separately is four round trips and four payments to answer one question. No model is involved in any of them, so the whole profile is parsed rather than inferred and is identical on every call. The four run in parallel and any one failing is reported in that section rather than sinking the request, so a domain that serves no website still returns its DNS and mail posture. The price is the sum of the four parts, with no discount: the work is the work, and pricing a bundle below its cost means funding it from the individual prices. No account, no API key. e.g. POST with {domain:\"stripe.com\"}. Returns JSON.","mimeType":"application/json","serviceName":"Full Company Technical Profile","tags":["company","profile","enrichment","diligence","b2b"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/crypto/nft/info","description":"Detect whether a contract is ERC-721, ERC-1155 or neither, with its name and symbol, and optionally the owner and tokenURI for a specific token id. Contracts that predate supportsInterface or implement it wrong are not written off: the check falls back to reading name and symbol before concluding an address is not a token. A token id with no owner comes back with exists false, so unminted and burned are distinguishable from an error. Chains: ethereum, base, arbitrum, optimism, polygon. Defaults to base. Flat $0.002 per call, no account, no API key. e.g. POST with {address:\"0xBC4CA...\", tokenId:\"1\", chain:\"ethereum\"}. Returns JSON.","mimeType":"application/json","serviceName":"NFT Contract and Token Info","tags":["nft","erc721","erc1155","token","owner"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/social/identity/resolve","description":"Every identity an EVM address can prove, in one call: its ENS name with a forward verification, and its Farcaster id and username read from the on-chain registry rather than an indexer. Each lookup reports ok, none or error separately, so a partial answer is readable instead of ambiguous. A Farcaster custody address is usually not the address a person is known by, so no fid does not mean no account, and the response says so. Flat $0.0025 per call, no account, no API key. e.g. POST with {address:\"0x6b0bda3f2ffed5efc83fa8c024acff1dd45793f1\"}. Returns JSON.","mimeType":"application/json","serviceName":"Cross-Protocol Identity","tags":["identity","ens","farcaster","address","social"]},"accepts":[]},{"resource":{"url":"https://api.cospel.dev/v1/social/company/enrich","description":"Give it a domain and get a structured company profile: name, description, industry, headquarters, founding year, employee range, products, and contact and social handles. Every field comes back with per-field provenance, the exact span of the page it was read from and a match quality, and anything the model produced rather than copied is listed in ungrounded. Enrichment output gets written into a CRM and trusted forever, so being able to point at the sentence is the difference between data and a guess. Fields that are not on the page come back null instead of being invented, and a profile that does not validate is not charged. Priced on the cleaned page size, not the raw one. No account, no API key. e.g. POST with {domain:\"stripe.com\"}. Returns JSON.","mimeType":"application/json","serviceName":"Company Profile from a Domain","tags":["company","enrichment","domain","firmographics","crm"]},"accepts":[]}]}