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 (requires the 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. |
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. Max is unlimited.
Deep Scan credits
deep_scan spends 1 credit per call. Max includes 50/mo.
Interact credits
interact spends 1 credit per call (and implies deep_scan). Max includes 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.
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"
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.