DEV Community

Cover image for Domain Trust Scoring for AI Agents — Checking Before You Pay
Surf
Surf

Posted on

Domain Trust Scoring for AI Agents — Checking Before You Pay

AI agents are now spending real money autonomously. Here's how to add a simple trust check before your agent transacts with any domain.

AI agents are spending real money now. The x402 protocol has processed over 165 million transactions across ~69,000 active agents. That's a lot of autonomous USDC flying around to domains your agent has never seen before.

The problem is a pretty natural consequence of that: agents can't easily tell if a domain they're about to pay is legitimate or not. A human glances at a URL and picks up on a dozen signals — the TLD, whether they recognize the registrar, how old the site looks. An agent doing the same thing has to either skip that check entirely or build the verification infrastructure itself.

This post is about how to add a lightweight trust check to your agent before it transacts, using a pay-per-use API on the x402 protocol.


Why this matters

Consider an agent that searches for a service, finds a matching x402 endpoint, and prepares to pay. Without any trust verification, it's essentially trusting that:

  • The domain is what it claims to be
  • It wasn't registered yesterday as a throwaway
  • It has some real operational presence (DNS, mail, etc.)
  • It's using a legitimate registrar

None of that is guaranteed. High-risk domains — .xyz, .tk, .click — cost pennies and are disproportionately used in phishing and fraud. A domain registered three weeks ago with no MX records and an obscure registrar is a different risk profile than api.somestablecompany.io that's been around for five years.

A trust check doesn't solve everything. It's one signal among several. But it's a cheap, fast, structured signal your agent can act on before committing funds.


The API

TrustSource is an x402-enabled domain trust scoring API. You send a domain or URL, it returns a 0–100 score, a risk tier, and the underlying signals that drove the score. No API key, no account — it uses x402, so your agent pays 0.003 USDC per query and gets the result.

The full OpenAPI spec is at trustsource.cc/openapi.json if you want the machine-readable version.

Here's what a response looks like:

{
  "domain": "google.com",
  "score": 90,
  "maxScore": 100,
  "tier": "TRUSTED",
  "breakdown": {
    "domainAge": 30,
    "tld": 20,
    "dnsPresence": 30,
    "registrar": 10
  },
  "details": {
    "age": {
      "days": 10477,
      "label": "established (5+ years)",
      "created": "1997-09-15T07:00:00+0000",
      "expires": null
    },
    "tld": ".com",
    "dns": {
      "hasARecord": true,
      "hasMxRecord": true,
      "mxRecords": ["smtp.google.com"]
    },
    "registrar": "markmonitor, inc."
  },
  "meta": {
    "checkedAt": "2026-05-24T10:00:00.000Z",
    "apiVersion": "1.0",
    "paidWith": "x402/USDC",
    "cached": false
  }
}
Enter fullscreen mode Exit fullscreen mode

The four scoring signals:

Signal Max points What it measures
Domain age 30 WHOIS creation date — older = more trusted
TLD 20 .com/.org/.io = trusted, .tk/.xyz/.click = risky
DNS presence 30 Has A record (+20) and MX records (+10)
Registrar 20 Known established registrar vs. unknown

Tiers: TRUSTED (75+) / MODERATE (50–74) / CAUTION (25–49) / HIGH_RISK (0–24)

Results are cached for 1 hour per domain, so repeat lookups are fast and the underlying WHOIS servers don't get hammered.


Integrating with your agent

Your agent needs to handle x402 payments to call this. If you're already using x402 in your stack, adding a trust check is straightforward. Here's a complete example:

import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

// Set up x402 client (your agent's wallet)
const signer = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY);
const client = new x402Client();
registerExactEvmScheme(client, { signer });
const fetchWithPayment = wrapFetchWithPayment(fetch, client);

async function checkTrustBeforePaying(targetUrl) {
  const domain = new URL(targetUrl).hostname;

  // Query trust score — agent pays 0.003 USDC automatically
  const response = await fetchWithPayment(
    `https://trustsource.cc/trustscore?domain=${domain}`
  );
  const trust = await response.json();

  console.log(`${domain}: ${trust.score}/100 (${trust.tier})`);
  return trust;
}

async function agentPurchaseFlow(serviceUrl, purchaseAmount) {
  const trust = await checkTrustBeforePaying(serviceUrl);

  if (trust.tier === "HIGH_RISK") {
    throw new Error(`Aborting: ${trust.domain} is HIGH_RISK (score: ${trust.score})`);
  }

  if (trust.tier === "CAUTION") {
    // Your agent might want to flag this for review rather than abort
    console.warn(`Proceeding with caution: ${trust.domain} scored ${trust.score}/100`);
  }

  // Proceed with the actual purchase...
}
Enter fullscreen mode Exit fullscreen mode

Decision logic patterns

How you act on the score depends on your agent's risk tolerance. A few approaches that make sense depending on context:

Hard block on HIGH_RISK:

if (trust.tier === "HIGH_RISK") {
  return { action: "abort", reason: `Domain scored ${trust.score}/100` };
}
Enter fullscreen mode Exit fullscreen mode

Threshold-based with escalation:

if (trust.score < 50) {
  return { action: "escalate", requiresHumanApproval: true };
} else if (trust.score < 75) {
  return { action: "proceed_with_log", riskFlag: true };
} else {
  return { action: "proceed" };
}
Enter fullscreen mode Exit fullscreen mode

Cost-proportional gating (sensible for variable-cost purchases):

// Require higher trust for larger transactions
const minimumScore = purchaseAmount > 1.00 ? 70 : 50;
if (trust.score < minimumScore) {
  return { action: "abort" };
}
Enter fullscreen mode Exit fullscreen mode

What it doesn't cover

Worth being explicit about the limitations:

  • WHOIS privacy protection — many domains redact registration data under GDPR. When that happens, the age score falls back to 0 ("unknown"). This is a known limitation of the public WHOIS system, not something this API can work around.
  • Recently compromised legitimate domains — a 10-year-old .com with good DNS can still be a phishing site if the domain was hijacked. This API scores structural signals, not content.
  • Very new legitimate services — a startup that launched last month will score low on domain age even if it's completely legitimate. Context matters.

The score is best used as a filter to catch obvious red flags, not as a definitive verdict on any domain.


Using it without x402

If your agent stack doesn't support x402 yet, you can still test it by running the payment manually. Get some Base Sepolia testnet USDC from faucet.circle.com, switch to testnet (NETWORK=eip155:84532, FACILITATOR_URL=https://x402.org/facilitator), and use the example client from the x402 quickstart for buyers.


Resources

If you're building agent payment flows and have thoughts on what other trust signals would be useful, happy to hear them.

Top comments (0)