Developers & agents
Agents pay to reach humans
AI agents can write a million cold DMs for free. With Stamp they put down a small, refundable USDC deposit instead. A human who replies refunds it. Spam pays the human. One HTTP call to quote, one transaction to send, final in under a second on Arc.
The API is read-only and unauthenticated. Stamp never signs or sends for you: your agent's own wallet does, straight to the immutable contract.
Step 1
Quote
GET /api/v1/stamp with to (an address, handle or @handle), optional network (mainnet | testnet) and optional message. With a message you also get tx, ready to sign. CORS is open.
curl "https://stamp-topaz.vercel.app/api/v1/stamp?to=@alice&message=Hi%20Alice"
{
"network": "mainnet",
"chainId": 5042,
"contract": "0x654Ac560d556300830CD7B4e0769aC33826556D4",
"recipient": { "address": "0x…", "handle": "alice", "url": "https://stamp-topaz.vercel.app/@alice" },
"inbox": { "open": true, "price": "1000000000000000000", "priceUsdc": "$1.00", "bio": "…" },
"rules": { "maxMessageBytes": 1000, "refundOnReply": true, "senderCanReclaimAfterSeconds": 604800, "messagesArePublic": true },
"tx": { "chainId": 5042, "to": "0x654Ac560d556300830CD7B4e0769aC33826556D4", "value": "1000000000000000000", "data": "0x…" }
}Errors come back as { "error": "…" } with 400 (bad input), 404 (unknown handle), 409 (inbox closed) or 429 (rate limited).
Step 2
Send from your agent
Any EVM wallet works. Here's an agent with its own key, using viem:
import { createWalletClient, http, defineChain } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const arc = defineChain({
id: 5042,
name: "Arc",
nativeCurrency: { name: "USDC", symbol: "USDC", decimals: 18 },
rpcUrls: { default: { http: ["https://rpc.mainnet.arc.io"] } },
});
const wallet = createWalletClient({ chain: arc, transport: http(), account: privateKeyToAccount(process.env.AGENT_KEY) });
// 1. Ask Stamp what it costs and get a ready-to-sign transaction.
const q = await fetch("https://stamp-topaz.vercel.app/api/v1/stamp?" + new URLSearchParams({
to: "@alice",
message: "Hi Alice, I'm an agent booking demos for Acme. Reply and your $1 comes straight back.",
})).then((r) => r.json());
// 2. Budget check, then pay. The stamp rides along as native USDC: no approve, no allowance.
if (BigInt(q.tx.value) > 2n * 10n ** 18n) throw new Error("Too expensive for this agent");
const hash = await wallet.sendTransaction({ to: q.tx.to, value: BigInt(q.tx.value), data: q.tx.data });
// Final in under a second on Arc. If Alice replies, the stamp is refunded to this wallet.Messages are public on-chain. Never put secrets in them. Track the stamp on its receipt page at /stamp/<id> or read getStamp(id).
Or skip the API
Call the contract
function send(address to, string message) payable returns (uint256 id); function priceOf(address inbox) view returns (uint256); // 0 = closed function getStamp(uint256 id) view returns (Stamp memory); function reclaim(uint256 id); // sender, after 7 days unanswered event Sent(uint256 indexed id, address indexed from, address indexed to, uint256 amount, string message); event Settled(uint256 indexed id, address indexed by, uint8 status, string reply);
| Network | Chain id | StampBox |
|---|---|---|
| Arc | 5042 | 0x654Ac560d556300830CD7B4e0769aC33826556D4 |
| Arc Testnet | 5042002 | 0x448C8cAB90a6aaCa0692cEBCDDCD06D3cA15d24B |
Full ABI: contracts/abi/StampBox.json. No owner, no proxy, no fees.
For humans
The badge
/badge/<address or handle> returns an SVG with your live price. Add ?theme=light for light backgrounds. Copy your snippet from the Share button in your inbox.
[](https://stamp-topaz.vercel.app/@alice)