Developers

Analyze The Deal · API & MCP

Run ATD's deal-analysis engine programmatically. You get the same verdict, tier, and 3 scenario money model the web app produces, over the Model Context Protocol (MCP), so any MCP-capable AI tool or agent (Claude, Cursor, your own) can analyze a deal in one call.

Overview

The ATD API is delivered as an MCP server at https://tools.analyzethedeal.com/api/mcp. It exposes four tools: list the supported strategies, run an analysis, run a deep market report, and fetch a past run. A call returns a structured verdict (ACQUIRE / PILOT / PASS), a tier from S to D, and conservative / realistic / stretch scenarios (Y1 net, ROI, payback, ADR, occupancy).

Accuracy & honesty. Numbers come from ATD's underwriting engine plus live research; researched inputs carry a source and anestimated flag, and a preliminary run is markedmeta.partial. The API never fabricates a comp or a figure. Out of credits returns a clear error and a top up link, never a made up result.

Access. API / MCP access is a Team-tier feature. Create an API key in your account, then point your MCP client at the server. Every call debits the same credits as the web app.

Authentication

Every request authenticates with an API key in the Authorization header:

header
Authorization: Bearer atd_sk_YOUR_KEY

Keys start with atd_sk_ and are secret. Treat them like a password. Create and revoke keys in Account → API & MCP access. A key is shown once at creation and stored only as a hash; if you lose it, revoke it and create a new one (that's how you rotate; there is no separate rotate step). Keys can be revoked anytime by their owner. Never commit a key or put it in client-side code.

Getting started

1. In the web app, go to Account → API & MCP access and Generate a key (Team tier). Copy it. It's shown once. 2. Point an MCP client at the server (see MCP integration), or call it directly. MCP uses JSON-RPC 2.0 over Streamable HTTP; the raw calls below are illustrative. For production, prefer an MCP client or the official @modelcontextprotocol/sdk.

Your first call: analyze_deal (raw JSON-RPC):

curl
curl -sN https://tools.analyzethedeal.com/api/mcp \
  -H "Authorization: Bearer atd_sk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0", "id": 1, "method": "tools/call",
    "params": {
      "name": "analyze_deal",
      "arguments": {
        "address": "500 S Ervay St", "city": "Dallas", "state": "TX",
        "zip": "75201", "beds": 1, "baths": 1, "sqft": 1083,
        "rent": 2000, "strategy": "STR", "strAllowed": "unsure"
      }
    }
  }'
javascript
const res = await fetch("https://tools.analyzethedeal.com/api/mcp", {
  method: "POST",
  headers: {
    Authorization: "Bearer atd_sk_YOUR_KEY",
    "Content-Type": "application/json",
    Accept: "application/json, text/event-stream",
  },
  body: JSON.stringify({
    jsonrpc: "2.0", id: 1, method: "tools/call",
    params: { name: "analyze_deal", arguments: {
      address: "500 S Ervay St", city: "Dallas", state: "TX",
      zip: "75201", beds: 1, baths: 1, sqft: 1083,
      rent: 2000, strategy: "STR", strAllowed: "unsure",
    } },
  }),
});
const data = await res.json(); // JSON-RPC result → result.structuredContent
python
import requests
res = requests.post(
    "https://tools.analyzethedeal.com/api/mcp",
    headers={
        "Authorization": "Bearer atd_sk_YOUR_KEY",
        "Content-Type": "application/json",
        "Accept": "application/json, text/event-stream",
    },
    json={
        "jsonrpc": "2.0", "id": 1, "method": "tools/call",
        "params": {"name": "analyze_deal", "arguments": {
            "address": "500 S Ervay St", "city": "Dallas", "state": "TX",
            "zip": "75201", "beds": 1, "baths": 1, "sqft": 1083,
            "rent": 2000, "strategy": "STR", "strAllowed": "unsure",
        }},
    },
)
print(res.json())

Example response (structuredContent):

json
{
  "schemaVersion": "2026-06-19",
  "status": "done",
  "dealId": "a1b2c3d4-...",
  "creditsCharged": 1,
  "cached": false,
  "verdict": { "tier": "B", "verdict": "PILOT" },
  "result": {
    "verdict": "PILOT", "tier": "B",
    "scenarios": {
      "conservative": { "adr": 150, "occupancy": 55, "y1Net": 8200,  "monthlyNet": 683,  "roi": 12.4, "paybackMonths": 22 },
      "realistic":    { "adr": 185, "occupancy": 65, "y1Net": 14500, "monthlyNet": 1208, "roi": 21.9, "paybackMonths": 14 },
      "stretch":      { "adr": 220, "occupancy": 75, "y1Net": 21800, "monthlyNet": 1817, "roi": 32.7, "paybackMonths": 9  }
    },
    "domains": { "pest": { "score": "CLEAN", "summary": "...", "citations": [] } },
    "reasoning": "...", "redFlags": [], "greenFlags": [],
    "meta": { "tier3Run": false, "partial": false }
  }
}

