Grant-Ingram Digital

coinop

A coin-operated vending machine of APIs for AI agents. Pay per call via x402 — no accounts, no API keys.

Endpoints
12
Per call
$0.002–$0.01
Paid in
USDC
Network
Base mainnet

What this is

coinop sells 12 HTTP endpoints at $0.002–$0.01 per call. Your code calls one, pays for that single call, and gets JSON back. There is no account to create, no API key to rotate, no minimum, no invoice, and no rate-limit tier — the payment is the authorization, carried in the HTTP request itself using x402.

Payments settle in USDC on Base mainnet (eip155:8453). That is real money on a live chain, not a testnet dry run — every paid call spends USDC from your wallet.

If you are wiring one of these into an agent, the handshake below is the part you actually need; the catalog after it is the price list.

How paying works

There is no signup and no API key. You call a route, get refused with 402 Payment Required and machine-readable terms, sign a payment for exactly that amount, and call again. A client library collapses the last two steps into one.

1 Ask without paying

Costs nothing — the request is refused before anything settles. Use curl -i: the response body is {}, and the terms arrive in the PAYMENT-REQUIRED header.

Request — free, nothing settles
curl -i "https://api.aicoinop.net/v1/validate-email?email=user@gmail.com"
Response
HTTP/1.1 402 Payment Required
content-type: application/json
PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQYXltZW50…   (1,924 chars of base64)

{}

2 Read the terms

The header value is base64-encoded JSON.

Decode it
curl -sD - "https://api.aicoinop.net/v1/validate-email?email=user@gmail.com" \
  -o /dev/null \
  | grep -i '^payment-required:' \
  | cut -d' ' -f2 | tr -d '\r' \
  | base64 -d | jq
Decoded PAYMENT-REQUIRED
{
  "x402Version": 2,
  "error": "Payment required",
  "resource": {
    "url": "https://api.aicoinop.net/v1/validate-email?email=user@gmail.com",
    "description": "Validate an email address: syntax check, MX/A DNS records, disposable-domain detection, free-provider flag, and typo suggestion (e.g. gamil.com -> gmail.com). Usage: /v1/validate-email?email=user@domain.com",
    "mimeType": "application/json",
    "serviceName": "coinop",
    "tags": [
      "email",
      "validation",
      "dns",
      "mx",
      "disposable",
      "verification"
    ]
  },
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:8453",
      "amount": "2000",
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "payTo": "0x558Dc0a83aCC890D5139Ba643e2a6784c0a449fC",
      "maxTimeoutSeconds": 300,
      "extra": {
        "name": "USD Coin",
        "version": "2"
      }
    }
  ],
  "extensions": {
    "bazaar": {
      "info": {
        "…": "…"
      },
      "schema": {
        "…": "…"
      }
    }
  }
}

accepts is the offer, and it is the only part you have to act on. amount is in atomic units of asset — USDC has six decimals, so 2000 is $0.002. payTo is the address the payment settles to, and scheme names how to sign it. A signed payment is good for 300 seconds. The collapsed extensions.bazaar holds the route's input and output schema — the same discovery metadata the x402 Bazaar reads.

3 Sign and retry

Payment is an EIP-3009 transfer authorization, signed by your wallet and resent in an X-PAYMENT header. That value cannot be typed by hand, so this step is a client library rather than a second curl.

TypeScript
// npm i @x402/fetch@2.17.0 @x402/evm@2.17.0 viem
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

// A wallet funded with USDC on this network — and nothing else.
const account = privateKeyToAccount(process.env.BUYER_PRIVATE_KEY as `0x${string}`);

const pay = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
  // Recommended: refuse any offer above your own per-call ceiling. Policies
  // filter the requirements the server sent, so an overpriced or unexpected
  // route fails instead of being paid.
  policies: [(_version, requirements) => requirements.filter((r) => BigInt(r.amount) <= 10_000n)],
});

// One call. The wrapper handles the 402, signs, and retries.
const res = await pay("https://api.aicoinop.net/v1/validate-email?email=user@gmail.com");
console.log(res.status, await res.json());

