API docs
NetKnife’s REST API — every endpoint that powers this site is public and queryable directly. Endpoints marked auth required need an X-API-Key header — get one on the account page. Unauthenticated requests are limited to 120 req/min per IP; with a key, 600 req/min.
Core lookup
Full route detail for a CIDR or bare IP — AS path, decoded communities, RPKI/IRR state, vantage point, bogon flag.
Example
{
"prefix": "204.69.247.0/24",
"as_path": [394177, 18636],
"origin_asn": 18636,
"path_type": "best",
"communities": [ /* array of Community */ ],
"rpki": { "state": "valid", "origin_asn": 18636, "matched_roas": [...], "checked_at": "..." },
"irr": { "match": true, "source_irr": "RADB", "registered_origins": [18636], "checked_at": "..." },
"vantage_point": "rrc00 (via 12.0.1.63)",
"observed_at": "2026-09-24T00:39:00Z",
"data_source": "ris_live_stream",
"is_bogon": false,
"hops": [ /* array of AS hop */ ]
}Every distinct currently-observed feed's own view of a prefix (not collapsed to one "best" row) — the multi-vantage-point comparison.
Example
{
"prefix": "204.69.247.0/24",
"vantage_points": [
{ "vantage_point": "rrc00 (via 12.0.1.63)", "peer_asn": 3356, "as_path": [3356, 18636],
"origin_asn": 18636, "communities": [...], "is_withdrawal": false, "observed_at": "..." }
]
}ASN profile — org info, announced prefixes, upstreams/peers/downstreams (each capped at 50 with an honest *_total count).
Example
{
"asn": 18636,
"org_name": "Example Org",
"org_country": "US",
"network_type": "content",
"announced_prefixes": ["204.69.247.0/24"],
"upstreams": [{ "asn": 394177, "org_name": "...", "relationship": "provider" }],
"upstreams_total": 1,
"peers": [...], "peers_total": 1,
"downstreams": [...], "downstreams_total": 1
}Every currently-observed AS path involving this ASN.
Example
{
"asn": 18636,
"paths": [{ "prefix": "204.69.247.0/24", "as_path": [394177, 18636], "peer_asn": 3356,
"vantage_point": "rrc00", "observed_at": "..." }]
}Cytoscape-ready {nodes, edges} graph, depth-limited from an ASN (default 2, max 4).
Example
{
"nodes": [
{ "id": "18636", "asn": 18636, "org_name": "Example Org", "tier": "origin", "network_type": "content" },
{ "id": "3356", "asn": 3356, "org_name": "Lumen (Level 3)", "tier": "tier1", "network_type": "tier1" }
],
"edges": [{ "source": "18636", "target": "3356", "relationship": "customer", "weight": 3 }]
}RPKI validation state only, lightweight.
Example
{
"prefix": "204.69.247.0/24", "state": "valid", "origin_asn": 18636,
"matched_roas": [...], "checked_at": "..."
}Free-text search across prefixes, ASNs, and org names. Capped at 20 results.
Example
{
"results": [
{ "type": "prefix", "value": "204.69.247.0/24", "label": "204.69.247.0/24" },
{ "type": "asn", "value": "18636", "label": "AS18636 — Example Org" }
]
}Per-dependency status + collector lag. No cache, no rate limit.
Example
{
"status": "ok", "postgres": "ok", "clickhouse": "ok", "redis": "ok",
"routinator": "ok", "collector_lag_seconds": 4.2
}Read-only review queue of pending community submissions — no auth needed to read.
Example
{
"submissions": [{ "id": 14, "asn": 174, "community_value": "174:12345", "meaning": "...",
"category": "other", "source": "contributor", "confidence": "pending", "created_at": "...",
"votes_up": 2, "votes_down": 0, "score": 2 }]
}Submit a proposed community meaning. Duplicate (asn, community_value) → 409.
Example
// body: { "community_value": "174:21001", "meaning": "...", "category": "geographic" }
// 201, confidence: "pending", source: "contributor"Up/down-vote a pending submission. Net score reaching +3 auto-promotes it to confidence: verified.
Example
// body: { "direction": "up" | "down" }
// 200: the updated row plus votes_up/votes_down/scoreDev-convenience key minting — no email verification. Idempotent per email (returns the existing key if one exists).
Example
// body: { "email": "you@example.com", "display_name": "optional" }
// 200: { "api_key": "..." }Historical / time-travel
Built entirely from data already in ClickHouse (both live and RouteViews-imported history share one table). No RIPEstat fallback — that's only a current-state snapshot.
What a CIDR's route looked like at a specific past time. 404 if nothing was observed that far back.
Example
{
"prefix": "204.69.247.0/24", "as_path": [...], "origin_asn": 18636,
"communities": [...], "rpki": { "state": "valid", "note": "reflects current RPKI state for the historical origin, not a point-in-time ROA snapshot" },
"vantage_point": "...", "observed_at": "...",
"as_of": "2026-09-24T12:00:00Z", "data_source": "historical", "hops": [...]
}The AS-path change history for a CIDR — one entry per contiguous era where the path stayed the same, newest first, capped at 100.
Example
{
"prefix": "204.69.247.0/24",
"eras": [{ "as_path": [394177, 18636], "origin_asn": 18636, "is_withdrawal": false,
"first_seen": "...", "last_seen": "..." }]
}IP tools
Reverse DNS.
Example
{ "ip": "1.1.1.1", "ptr": "one.one.one.one" }Up to 500 IPs → covering prefix, origin ASN, org, RPKI state in one request.
Example
// body: { "ips": ["1.1.1.1", "8.8.8.8"] }
{ "results": [{ "ip": "1.1.1.1", "prefix": "1.1.1.0/24", "origin_asn": 13335,
"org_name": "Cloudflare Inc.", "rpki_state": "valid" }] }IP geolocation via ip-api.com (free, no key).
Example
{ "ip": "1.1.1.1", "country": "Australia", "country_code": "AU", "city": "Sydney",
"lat": -33.8, "lon": 151.2, "org": "Cloudflare", "source": "ip-api" }DNSBL check across zen.spamhaus.org, b.barracudacentral.org, dnsbl.sorbs.net.
Example
{ "ip": "...", "listed": false,
"zones": [{ "zone": "zen.spamhaus.org", "listed": false, "reason": null }] }Pure local range check (RFC 1918/5737/6598, loopback, link-local, multicast, reserved) — no external call.
Example
{ "prefix": "10.0.0.0/8", "is_bogon": true, "reason": "RFC 1918 private range" }DNS tools
A/AAAA/MX/TXT/NS/SOA/CNAME lookup.
Example
{ "name": "example.com", "type": "A", "records": ["1.2.3.4"] }Fans out to Cloudflare + Google DoH in parallel to compare answers.
Example
{ "name": "example.com", "type": "A",
"resolvers": [{ "resolver": "Cloudflare", "records": ["1.2.3.4"], "error": null },
{ "resolver": "Google", "records": ["1.2.3.4"], "error": null }] }Reads the AD flag from Cloudflare's DoH resolver — defers to their validation, not a from-scratch chain checker.
Example
{ "name": "example.com", "has_ds": true, "validated": true, "detail": "..." }Domain RDAP (registrar, dates, nameservers) — same bootstrap pattern as ASN RDAP.
Example
{ "domain": "example.com", "registrar": "...", "created": "...", "expires": "...",
"nameservers": [...], "source": "rdap" }SPF/DMARC check, plus DKIM if a selector is provided (selectors aren't discoverable).
Example
{ "domain": "example.com",
"spf": { "record": "...", "valid": true, "issues": [] },
"dmarc": { "record": "...", "valid": true, "policy": "reject" },
"dkim": null }Compares parent-zone NS delegation against the authoritative NS set.
Example
{ "domain": "example.com", "parent_ns": [...], "authoritative_ns": [...],
"match": true, "glue_issues": [] }Checks whether a prefix's reverse zone is properly delegated.
Example
{ "prefix": "204.69.247.0/24", "reverse_zone": "247.69.204.in-addr.arpa",
"delegated": true, "ns": [...], "sample_ptr_check": { "ip": "...", "resolves": true } }Looking glass (RIPE Atlas)
Requires the server to have a RIPE_ATLAS_API_KEY configured — without one, both endpoints return 503 with a clear "not configured" message.
Creates a one-off ping or traceroute from real RIPE Atlas probes worldwide.
Example
// body: { "type": "ping", "target": "1.1.1.1", "probe_count": 5, "af": 4 }
// 201: { "measurement_id": 12345678, "status": "scheduled" }Poll for results — null until RIPE Atlas has data (frontend polls ~every 5s).
Example
{ "measurement_id": 12345678, "status": "stopped", "type": "ping", "target": "1.1.1.1",
"results": [{ "probe_id": 1001, "country": "US", "rtt_ms": 4.2, "hops": null }] }Diagnostics
No auth, no external API key needed for any of these five.
TLS certificate inspector — connects with rejectUnauthorized: false deliberately, so it can inspect invalid/self-signed/expired certs, not just reject them.
Example
{ "host": "example.com", "port": 443, "subject": "CN=example.com", "issuer": "CN=...",
"valid_from": "...", "valid_to": "...", "subject_alt_names": [...], "protocol": "TLSv1.3",
"cipher": "TLS_AES_256_GCM_SHA384", "is_expired": false, "is_self_signed": false }HTTP header/security inspector. Follows no redirects — a redirect is reported, not chased.
Example
{ "url": "https://example.com", "status": 200, "redirect_location": null,
"headers": { "...": "..." },
"security": { "hsts": true, "csp": false, "x_frame_options": true,
"x_content_type_options": true, "referrer_policy": true } }Server-side traceroute (-n -w 1 -q 1 -m 30, capped at 15s). Reverse DNS is disabled so one slow hop can't stall the whole run.
Example
{ "target": "1.1.1.1",
"hops": [{ "hop": 1, "ip": "10.0.0.1", "hostname": null, "rtt_ms": 1.234 },
{ "hop": 2, "ip": null, "hostname": null, "rtt_ms": null }] }ASN allocation history via RDAP events (registration, last changed).
Example
{ "asn": 13335, "handle": "AS13335", "name": "...", "country": "US",
"events": [{ "action": "registration", "date": "2010-07-14T18:35:57-04:00" }] }MAC address / OUI vendor lookup via api.macvendors.com (free, no key).
Example
{ "mac": "AA:BB:CC:DD:EE:FF", "oui": "AABBCC", "vendor": "Example Vendor, Inc." }Saved lookups
A per-user bookmark list — not the same as the internal collector watchlist.
Save a prefix or ASN with an optional label. Re-saving the same (kind, value) just updates the label.
Example
// body: { "kind": "prefix", "value": "204.69.247.0/24", "label": "my network" }
// 201: { "id": 1, "user_id": 3, "kind": "prefix", "value": "204.69.247.0/24",
// "label": "my network", "created_at": "..." }Your own saved lookups, newest first, each with a lightweight live-status snapshot.
Example
{ "saved_lookups": [
{ "id": 1, "kind": "prefix", "value": "204.69.247.0/24", "label": "my network",
"created_at": "...", "status": { "origin_asn": 18636, "is_withdrawal": false } }
] }Deletes only your own row — 404 either way if it's not yours or doesn't exist.
Example
// 200: { "deleted": true, "id": 1 }Alerting
Route hijack/leak-style watch notifications for a prefix or ASN. A background checker polls every active subscription and fires on a real change — never on the first check tick, since that's just establishing a baseline.
Create or update a watch subscription. At least one of webhook_url / email_enabled is required (400 no_delivery_method otherwise).
Example
// body: { "kind": "prefix", "value": "204.69.247.0/24", "watch_origin_change": true,
// "watch_rpki_change": true, "webhook_url": "https://example.com/hooks/netknife" }
// 201: the created/updated subscription, last_origin_asn/last_rpki_state both null until
// the first check establishes a baselineYour own subscriptions, newest first.
Example
{ "subscriptions": [ /* subscription rows */ ] }Deletes only your own subscription.
Example
// 200: { "deleted": true, "id": 14 }Recent firings for one subscription (origin/RPKI changes, delivery status), newest first, capped at 50.
Example
{ "events": [{ "id": 1, "event_type": "origin_change", "detail": { "...": "..." },
"created_at": "...", "delivered": true, "delivery_error": null }] }