Skip to content

MCP Data API

General overview

The FraudScore MCP server lets language models (LLMs) and MCP-compatible clients retrieve traffic quality analytics from the FraudScore Data API. The user states a task ("show me the top affiliates by fraud score for September"), the LLM calls the appropriate tool with correct parameters, the server queries the Data API and returns ready-to-use data.

Capabilities:

  • install and custom event data for a period (raw rows or aggregated);
  • grouping, filtering, sorting, pagination;
  • aggregated reports on install ↔ custom event joins;
  • sensible defaults — a channel and a date range are enough to start;
  • listing the account's channels (list_channels) — the recommended starting point;
  • access control: an account only sees its own channels;
  • all tools carry the read-only annotation (rendered by clients such as Claude Desktop and Cursor).

Connecting

Parameter Value
URL https://mcp-data.fraudscore.ai/mcp
Transport Streamable HTTP (stateless: no session, every request is independent)
Method POST
Headers Authorization: Bearer <MCP_TOKEN>, Content-Type: application/json, Accept: application/json, text/event-stream
Health check GET /healthz → {"status":"ok"}

The token (mcp_*) is issued by FraudScore and sent in the Authorization header with every request. The server uses the token to identify the account and its available channels. The token is personal — treat it as a secret.

Configuration for a typical MCP client (Claude Desktop, Cursor, etc.) — note the "type": "http" entry: without it the client tries to launch a local stdio process:

{
  "mcpServers": {
    "fraudscore-data-api": {
      "type": "http",
      "url": "[https://mcp-data.fraudscore.ai/mcp](https://mcp-data.fraudscore.ai/mcp)",
      "headers": {
        "Authorization": "Bearer mcp_your_token"
      }
    }
  }
}

Node.js client example:

import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'

const transport = new StreamableHTTPClientTransport(new URL('[https://mcp-data.fraudscore.ai/mcp](https://mcp-data.fraudscore.ai/mcp)'), {
  requestInit: { headers: { Authorization: `Bearer ${MCP_TOKEN}` } }
})
const client = new Client({ name: 'my-app', version: '1.0.0' })
await client.connect(transport)

const result = await client.callTool({
  name: 'get_installs',
  arguments: { channelId: 'my-channel', date_from: '2026-09-01', date_to: '2026-09-15' }
})

Or plain JSON-RPC over HTTP:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_installs",
    "arguments": { "channelId": "my-channel", "date_from": "2026-09-01", "date_to": "2026-09-15" }
  }
}

Tools

list_channels

Returns the channel identifiers (channelId) available to the account. Takes no parameters.

{ "channels": ["12345", "67890"] }

Recommended starting point: fetch your channelId values first, then use them with the data tools (get_installs, get_custom_events, get_install_custom_groups, get_custom_install_groups).

The channel list is identical on every endpoint. An individual channel may still be served by a different endpoint: if a data tool returns a zone error, connect to the endpoint named in that error.

Common request parameters

The table applies to the data tools; list_channels takes no parameters.

Parameter Type Required Description
channelId string / number yes a channel of the account
date_from string yes period start, YYYY-MM-DD
date_to string yes period end, YYYY-MM-DD
group string[] see below grouping fields (plain field keys: offer_id, affiliate_id, date). Provided = aggregated report, omitted = raw event list
fields string[] — response fields (by name or API key; valid names — see the list_available_fields tool). Defaults if omitted
filters object — equality filters: {"affiliate_id": "136"} or a value list {"offer_id": ["1","2"]}
sort_field string — defaults to score (score_avg in groups). API rule: sorting is only allowed by a field present in the response — the server adds it to fields automatically
sort_direction "asc" | "desc" — defaults to desc
page number — page number. Omitted = full result (page=all)
page_size number — rows per page when page is set (default 100, max 1000)

get_installs

Install data for a period. Without group — a raw event list; with group — an aggregated report (fraud scores, counts, payouts, cost). For questions about installs, install fraud, and anything grouped by install dimensions.

get_custom_events