If a run takes longer than a moment, the response is { "status": "running", "dealId": "…" }. Poll get_deal with that dealId in ~1 minute.

API reference

Four MCP tools. Credit costs are the same as the web app; internal accounts run uncharged.

list_strategies

No charge

List the supported analysis strategies and the inputs each needs.

Input
input
{}   // no arguments
Returns
returns
{ "schemaVersion": "2026-06-19",
  "strategies": [ { "key": "STR", "label": "Short term rental", "tagline": "…", "researchLive": true }, … ],
  "requiredInputs": ["address","city","state","zip","beds","baths","sqft","rent","strAllowed"] }

analyze_deal

1 credit (a recent cached run is free)

Run a full analysis and get the verdict, tier, and 3 scenario money model. Team tier; rate limited 30/min.

Input
input
{ "address": "500 S Ervay St", "city": "Dallas", "state": "TX",
  "zip": "75201", "beds": 1, "baths": 1, "sqft": 1083,
  "rent": 2000, "strategy": "STR", "strAllowed": "unsure",
  "inputs": { /* optional strategy extras: purchasePrice, marketRentMonthly, arv, … */ } }
Returns
returns
{ "schemaVersion", "status": "done"|"running", "dealId",
  "creditsCharged", "cached", "verdict": { "tier", "verdict" }, "result": ResearchResult }

run_deep_strfax

5 credits (Pro tier; refunded if the run fails)

Run the deep market report for a finished analysis: live comps, regulatory + landlord carfax, rate card. Returns 'running'; poll get_deal for the deepReport.

Input
input
{ "dealId": "a1b2c3d4-…"   // from a finished analyze_deal run }
Returns
returns
{ "schemaVersion", "status": "running"|"done", "dealId", "creditsCharged", "deepReport": DeepCompResult }

get_deal

No charge

Fetch a past run by id (and its deep report if present). You can only read your own deals.

Input
input
{ "id": "a1b2c3d4-…"   // the dealId returned by analyze_deal }
Returns
returns
{ "schemaVersion", "dealId", "status",
  "verdict"?: { "tier", "verdict" }, "result"?: ResearchResult, "deepReport"?: DeepCompResult }

Public read feeds (no key)

The published investor inventory is also available unauthenticated (read only, field filtered, no PII): GET /api/public/units and GET /api/public/deals. These power deals.revarity.com and are safe to consume from a browser.

MCP integration

This is the fastest path: connect ATD to any MCP capable AI tool and it can analyze deals in conversation. Server: https://tools.analyzethedeal.com/api/mcp (Streamable HTTP). Auth is youratd_sk_ key as a Bearer token.

Claude Desktop (via the mcp-remote bridge, which injects the auth header):

claude_desktop_config.json
{
  "mcpServers": {
    "analyzethedeal": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://tools.analyzethedeal.com/api/mcp",
        "--header", "Authorization: Bearer atd_sk_YOUR_KEY"]
    }
  }
}

Cursor (native remote MCP with headers):

mcp.json
{
  "mcpServers": {
    "analyzethedeal": {
      "url": "https://tools.analyzethedeal.com/api/mcp",
      "headers": { "Authorization": "Bearer atd_sk_YOUR_KEY" }
    }
  }
}

Once connected, tell the agent: “Analyze 500 S Ervay St, Dallas TX, 1bd/1ba, 1083 sqft, $2,000 rent, as a short term rental.” It calls analyze_deal, gets the verdict + money model, and can then call run_deep_strfax for the deep report.

Rate limits & credits

  • analyze_deal & run_deep_strfax: 30 requests / minute per account. Exceeding returns a clear “Rate limit reached (30/min)” error.
  • list_strategies & get_deal: unmetered.
  • Credits: analyze_deal = 1 (a recent cached run is free); run_deep_strfax = 5 (refunded if it fails); the other two are free.
  • Out of credits → a clear error with a top up link (/account), never a fabricated result.

Errors

A bad or missing API key is rejected at the transport with HTTP 401. Tool-level problems come back as an MCP error result: isError: true with a plain text message (not an HTTP status). Common messages:

MessageFix
HTTP 401 (transport)Missing/invalid key. Check the Authorization header and that the key isn't revoked.
Unauthorized. Generate an API key…The key resolved to no account. Create a key in Account → API & MCP access.
API / MCP access is a Team tier feature.Upgrade to Team to use analyze_deal / run_deep_strfax.
Rate limit reached (30/min).Pause briefly and retry; batch fewer calls per minute.
Out of credits (+ top up link)Top up at /account, then retry.
Invalid inputs. <field: message>Fix the flagged field(s); see analyze_deal's input schema.
Not found.get_deal: the dealId is unknown, expired, or not yours.

Changelog

  • 2026-06-19 · Response schemaVersion introduced; every tool payload is versioned so future changes don't silently break agents. Four tools live: list_strategies, analyze_deal, run_deep_strfax, get_deal.

Response shapes are versioned via schemaVersion (currently 2026-06-19). Pin to it and treat additive fields as forward-compatible.