TechSpy API
POST a domain and get back its detected tech stack, DNS/DMARC posture, subdomains, and hidden APIs as structured JSON. It's the same engine that powers the app — a single endpoint whose stages you toggle with boolean flags, so one call can be a fast tech-stack read or a full deep audit.
https://techspy.hi-daniel.com/api/analyzeQuickstart
- 1
Generate a key on the API settings page (Plus or Max plan).
- 2
Send a
POSTto/api/analyzewith your key in theAuthorizationheader. - 3
Read the JSON —
tech_stackis grouped by category, each finding named and versioned.
curl -X POST https://techspy.hi-daniel.com/api/analyze \
-H "Authorization: Bearer ts_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://stripe.com",
"static_analysis": true,
"dns_scan": true,
"subdomain_analysis": true
}'Authentication
Every request is authenticated with a Bearer API key. Keys are prefixed ts_, generated on the API settings page, and available on the Max plan. The key is shown once at creation — store it securely; only a hash is kept on our side.
Authorization: Bearer ts_YOUR_API_KEYRegenerating a key invalidates the old one immediately. If a key leaks, revoke it from the settings page.
POST /api/analyze
There is a single endpoint. Which stages run is controlled entirely by the boolean flags in the body — so one call can be a fast tech-stack read or a full deep audit.
https://techspy.hi-daniel.com/api/analyzeParameters
JSON body. Only url is required; every stage flag defaults off except static_analysis.
| Field | Type | Default | Description |
|---|---|---|---|
url | string | — | Required. The website to analyze, e.g. https://stripe.com. |
static_analysis | boolean | true | Tech-stack detection (HTML + JS-runtime + HTTP headers). On by default. |
dns_scan | boolean | false | DNS / DMARC / SPF / DKIM audit, CDN, TLS, email provider. |
subdomain_analysis | boolean | false | Discover subdomains and group them by layer (app, docs, api…). |
sitemap_scan | boolean | false | Parse sitemap structure and page tree. |
deep_scanPaid | boolean | false | Headless render + HAR capture — surfaces hidden APIs & SDKs. Takes minutes. Consumes 1 Deep Scan credit. |
interactPaid | boolean | false | LLM drives the page (click/fill) to reveal post-interaction tools. Implies deep_scan. Consumes 1 Interact credit. |
force | boolean | false | Bypass per-stage caches and force a fresh scan. |
save | boolean | false | Set true to save an API-key scan to your scan history (dashboard, Zapier's New Saved Scan, MCP) and get saved_scan_id back. The MCP server and CLI save by default. |
Response
200 OK with the analysis. Sections beyond tech_stack only appear when their flag was set. Each finding carries a confidence marker; a blocked scan is reported honestly in warnings rather than faked.
{
"url": "https://stripe.com",
"status": "completed",
"analyzed_at": "2026-07-07T18:20:04.512Z",
"tech_stack": {
"Framework": [{ "name": "Next.js", "version": "14" }],
"Hosting & CDN": [{ "name": "Cloudflare" }],
"Analytics": [{ "name": "Segment" }],
"Payment": [{ "name": "Stripe" }]
},
"dns": {
"cdn": "Cloudflare",
"dns_provider": "Cloudflare",
"email_provider": "Google Workspace",
"tls_issuer": "Let's Encrypt",
"email_security": { "spf": "pass", "dmarc": "reject" },
"scorecard": { "grade": "A", "overall": 92, "security": 88 }
},
"subdomains": [{ "hostname": "dashboard.stripe.com" }],
"layers": { "app": { "label": "Application", "subdomains": ["dashboard.stripe.com"] } },
"api_domains": [],
"pages_analyzed": ["stripe.com"],
"warnings": null,
"static_analysis": true,
"dns_scan": true,
"subdomain_analysis": true,
"deep_scan": false,
"interact": false
}Rate limits & tiers
API calls draw on the same allowances as the app. Every response includes an X-RateLimit-Remaining header.
Daily scans
Every call counts against your plan's daily scan cap: Plus 30/day, Max unlimited. Resets 00:00 UTC.
Deep Scan credits
deep_scan spends 1 credit per call. Plus includes 10/mo, Max 50/mo.
Interact credits
interact spends 1 credit per call (and implies deep_scan). Plus includes 5/mo, Max 25/mo.
Over a limit, the API returns 402 with a message — any credits consumed on a rejected call are refunded automatically.
Errors
Errors return a JSON body of the form { "error": "…" } with the status below.
Account & saved scans
Check your budget before scanning, then read back saved scans and their strategy analysis. None of these use credits.
GET /api/accountPlan, today's scans used / remaining, and Deep Scan / Interact credits left.GET /api/scans/list?limit=&offset=Your saved scans, newest first (paginated).GET /api/scans/{id}One saved scan with its full result.GET /api/scans/{id}/analysisThe five-pillar strategy analysis, if one exists.POST /api/scans/{id}/analysisGenerate it (free; cached). body { "force": true } regenerates: your own scans only, once per scan per 24h. Max 10 generations per hour per IP. Takes a few minutes; returns 202 { status: "generating" } if one is already running.curl https://techspy.hi-daniel.com/api/account \
-H "Authorization: Bearer ts_YOUR_API_KEY"{
"email": "you@company.com",
"tier": "plus",
"api_access": true,
"daily_scans": { "limit": 30, "used": 4, "remaining": 26, "resets_at": "2026-10-01T00:00:00.000Z" },
"credits": { "deep_scan": 9, "interact": 5 }
}null limit / remaining means unlimited (Max).
Automation endpoints
Beyond the scan endpoint, these power the Zapier triggers and let you pull report feeds, sync saved scans, and manage domain monitoring directly with your API key.
Automation & Monitoring (/api/zapier/*)
These endpoints back the Zapier integration, but you can call them directly with a Bearer ts_ key. Use them to pull report feeds, look up your saved scans, manage domain watches, and read detected changes. Base URL: https://techspy.hi-daniel.com. Every endpoint requires auth, scopes to your own data, and returns newest-first arrays. Each item includes a stable id for deduping.
GET /api/zapier/reports
- Returns the newest published reports across all content types. Use it to post new reports to Slack or a newsletter as they go live.
- Auth: Bearer
ts_API key - Returns: array of
{ id, title, content_type, slug, url, published_at }
curl https://techspy.hi-daniel.com/api/zapier/reports \
-H "Authorization: Bearer ts_YOUR_API_KEY"
GET /api/zapier/scans
- Returns your recent saved scans with tech and DNS summaries. Use it to sync scan results into a sheet or CRM.
- Auth: Bearer
ts_API key - Returns: array of
{ id, url, created_at, tech_count, tech_summary, dns_grade }
curl https://techspy.hi-daniel.com/api/zapier/scans \
-H "Authorization: Bearer ts_YOUR_API_KEY"
GET /api/zapier/watches
- Returns the domains you are watching for changes.
- Auth: Bearer
ts_API key - Returns: array of
{ id, url, created_at, last_checked_at }
curl https://techspy.hi-daniel.com/api/zapier/watches \
-H "Authorization: Bearer ts_YOUR_API_KEY"
POST /api/zapier/watches
- Adds a domain to your watch list. This is an upsert: calling it again with the same URL returns the existing watch instead of creating a duplicate.
- Auth: Bearer
ts_API key - Body params:
| Param | Type | Default | Description |
|---|---|---|---|
url |
string | — | Domain URL to watch |
- Returns:
{ id, url, created_at, watching }wherewatchingis alwaystrue
curl -X POST https://techspy.hi-daniel.com/api/zapier/watches \
-H "Authorization: Bearer ts_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://stripe.com"}'
DELETE /api/zapier/watches
- Removes a watch you own. Pass the watch
idreturned by the GET or POST calls above. - Auth: Bearer
ts_API key - Query params:
| Param | Type | Default | Description |
|---|---|---|---|
id |
string | — | ID of the watch to remove |
- Returns:
{ ok }whereokistrue
curl -X DELETE "https://techspy.hi-daniel.com/api/zapier/watches?id=wch_1a2b3c" \
-H "Authorization: Bearer ts_YOUR_API_KEY"
GET /api/zapier/changes
- Returns recent changes detected for your account, filtered by
type. Use it to trigger an alert when a domain adds a tech, exposes a new subdomain, or changes an email record. Which fields are populated depends ontype:techandsubdomainchanges useitem(and may includeitems);emailchanges usefield,old_value, andnew_value. - Auth: Bearer
ts_API key - Query params:
| Param | Type | Default | Description |
|---|---|---|---|
type |
string | — | Change type: tech, subdomain, or email |
- Returns: array of
{ id, url, change_type, detected_at, item, items, field, old_value, new_value }. Present fields depend ontype—tech/subdomainpopulateitem/items;emailpopulatesfield,old_value,new_value.
curl "https://techspy.hi-daniel.com/api/zapier/changes?type=tech" \
-H "Authorization: Bearer ts_YOUR_API_KEY"
MCP for AI agents
TechSpy runs as a remote MCP server so Claude Code, Cursor and other agents can scan sites and read results as native tools. It uses Streamable HTTP at https://techspy.hi-daniel.com/api/mcp and your API key — same daily scans and credits as the REST API. See what agents can do with it.
Claude Code
claude mcp add --transport http techspy https://techspy.hi-daniel.com/api/mcp \
--header "Authorization: Bearer ts_YOUR_API_KEY"Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"techspy": {
"url": "https://techspy.hi-daniel.com/api/mcp",
"headers": { "Authorization": "Bearer ts_YOUR_API_KEY" }
}
}
}Any client that supports remote Streamable HTTP servers with a custom header works the same way. The key is also accepted without the Bearer prefix or as an x-api-key header.
scan_domainDetect a site's tech stack; optional dns, subdomains, sitemap, deep, interact. Uses 1 daily scan (+ credits for deep / interact) and returns a saved_scan_id.get_accountPlan, scans left today and remaining credits. Free.list_scansYour saved scans, newest first. Free.get_scanTech stack, DNS grade, subdomains and sitemap summary of a saved scan. Free.get_strategy_analysisFive-pillar strategy analysis of a saved scan; generate: true creates one. No credits.Out of scans or credits, a tool returns the API's 402 message unchanged so the agent can tell you why.
Command-line (CLI)
The techspy CLI wraps the same API for terminals, scripts and coding agents. Node 18+, no install needed with npx.
export TECHSPY_API_KEY=ts_YOUR_API_KEY # or: npx techspy login
npx techspy scan stripe.com
npx techspy scan stripe.com --dns --subdomains --json
npx techspy account
npx techspy scans list
npx techspy analysis <scan-id> --generate--json prints machine-readable output, and exit codes tell agents what happened without parsing text: 3 invalid key, 4 out of scans or credits (402), 5 rate limited, 6 not found.
Use with Zapier (no app required)
You don't need a published Zapier integration to automate TechSpy. Add a Webhooks by Zapier → Custom Request action and point it at the endpoint with your key:
Method: POST
URL: https://techspy.hi-daniel.com/api/analyze
Headers: Authorization | Bearer ts_YOUR_API_KEY
Content-Type | application/json
Data: { "url": "{{trigger.domain}}", "dns_scan": true }Map any field from an earlier Zap step into url, and use the returned JSON in later steps.
Prefer the native integration? The TechSpy for Zapier guide covers all 5 triggers and 9 actions, including domain-change monitoring.
Ready to build?
Generate a key and make your first call in under a minute.