Docs
Every Exepal tool is an HTTP endpoint that takes JSON and returns JSON. You can call it three ways; the tool and the answer are the same. The two micro-tools (page reader, domain intel) are x402 and MCP only.
Pay in USDC with x402
Send the request without any payment. The response is 402 Payment Required with a PAYMENT-REQUIRED header describing the price, the network (Base) and the receiving address. An x402-capable client signs a USDC payment, retries with the PAYMENT-SIGNATURE header, and gets the answer. Most agent frameworks have this built in; for a plain script, use the x402-fetch package.
import { wrapFetchWithPayment } from "x402-fetch";
const fetchPaid = wrapFetchWithPayment(fetch, walletClient);
const res = await fetchPaid("https://api.exepal.com/v1/ai-visibility", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ brand: "Notion", category: "note-taking app",
competitors: ["Obsidian", "Evernote"] })
});
const report = await res.json();
Prices are flat per request, so each tool has size-capped tiers. GET https://api.exepal.com/ lists them.
Pay by card through Apify
Each of the five analysis tools is also an Apify Actor under apify.com/exepal. Apify bills your account per event (per report, per profile, per keyword) and handles cards and invoices. The input fields are the same as the HTTP body.
import { ApifyClient } from "apify-client";
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor("exepal/ai-brand-visibility")
.call({ brand: "Notion", category: "note-taking app" });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
Use from Claude, Cursor or any MCP client
Exepal MCP server (pay in USDC): https://api.exepal.com/mcp, Streamable HTTP, no sign-in. Every endpoint above is a tool (read, domain, company_enrich, ai_visibility_quick, serp_ai_monitor, ...) at the same price. A call without payment returns an x402 payment request as the tool result; an x402-capable MCP client pays it in USDC on Base and repeats the call with the payment in _meta["x402/payment"]. The payment only settles if the tool succeeds.
{ "mcpServers": { "exepal": { "type": "http", "url": "https://api.exepal.com/mcp" } } }
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { wrapMCPClientWithPaymentFromConfig } from "@x402/mcp";
import { ExactEvmScheme } from "@x402/evm/exact/client";
const mcp = new Client({ name: "my-agent", version: "1.0.0" });
await mcp.connect(new StreamableHTTPClientTransport(new URL("https://api.exepal.com/mcp")));
const paid = wrapMCPClientWithPaymentFromConfig(mcp, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }], // viem account holding USDC on Base
});
const res = await paid.callTool("company_enrich", { domain: "stripe.com" });
Apify MCP server (pay by card): add https://mcp.apify.com to your client and sign in with your Apify account once. Then ask for a tool by name; the agent fills the input and Apify bills per result.
{ "mcpServers": { "apify": { "type": "http", "url": "https://mcp.apify.com" } } }
Page reader
One public URL in; clean markdown (or plain text) out, with the page's title, description, author, publish date, canonical URL, site name, language, lead image and the links found in the content. The reader picks the main content region (<main>, <article> or the body with navigation, footers, cookie banners and hidden elements removed). Static HTML, text, markdown and JSON responses are supported; there is no JavaScript rendering. Private and local addresses are refused.
| Endpoint | POST /v1/read $0.005 per page · POST /v1/read/batch $0.03 for up to 10 pages (urls[]) | |
|---|---|---|
| MCP | read, read_batch | |
Request
| Field | Type | Notes |
|---|---|---|
| url | string | Required. http or https. |
| format | string | markdown (default) or text. |
| maxChars | number | 1 000 – 200 000. Default 60 000 (20 000 per page in the batch). |
| links | boolean | Include links found in the content. Default true. |
| images | boolean | Keep images as . Default true. |
Response
| Field | Meaning |
|---|---|
| content | The page as markdown or text. |
| title, description, author, publishedAt, modifiedAt, canonical, siteName, lang, image | From <title>, meta, Open Graph and JSON-LD. |
| links[] | {text, href} for links inside the content, absolute, deduplicated, up to 200. |
| wordCount, truncated, region | Size, whether maxChars cut it, and which element the content came from. |
| finalUrl, status, contentType, fetchMs | Where the fetch ended after redirects and how the site answered. |
Not charged when the site cannot be fetched, times out, or answers 4xx/5xx (the response is a 502 with the reason). In the batch, a page that fails is reported inline as {url, error}; the batch is only uncharged when every page failed.
Domain intel
One domain in; what a security, sales or fraud agent wants to know before trusting it. DNS comes from a public resolver, registration from RDAP (the registries' own JSON successor to WHOIS), and the web probe from the site itself, so there are no upstream keys and the answer is cached for six hours.
| Endpoint | POST /v1/domain $0.005 per domain | |
|---|---|---|
| MCP | domain | |
Request
| Field | Type | Notes |
|---|---|---|
| domain | string | Required. A URL or email address is reduced to its domain. |
| web | boolean | Probe https://<domain>. Default true. |
| registration | boolean | RDAP lookup. Default true. Some ccTLDs (for example .np) publish no RDAP; registration is then null with a registrationNote. |
Response
| Field | Meaning |
|---|---|
| dns | a, aaaa, cname, mx[], ns[], txt[], caa[], www. |
| canReceive, provider (Google Workspace, Microsoft 365, …), spf {record, allMechanism, includes}, dmarc {policy, percent, rua}, dkim {found selectors}, mtaSts, bimi, and a grade: A (SPF -all/~all + DMARC quarantine/reject), B, C, D, F, or none when the domain has no mail. | |
| registration | registrar, registrarIanaId, createdAt, updatedAt, expiresAt, ageDays, expiresInDays, status[], nameservers[], dnssec, registrant {organization, country} when published. |
| web | reachable, finalUrl, status, server, hsts, securityHeaders[], title, description, generator, tech[] (same fingerprints as company enrichment), redirectsOffDomain. |
| hosting | dnsProvider, mailProvider, cdn, parked. |
| flags[] | registered-recently, expires-soon, registry-hold, parked, no-mx, no-spf, no-dmarc, dmarc-policy-none, spf-plus-all, no-common-dkim-selector, website-unreachable, no-hsts, redirects-off-domain, dnssec, … |
| summary | One line, e.g. stripe.com · 16y old via MarkMonitor · site up (HTTP 200, Cloudflare) · mail: Google Workspace, email security A. |
AI brand visibility
How often AI assistants recommend a brand when asked buyer questions about its category, measured without naming the brand in the prompt.
| Endpoint | POST /v1/ai-visibility/quick $0.50 (5 prompts, 1 engine) · POST /v1/ai-visibility $3.00 (20 prompts, all engines) · POST /v1/ai-visibility/deep $7.00 (50 prompts) | |
|---|---|---|
| Apify | exepal/ai-brand-visibility — $1.00 per report + $0.03 per prompt check | |
Request
| Field | Type | Notes |
|---|---|---|
| brand | string | Required. Exact brand name. |
| category | string | Required. What it is, in buyer language: "CRM for small business". |
| domain | string | Tightens matching, e.g. notion.so |
| competitors | string[] | Brands for share of voice. |
| market | string | Country or region appended to prompts. |
| engines | string[] | Any of openai, anthropic, google, perplexity. Default: all. |
| promptCount | number | 5–50. Capped by tier. |
| prompts | string[] | Your own questions instead of generated ones. |
Response
| Field | Meaning |
|---|---|
| score | 0–100 composite: 60% visibility, 25% rank quality, 15% first mention. |
| engines[] | Per engine: visibility %, firstMentionRate %, avgRank, avgSentiment. |
| shareOfVoice[] | Brand, mentions, share % across all answers. |
| topCitedDomains[] | Domains the engines cite for this category (Gemini and Perplexity return citations). |
| missedPrompts[] | Prompts where a competitor was named and the brand wasn't. |
| recommendations[] | Plain-language next steps. |
| results[] | Every prompt, engine, answer, mentions and citations. |
Creator vetting
Input a platform and handle (or supply the profile stats yourself); get fake-follower risk, engagement quality, posting consistency, red flags and an estimated UGC rate range. $0.20 per profile.
Company enrichment
Input a domain; get name, description, industry, size range, HQ, social profiles, contact channels, tech stack, pricing page, recent news, with a confidence per field group. $0.10 per company, $0.80 per 10 (/v1/company-enrich/batch).
Ad creative score
Input a script, on-screen text, caption and platform; get hook, clarity, CTA, platform-fit, pacing and credibility scores with concrete rewrites. $0.25 per creative, $2.00 per 10 (/v1/ad-creative-score/batch).
SERP + AI answer monitor
Input a domain and keywords; get Google rank, AI Overview citation and AI-assistant mentions per keyword, plus a diff against your previous snapshot. $0.70 per 10 keywords, $2.50 deep (25 keywords, all engines).
Caching and limits
Upstream answers are cached for 24 hours (SERP results and domain intel for 6 hours; page reads are always fresh). Identical questions within that window return instantly and don't cost us upstream, which is how prices stay low. Requests over the tier's cap are trimmed to the cap, not rejected.
Errors
| Status | Meaning |
|---|---|
| 400 | Body missing or invalid. The error field says which field. |
| 402 | Payment required. Normal first response on api.exepal.com. |
| 502 | The site a tool had to read refused or failed (page reader). Not charged. |
| 503 | Upstream engines unavailable. Not charged. |
Questions: contact@laxmankafle.com