On success the route answers 200 with its normal JSON, plus a PAYMENT-RESPONSE header carrying the settlement receipt — including the on-chain transaction hash. The wallet needs USDC on Base mainnet, and each call spends real money.

The catalog

Paths are relative to https://api.aicoinop.net. Every route is priced per call and charged only on a successful response.

The examples are illustrative rather than ready to run — one truncates a base64 payload, and /v1/inbox/poll needs an id returned by POST /v1/inbox.

Method Path Price What it does
GET /v1/validate-email $0.002

Validate an email address: syntax check, MX/A DNS records, disposable-domain detection, free-provider flag, and typo suggestion (e.g. gamil.com -> gmail.com). Usage: /v1/validate-email?email=user@domain.com

Example request and response
Input (as query parameters)
{
  "email": "user@gmail.com"
}
Response
{
  "email": "user@gmail.com",
  "valid": true,
  "hasMx": true,
  "disposable": false,
  "freeProvider": true,
  "suggestion": null
}
POST /v1/summarize $0.005

Summarize any text (up to 50,000 characters) into a concise summary of at most maxWords words. Pay-per-use LLM inference with no API key or account required.

Example request and response
Request body
{
  "text": "Long article text...",
  "maxWords": 150
}
Response
{
  "summary": "The article argues that...",
  "model": "llama-3.1-8b"
}
POST /v1/embed $0.002

Generate embedding vectors for up to 16 texts in one call (BGE-M3, 1024 dimensions). For semantic search, RAG, deduplication, and clustering — no API key or account required.

Example request and response
Request body
{
  "texts": [
    "first document",
    "second document"
  ]
}
Response
{
  "vectors": [
    [
      0.01,
      -0.02
    ],
    [
      0.03,
      0.04
    ]
  ],
  "dims": 1024,
  "count": 2
}
GET /v1/crypto/snapshot $0.002

Normalized spot prices for major cryptocurrencies (BTC, ETH, SOL, ...) aggregated from Coinbase and Kraken public tickers, served from edge cache refreshed every 5 minutes. One call instead of juggling exchange APIs. Usage: /v1/crypto/snapshot?symbols=BTC,ETH

Example request and response
Input (as query parameters)
{
  "symbols": "BTC,ETH"
}
Response
{
  "ts": "2026-07-03T12:00:00.000Z",
  "currency": "USD",
  "prices": {
    "BTC": {
      "usd": 109000.5,
      "sources": {
        "coinbase": 109001,
        "kraken": 109000
      }
    }
  }
}
POST /v1/search $0.008

Web search for AI agents — the capability most agents lack. Returns ranked results (title, URL, snippet) for a query, backed by an independent search index and briefly cached. No API key or account required.

Example request and response
Request body
{
  "query": "x402 payment protocol",
  "count": 10
}
Response
{
  "query": "x402 payment protocol",
  "count": 1,
  "results": [
    {
      "title": "x402",
      "url": "https://x402.org",
      "description": "An open payment protocol for the web."
    }
  ]
}
POST /v1/extract $0.01

Extract structured JSON from unstructured text. Provide the text plus a JSON schema (the shape you want) and get back JSON matching it, with nulls for missing fields. Turns scraped or pasted content into typed data. Keyless pay-per-use.

Example request and response
Request body
{
  "text": "Acme Corp raised $12M Series A led by Foo Ventures in March 2025.",
  "schema": {
    "company": "string",
    "amount": "string",
    "round": "string",
    "investors": [
      "string"
    ],
    "date": "string"
  }
}
Response
{
  "data": {
    "company": "Acme Corp",
    "amount": "$12M",
    "round": "Series A",
    "investors": [
      "Foo Ventures"
    ],
    "date": "March 2025"
  },
  "model": "llama-3.3-70b"
}
POST /v1/rerank $0.002

Rerank candidate documents by relevance to a query using a cross-encoder (BGE reranker). The precision stage after embedding retrieval in a RAG pipeline: pass the query and your shortlisted passages, get them back ordered with scores. No API key or account required.

