VoidhashDocs
DocumentationAPI reference
Dashboard
Get started
Introduction
Quickstart
Setup
Setup overview
Create a project
Products and perks
Paywall locations
CLI
Paywall components
Components
Develop a component
Editor panels
Component definition
Publishing
Installing and capabilities
SDKs
Swift
Kotlin
React Native
Web
Store setup
Connect the App Store
Connect Google Play
Connect Stripe
API libraries
Node.js
PHP
Rust
Go
Resources
MCP server
Ad measurement
Meta ads
Migrate in observer mode
Delete a person's data

MCP server

Connect an AI agent to your Voidhash analytics and paywall workspace.

The Voidhash MCP server connects an AI agent to your project. A compatible agent can read revenue, subscription and trial analytics and ad campaign performance, and inspect and edit paywalls, write components, and render previews. This page shows how to create credentials, point your client at the server, and confirm that it works.

Server

The server runs at one URL:

https://api.voidhash.com/api/mcp

It uses streamable HTTP as its transport and bearer authentication, so the client sends a key in the Authorization header on every request.

The server implements the stateless MCP protocol, version 2026-07-28. Each request stands on its own, with no initialization handshake or session to keep alive. Clients that support only the earlier session-based versions cannot connect.

Tools

The server groups its tools into toolsets. A request lists, and can call, only the tools its credential has permission for, so the same server serves a read-only reporting agent and a paywall designer.

ToolsetToolsPermission
Analyticslist_insights, run_insight, acquisition_reportproject:analytics:read
Adsads_overview, campaign_performance, ads_issues, ads_cohorts, list_ad_campaignsproject:ads:read (and project:analytics:read for Voidhash numbers)
Paywallslist_paywalls, list_products, list_fonts, bash, list_components, read_component, get_component_buildproject:paywalls:read (project:products:read for products)
Paywallsbegin_paywall_edit and every tool that uses its edit session, create_product, write_componentproject:paywalls:write (project:products:write for products)

Tools that only read are marked with MCP's read-only annotation, so clients can run them without asking for confirmation.

Analytics

list_insights returns the built-in insights, such as revenue, MRR, active subscriptions, trials, trial conversions and churn, with what each measures, its unit, and the time ranges, granularities and filters it accepts. run_insight runs one insight with the same inputs as the insights endpoint: a time range preset such as last_30d or a custom start and end, a granularity, and an optional filter. It returns the period it covered, a summary, and one value per bucket, with the unit:

{
  "insightId": "builtin/revenue",
  "unit": "USD",
  "environment": "production",
  "period": {
    "start": "2026-10-01T00:00:00.000Z",
    "end": "2026-10-08T00:00:00.000Z",
    "granularity": "day"
  },
  "summary": { "value": 1250.4, "meaning": "total over the period" },
  "series": [{ "start": "2026-10-01T00:00:00.000Z", "value": 180.25 }]
}

Amounts are in US dollars and net of refunds, rates are percentages, and periods are in UTC. run_insight reports production purchases only, unlike the insights endpoint. To include sandbox purchases, filter on provider.environment yourself (1 is production, 2 sandbox); the result's environment field shows whether the production default applied.

acquisition_report takes the same inputs as the acquisition endpoint: a from and to day, the level to group by (network, campaign, adset, ad or surface), and optionally a network, campaign, ad set or ad filter, currency, time zone, revenue window, key conversion and environment. Each group reports the visits its ads brought, the people who signed up after their first touch, their app installs, trials, payers and revenue, with the ad platform's campaign, ad set and ad IDs, so an agent can join them to the spend it reads from the ad platform. The report also has a funnel by surface, where payers paid, and how much revenue can be traced to a first touch. Amounts are in the requested currency. returningPeople were reached by a touch but were already known, so they are not counted as acquired. Revenue comes from production unless you set environment. See ad measurement for the definitions.

Ads

When the project has a connected Meta ad account, the ads tools report paid acquisition the way the Ads pages in Studio do. Every tool only reads.

