A powerful, easily deployable network traffic analysis tool suite for network security monitoring
POST /mapi/event (also accepts POST /mapi/alert)
A webhook that accepts alert data to be reindexed into OpenSearch as session records for viewing in Malcolm’s dashboards. See Alerting for more details and examples of how this API is used.
When a POST request is received, the endpoint constructs a document and indexes it into OpenSearch under the configured network index (e.g., the default arkime_sessions3-YYMMDD).
The endpoint accepts data from three sources, checked in this order of priority:
alert key (standard OpenSearch Alerting webhook format)_contents key_raw keyThe top-level alert object supports the following fields:
| Field | Type | Description |
|---|---|---|
alert.monitor.name |
string | Name of the monitor that generated the alert. Mapped to rule.name in the indexed document. |
alert.trigger.name |
string | Name of the trigger. Mapped to event.reason. |
alert.trigger.severity |
integer | OpenSearch severity (1–5, where 1 is highest). Converted to a 0–100 risk score: severity 1 → 100, severity 2 → 80, severity 3 → 60, severity 4 → 40, severity 5 → 20. Mapped to event.risk_score, event.risk_score_norm, and event.severity. |
alert.period.start |
ISO 8601 string | Start of the alert period. Used as the document timestamp, firstPacket, event.start. Falls back to request time if absent. |
alert.period.end |
ISO 8601 string | End of the alert period. Mapped to lastPacket and event.end. Falls back to request time if absent. |
alert.results |
array | Raw OpenSearch query results. If present, results[0].hits.total.value is mapped to event.hits. |
alert.alert |
string | The OpenSearch alert ID. Mapped to event.id. A random ID is generated if absent. |
alert.error |
string | Error string from the alerting plugin, if any. |
alert.body |
string or object | Optional arbitrary payload. See Custom payload via body below. |
bodyThe alert.body field is the primary mechanism for including custom data in the indexed document. If present, it is parsed as JSON (or used directly if already an object) and deep-merged into the indexed document.
Merge behavior:
body that do not exist in the document are added at the top level.body whose value conflicts with a scalar already set by the handler) are preserved under a top-level conflicts key rather than silently dropped or overwritten.This means you can use body to populate ECS-style nested fields. For example, including {"source": {"ip": [...]}, "destination": {"ip": [...]}, "event": {"risk_score": [...], "severity_tags": [...]}} in body will merge cleanly — source and destination are added directly, and the fields inside event are merged into the existing event object without clobbering handler-set fields like event.kind or event.provider.
Note: The
bodyvalue is parsed withpython-rapidjson, which tolerates trailing commas in arrays and objects. This is useful when generatingbodyfrom an OpenSearch Alerting Mustache template, since Mustache has no native mechanism to suppress the trailing comma after the last iteration of a loop.
This endpoint is designed to be used as a custom webhook destination in OpenSearch Alerting. A Mustache message template targeting this endpoint might look like:
{
"alert": {
"monitor": {"name": ""},
"trigger": {"name": "","severity": },
"period": {"start": "","end": ""},
"body": "{\"source\":{\"ip\":[\"\",]},\"destination\":{\"ip\":[\"\",]}}",
"alert": "",
"error": ""
}
}
The body field is a JSON-encoded string containing the aggregation results from the monitor query. The trailing commas produced by Mustache iteration are handled transparently by the parser.
Regardless of input format, every indexed document includes the following fields set by the handler:
| Field | Value |
|---|---|
ecs.version |
1.6.0 |
event.kind |
alert |
event.provider |
malcolm |
event.dataset |
alerting |
event.module |
alerting |
event.url |
/dashboards/app/alerting#/dashboard |
event.ingested |
Request timestamp (UTC) |
event.severity_tags |
Alert |
{
"alert": {
"monitor": {
"name": "High Risk Traffic Monitor"
},
"trigger": {
"name": "risk_score >= 100",
"severity": 1
},
"period": {
"start": "2022-03-08T18:03:30.576Z",
"end": "2022-03-08T18:04:30.576Z"
},
"body": "{\"source\":{\"ip\":[\"10.9.0.215\",]},\"destination\":{\"ip\":[\"10.9.0.216\",]},\"event\":{\"risk_score\":[101.0,],\"severity_tags\":[\"Suricata Alert\",]}}",
"alert": "PLauan8BaL6eY1yCu9Xj",
"error": ""
}
}
{
"_index": "arkime_sessions3-220308",
"_type": "_doc",
"_id": "220308-PLauan8BaL6eY1yCu9Xj",
"_version": 4,
"result": "updated",
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"_seq_no": 9045,
"_primary_term": 1
}