Custom event data for a period (your app's in-app events: registration, purchase, level-up, etc.). Same modes; the default field set is adapted for custom events (includes the event name and value). Default custom aggregates: score_avg and count.

get_install_custom_groups

Installs with a custom event breakdown: groups installs by the given key; each row shows the install count plus a per-custom-event breakdown (custom_count/custom_users arrays aligned with the events header by index). For questions like "installs by affiliate with their custom events". group is required; filters applies to installs, custom_filters — to custom events. Do not confuse with get_custom_install_groups.

get_custom_install_groups

Custom events with install counts: groups custom events by the given key, with counts joined to installs (custom_count/custom_users arrays aligned with events by index). For questions like "custom events by country". group is required; default aggregates are score_avg and count (payout aggregates are not accepted). The grouping key is present in rows but may be empty when custom events have no such field. Do not confuse with get_install_custom_groups.

list_available_fields

Reference of available fields: keys, modes (list/group), group keys, filterability. Optional parameter mode: "list" | "group". Recommended before using unfamiliar field names.

Defaults

When parameters are omitted, the server applies verified defaults:

  • List fields: the standard field set of the method (custom has its own set without install-only fields, plus name and value).
  • Group fields: score_avg, count, affiliate_payout_sum, cost_sum, score_ok/low/mid/high for install-based methods; for custom-based methods — only score_avg and count (payout aggregates are unavailable).
  • score is added to every request automatically (score_avg in groups).
  • The sort field, if not present in the response, is added to fields automatically (API rule: sorting only by fields present in the response).
  • Sorting: score_desc (score_avg_desc in groups).
  • Pagination: full result without paging (page=all).

Field aliases: in group mode offer_name → any_offer_name, affiliate_payout → affiliate_payout_sum, etc. — either name can be passed. The group parameter always takes plain field keys (offer_id), never any_*.

Response format

A tool returns compact JSON. The examples below are illustrative; the set of events and the values depend on your application:

{"url":"[https://api.fraudscore.ai/{channel}/install?key=***&](https://api.fraudscore.ai/{channel}/install?key=***&)...","mode":"list","period":{"from":"2026-09-01","to":"2026-09-15"},"page":"all","events":null,"row_count":2,"truncated":false,"rows":[{"datetime":"2026-09-01T10:00:00","offer_id":"...","score":87}]}

Aggregation methods add an events header (custom event names), separated from the data rows:

{"url":"...","mode":"group","page":"all","events":["registration","first_purchase"],"row_count":54,"truncated":false,"rows":[{"affiliate_id":"123","count":"1050","score_avg":15,"custom_count":["600","350"],"custom_users":["590","340"]}]}
  • url — the Data API request with a masked key (for transparency and debugging);
  • events — the aggregation methods header: custom event names; the custom_count/custom_users arrays in rows are aligned with it by index;
  • rows — array of result rows;
  • truncated — true when a paged request returned a full page; accompanied by next_page — the number of the next page.

Errors

HTTP level (authorization and request body):

Code Reason
400 invalid request body: malformed JSON or forbidden properties (e.g. __proto__)
401 missing Authorization header or token does not match the mcp_* format
403 token not found or account does not exist
502 authorization service unavailable, retry later

Tool level (JSON-RPC): on execution errors the result has isError: true with a human-readable reason in English: channel access denied, integration not available in the current zone (with the appropriate endpoint), unknown field (with the list of allowed values), inverted date range, Data API error. The LLM can use the error text to self-correct the request.

Limitations

  • At most 60 requests per minute and at most one request per second to the Data API (enforced automatically by the server).
  • An account only has access to its own channels; a foreign channelId is rejected.
  • The page=all response is not size-limited: for chat scenarios (Claude Desktop, Cursor) keep in mind that the entire result goes into the model context.
  • The endpoint serves integrations of its own zone only: requesting an integration from another zone returns an error pointing to the appropriate endpoint. The channel list (list_channels) is always complete, regardless of the endpoint.

Security

  • The token is a personal secret: send it only in the Authorization header, keep it in secure storage and have it reissued if you suspect compromise.
  • All connections use HTTPS.
  • An account has access only to its own channels' data.
  • The server keeps no state between requests.

oct 7, 2026