Developer Reference

Brainito API & MCP

Integrate marketing health scores and website audits into your apps, AI assistants, and automation pipelines. Two ways to use the API — a clean REST interface and a full MCP server for AI clients.

REST API v1
MCP compatible
API key auth
JSON responses

Overview

Brainito exposes two interfaces for the same underlying API — choose whichever fits your use case:

REST API

REST API v1

https://brainito.com/api/v1

Standard HTTP endpoints. Clean JSON responses, proper HTTP status codes. Best for server-side integrations, automation scripts, and backend pipelines.

  • POST /api/v1/scan
  • GET /api/v1/report/:scan_uid
  • GET /api/v1/reports
MCP

MCP Server

https://brainito.com/api/mcp

JSON-RPC 2.0 over HTTP (Model Context Protocol). Works with Claude Desktop, Cursor, Windsurf, and any MCP-aware AI client out of the box.

  • scan_website tool
  • get_report tool
  • list_reports tool

Both interfaces use the same API key authentication and scopes.

Authentication

Every request must include an Authorization header with a Bearer token. Brainito supports two credential types:

API Key
brn_live_XXXXXXXX.SECRET

For server-to-server integrations, scripts, and direct HTTP calls. Create in Settings → API Keys.

Service Account
brn_sa_XXXXXXXX.SECRET

For AI assistants and long-running bots. Ideal for MCP clients like Claude Desktop. Create in Settings → Service Accounts.

http
Authorization: Bearer brn_live_XXXXXXXX.YOUR_SECRET
Security: Never expose credentials in client-side code or public repositories. Store them in environment variables or a secrets manager. Secrets are hashed on creation and cannot be recovered — if lost, rotate the key.

Quick Start

The fastest way to get a report is with the REST API — three steps, plain curl.

  1. 1

    Create an API key

    Go to Settings → API Keys and click Create key. Select scopes website.scan and reports.read. Copy the key immediately — it won't be shown again.

  2. 2

    Start a scan

    bash
    curl -X POST https://brainito.com/api/v1/scan \
      -H "Authorization: Bearer brn_live_XXXXXXXX.YOUR_SECRET" \
      -H "Content-Type: application/json" \
      -d '{"url": "https://example.com"}'
  3. 3

    Poll for the report

    Scans take 60–90 seconds. Call until status === "completed".

    bash
    curl https://brainito.com/api/v1/report/abc123xyz \
      -H "Authorization: Bearer brn_live_XXXXXXXX.YOUR_SECRET"

REST API

Base URL: https://brainito.com/api/v1

All responses are plain JSON with standard HTTP status codes. No JSON-RPC wrapper.

POST/api/v1/scanRequires: website.scan

Start a full marketing audit on a website. Returns immediately with a scan_uid — use it to poll GET /api/v1/report/:scan_uid. Deducts 1 credit per scan.

