BrumeDomain Intelligence
API Documentation
Version 1.0 · REST over HTTPS · NDJSON streaming or JSON · 10 requests per minute.
Contents
Introduction
Brume exposes a RESTful API for programmatic domain intelligence. All endpoints are available at https://brume.work/api/v1/
Authentication
No authentication required. Rate limited to 10 scans per minute per IP.
Scan domain
GET /api/v1/scan?domain={domain}
GET /api/v1/scan/{domain}
Scan a domain and return its findings. By default the response is an NDJSON stream of events, one JSON object per line, flushed as each module runs. Send Accept: application/json to receive the complete result once the scan finishes.
Parameters
Headers
Example request
# NDJSON stream (the default)
curl -N "https://brume.work/api/v1/scan?domain=stripe.com"
# Full JSON result (path-parameter variant)
curl -H "Accept: application/json" "https://brume.work/api/v1/scan/stripe.com"Example response
{
"domain": "stripe.com",
"startedAt": "2026-10-25T14:02:08.114Z",
"completedAt": "2026-10-25T14:02:22.317Z",
"progress": {
"dns": "complete",
"identity": "complete",
"http": "complete",
"infrastructure": "complete"
},
"findings": [
{
"id": "mx-google",
"category": "email",
"service": "Google Workspace",
"confidence": 0.98,
"method": "MX record analysis",
"evidence": ["aspmx.l.google.com", "alt1.aspmx.l.google.com"],
"tags": ["email", "mx"],
"url": "https://workspace.google.com"
}
],
"summary": {
"totalFindings": 148,
"highConfidence": 97,
"categories": { "email": 6, "dns": 24, "identity": 4, "security": 11 },
"services": ["Amazon Web Services", "Cloudflare", "Google Workspace", "Okta"]
}
}The streaming response carries the same data as a sequence of events — see Streaming format.
Status codes
Health
GET /api/v1/health
Liveness and metadata. Returns the service status, the API version and the detection modules a scan runs.
Example response
{
"status": "ok",
"version": "1.0.0",
"modules": [
"dns", "dnsDeep", "subdomains", "identity", "http",
"infrastructure", "endpoints", "attackSurface", "tenants",
"orgIntel", "apps", "github", "cloudStorage", "wellKnown"
]
}Response schema
Every finding in a report is a Finding:
interface Finding {
id: string
category: 'email' | 'dns' | 'identity' | 'infrastructure' | 'saas' | 'security'
service: string
confidence: number
method: string
evidence: string[]
tags: string[]
url?: string
risk?: string
metadata?: Record<string, string>
}Streaming format
The default response is newline-delimited JSON: one event object per line, flushed as the scan progresses. Four event types appear.
progress— a module changed state (scanning, complete, error).findings— a batch of findings from a module.error— a single module failed; the scan continues.complete— the final result, identical to the JSON response.
{"type": "progress", "module": "dns", "status": "scanning"}
{"type": "findings", "module": "dns", "data": [ ... ]}
{"type": "progress", "module": "dns", "status": "complete"}
{"type": "error", "module": "github", "message": "request timed out"}
{"type": "complete", "data": { ... }}Modules
A scan runs these detection modules concurrently. The module field on each event names the module, and /health lists them. Further intelligence — security posture, identity chain, network topology, CVE mapping and more — is derived after the modules settle and folded into the final findings.
DNS & Email
dns
Nameservers, registrar, mail exchangers and the SPF, DKIM, DMARC and SOA records that decide who may send as the domain.
Deep DNS
dnsDeep
Records the primary pass omits: SSHFP, DANE/TLSA, OPENPGPKEY, DNSLink, HTTPS/SVCB with ECH, and LOC.
Subdomains
subdomains
Every hostname disclosed in certificate transparency logs, sorted and counted.
Identity
identity
Single sign-on providers, SAML and OIDC endpoints, and the federation path a user takes to sign in.
HTTP
http
Server, framework, CMS and CDN fingerprints drawn from response headers and the landing HTML.
Infrastructure
infrastructure
CDN, hosting provider, WAF, ASN attribution and the live TLS certificate behind the front door.
Endpoints
endpoints
Service endpoints probed on resolved hosts — Grafana, Vault, Teleport, GitLab and similar self-managed tools.
Attack surface
attackSurface
OpenAPI, GraphQL and exposed-path discovery across the subdomains and endpoints found so far.
Tenants
tenants
SaaS workspace and tenant discovery derived from the organisation's slug.
Organisation
orgIntel
Organisation identity: company metadata, GitHub organisation and related slugs.
Mobile apps
apps
Published applications on the App Store and Google Play.
GitHub
github
Public repositories, CI/CD workflow fingerprints and infrastructure signals from the organisation's GitHub presence.
Cloud storage
cloudStorage
Publicly reachable S3, GCS and Azure Blob buckets inferred from the domain and organisation name.
Well-known
wellKnown
`.well-known` resources: security.txt, JWKS, WebFinger, change-password, host-meta, Matrix, NodeInfo and more.
Code examples
# Stream findings as NDJSON
curl -N "https://brume.work/api/v1/scan?domain=stripe.com"
# Wait for the complete result as JSON
curl -H "Accept: application/json" "https://brume.work/api/v1/scan/stripe.com"
# Service health
curl "https://brume.work/api/v1/health"import requests
resp = requests.get(
"https://brume.work/api/v1/scan/stripe.com",
headers={"Accept": "application/json"},
timeout=60,
)
resp.raise_for_status()
report = resp.json()
for finding in report["findings"]:
print(finding["service"], finding["confidence"])// Read the NDJSON stream line by line.
const res = await fetch(
"https://brume.work/api/v1/scan?domain=stripe.com",
)
const reader = res.body.getReader()
const decoder = new TextDecoder()
let buffer = ""
while (true) {
const { value, done } = await reader.read()
if (done) break
buffer += decoder.decode(value, { stream: true })
const lines = buffer.split("\n")
buffer = lines.pop() ?? ""
for (const line of lines) {
if (!line.trim()) continue
const event = JSON.parse(line)
console.log(event.type, event.module ?? "")
}
}package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET",
"https://brume.work/api/v1/scan/stripe.com", nil)
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var report map[string]any
json.NewDecoder(resp.Body).Decode(&report)
for _, raw := range report["findings"].([]any) {
f := raw.(map[string]any)
fmt.Printf("%s %v\n", f["service"], f["confidence"])
}
}Rate limits
The API is limited to 10 requests per minute per IP. Requests beyond the limit receive a 429 Too Many Requests response. Every response carries X-RateLimit-Limit and X-RateLimit-Remaining headers, alongside X-Brume-Version.