← AgentPay guides

The x402 envelope bug that quietly tanks your trust score

Published 2026-08-13 · AgentPay (agentpay.tools)

On 12 August 2026 three of our paid endpoints carried a grade of C on a public x402 trust directory, each with a machine-readable recommendation attached: avoid. Downtime wasn't the cause. One missing block in the 402 response body was — and it had failed every probe for thirty days straight.

This is what the bug is, how to check whether your endpoint has it, and how the scores that punish it are actually computed. If you operate an x402 endpoint, the check at the bottom takes about thirty seconds.

Two copies of the truth

An x402 402 Payment Required response carries its payment requirements in two places: the PAYMENT-REQUIRED header (base64 JSON) and the JSON body. Paying clients generally read the header. Indexers, validators and trust directories generally read the body — it is cheaper to parse and it doesn't depend on a header that not every implementation sets.

Our envelope was complete in the header. The body carried error, x402Version, accepts[] and our legacy payment_options — but no top-level resource object. So every validator reading the body reached the same verdict: missing-resource-info.

The measurement was unambiguous once we could see it: 793 probes over 30 days, zero valid envelopes. Payments worked the entire time. Agents paid, tools delivered, receipts settled on-chain. The endpoint was healthy and publicly labelled untrustworthy.

How the score is actually computed

Public directory pages show you a grade. They don't show you which component produced it, which is why this sat unnoticed: a C looks like a reliability problem, so you go hunting through uptime and latency. We bought the paid report instead — half a cent per endpoint, settled over x402 — and it named the component immediately.

With four observations (two endpoints, before and after the fix) the model solves exactly:

score = 0.45 x technicalReliability
      + 0.30 x specCompliance
      + 0.25 x economicReputation

specCompliance = 30 + 70 x (validEnvelopes30d / scoredProbes30d)

grades: A >= 80   B >= 65   C >= 50   D >= 35

That formula is inferred from observation, not published — treat it as a working model rather than gospel, and correct us if your own numbers disagree. But the shape holds, and the shape is the useful part:

componentours, beforewhat it measures
technicalReliability86uptime, weighted with latency
specCompliance30share of probes with a valid envelope
economicReputation47settlement history, payer count, age

An endpoint that was fundamentally healthy — 86 on reliability — sat at 59 overall because one component was pinned at its floor. Compliance is worth 21 points of grade. That is the difference between avoid and an A.

The part that costs you time: it's a trailing window

specCompliance is a ratio over the trailing 30 days, not a current-state check. Fixing the bug does not restore the grade; it starts a thirty-day clock. At roughly 26 probes a day into a 793-probe window, a corrected envelope earns back about 0.7 points of score per day.

So the practical cost of shipping this bug is not the day you find it — it is the month of trailing average you spend climbing out. Every day you leave it unfixed is a day added to the recovery, and the public page caches on top of that. Check yours now rather than next quarter.

Check your own endpoint

Compare what your 402 says in the body against what it says in the header. If the header has resource and the body doesn't, you have this bug:

curl -sD /tmp/h -o /tmp/b https://your-endpoint.example/your/tool

# what validators and directories read:
jq 'keys' /tmp/b

# what paying SDK clients read:
grep -i '^payment-required:' /tmp/h | cut -d' ' -f2 | tr -d '\r' | base64 -d | jq 'keys'

Both lists should contain resource. While you're there, confirm the body's accepts[] entry carries the standard field names (payTo, maxAmountRequired, asset, network) — a generic payer that can't find those will silently skip your endpoint too, and that failure never appears in your logs as an error.

The fix

It is additive. Nothing is renamed, nothing is removed, and no existing client changes behaviour — you are giving body-readers what header-readers already had:

{
  "x402Version": 2,
  "error": "Payment required",
  "accepts": [ ... ],
+ "resource": {
+   "url":         "https://your-endpoint.example/your/tool",
+   "serviceName": "What you sell",
+   "description": "One clear sentence",
+   "mimeType":    "application/json"
+ }
}

The more durable half of the fix is structural: build the envelope once and emit it to both places, then assert in a test that the body is a superset of the header. This was our third bug in that family — standard fields reaching only the header, then one tool serving two different envelopes on two paths, now this. All three have the same root shape: two copies of the truth, drifting quietly, with only one of them being watched.

Did it work?

Same paid probe, 85 minutes apart, one deploy in between:

18:33 UTC19:58 UTC
valid envelopes (30d)0 / 7931 / 793
flagsenvelope-noncompliantcleared
recommendationavoidcaution

The public grade didn't move that day and won't for a while — trailing window, plus a 24-hour cache on the free page. That is expected, and it is worth writing down somewhere your future self will find it, because the natural instinct a week later is to conclude the fix didn't work and go re-diagnose a solved problem.

Why this is worth an afternoon

Trust scores are becoming the thing agents route on. An autonomous buyer choosing between two endpoints that both return data will take the one that isn't labelled avoid — and unlike a human, it will never read your documentation to discover that the label was about a JSON field rather than your service. Every report we bought also named a higher-scoring competitor as a suggested alternative. That is what a compliance bug actually costs: not a bad grade, a redirected buyer.

The general rule we'd offer: your 402 is your storefront. If you serve one version of it to SDKs and another to crawlers, you will eventually be graded on the one you weren't watching.

Credit where it's due: the directory's free page told us we had a problem, and its paid report told us what the problem was. Half a cent, settled over x402, to find a bug that thirty days of our own green dashboards had missed. Buying a probe of yourself is cheap; assuming your own surface is fine is not.

What we do with this

AgentPay (agentpay.tools) runs paid probes against x402 endpoints — not just liveness checks, but settle-and-verify runs that confirm a service actually delivers after it takes the money. Those results are public, with receipts:

See the delivery scores →

All tools · x402 delivery scores · Receipt ledger · Guides · llms.txt · AgentPay