WhatsApp lookups for AI agents, paid per request
Most APIs assume a person is on the other end: someone who signs up, confirms an email, picks a plan and pastes a key into a config file. An AI agent can't do most of that. It can make HTTP requests, though, and with x402 it can also pay for them.
wtsp.dev is built for that case. An agent can check whether a number is on WhatsApp, read its business profile or find its carrier, paying a fraction of a cent with each request, without an account.
How a paid request works
x402 brings back HTTP's long-unused 402 Payment Required status:
- The agent calls an endpoint, say
GET /v1/exists?phone=447400123456. - wtsp.dev answers
402with a price quote in thePAYMENT-REQUIREDheader: 0.004 USDC on Base, and the address to pay. - The agent signs a USDC authorization for exactly that amount and sends the same request again with the signature attached.
- wtsp.dev looks the number up, returns the answer, and only then settles the payment on Base.
Signing costs no gas, and the agent never pays for a failed lookup: if there's no answer, the payment is cancelled rather than settled. Agents that hold stablecoins on Tempo can pay the same quote with MPP instead.
The quickest start: the CLI
The @wtsp/cli package holds a wallet and pays for each lookup:
npx @wtsp/cli start # creates a wallet and prints its addressnpx @wtsp/cli exists +447400123456 # 0.004 USDC: on WhatsApp or notnpx @wtsp/cli profile +447400123456 # 0.006 USDC: account type, about, business profilenpx @wtsp/cli carrier +447400123456 # 0.002 USDC: carrier, line type, time zonesFund the wallet with a few dollars of USDC on Base and every lookup pays for itself. The JSON answer goes to stdout, so an agent can read it directly.
From your own code
Any x402 client works. In TypeScript, wrap fetch once and call the endpoint as usual:
import { wrapFetchWithPayment, x402Client } from "@x402/fetch";import { ExactEvmScheme } from "@x402/evm/exact/client";import { privateKeyToAccount } from "viem/accounts";
const wallet = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);const client = new x402Client().register("eip155:*", new ExactEvmScheme(wallet));const fetchWithPayment = wrapFetchWithPayment(fetch, client);
const res = await fetchWithPayment("https://wtsp.dev/v1/profile?phone=447400123456");console.log(await res.json());The wrapper sees the 402, signs the payment and retries. Your code just gets the answer.
Teaching the agent
Agents find their way around with three files, all generated from the same catalog as the API itself, so they never go stale:
/skill.md: a skill an agent can install, covering setup, every lookup and how to read the results./llms.txt: the full API reference in plain text./openapi.json: the OpenAPI document, for tools that generate clients.
Give an agent the skill and ask it "is +44 7400 123456 on WhatsApp?". It runs the lookup, pays 0.004 USDC and tells you.
When a key makes more sense
Signing a payment for every request suits agents. For a backend that runs thousands of lookups, prepaid credit is simpler: buy any amount once and send it as a bearer key. The prices are the same, and failed lookups go back on the balance. See API keys.