Skip to content

Latest commit

 

History

History
137 lines (96 loc) · 6.17 KB

File metadata and controls

137 lines (96 loc) · 6.17 KB

For AI agents — x402-notify

How an autonomous agent finds this service, pays for a call, and uses what comes back.

1. Discovery

Two machine-readable entry points, both free:

curl -s {BASE_URL}/.well-known/x402      # the manifest below
{
  "x402Version": 1,
  "name": "x402-notify",
  "description": "Real message delivery per-message: Telegram bot messages and SMTP email with delivery receipts in-response",
  "resources": [
    {
      "resource": "POST /telegram",
      "description": "Deliver one Telegram message to a chat, group or channel.",
      "price": "$0.002",
      "accepts": [
        { "scheme": "exact", "network": "base-sepolia", "asset": "USDC", "payTo": "0x40252CFDF8B20Ed757D61ff157719F33Ec332402", "maxAmountRequired": "2000" },
        { "scheme": "exact", "network": "solana",       "asset": "USDC", "payTo": "WwwuGbqHrwF5RG89KhUbmRWEvjnRH9k5kVM5p7T3WwW", "maxAmountRequired": "2000" }
      ],
      "outputSchema": { /* … */ }
    }
    // …
  ]
}

And skill.md at the repo root — the prose contract written for a model to read directly: what each endpoint does, its price, its exact response shape, and the error codes. Drop it into your agent's context and it can call this service without any other documentation.

2. Paying

Pay in USDC on Base or Solana — your client picks the rail. Every 402 lists both:

Rail Network Asset payTo Facilitator
EVM base-sepolia / base USDC 0x036CbD53842c5426634e7929541eC2318f3dCF7e 0x40252CFDF8B20Ed757D61ff157719F33Ec332402 https://x402.org/facilitator
Solana solana USDC EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v WwwuGbqHrwF5RG89KhUbmRWEvjnRH9k5kVM5p7T3WwW https://facilitator.payai.network

EVM

The wallet signs an EIP-3009 transfer authorization entirely locally — no round-trip, no gas from the agent. With x402-fetch it's two lines:

import { privateKeyToAccount } from "viem/accounts";
import { wrapFetchWithPayment } from "x402-fetch";

const payFetch = wrapFetchWithPayment(fetch, privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`));
const res = await payFetch("{BASE_URL}/telegram");   // 402 → pay → 200, transparently

Solana

Solana wallets sign serialized transactions, so the server builds one for you:

POST {BASE_URL}/api/x402-checkout?action=prepare
  { "accept": <solana entry from the 402>, "buyer": "<base58 pubkey>" }
  → { "tx_base64", "recent_blockhash" }

POST {BASE_URL}/api/x402-checkout?action=encode
  { "accept": <same>, "signed_tx_base64": "<signed>", "resource_url": "<resource>" }
  → { "x_payment" }

Retry the original request with X-PAYMENT: <x_payment>. The extra.feePayer sponsor covers the SOL network fee, so the agent's wallet needs only USDC.

What the 402 tells you

Each entry in accepts[] carries an outputSchema describing the route it guards:

"outputSchema": {
  "input":  { "type": "http", "method": "POST", "bodyType": "json",
              "bodyFields": { "chatId": { "type": "string" }, "text": { "type": "string" } } },
  "output": { "type": "object", "properties": { "delivered": { "type": "boolean" } } }
}

input is how to call the route, output is the shape of the 200 body. Both are generated from openapi.json, so a client that only ever sees a 402 can still invoke the endpoint correctly and parse what comes back. Both rails carry the same schema.

Protocol version

This service speaks x402 v1: the challenge is { x402Version: 1, error, accepts[] }, which is what the x402-fetch clients in examples/ and every current wallet integration expect. x402 v2 — CAIP-2 network ids and extensions.bazaar.schema instead of outputSchema — is a future upgrade for agentcash compatibility; it changes the challenge shape, so it will land as a deliberate version bump rather than silently.

3. What you get back

A 200 whose body is the artifact — every paid route in this service returns what you bought inline. No job ids, no polling, no webhooks. Alongside it:

  • X-PAYMENT-RESPONSE header — base64 JSON settlement receipt
  • payment field in the body — the same receipt, for agents that only parse JSON
{ "success": true, "rail": "solana", "network": "solana", "transaction": "5xk…", "payer": "9wF…", "amount": "2000" }

Persist it — it's the audit trail linking a spend to the data it bought.

4. Budgeting

  • POST /telegram → $0.002
  • POST /email → $0.002

Both channels are $0.002 per message. An email to 50 recipients is one call and one payment, not fifty. 1,000 notifications cost $2.

5. MCP integration

examples/mcp-tool.md has a complete MCP server exposing these 2 endpoints as tools for Claude, with the payment wrapper already wired in.

6. Listing this service

Once deployed at a public origin (set PUBLIC_BASE_URL so the 402 resource is correct):

  • x402scan.com — crawls /.well-known/x402; submit your base URL.
  • x402 Bazaar — the protocol's own directory, reachable through the facilitator's list API; see https://x402.org.
  • agentic.market — agent-facing marketplace; the manifest plus skill.md is all it needs.

All three read the same manifest this repo already serves, so listing is a URL submission, not an integration.

7. Data honesty

Telegram delivers for real when TELEGRAM_BOT_TOKEN is set (a free token from @BotFather). Email relays for real when SMTP_HOST is set (any server: Gmail app password, Postmark, SES, Mailtrap, a local relay). Each channel is independent — you can run one live and one dry. Unconfigured channels return "source": "fixture", "delivered": false and a dryRunReason explaining exactly what was skipped. Nothing ever reports a delivery that didn't happen.

An agent should branch on the source field rather than assume live data.