Body fieldTypeRequiredDescription
urlstringYesFull URL to audit (e.g. https://example.com)
bash
curl -X POST https://brainito.com/api/v1/scan \
  -H "Authorization: Bearer brn_live_XXXXXXXX.YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'
json
HTTP/1.1 202 Accepted
{
  "scan_uid": "abc123xyz",
  "domain": "example.com",
  "status": "pending",
  "message": "Scan started. Poll GET /api/v1/report/{scan_uid} until status is 'completed'."
}
StatusMeaning
202 AcceptedScan started — use scan_uid to poll for the report
400 Bad RequestMissing or invalid url field
402 Payment RequiredInsufficient credits
403 ForbiddenMissing website.scan scope or not on a paid plan
409 ConflictA scan for this domain is already in progress
GET/api/v1/report/:scan_uidRequires: reports.read

Get the full report for a scan. Poll every 5–10 seconds until status === "completed". Returns all 77 factor analyses, section scores, priority actions, and traffic data.

bash
curl https://brainito.com/api/v1/report/abc123xyz \
  -H "Authorization: Bearer brn_live_XXXXXXXX.YOUR_SECRET"

While pending:

json
{
  "scan_uid": "abc123xyz",
  "domain": "example.com",
  "status": "pending",
  "message": "Scan is pending. Poll again in a few seconds."
}

When completed:

json
{
  "scan_uid": "abc123xyz",
  "domain": "example.com",
  "status": "completed",
  "report_url": "https://brainito.com/dashboard/marketing-audit-report/example.com/abc123xyz",
  "scores": {
    "overall": 62,
    "website_essentials": 58,
    "on_page_seo": 55,
    "technical_seo": 70,
    "marketing_channels": 65
  },
  "priority_actions": [
    "Add pricing information clearly on the website.",
    "Implement a cookie consent banner for compliance.",
    "..."
  ],
  "factors": {
    "website_essentials": [
      {
        "id": "pricing_page",
        "name": "Pricing Page",
        "score": 10,
        "status": "No",
        "reasoning": "No dedicated pricing page found.",
        "analysis": "The site lacks a clear pricing page...",
        "suggestions": ["Add a /pricing page", "Show plan tiers clearly", "..."]
      }
    ],
    "on_page_seo": [ ... ],
    "technical_seo": [ ... ],
    "marketing_channels": [ ... ]
  },
  "traffic": {
    "monthly_visits": 1200,
    "domain_authority": 18,
    "organic_traffic": 450,
    "keywords_ranking": 34,
    "backlinks": 120,
    "bounce_rate": 0.62,
    "top_countries": [{ "country": "United States", "code": "US", "share": 0.45 }],
    "top_keywords": [{ "keyword": "marketing audit tool", "volume": 320, "position": 8 }],
    "traffic_sources": { "organic": 0.38, "direct": 0.29, "referral": 0.18 },
    "ads_active": false,
    "ads_platforms": [],
    "social_mentions_count": 12
  }
}
factors is grouped into four sections: website_essentials, on_page_seo, technical_seo, marketing_channels. Each factor has id, name, score (0–100), status (Yes / No / Not Applicable), reasoning, analysis, and suggestions. Factors that could not be evaluated show "status": "unavailable".
GET/api/v1/reportsRequires: reports.read

List recent audit reports for your account, sorted newest first.

Query paramTypeDefaultDescription
limitnumber10Number of reports to return (1–20)
bash
curl "https://brainito.com/api/v1/reports?limit=5" \
  -H "Authorization: Bearer brn_live_XXXXXXXX.YOUR_SECRET"

MCP Protocol

The MCP server at POST /api/mcp implements the Model Context Protocol (JSON-RPC 2.0 over HTTP). Use this when connecting to AI clients like Claude Desktop, Cursor, or Windsurf — they discover the tools automatically.

Initialize

Optional handshake. Returns server info and supported protocol version.

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "clientInfo": { "name": "my-app", "version": "1.0" },
    "capabilities": {}
  }
}

List Tools

Discover available tools and their input schemas.

json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}

MCP Tools

scan_websiteRequires: website.scan

Start a marketing health scan. Returns a scan_uid to pass to get_report.

ParameterTypeRequiredDescription
urlstringYesFull URL of the website to scan (e.g. https://example.com)
json
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "scan_website",
    "arguments": { "url": "https://example.com" }
  }
}
get_reportRequires: reports.read

Retrieve the full report for a scan. Call repeatedly until status === "completed". Returns all 77 factor analyses, scores, priority actions, and traffic data.

ParameterTypeRequiredDescription
scan_uidstringYesThe scan UID returned by scan_website
json
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "get_report",
    "arguments": { "scan_uid": "abc123xyz" }
  }
}
list_reportsRequires: reports.read

List recent marketing audit reports for your account, ordered by creation date.

ParameterTypeRequiredDescription
limitnumberNoNumber of reports to return (1–20, default: 5)
json
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "list_reports",
    "arguments": { "limit": 5 }
  }
}

Integrations

Brainito ships an official @brainito/mcp npm package — a stdio MCP server that works with every major AI client out of the box. No HTTP transport issues, no OAuth setup. Requires Node.js 18+.

Use a Service Account key (brn_sa_…) for AI integrations — scope it to website.scan + reports.read.

Claude Desktop

Mac: ~/Library/Application Support/Claude/claude_desktop_config.json

Windows: %APPDATA%\Claude\claude_desktop_config.json

json
// ~/Library/Application Support/Claude/claude_desktop_config.json
// (Windows: %APPDATA%\Claude\claude_desktop_config.json)
{
  "mcpServers": {
    "brainito": {
      "command": "npx",
      "args": ["-y", "@brainito/mcp@latest"],
      "env": {
        "BRAINITO_API_KEY": "brn_sa_XXXXXXXX.YOUR_SECRET"
      }
    }
  }
}

Cursor

Go to Settings → MCP → Add new global MCP server, or add to .cursor/mcp.json in your project root:

json
// Settings → MCP → Add new global MCP server
// or .cursor/mcp.json in your project root
{
  "mcpServers": {
    "brainito": {
      "command": "npx",
      "args": ["-y", "@brainito/mcp@latest"],
      "env": {
        "BRAINITO_API_KEY": "brn_sa_XXXXXXXX.YOUR_SECRET"
      }
    }
  }
}

Windsurf

Edit ~/.codeium/windsurf/mcp_config.json:

