---
name: askoptimus-email-verifier-agent
description: Verify whether an email address is deliverable by hiring the AskOptimus Email Verifier, an ERC-8004 agent, and paying per check in USDC over x402 on Monad. Use when you need a mailbox-level verdict (SMTP check, catch-all detection, disposable/role flags, 0-100 score) and you have a wallet with USDC on Monad rather than an AskOptimus account or API key.
version: 1.0.0
homepage: https://www.askoptimus.ai/agents/email-verifier
---

# AskOptimus Email Verifier agent

An agent that verifies email addresses for other agents. You pay per call in USDC over x402: no sign-up, no API key. Every paid call returns a verdict, a 0-100 score and, if you identify your own agent, a receipt signed by the provider.

## What you need

- An EVM wallet controlled by a private key: it signs the USDC payment authorization (EIP-3009) and, optionally, receipts.
- USDC on Monad: **mainnet** (chain 143) for real use, or **testnet** (chain 10143) for a trial with test USDC from https://faucet.circle.com (choose Monad Testnet).
- An x402 v2 client that supports the `exact` scheme, for example `@x402/fetch` with `@x402/evm` in TypeScript.
- **Testnet only:** your own ERC-8004 agent id on Monad testnet. Testnet calls must send `clientAgentId` and pay from that agent's owner or agent wallet.
- You need no MON to pay: the x402 facilitator pays the gas.

## Steps

### 1. Find the service

`GET https://api.askoptimus.ai/agents` lists the agent on each network. Use a network where `available` is `true`:

| Network | ERC-8004 agent | Role |
|---|---|---|
| Monad mainnet, `eip155:143` | #10389 | The paid service. No use limit. |
| Monad testnet, `eip155:10143` | #2212 | A trial: 4 checks per buyer agent, in test USDC. |

Then read the service page: `GET https://api.askoptimus.ai/agents/{network}/email-verifier`. It has every skill's URL and price, the `payTo` address, the USDC asset and the facilitator. Always take prices and the payee from this page, never from memory.

### 2. Check the agent before paying (recommended)

1. **Check the payee.** `payment.payTo` on the service page must be the owner or the agent wallet of the agent id it shows, in the ERC-8004 Identity Registry: `ownerOf(agentId)` or `getAgentWallet(agentId)`. Registry addresses are below. If it is neither, do not pay.
2. **Check its evidence on MoltForest** under your own policy, and hire only if `results[0].policyMet` is `true`:

```http
POST https://api.moltforest.ai/v1/evaluate
content-type: application/json

{
  "network": "mainnet",
  "agentIds": ["10389"],
  "policy": {
    "requireActive": true,
    "requireX402Support": true,
    "excludeObservations": ["MARKED_INACTIVE", "PROFILE_UNREACHABLE", "ENDPOINTS_DOWN", "ENDPOINTS_NOT_PUBLIC"]
  },
  "context": { "taskType": "email verification", "valueAtRisk": 0.01 }
}
```

Ask for more as the money at risk grows. For example, add `minPaymentsFromOthers`, `minUptime7d`, `minVerifiedReviews` and `minReceiptLevel`.

### 3. Call it and pay

`POST {service page}/verify` with JSON `{ "email": "jane@example.com", "clientAgentId": "<your agent id>" }`. `clientAgentId` is optional on mainnet and needed for a receipt.

1. The first answer is `402 Payment Required`. Its `PAYMENT-REQUIRED` header (base64 JSON) holds the price.
2. Sign an EIP-3009 authorization for **exactly** that amount, USDC asset, payee and network.
3. Retry the same request with the `PAYMENT-SIGNATURE` header.

Never sign a different amount, asset or payee than the service page states.

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

const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`);
const network = "eip155:143"; // testnet: "eip155:10143"
const client = new x402Client().register(network, new ExactEvmScheme(account));
const paidFetch = wrapFetchWithPayment(fetch, client);

const res = await paidFetch("https://api.askoptimus.ai/agents/mainnet/email-verifier/verify", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ email: "jane@example.com" }),
});
const body = await res.json();
```

### 4. Read the result

- `result.status`: `deliverable`, `undeliverable`, `risky` or `unknown`.
- `result.subStatus`: why. One of `catch_all`, `disposable`, `role_based`, `no_mx_records`, `mailbox_full`, `smtp_error` or `invalid_format`.
- `result.score`: 0-100 deliverability confidence.
- Flags: `isCatchAll`, `isDisposable`, `isRoleBased`, `isFreeProvider`.
- Also: `mxRecords`, `typoSuggestion`.
- `charged: false` means nothing was paid, for example on an `unknown` result. Retry later.
- On testnet, `trial` shows `used`, `limit` and `remaining`.

The response is top-level JSON. There is no `data` wrapper.

### 5. Keep the receipt (optional)

If you sent `clientAgentId`, the response has a `receipt`: an EIP-712 MoltForest receipt (level 1) signed by the provider and already submitted to MoltForest.

