<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: teppi-xyz</title>
    <description>The latest articles on DEV Community by teppi-xyz (@teppixyz).</description>
    <link>https://dev.to/teppixyz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4212393%2Fa694c1f5-4d27-4430-b675-a58b867e0c25.png</url>
      <title>DEV Community: teppi-xyz</title>
      <link>https://dev.to/teppixyz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/teppixyz"/>
    <language>en</language>
    <item>
      <title>A 2xx Is Not a Delivery</title>
      <dc:creator>teppi-xyz</dc:creator>
      <pubDate>Wed, 28 Oct 2026 07:26:09 +0000</pubDate>
      <link>https://dev.to/teppixyz/a-2xx-is-not-a-delivery-6l9</link>
      <guid>https://dev.to/teppixyz/a-2xx-is-not-a-delivery-6l9</guid>
      <description>&lt;p&gt;&lt;strong&gt;We paid 422 x402 APIs 3,618 times and checked every answer. 69 were wrong, and every one was billed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A transaction hash proves money moved. Nothing records whether anything came back for it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;x402 lets an agent pay for an API call with a stablecoin in the same HTTP request: the server answers &lt;code&gt;402 Payment Required&lt;/code&gt;, the client signs a payment, the server settles it and returns the answer. By the time the answer arrives the money has moved, and nothing in the protocol ever reads the answer. A &lt;code&gt;200 OK&lt;/code&gt; means the seller replied. It does not mean the reply was right.&lt;/p&gt;

&lt;p&gt;So we measured it. From 31 August to 28 October 2026 we paid 422 x402 endpoints on 355 hosts, 3,618 times, at their listed prices, and held every answer to a check the seller could not see.&lt;/p&gt;

&lt;h3&gt;
  
  
  What came back
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Calls&lt;/th&gt;
&lt;th&gt;Share&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;td&gt;3,618&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Answered 2xx&lt;/td&gt;
&lt;td&gt;3,434&lt;/td&gt;
&lt;td&gt;94.9% of paid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Could be checked against an independent answer&lt;/td&gt;
&lt;td&gt;2,695&lt;/td&gt;
&lt;td&gt;78.5% of 2xx&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Answered 2xx and wrong&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;69&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2.6% of checked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Answered 2xx with nothing to check against&lt;/td&gt;
&lt;td&gt;739&lt;/td&gt;
&lt;td&gt;21.5% of 2xx&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No usable answer (error status, timeout, broken body)&lt;/td&gt;
&lt;td&gt;184&lt;/td&gt;
&lt;td&gt;5.1% of paid&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two facts in that table matter more than the rate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every one of the 69 wrong answers was billed.&lt;/strong&gt; Not most: all 69 settled. In x402 a wrong answer costs exactly what a right one does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Money moved for 144 calls that delivered nothing usable&lt;/strong&gt;: the 69 wrong answers, 64 calls that returned an error or nothing at all after the payment settled, and 11 that answered 2xx with a body that could not be used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrong answers cluster where checking is hard
&lt;/h3&gt;

&lt;p&gt;Endpoints that report a public fact were almost never wrong: price feeds, chain reads and code runs gave &lt;strong&gt;2 wrong answers in 1,133 checked&lt;/strong&gt;. Endpoints that do judgment work were wrong far more often:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Class&lt;/th&gt;
&lt;th&gt;Checked&lt;/th&gt;
&lt;th&gt;Wrong&lt;/th&gt;
&lt;th&gt;Share&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;research&lt;/td&gt;
&lt;td&gt;159&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;10.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;inference&lt;/td&gt;
&lt;td&gt;239&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;5.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;extraction&lt;/td&gt;
&lt;td&gt;240&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;5.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;search&lt;/td&gt;
&lt;td&gt;554&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;4.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;market data, onchain, compute&lt;/td&gt;
&lt;td&gt;1,133&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is the uncomfortable shape for agent builders: the calls an agent is least able to verify itself are the ones most likely to be wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three cases, each with its transaction
&lt;/h3&gt;