json
// ~/.codeium/windsurf/mcp_config.json
{
  "mcpServers": {
    "brainito": {
      "command": "npx",
      "args": ["-y", "@brainito/mcp@latest"],
      "env": {
        "BRAINITO_API_KEY": "brn_sa_XXXXXXXX.YOUR_SECRET"
      }
    }
  }
}
After saving and restarting your AI client, the tools scan_website, get_report, and list_reports appear automatically. The first run fetches the package via npx — subsequent starts use the cached version.

Code Examples

JavaScript / TypeScript — full scan + poll loop

REST API v1

typescript
const API_KEY = "brn_live_XXXXXXXX.YOUR_SECRET";
const BASE = "https://brainito.com/api/v1";

async function auditWebsite(url) {
  // 1. Start scan
  const scanRes = await fetch(`${BASE}/scan`, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ url }),
  });
  const { scan_uid } = await scanRes.json();

  // 2. Poll until complete
  let report;
  while (true) {
    await new Promise(r => setTimeout(r, 5000)); // wait 5s between polls
    const res = await fetch(`${BASE}/report/${scan_uid}`, {
      headers: { "Authorization": `Bearer ${API_KEY}` },
    });
    report = await res.json();
    if (report.status === "completed") break;
    console.log(`Still ${report.status}...`);
  }

  return report;
}

const result = await auditWebsite("https://example.com");
console.log("Overall score:", result.scores.overall);
console.log("Top priority:", result.priority_actions[0]);

Python — full scan + poll loop

REST API v1

python
import requests
import time

API_KEY = "brn_live_XXXXXXXX.YOUR_SECRET"
BASE = "https://brainito.com/api/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

def audit_website(url: str) -> dict:
    # 1. Start scan
    res = requests.post(f"{BASE}/scan", headers=HEADERS, json={"url": url})
    res.raise_for_status()
    scan_uid = res.json()["scan_uid"]

    # 2. Poll until complete
    while True:
        time.sleep(5)
        res = requests.get(f"{BASE}/report/{scan_uid}", headers=HEADERS)
        report = res.json()
        if report["status"] == "completed":
            return report
        print(f"Still {report['status']}...")

report = audit_website("https://example.com")
print("Overall score:", report["scores"]["overall"])
print("Top priority:", report["priority_actions"][0])

cURL — MCP protocol

Calling the MCP endpoint directly over HTTP

bash
# Initialize
curl -X POST https://brainito.com/api/mcp \
  -H "Authorization: Bearer brn_live_XXXXXXXX.YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}}}'

# Scan
curl -X POST https://brainito.com/api/mcp \
  -H "Authorization: Bearer brn_live_XXXXXXXX.YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"scan_website","arguments":{"url":"https://example.com"}}}'

Scopes

Scopes limit what a credential can do. Assign only the scopes your application actually needs.

ScopeAllowsUsed by
website.scanStart website marketing health scansPOST /api/v1/scan · scan_website
reports.readRead completed reportsGET /api/v1/report · GET /api/v1/reports · get_report · list_reports
reports.writeWrite / update report data (reserved)Future use

Rate Limits

Rate limits apply per credential using a sliding window and are consistent across both the REST API and MCP endpoints.

PlanRequests / minuteScans / dayConcurrent scans
Starter60501
Pro1202003
Agency3001,00010

When exceeded: REST API returns HTTP 429 with {"error": "Rate limit exceeded"}. MCP endpoint returns JSON-RPC error code: -32029. Use exponential backoff before retrying.

Errors

REST API errors

Plain JSON body with an error string.

json
HTTP/1.1 402 Payment Required
{ "error": "Insufficient credits. You have 40; a scan costs 100.", "available_credits": 40, "required_credits": 100 }
HTTP StatusMeaning
400 Bad RequestMissing or invalid request fields
401 UnauthorizedMissing or invalid Authorization header
402 Payment RequiredInsufficient credits
403 ForbiddenWrong scopes or plan level required
404 Not FoundReport not found or access denied
409 ConflictScan already running for this domain
429 Too Many RequestsRate limit exceeded — back off and retry
500 Internal Server ErrorUnexpected server error

MCP errors

JSON-RPC 2.0 error format inside the response body.

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32001,
    "message": "Invalid API key format"
  }
}
HTTPJSON-RPC codeMeaning
401-32001Missing or invalid Authorization header
403-32002Tool call rejected — scope or plan error
429-32029Rate limit exceeded
400-32600Invalid JSON-RPC request
404-32601Method not found
400-32602Invalid parameters
500-32603Internal server error
Questions or issues? Contact support or open an issue on our changelog page.