Web API
Note
The endpoints below are listed under their application
paths – the paths each route handler registers. At runtime
the application is usually served under a deployment-specific
mount prefix, so every route is reached one level deeper than
it appears here. ivre httpd and the bundled NGINX example
use /cgi/ (/scans is reached at /cgi/scans,
/audit/ at /cgi/audit/, and so on); the bundled Apache
example instead mounts the application at /ivre/cgi.
Prepend your deployment’s prefix, if any, to every path in
this reference when calling the API (a deployment that mounts
the application at the root serves the paths exactly as shown).
- GET /config
Returns JavaScript code to set client-side configuration values
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
- Response JSON Object:
config (object) – the configuration values
- GET /(subdb:re:scans|view)/(action:re:onlyips|ipsports|timeline|coordinates|countopenports|diffcats)
Get special values from Nmap & View databases
- Parameters:
subdb (str) – database to query (must be “scans” or “view”)
action (str) – specific value to get (must be one of “onlyips”, “ipsports”, “timeline”, “coordinates”, “countopenports” or “diffcats”)
- Query Parameters:
q (str) – query (including limit/skip and sort)
f (str) – filter
ipsasnumbers (bool) – to get IP addresses as numbers rather than as strings
datesasstrings (bool) – to get dates as strings rather than as timestamps
format (str) – “json” (the default), “ndjson” or “txt”
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – module is not exposed by this server
- Response JSON Array of Objects:
object – results
- GET /(subdb:re:scans|view)/count
Get special values from Nmap & View databases
- Parameters:
subdb (str) – database to query (must be “scans” or “view”)
- Query Parameters:
q (str) – query (including limit/skip and sort)
f (str) – filter
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – module is not exposed by this server
- Response JSON Object:
int – count
- GET /(subdb:re:scans|view|passive|rir)/top/(field: path)
Get top values from Nmap, View, Passive & RIR databases
- Parameters:
subdb (str) – database to query (must be “scans”, “view”, “passive” or “rir”)
field (str) – (pseudo-)field to get top values (e.g., “service”)
- Query Parameters:
q (str) – query (including limit/skip and sort)
f (str) – filter
ipsasnumbers (bool) – to get IP addresses as numbers rather than as strings
datesasstrings (bool) – to get dates as strings rather than as timestamps
format (str) – “json” (the default) or “ndjson”
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – module is not exposed by this server
- Response JSON Array of Objects:
label (str) – field value
value (int) – count for this value
- GET /(subdb:re:scans|view|passive|rir)/distinct/(field: path)
Get distinct values from Nmap, View, Passive & RIR databases
- Parameters:
subdb (str) – database to query (must be “scans”, “view”, “passive” or “rir”)
field (str) – (pseudo-)field to get distinct values (e.g., “service”)
- Query Parameters:
q (str) – query (including limit/skip and sort)
f (str) – filter
ipsasnumbers (bool) – to get IP addresses as numbers rather than as strings
datesasstrings (bool) – to get dates as strings rather than as timestamps
format (str) – “json” (the default) or “ndjson”
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – module is not exposed by this server
- Response JSON Array of Objects:
label (str) – field value
value (int) – count for this value
- GET /(subdb:re:scans|view)
Get records from Nmap & View databases
- Parameters:
subdb (str) – database to query (must be “scans” or “view”)
- Query Parameters:
q (str) – query (including limit/skip and sort)
f (str) – filter
ipsasnumbers (bool) – to get IP addresses as numbers rather than as strings
datesasstrings (bool) – to get dates as strings rather than as timestamps
format (str) – “json” (the default) or “ndjson”
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – module is not exposed by this server
- Response JSON Array of Objects:
object – results
- POST /(subdb:re:scans|view)
Add records to Nmap & View databases
- Parameters:
subdb (str) – database to query (must be “scans” or “view”)
- Form Parameters:
categories – a coma-separated list of categories
source – the source of the scan results (mandatory)
result – scan results (as XML or JSON files)
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer, source or username missing
403 Forbidden – uploads disabled (
WEB_UPLOAD_OKisFalse)404 Not Found – module is not exposed by this server
- Response JSON Object:
count (int) – number of inserted results
- GET /flows
Get a flow graph, count, or details payload.
The query is JSON-encoded under the
qURL parameter and carriesnodes/edgesfilter lists in theflow.Querygrammar plus the pagination / mode knobs listed below.action=detailsreturns details for a single node or edge instead of a graph.- Query Parameters:
q (str) –
JSON-encoded query object. Recognised keys:
nodeslist of node-filter clausesedgeslist of edge-filter clauseslimitcap on returned edges; defaults toconfig.WEB_GRAPH_LIMIT(1000)
skippagination offset; defaults to0modedefault/flow_map/talk_mapcounttruereturns ``{clients, servers,flows}`` instead of the graph
orderbysrc/dst/flow(or unset)timelinetrueembedsdata.meta.timesper edgebefore/after"YYYY-MM-DD HH:MM"time bounds
action (str) –
"details"to fetchhost_details/flow_detailsfor the node or edge id supplied inq.id;q.typeis"node"or"edge".
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – module is not exposed by this server, or
action=detailsand the entity does not exist
- Response JSON Object:
object – results
- POST /flows
Ingest a bulk of flow records.
Mirrors the bulk-insert API documented in
ivre.db.mongo.MongoDBFlow: the request body is a JSON object{"records": [{"kind": "...", ...}, ...]}where each entry carries one of the three ingestion kinds:{"kind": "any", "name": "<zeek-log>", "rec": {...}}maps todb.flow.any2flow(),{"kind": "conn", "rec": {...}}maps todb.flow.conn2flow(),{"kind": "flow", "rec": {...}}maps todb.flow.flow2flow().
Records are dispatched in order, then a single
db.flow.bulk_commit()flushes the bulk. Returns{"count": <records-ingested>}.- Status Codes:
200 OK – no error
400 Bad Request – invalid referer or malformed body
403 Forbidden – uploads disabled (
WEB_UPLOAD_OKisFalse)404 Not Found – module is not exposed by this server
- Response JSON Object:
count (int) – number of records ingested
- POST /flows/cleanup
Run the backend’s
cleanup_flowsheuristic.The handler dispatches to the configured backend’s
cleanup_flows()(a no-op on the SQL backend until the host-swap heuristic is ported); the response carries no body besides{"status": "ok"}so theivre.db.http.HttpDBFlowclient can treat any non-2xx as an error.- Status Codes:
200 OK – cleanup completed
400 Bad Request – invalid referer
403 Forbidden – uploads disabled (
WEB_UPLOAD_OKisFalse)404 Not Found – module is not exposed by this server
- GET /ipdata/(addr)
Returns (estimated) geographical and AS data for a given IP address.
- Parameters:
addr (str) – IP address to query
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
- Response JSON Object:
object – the result values
- GET /iprange
Enumerate IP addresses matching a selector (country, AS, network, range, or all routable IPs).
Exactly one selector must be set. The response always carries
count; the additional fields depend onoutput.- Query Parameters:
country – comma-separated ISO 3166-1 alpha-2 codes
registered_country – comma-separated ISO 3166-1 codes matched against the “registered” GeoIP attribute
region –
CC,REGION(country code, region code)city –
CC,CITY(country code, city name)asnum – comma-separated AS numbers (
AS3215or3215)range_start – start of an explicit address range
range_stop – stop of an explicit address range
network – CIDR network
routable – any truthy value selects the full routable APNIC BGP set
output – one of
count/ranges/cidrs(default) /addrslimit – cap the number of returned entries
- Status Codes:
200 OK – no error
400 Bad Request – invalid selector, output or input combination
- Response JSON Object:
count (int) – total number of IP addresses matched
cidrs (array) – list of CIDRs (
output=cidrs)ranges (array) – list of
[start, stop]pairs (output=ranges)addrs (array) – list of IP strings (
output=addrs, capped)
- GET /passivedns/(query: path)
Query passive DNS data. This API is compatible with the Common Output Format and implemented in CIRCL’s PyPDNS.
It accepts two extra parameters, not supported (yet?) in PyPDNS:
subdomains: if this parameter exists and a domain name is queried, records for any subdomains will also be returned.
reverse: if this parameter exists and a domain name is queried, records pointing to the queried domain (CNAME, NS, MX) will be returned.
It also returns additional information:
“sensor”: the “sensor” field of the record; this is useful to know where this answer has been seen.
“source”: the IP address of the DNS server sending the answer.
- Parameters:
query (str) – IP address or domains name to query
- Query Parameters:
subdomains (bool) – query subdomains (domain name only)
reverse (bool) – use a reverse query (domain name only)
type (str) – specify the DNS query type
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – passive module is not exposed by this server
- Response JSON Object:
object – the result values (JSONL format: one JSON result per line)
- GET /passive
Get records from Passive database
- Query Parameters:
q (str) – query (only used for limit/skip and sort)
f (str) – filter
ipsasnumbers (bool) – to get IP addresses as numbers rather than as strings
datesasstrings (bool) – to get dates as strings rather than as timestamps
format (str) – “json” (the default) or “ndjson”
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – passive module is not exposed by this server
- Response JSON Array of Objects:
object – results
- GET /passive/count
Get special values from Nmap & View databases
- Query Parameters:
q (str) – query (only used for limit/skip and sort)
f (str) – filter
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – passive module is not exposed by this server
- Response JSON Object:
int – count
- GET /dns
Return a merged DNS view across the active scan database (
db.nmap) and the passive observation database (db.passive).Each result is a pseudo-record keyed on
(name, addr): a single row aggregates every observation of that pair across both backends, withcountbeing the sum of the per-source counts (rec['count']on the passive side, one per matching nmap document on the active side).typesandsourcesare unions of the contributing backend values (e.g.["A", "PTR", "user"],["sensor1", "scan-2024-Q1"]);firstseen/lastseenextend the union of the contributing intervals.Results are sorted
lastseendescending, thencountdescending. The user’sq=filter is applied to both backends — tokens that are meaningful only on one side (e.g.recontype:on passive,port:on nmap) are silently dropped on the other via the standardhasattr(dbase, "searchXXX")gate inflt_from_query.Note: the merge happens in-process; every contributing record is materialised before sorting and pagination. The server-side
MONGODB_QUERY_TIMEOUT_MScap bounds the worst-case request time. For deployments where this matters, a future change can introduce a materialised summary collection updated at ingest time.- Query Parameters:
q (str) – query (filter, plus
skip,limitmeta-params)datesasstrings (bool) – emit ISO-ish date strings rather than Unix timestamps
format (str) –
"json"(default) or"ndjson"
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – dns module is not exposed by this server
- Response JSON Array of Objects:
object – pseudo-records as
{name, addr, count, firstseen, lastseen, types, sources}
- GET /rir
Get records from the RIR database.
Records are sorted narrowest-first by default (most-specific inet[6]num allocation at the top), so a
host:/net:/range:filter naturally surfaces the leaf record covering the queried address.aut-numrecords (no range, nosize) sort to the end. Pass?sortby=<field>(or?sortby=~<field>for descending) to override.- Query Parameters:
q (str) – query (only used for limit/skip and sort)
f (str) – filter
format (str) – “json” (the default) or “ndjson”
sortby (str) – optional sort field; default is
sizeascending thenstartdescending thenstopascending (narrowest range first)
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – rir module is not exposed by this server
- Response JSON Array of Objects:
object – results
- GET /rir/count
Count records from the RIR database.
- Query Parameters:
q (str) – query (only used for limit/skip and sort)
f (str) – filter
- Status Codes:
200 OK – no error
400 Bad Request – invalid referer
404 Not Found – rir module is not exposed by this server
- Response JSON Object:
int – count
- GET /audit/
List audit events.
- Query Parameters:
event_type (str) – narrow to one event type (one of
upload/admin_action/oversize_query).user_email (str) – narrow to one user’s events. Non-admins may only supply their own email (any other value returns 403); admins may filter by any user.
since (str) – lower bound on
created_at(inclusive); Unix timestamp or ISO 8601 string.until (str) – upper bound on
created_at(exclusive); same format assince.limit (int) – cap on returned entries (default
WEB_LIMIT; capped byWEB_MAXRESULTS).skip (int) – pagination offset (default 0).
- Status Codes:
200 OK – JSON array, newest-first.
400 Bad Request – invalid parameters.
401 Unauthorized – authentication required.
403 Forbidden – non-admin attempted to read another user’s events.
501 Not Implemented – audit backend not configured on this server.
- GET /audit/count
Count audit events matching a filter (same filter semantics as
list_audit_events()).- Query Parameters:
event_type (str) – narrow to one event type.
user_email (str) – narrow to one user’s events. Non-admins may only supply their own email.
since (str) – lower bound on
created_at.until (str) – upper bound on
created_at.
- Status Codes:
200 OK – integer count.
400 Bad Request – invalid parameters.
401 Unauthorized – authentication required.
403 Forbidden – non-admin attempted to count another user’s events.
501 Not Implemented – audit backend not configured on this server.
- GET /audit/(event_id)
Read a single audit event by
event_id.- Parameters:
event_id (str) – any UUID textual form
uuid.UUIDaccepts – 32-char hex, 36-char hex with dashes, brace-wrapped{...}, orurn:uuid:.... Normalised to the 32-char dashes-less hex form before reaching the storage layer.
- Status Codes:
200 OK – JSON object.
401 Unauthorized – authentication required.
404 Not Found – no event with that id (or the caller is not permitted to see it – the two are indistinguishable on purpose, so the route does not double as an existence oracle for events outside the caller’s scope).
501 Not Implemented – audit backend not configured on this server.
- GET /notes/(entity_type)/(entity_key)
Read a single note.
- Parameters:
entity_type (str) – entity type registered with
_ENTITY_CANONICALIZERS("host"only at v1)entity_key (str) – caller-facing entity key (e.g. printable IP string for
host)
- Status Codes:
200 OK – note found; JSON body
400 Bad Request – invalid entity_type / entity_key
404 Not Found – no note exists for this entity (or the
notesmodule is not exposed byWEB_MODULES)501 Not Implemented – notes backend not configured on this server
- PUT /notes/(entity_type)/(entity_key)
Create or update a note.
Body must be valid UTF-8 markdown; invalid byte sequences are rejected with HTTP 400 (no silent
U+FFFDsubstitution). Optimistic concurrency is opt-in viaIf-Match(matching theETagreturned byGET) or?expected_revision=<int>.If-None-Match: *opts into create-only semantics (HTTP 409 if a note already exists).If-Matchaccepts the standard HTTP forms: bare integer (7), double-quoted ("7"), weak validator (W/"7"), and the first ETag of a comma-list ("7", "8"is treated as 7).If-Match: *(generic “must exist”) is not supported and returns 400.- Parameters:
entity_type (str) – entity type
entity_key (str) – caller-facing entity key
- Request Headers:
If-Match – expected revision for optimistic concurrency
If-None-Match –
*for create-only mode
- Status Codes:
200 OK – persisted; JSON body of the note
400 Bad Request – invalid entity_type / entity_key / params / body not valid UTF-8 / unsupported
If-Matchform401 Unauthorized – authentication required
404 Not Found –
If-Matchset but no note exists409 Conflict – concurrent edit (revision mismatch) or create-only collision
413 Request Entity Too Large – body exceeds
WEB_HOST_NOTES_MAX_BYTES501 Not Implemented – notes backend not configured on this server
- DELETE /notes/(entity_type)/(entity_key)
Delete a note (and its full revision history).
- Parameters:
entity_type (str) – entity type
entity_key (str) – caller-facing entity key
- Status Codes:
204 No Content – deleted
400 Bad Request – invalid entity_type / entity_key
401 Unauthorized – authentication required
404 Not Found – no note exists for this entity (or the
notesmodule is not exposed byWEB_MODULES)501 Not Implemented – notes backend not configured on this server
- GET /notes/(entity_type)/(entity_key)/revisions
Read the full revision history of a note, newest first.
- Parameters:
entity_type (str) – entity type
entity_key (str) – caller-facing entity key
- Status Codes:
200 OK – JSON array of
{revision, body, created_at, created_by}entries400 Bad Request – invalid entity_type / entity_key
404 Not Found –
notesmodule is not exposed byWEB_MODULES501 Not Implemented – notes backend not configured on this server
- GET /notes/
List or search notes.
With no parameters, returns every note in the database (full body included). Add
entity_typeto narrow to one type,qto free-text search across note bodies (results ranked by relevance), orfieldsto skip the bodies and paginate cheaply.- Query Parameters:
entity_type (str) – narrow to one entity type
q (str) – free-text search query (
$textover note bodies; requires thenotes_body_textindex)fields (str) – comma-separated projection list (e.g.
"entity_type,entity_key,updated_at,revision"). The storage halvesentity_key_0/entity_key_1are always added internally so the caller-facingentity_keycan be reassembled.limit (int) – cap on returned entries (default
WEB_LIMIT; capped byWEB_MAXRESULTS)skip (int) – pagination offset (default 0)
- Status Codes:
200 OK – JSON array
400 Bad Request – invalid parameters
404 Not Found –
notesmodule is not exposed byWEB_MODULES501 Not Implemented – notes backend not configured on this server
- GET /auth/check
When auth is disabled, allow all requests.