Skip to main content

Analysis endpoints

/analysis/* group + /rulesets/compile — ruleset validation, native logtest (predecoder → decoder → rule) and consultation of the XML schema supported by the engine.

All endpoints require the analysis:run scope (or a session with equivalent permission).

Endpoint table

MethodPathScopeDescription
POST/rulesets/compileanalysis:runHistorical alias for /analysis/validate.
POST/analysis/validateanalysis:runCompile and validate a ruleset, returns diagnostics.
GET/analysis/schemaanalysis:runReturns the accepted XML schema (tags, attributes, values).
POST/analysis/logtest-nativeanalysis:runRuns an event against the ruleset and returns the full trace.
POST/analysis/fullanalysis:runIdentical to logtest-native + extra static analysis.

/rulesets/compile and /analysis/validate accept the same request/response. Use /analysis/validate — the other exists for backward compatibility.

POST /analysis/validate

Compiles a set of rules/decoders and returns diagnostics. Used to validate before publishing, or in CI as a quality gate.

Auth: analysis:run scope.

Query parameters:

NameTypeDefaultDescription
include_baselineboolfalseWhen true, diagnostics[] also contains items originating from the Wazuh baseline (source_scope="default"). By default the API returns only findings in your content — baseline_issue_count still reflects the full set. Use true to inspect baseline warnings (e.g., local debugging, comparing with the UI).

Request body (ValidationRequest):

{
"include_disk_defaults": true,
"include_disk_custom": true,
"files": [
{
"filename": "local_rules.xml",
"kind": "rules",
"scope": "adhoc",
"content": "<group name=\"local\"><rule id=\"100010\" level=\"3\">...</rule></group>"
},
{
"filename": "local_decoders.xml",
"kind": "decoders",
"scope": "adhoc",
"content": "<decoder name=\"custom\">...</decoder>"
}
]
}
  • include_disk_defaults (bool, default true) — include the Wazuh rules/decoders shipped with the server.
  • include_disk_custom (bool, default true) — include rules/decoders from the instance's data/custom folder.
  • files[] — extra content sent inline. Each file:
    • filename (string, 1–255 chars) — logical name; used in error messages.
    • kind"rules" or "decoders".
    • scope"default", "custom" or "adhoc" (the normal for client-sent content).
    • content — raw XML.

Response 200 (ValidationResponse):

{
"ok": true,
"summary": {
"total_rule_files": 12,
"total_decoder_files": 8,
"total_rules": 8621,
"total_decoders": 623,
"compiled_hash": "abc123…",
"loaded_from_disk": true
},
"diagnostics": [
{
"severity": "warning",
"source": "rules",
"code": "rule_overlapping_level",
"message": "Rule 100010 shadows rule 5716",
"filename": "local_rules.xml",
"line": 3,
"column": 5,
"hint": "Consider using an ID outside the baseline range",
"evidence": "<rule id=\"100010\">",
"source_scope": "adhoc"
}
],
"performance": {
"source_build_ms": 45.2,
"compile_ms": 120.5,
"total_ms": 165.7,
"cache_hit": false
},
"baseline_issue_count": 0
}
  • oktrue if no diagnostic with severity="error" was found in your content (baseline errors don't block the gate, even when include_baseline=true).
  • diagnostics[] — by default, only diagnostics from client content (files with scope="custom" or "adhoc"). Problems in the Wazuh baseline are hidden and counted in baseline_issue_count. To include baseline items, pass ?include_baseline=true.
  • performance.cache_hittrue when the compiled_hash was already cached.

Diagnostic

Each item in diagnostics[]:

FieldPossible values
severityerror, warning, info, success
sourcexml, rules, decoders, engine, session, filesystem
codeError-type identifier (e.g., decoder_missing_parent, regex_invalid, rule_duplicate_id).
messageHuman-readable message.
filenameSource file (if applicable).
line, columnPosition in the file (1-indexed).
hintSuggested action.
evidenceXML snippet that triggered the diagnostic.
source_scopedefault, custom, adhoc or null.

Side effects

  • Emits webhook validation.completed with {ok, diagnostic_count, total_rules, total_decoders}.
  • Counts against the organization plan (analysis_runs metric — although /validate itself currently doesn't consume a run; consumption happens in logtest-native and full).

curl example (clean response, only your own findings):

# RF_BASE without trailing slash — avoids //analysis/validate, which some proxies don't normalize.
RF_BASE="https://www.ruleforge.cloud/api/v1"

curl -X POST "$RF_BASE/analysis/validate" \
-H "X-API-Key: $RF_KEY" \
-H "Content-Type: application/json" \
-d @payload.json

To inspect Wazuh baseline warnings as well (e.g., local debugging, comparing with the UI):

curl -X POST "$RF_BASE/analysis/validate?include_baseline=true" \
-H "X-API-Key: $RF_KEY" \
-H "Content-Type: application/json" \
-d @payload.json

GET /analysis/schema

Returns the declarative schema of accepted XML tags — tags, attributes, allowed values. Used by the frontend editor for autocomplete/validation; can be useful for content generators.

Auth: analysis:run scope.

Response 200 (ValidationSchemaResponse):

{
"version": "4.10",
"references": ["https://documentation.wazuh.com/…"],
"decoders": {
"top_level_tags": ["decoder"],
"wrapper_tags": [],
"elements": [
{
"name": "decoder",
"context": "root",
"description": "Root decoder element",
"runtime_supported": true,
"attributes": [
{
"name": "name",
"required": true,
"allowed_values": [],
"description": "Unique decoder identifier"
}
],
"child_tags": ["program_name", "prematch", "regex", "order"],
"allowed_values": []
}
],
"root_attributes": [],
"group_attributes": [],
"mitre_elements": []
},
"rules": { "...": "..." }
}

POST /analysis/logtest-native

Runs the full pipeline over a single event: predecoder → decoder → rule → insights. Returns the execution trace for debugging.

Auth: analysis:run scope. Consumes 1 unit of the plan (analysis_runs).

Request body (LogtestRequest):

{
"include_disk_defaults": true,
"include_disk_custom": false,
"files": [],
"input": {
"event": "Jan 10 12:00:01 web01 sshd[1234]: Failed password for root from 10.0.0.5",
"log_format": "syslog",
"location": "/var/log/auth.log",
"session_id": "correlation-123"
}
}
  • Everything in ValidationRequest is accepted (ruleset).
  • input.event — event string (1 byte to 8 MB).
  • input.log_formatauto, syslog, json, eventchannel, plain.
  • input.location — optional, 0–512 chars; used by decoders that depend on path.
  • input.session_id — optional, 0–128 chars; groups events for correlation/frequency rules.

Response 200 (LogtestResponse):

{
"ok": true,
"summary": { "total_rules": 8621, "...": "..." },
"diagnostics": [],
"performance": {
"source_build_ms": 0,
"compile_ms": 0,
"predecode_ms": 0.8,
"decode_ms": 2.1,
"rule_ms": 6.4,
"total_ms": 10.1,
"cache_hit": true
},
"predecoded": {
"timestamp": "Jan 10 12:00:01",
"hostname": "web01",
"program_name": "sshd",
"location": "/var/log/auth.log",
"raw_message": "Failed password for root from 10.0.0.5",
"detected_format": "syslog"
},
"decoder": {
"name": "sshd",
"parent": null,
"order": ["srcip", "dstuser"]
},
"rule": {
"id": "5716",
"level": 5,
"description": "sshd: authentication failed.",
"groups": ["syslog", "sshd", "authentication_failed"],
"mitre_ids": ["T1110"],
"matched": true
},
"matched_rules": [
{ "id": "5716", "matched": true, "...": "..." }
],
"extracted_fields": {
"dstuser": "root",
"srcip": "10.0.0.5"
},
"trace": [
{ "phase": "predecode", "name": "predecoder", "matched": true, "details": {} },
{ "phase": "decode", "name": "sshd", "matched": true, "line": 42, "filename": "0100-pam_decoders.xml", "details": {} },
{ "phase": "rule", "name": "5716", "matched": true, "line": 105, "filename": "0025-sshd_rules.xml", "details": {} }
],
"insights": [
"Rule 5716 matched based on decoded field dstuser='root'.",
"Consider correlating with rule 5720 to detect brute-force."
]
}
  • rule — the highest-severity rule that matched (may be null).
  • matched_rules — every rule that matched, in evaluation order.
  • trace — each step executed; phase says which layer. Useful to understand why a rule didn't match (e.g., decoder didn't match first).
  • insights — natural-language tips.

Side effects

  • Emits webhook logtest.completed with {ok, matched_rule_id, matched_rules}.
  • Consumes 1 unit of analysis_runs from the organization.

POST /analysis/full

Identical to logtest-native in input and output — it is a distinct endpoint reserving room to grow with extra static analysis (decoder complexity, duplicates, etc.). Today returns the same LogtestResponse.

Recommendation: use /analysis/logtest-native. This endpoint exists for when additional features are enabled.

POST /rulesets/compile

Historical alias for /analysis/validate with the same request/response. Kept for backward compatibility.

Common errors

CodecodeCause
400bad_requestfiles[].content isn't valid XML.
403forbiddenInsufficient scope.
413payload_too_largeRuleset > 8 MB — split files.
422validation_failedInvalid body schema.
429rate_limited> 120 req/min or plan quota exhausted.