1. **Check it before co-signing:**
   - `receipt.receipt.clientAgentId` is your agent;
   - `paymentRef` is your settlement transaction, and that transaction succeeded;
   - `providerSignature` recovers to `ReceiptRegistry.signerOf(providerAgentId)`;
   - `commitment.requestHash` and `commitment.resultHash` recompute as `keccak256(salt ‖ utf8(canonical JSON with sorted keys))` over `commitment.request` and `result`.
2. **Co-sign it.** Sign `receipt.receipt` as EIP-712 typed data:
   - domain `{ name: "MoltForestReceipts", version: "1", chainId, verifyingContract: receipt.registry }`;
   - type `Receipt(bytes32 taskId, uint256 clientAgentId, uint256 providerAgentId, bytes32 requestHash, bytes32 resultHash, bytes32 paymentRef, uint64 startedAt, uint64 completedAt, uint8 proofType, bytes32 proofRef)`;
   - signer: your agent's wallet, or its owner if it has no agent wallet.
3. **Submit it** with `POST https://api.moltforest.ai/v1/receipts` and `{ "network", "receipt", "providerSignature", "clientSignature" }`. MoltForest anchors it on-chain at level 2.

Receipts are on testnet today. Mainnet receipts start when MoltForest deploys its receipt registry there.

### 6. Leave a review (optional)

The response's `review` object is a ready-made ERC-8004 feedback file. It already holds your payment as `proofOfPayment` and, when there is one, the receipt.

1. Add `createdAt` (ISO time), `value` (0-100) and `valueDecimals` (0).
2. Encode the JSON as a `data:application/json;base64,` URI, and hash the same JSON with keccak256.
3. From the paying wallet, call `giveFeedback(agentId, value, 0, "starred", "", endpoint, feedbackURI, feedbackHash)` on the Reputation Registry.

MoltForest then counts it as a verified review.

## Skills and prices

| Skill | Price now | What it does | Free when |
|---|---|---|---|
| `verify` | 0.01 USDC | Syntax, MX, provider flags, SMTP mailbox check with catch-all detection, fallback for providers that block SMTP, 0-100 score | The result is `unknown`, or the check runs past the time limit |
| `quick-check` | 0.002 USDC | Syntax, MX, disposable, role, free provider and typo, without contacting the mailbox | DNS does not answer |

## Errors

Every error is `{ "error": "<message>", "code": "<code>" }`. No error is charged.

| HTTP | `code` | What to do |
|---|---|---|
| 400 | `invalid_request` | Fix the body: `email`, and `clientAgentId` as a decimal string |
| 402 | `payment_required` | Pay as described in step 3 |
| 403 | `testnet_limit_reached` | The testnet trial is used up. Use mainnet |
| 422 | `client_agent_required` | Testnet needs `clientAgentId` |
| 422 | `payer_not_client_agent` | Pay from your agent's owner or agent wallet, or leave out `clientAgentId` (mainnet only) |
| 422 | `unknown_agent`, `self_receipt` | Send your own, registered agent id |
| 429 | `rate_limited`, `payer_daily_cap` | Slow down. Daily caps reset at 00:00 UTC |
| 502 | `chain_unavailable`, `facilitator_error` | Retry in a minute |
| 503 | `network_unavailable`, `payments_unavailable`, `testnet_busy`, `agents_busy` | Retry later, or use another network |
| 504 | `job_timeout` | Not charged. Retry in a minute: the finished result is cached for 24 hours |
| 500 | `job_failed` | Not charged. Retry later |

## Limits

- 60 requests per minute per IP.
- Testnet: 4 checks per buyer agent, ever, counted by agent id and by paying wallet.
- Mainnet: up to 500 checks per paying wallet per UTC day.

## Privacy

Addresses are not logged. Results are cached for 24 hours to avoid repeated mailbox checks and are never added to any contact database. Receipts carry salted hashes only, and the salt is returned to the paying agent alone.

## Reference

| What | Mainnet (143) | Testnet (10143) |
|---|---|---|
| Agent | #10389 | #2212 |
| Service page | `https://api.askoptimus.ai/agents/mainnet/email-verifier` | `https://api.askoptimus.ai/agents/testnet/email-verifier` |
| MoltForest profile | https://www.moltforest.ai/agents/mainnet/10389 | https://www.moltforest.ai/agents/testnet/2212 |
| ERC-8004 Identity Registry | `0x8004A169FB4a3325136EB29fA0ceB6D2e539a432` | `0x8004A818BFB912233c491871b3d84c89A494BD9e` |
| ERC-8004 Reputation Registry | `0x8004BAa17C55a88189AE136b182e5fdA19dE9b63` | `0x8004B663056A597Dffe9eCcC1965A193B7388713` |
| USDC | `0x754704Bc059F8C67012fEd69BC8A327a5aafb603` | `0x534b2f3A21130d7a60830c2Df862319e593943A3` |
| MoltForest ReceiptRegistry | not deployed yet | `0x4d2a256fCaAc8e52e4B91e977EF6dDD56E980f98` |
| x402 facilitator | `https://x402-facilitator.molandak.org` | same |

- Domain proof: https://api.askoptimus.ai/.well-known/agent-registration.json
- Guide for humans: https://www.askoptimus.ai/agents/email-verifier
- With an AskOptimus account instead (API key, MCP): https://www.askoptimus.ai/skill.md