ToolWhat it returns
ads_overviewSpend, net revenue, people acquired, key conversions, cost per key conversion and ROAS, with the previous period; spend and revenue by day; the funnel by surface; where payers paid; each platform next to organic and other sources; issues to look at.
campaign_performanceOne row per campaign, ad group (Meta's ad set) or ad with delivery and its reason, destination, budget, the platform's numbers and Voidhash's numbers, plus totals over every matching row.
ads_issuesRejected ads, learning-limited ad groups, objects that are on but not delivering, account problems, spending limits close to the cap, failed syncs, and active ads whose links miss the tracking parameters.
ads_cohortsWeekly or monthly cohorts of the people your connected ad platform brought in (organic people are not included), with ROAS (or revenue per payer, or payers) at days 0 to 90 after acquisition, and the day each group pays back.
list_ad_campaignsThe synced campaigns with delivery, reasons, destination, objective, optimization event, bid strategy and budget, and each ad account's currency, time zone, status and sync status.
campaign_performance changed

Agents that called the first version of campaign_performance need to change; see the list below.

Changes to campaign_performance:

  • adAccountId and revenueWindow are removed. A call that still passes one fails with a message naming its replacement: list_ad_campaigns with adAccountId for one account's campaigns, and ads_cohorts for revenue by day after acquisition. Revenue is to date.
  • Each row keeps the platform's numbers in platform and Voidhash's in voidhash. roas is now voidhash.trueRoas, metaRoas is platform.platformRoas, and costPerAcquisition is voidhash.costPerSignup.
  • Rows cover synced campaigns, ad groups and ads only. People attributed to IDs no account has synced are no longer separate rows, and account spend that no ad row accounts for (such as deleted ads), formerly unallocated, is no longer part of the totals; the overview's spend still includes it.
  • level takes ad_group (adset is still accepted). A range is a range preset or both from and to; one without the other is refused.

Two sources, never blended. Every row keeps two objects apart. platform holds what the ad platform reports with its own attribution: spend, impressions, link clicks, CTR, its purchase value and ROAS, and its results with their type. voidhash holds what Voidhash measured for the people whose first touch came from the ad: visits, app installs, signups, trials, payers, key conversions, and gross, refunded and net revenue to date. Spend is the one platform number Voidhash's ratios use.

MetricDefinition
People acquired, signupsPeople who signed up after a first touch from the ad, counted once.
Key conversionThe step the project measures cost against: signup, trial or payer (payer by default).
Net revenueRevenue after refunds from those people, to date, in the report currency.
True ROASVoidhash net revenue ÷ spend. The platform's ROAS (its purchase value ÷ spend) is shown beside it.
Cost per stepSpend ÷ the people Voidhash measured at the step: cost per signup, payer or key conversion.
Cost per link clickSpend ÷ the platform's link clicks; both numbers come from the platform.
Cohort ROASA cohort's cumulative net revenue ÷ the spend on the days its people were acquired. Curves only rise, except through refunds.

Totals add only what adds up. Reach and frequency are per row and never summed, because one person can see ads from many rows, and results of different types, such as landing page views and app installs, are listed apart rather than added. Steps a project does not use are left out, so a web-only project has no installs and an app-only project has no visits, and website ads never report installs.

ads_overview, campaign_performance and ads_cohorts take a range preset (last_7_days by default, last_13_weeks for cohorts; the last_* presets end yesterday) or both from and to days, and optionally compare, platform, currency, timezone and environment. list_ad_campaigns and ads_issues report current state and take no range. campaign_performance reads reach and frequency per row only with includeReach, and hides ended objects only when they had no delivery in the range. Money defaults to the ad accounts' currency, converted at each day's rate when you ask for another, and days to the ad accounts' time zone. Revenue comes from production unless you choose another environment. Days from provisionalFrom on are still changing, as the platform keeps attributing conversions to them. Read warnings before acting on the numbers: each has a code, such as sync_failed, currency_converted or reach_limited, and the details that go with it. Spend in the overview is the ad accounts' total; the part no ad accounts for, such as deleted ads, is listed separately.

Voidhash numbers need project:analytics:read as well. Without it, the tools still answer with the platform's numbers and say what is left out, and ads_cohorts explains that it needs the permission. The analytics read-only key has both permissions.

Create credentials

For a single project, use a secret key of the project and keep it out of source control. An agent that only reports on your business needs no more than a key with Read-only analytics access, which sees only the analytics and ads tools; see Limit what a secret key can do. Send the key as a bearer token:

Authorization: Bearer vh_sk_...

A user key can access several projects, so the server also needs to know which one you mean. Send the project ID or slug in a second header:

Authorization: Bearer vh_...
X-Voidhash-Project: my-project

The CLI can print these headers for the current login. This keeps the key out of a command argument:

npx voidhash-cli auth token --project my-project

Configure your client

In your MCP client, add a remote or streamable HTTP server named voidhash, then set the URL and headers from above. Clients that use JSON configuration commonly accept this shape:

{
  "mcpServers": {
    "voidhash": {
      "type": "http",
      "url": "https://api.voidhash.com/api/mcp",
      "headers": {
        "Authorization": "Bearer vh_sk_..."
      }
    }
  }
}

Configuration keys differ between clients. Some expect servers instead of mcpServers, or serverUrl instead of url. In those cases, follow your client's own remote MCP instructions.

Verify the connection

Ask the agent a question that needs the server:

What paywalls do I have in Voidhash?

The agent should call list_paywalls and return the current project's paywalls. With a read-only analytics key, ask for a metric instead, such as "What was my revenue over the last 30 days?", and the agent should call run_insight. If it receives a 401, replace the key. If a user key authenticates but no project is selected, add the X-Voidhash-Project header. If a tool you expect is missing, the credential lacks its permission.

Treat MCP credentials as secrets

A full-access key lets the MCP server modify project content. Give each agent a key with only the access it needs, store it in your client's secret storage, and rotate it whenever a device or configuration is shared.

PreviousReceive webhooksNextAd measurement

On this page

ServerToolsAnalyticsAdsCreate credentialsConfigure your clientVerify the connection