Example request and response
Request body
{
  "query": "how do refunds work",
  "documents": [
    "Shipping takes 3-5 days.",
    "Refunds are issued to the original payment method within 7 days."
  ],
  "topK": 2
}
Response
{
  "query": "how do refunds work",
  "count": 2,
  "results": [
    {
      "index": 1,
      "score": 0.98,
      "document": "Refunds are issued to the original payment method within 7 days."
    }
  ]
}
POST /v1/docs $0.005

Look up current documentation for a software library or framework — the fix for stale training data. Give a library name and optional topic; get fresh, ranked links to official docs with snippets. No API key or account required.

Example request and response
Request body
{
  "library": "react-router",
  "query": "loaders",
  "language": "javascript"
}
Response
{
  "library": "react-router",
  "query": "loaders",
  "results": [
    {
      "title": "Loading Data | React Router",
      "url": "https://reactrouter.com/start/data",
      "description": "..."
    }
  ]
}
POST /v1/document-to-markdown $0.005

Convert a document you supply (PDF, image with OCR, HTML, Office file, or CSV) into clean Markdown. Send the file as base64 — nothing is fetched from the web, so private documents are safe to send. Keyless pay-per-use.

Example request and response
Request body
{
  "filename": "invoice.pdf",
  "data_base64": "JVBERi0xLjQKJ..."
}
Response
{
  "filename": "invoice.pdf",
  "format": "markdown",
  "markdown": "# Invoice\n\n...",
  "bytes": 20481
}
GET /v1/geocode $0.002

Forward and reverse geocoding backed by OpenStreetMap data (redistributable). Turn an address into coordinates, or pass 'lat,lng' as q for reverse lookup. Usage: /v1/geocode?q=Brandenburg+Gate&limit=1

Example request and response
Input (as query parameters)
{
  "q": "Brandenburg Gate, Berlin",
  "limit": 1
}
Response
{
  "query": "Brandenburg Gate, Berlin",
  "count": 1,
  "results": [
    {
      "formatted": "Brandenburg Gate, Berlin, Germany",
      "lat": 52.5163,
      "lng": 13.3777,
      "country": "Germany",
      "countryCode": "DE"
    }
  ]
}
POST /v1/inbox $0.01

Rent a disposable webhook inbox: get a public URL that captures whatever is POSTed to it, then poll to read the events. Fills a hard gap for agents — receiving inbound HTTP like OAuth callbacks or payment webhooks. Everything is TTL'd and expires automatically.

Example request and response
Request body
{
  "ttl": 3600,
  "label": "stripe-callback"
}
Response
{
  "id": "a1b2c3d4e5f6a7b8c9d0e1f2",
  "receiveUrl": "https://api.example.com/hook/a1b2c3d4e5f6a7b8c9d0e1f2",
  "pollUrl": "https://api.example.com/v1/inbox/poll?id=a1b2c3d4e5f6a7b8c9d0e1f2",
  "ttl": 3600,
  "expiresAt": "2026-07-06T13:00:00.000Z"
}
GET /v1/inbox/poll $0.002

Read the events captured by a webhook inbox created via POST /v1/inbox. Pass the inbox id, and optionally an 'after' cursor to fetch only newer events. Usage: /v1/inbox/poll?id=<id>&after=<cursor>

Example request and response
Input (as query parameters)
{
  "id": "a1b2c3d4e5f6a7b8c9d0e1f2",
  "after": "000001720000000000-1a2b"
}
Response
{
  "id": "a1b2c3d4e5f6a7b8c9d0e1f2",
  "count": 1,
  "events": [
    {
      "id": "000001720000000000-1a2b",
      "ts": 1720000000000,
      "method": "POST",
      "body": "{\"type\":\"payment.succeeded\"}"
    }
  ],
  "nextCursor": "000001720000000000-1a2b"
}

Machine-readable

Everything on this page comes from endpoints you can read yourself.