&lt;p&gt;Every case below links to the published evidence: the request, the response hash, the settlement transaction and the check that ran. A seller who disagrees can publish its own probe in the same format, and it appears beside ours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. A search that ignored the query.&lt;/strong&gt; A Federal Register search endpoint was asked for documents on a named regulation. Its answer echoed &lt;code&gt;"term": null&lt;/code&gt;, reported 10,000 available results and returned the day's newest documents, none of them about the question. It did this on 5 of the 6 calls we could check, between 27 and 28 October, at $0.005 each, every one settled. &lt;a href="https://teppi.xyz/evidence/sha256:46a732bd4e136e520a9705e4af76316f3ed4528b84bff6692009821ebb48eac7" rel="noopener noreferrer"&gt;Evidence&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A number that froze for sixteen days.&lt;/strong&gt; A market index endpoint returned &lt;strong&gt;24,427&lt;/strong&gt; on every call from 3 to 19 October. Over the same days the public source it reports rose from 24,520 to a peak of 46,341. Ten of those answers were outside tolerance and every one was billed. Nothing about the response looked broken: right shape, right field, a plausible number. &lt;a href="https://teppi.xyz/evidence/sha256:181b2fdfb1437efe1fcffa5d352d0a69478ffba6ddef906fe5ee3406260671e7" rel="noopener noreferrer"&gt;Evidence&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Paid, then 503.&lt;/strong&gt; An LLM endpoint settled our $0.002525 payment and answered &lt;code&gt;503 Service Unavailable&lt;/code&gt; with an error body. The payment is on Base: &lt;a href="https://basescan.org/tx/0x101d46161da5e2d89a08b7cdc35bb4127a4b71cf5b6a66ee512b6fb871a4c4e7" rel="noopener noreferrer"&gt;&lt;code&gt;0x101d4616…a4c4e7&lt;/code&gt;&lt;/a&gt;. &lt;a href="https://teppi.xyz/evidence/sha256:bdfb2c621a3b6fa62be324f659fcca61b9c0dc43b2d26f6fb807b74b69ad70b2" rel="noopener noreferrer"&gt;Evidence&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How an answer is checked
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Held-out answers.&lt;/strong&gt; For each endpoint we write tasks whose answer we know and the seller never sees: an RFC number that must appear among search results, a sum a chat model must get right, a sentence that must appear in a fetched page. The task's expected answer is never published; the request and the response are.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Questions written at call time.&lt;/strong&gt; For endpoints that report a public fact, the question is generated at the moment of the call from recent chain activity, and the true value is read from two independent nodes at the same block (or the median of three exchanges within 0.3%). A seller cannot prepare for a question that did not exist before the call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agreement with a public source.&lt;/strong&gt; Index and feed values are compared with the source they claim to report, fetched at call time, within a stated tolerance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unknown stays unknown.&lt;/strong&gt; If there is nothing to check an answer against, it is counted as unchecked, never as right. That is the 739.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What this does not say
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The sample leans toward sellers that work.&lt;/strong&gt; Tasks are written for endpoints that answered at least once, so endpoints that never worked are under-represented in the checked set.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Probes are recognisable.&lt;/strong&gt; Payments come from a pool of wallets funded from one address; a seller who looks can tell. A seller that behaves only when watched would look better here than it is, not worse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;We get things wrong too.&lt;/strong&gt; This month we found 35 answers we had scored wrong that were right: one seller streams its reply unless asked not to, and our tasks for it did not ask. They are withdrawn by a published correction that names each record, not deleted. 168 calls are withdrawn this way in all, and none of them is in the figures above.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why this matters now
&lt;/h3&gt;

&lt;p&gt;Agents are being given wallets. &lt;a href="https://aws.amazon.com/blogs/machine-learning/agents-that-transact-introducing-amazon-bedrock-agentcore-payments-built-with-coinbase-and-stripe/" rel="noopener noreferrer"&gt;Amazon Bedrock AgentCore Payments&lt;/a&gt; (built with Coinbase and Stripe) lets an agent pay x402 endpoints during a run and offers it more than 10,000 of them to discover. Cloudflare has &lt;a href="https://secure.businesswire.com/news/home/20260804228183/en/Cloudflare-Gives-AI-Agents-an-Identity-and-a-Wallet" rel="noopener noreferrer"&gt;announced capped wallets for agents&lt;/a&gt;. Both put a limit on how much an agent can spend. Neither looks at what it got back.&lt;/p&gt;

&lt;p&gt;A spending limit bounds the loss. It does not stop an agent from paying, again and again, for an answer that is wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  You do not have to take our word for any of it
&lt;/h3&gt;

&lt;p&gt;Every figure in this post is a count over one public file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://api.teppi.xyz/v1/market/records &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; records.ndjson
jq &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s1"&gt;'[.[] | select(.source == "probe" and (.first_party | not) and (.corrected | not))
  | select(.liveness == 1 and .correctness != null and .correctness &amp;lt; 1)] | length'&lt;/span&gt; records.ndjson
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each line is one paid call: the url, the chain, the settlement transaction, every check's score, and a link to its evidence. Pick any line, look its transaction up on Basescan, open the evidence, and rerun the check. The live page is &lt;a href="https://teppi.xyz/report" rel="noopener noreferrer"&gt;teppi.xyz/report&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before an agent pays, it can ask what paying an endpoint delivered: &lt;code&gt;GET https://api.teppi.xyz/v1/check?url=&amp;lt;endpoint&amp;gt;&lt;/code&gt; (signed, free), or put the same check inside the official x402 client with &lt;code&gt;teppiHook&lt;/code&gt; from &lt;a href="https://github.com/teppi-xyz/teppi-client" rel="noopener noreferrer"&gt;&lt;code&gt;teppi-client&lt;/code&gt;&lt;/a&gt;. More at &lt;a href="https://teppi.xyz/check-before-paying" rel="noopener noreferrer"&gt;teppi.xyz/check-before-paying&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>api</category>
      <category>agents</category>
      <category>x402</category>
      <category>payments</category>
    </item>
  </channel>
</rss>
