Token security on 63 chains and AI trading on 24 chains. Pay per request via MPP, the open standard for autonomous agent payments. No accounts. No API keys.
Both Quick Intel and Tator use the Machine Payments Protocol, an open HTTP 402 standard for autonomous agent payments. Your agent requests a resource, pays the 402 challenge, and gets the result back with a receipt. One round-trip, no checkout flow.
mppx.fetch() and it deals with the rest. For the full protocol spec visit mpp.dev or read the IETF draft.MPP is payment-method agnostic. This gateway accepts Tempo stablecoins and Stripe (cards, Link, and stablecoins via Stripe). Bitcoin Lightning is on the roadmap.
Pay per request. No account. No key. Your agent pays $0.03 or $0.20, gets results, moves on.

npm install mppx viem
0x20c000000000000000000000b9537d11c60e8b50 on chainId 4217.# Create and fund a testnet wallet npx mppx account create npx mppx account fund # Mainnet wallet: https://wallet.tempo.xyz # Mainnet USDC: 0x20c000000000000000000000b9537d11c60e8b50 # Testnet pathUSD:0x20c0000000000000000000000000000000000000
import { Mppx, tempo } from 'mppx/client'; import { privateKeyToAccount } from 'viem/accounts'; const account = privateKeyToAccount(process.env.PRIVATE_KEY); export const mppx = Mppx.create({ methods: [tempo({ account })] });
import { Challenge } from 'mppx'; import { loadStripe } from '@stripe/stripe-js'; // 1. Hit the endpoint, get the 402 challenge const response = await fetch('https://mpp.quickintel.io/v1/scan/full', { method: 'POST', body: JSON.stringify({ chain: 'base', tokenAddress: '0x...' }) }); const charge = stripe.charge({ createToken: async (params) => { const res = await fetch('/api/create-spt', { method: 'POST', body: JSON.stringify(params) }); return (await res.json()).spt; }}); const challenge = Challenge.fromResponse(response, { methods: [charge] }); // 2. Collect card details with Stripe Elements, create PaymentMethod const stripeClient = await loadStripe(process.env.STRIPE_PUBLISHABLE_KEY); const { paymentMethod } = await stripeClient.createPaymentMethod({ elements }); // 3. Create credential and retry with payment const credential = await charge.createCredential({ challenge, context: { paymentMethod: paymentMethod.id } }); const paid = await fetch('https://mpp.quickintel.io/v1/scan/full', { method: 'POST', headers: { 'Authorization': credential }, body: JSON.stringify({ chain: 'base', tokenAddress: '0x...' }) });
mppx.fetch() handles the full 402 challenge cycle automatically. For Stripe card payments the SPT flow requires Stripe Elements to collect card details, so you handle credentials manually as shown above.# Full end-to-end payment test
npx mppx post https://mpp.quickintel.io/v1/scan/full \
--body '{"chain":"base","tokenAddress":"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}'import { mppx } from './client.js'; const res = await mppx.fetch( 'https://mpp.quickintel.io/v1/scan/full', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chain: 'base', tokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' }) } ); const scan = await res.json(); console.log(scan.tokenDynamicDetails.is_Honeypot); // false
async function safeToTrade(chain, tokenAddress) { const scan = await ( await mppx.fetch('https://mpp.quickintel.io/v1/scan/full', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chain, tokenAddress }) }) ).json(); if (scan.tokenDynamicDetails.is_Honeypot) throw new Error('Honeypot detected'); if (scan.isScam === true) throw new Error('Known scam token'); const sellTax = parseFloat(scan.tokenDynamicDetails.sell_Tax); if (sellTax > 5) console.warn(`High sell tax: ${sellTax}%`); return scan; }
| Field | Type | Required | Description |
|---|---|---|---|
| chain | string | required | "eth", "base", "bsc", "sol", "sui", "trx", "arb", "op", and 55 more |
| tokenAddress | string | required | EVM: 0x-hex. Solana: base58. Sui: full object ID. |
| Field | Type | Description |
|---|---|---|
| tokenDynamicDetails.is_Honeypot | boolean | True = cannot be sold |
| tokenDynamicDetails.buy_Tax | string | Buy tax % e.g. "5.0" |
| tokenDynamicDetails.sell_Tax | string | Sell tax % |
| isScam | boolean|null | True = known scam. null = unknown. |
| contractVerified | boolean | Source verified on block explorer |
| quickiAudit.contract_Renounced | boolean | Ownership renounced |
| quickiAudit.can_Mint | boolean | Can mint new supply |
| quickiAudit.can_Blacklist | boolean | Can blacklist wallets |
| quickiAudit.is_Proxy | boolean | Upgradeable proxy contract |
| quickiAudit.has_Scams | boolean | Matches known scam patterns |
const res = await mppx.fetch( 'https://mpp.quickintel.io/v1/tator/prompt', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: 'Swap 0.1 ETH to USDC on Base', walletAddress: '0xYourAgentWallet', provider: 'my-agent' }) } ); const { transactions } = await res.json(); // Sign and broadcast, you keep full custody for (const tx of transactions) { const hash = await wallet.sendTransaction(tx); }
// async: true returns jobId immediately, poll for result const { jobId } = await ( await mppx.fetch('https://mpp.quickintel.io/v1/tator/prompt', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: 'Bridge 500 USDC from Base to Arbitrum', walletAddress: '0xYourAgentWallet', provider: 'my-agent', async: true }) }) ).json(); // Poll for result (FREE, no payment required) let job; do { await new Promise(r => setTimeout(r, 2000)); job = await (await fetch( `https://mpp.quickintel.io/v1/tator/jobs/${jobId}` )).json(); } while (job.status === 'pending');
| Field | Type | Required | Description |
|---|---|---|---|
| prompt | string | required | "swap 0.1 ETH to USDC on Base", "buy PEPE with 100 USDC", "bridge ETH to Arbitrum" |
| walletAddress | string | required | EVM or Solana wallet that will sign and broadcast returned transactions |
| provider | string | required | Your agent identifier e.g. "my-agent", "openclaw" |
| async | boolean | optional | Default false. True → returns jobId to poll at /v1/tator/jobs/:jobId (free) |
| chain | string | optional | "base", "ethereum", "solana", etc. Tator infers if omitted. |
| slippage | number | optional | Slippage tolerance %. Default 1. |
{ chain, tokenAddress }. Payment via MPP or x402. Returns full security analysis.{ prompt, walletAddress, provider }. Returns unsigned transactions. Includes auto security scan.{ status: "pending"|"complete"|"error", result }.x-payment-info. Used by MPPScan and AgentCash.mppx.fetch() intercepts, pays, and retries. You only receive 200 or non-payment errors. If payment fails (e.g. insufficient USDC), mppx throws with an error message.try { const res = await mppx.fetch('...', options); if (!res.ok) { const err = await res.json(); throw new Error(`${res.status}: ${err.message}`); } return await res.json(); } catch (err) { if (err.message.includes('insufficient')) { // Fund wallet: https://wallet.tempo.xyz } throw err; }
| Status | Meaning | Action |
|---|---|---|
| 200 | Success | Parse response body |
| 400 | Bad request | Check required fields |
| 402 | Payment required (auto-handled) | mppx retries automatically |
| 502 | Backend unavailable | Retry with backoff, check /health |
| 503 | Backend not configured | Contact support |
| Type suffix | Description |
|---|---|
| /payment-required | Standard challenge, resource requires payment |
| /payment-insufficient | Amount sent is too low |
| /payment-expired | Challenge expired (5-minute window) |
| /verification-failed | Credential signature invalid |
| /invalid-challenge | Challenge ID unknown, expired, or already used |
| /malformed-credential | Authorization header malformed |
Authorization: Payment routes to MPP. X-PAYMENT or PAYMENT-SIGNATURE routes to x402. No header on mpp.quickintel.io issues an MPP challenge. No header on x402.quickintel.io issues an x402 challenge.import { x402Fetch } from '@x402/fetch'; // Fully unchanged const res = await x402Fetch( 'https://x402.quickintel.io/v1/scan/full', { method: 'POST', body: JSON.stringify({...}), wallet } );
import { Mppx, tempo } from 'mppx/client'; const mppx = Mppx.create({ methods: [tempo({ account })] }); const res = await mppx.fetch( 'https://mpp.quickintel.io/v1/scan/full', { method: 'POST', body: JSON.stringify({...}) } );
| x402 | MPP | |
|---|---|---|
| Payment header | X-PAYMENT · PAYMENT-SIGNATURE | Authorization: Payment |
| Challenge header | PAYMENT-REQUIRED | WWW-Authenticate: Payment |
| Receipt header | PAYMENT-RESPONSE | Payment-Receipt |
| Settlement | Base, ETH, ARB, SOL + 11 more | Tempo (chainId 4217) |
| Idempotency | payment-identifier extension | Built-in (challengeId) |
| Replay protection | Redis nonce tracking | Built-in single-use semantics |
| SDK | @x402/fetch | mppx |
Point any agent, discovery tool, or MPPScan indexer at these endpoints to find and invoke this API automatically.