DetectionEngineClient¶
Client for the Kibana Security Detections API.
The detection engine powers Elastic Security: detection rules run over your data and create detection alerts (historically called signals). This client manages detection rules (CRUD, find, bulk actions, preview, NDJSON export/import, Elastic prebuilt rules), detection alerts (search, workflow status, tags, assignees, legacy signals migrations) and the per-space alerts index.
Detection rules and alerts are space-scoped resources: a rule created in one
space is not visible from another space. Every method accepts an optional
space_id to target a specific space.
Note
The rule-exceptions endpoint
(POST /api/detection_engine/rules/{id}/exceptions) is exposed on the
exception_lists namespace.
- class kibana._sync.client.detection_engine.DetectionEngineClient(client, default_space_id=None, validate_spaces=True)[source]¶
Bases:
NamespaceClientClient for the Kibana Security Detections API.
Manages Elastic Security detection rules (create, read, update, delete, find, bulk actions, preview, export/import, prebuilt rule installation), detection alerts – also called signals – (search, status, tags, assignees, legacy signals migrations) and the
.alerts-security.alertsindex for a Kibana space.All Security Detections APIs are space-scoped: rules and alerts live in the space they were created in. Every method accepts an optional
space_idto target a specific space (Nonetargets the default space or the space the client is scoped to).Note: the rule-exceptions endpoint
POST /api/detection_engine/rules/{id}/exceptionsis exposed on theexception_listsnamespace, not here.Example
>>> from kibana import Kibana >>> client = Kibana("http://localhost:5601", api_key="...") >>> >>> # Create a custom query rule and find it >>> rule = client.detection_engine.create_rule( ... type="query", ... name="Suspicious login", ... description="Detects suspicious logins", ... severity="low", ... risk_score=21, ... query='user.name: "suspicious"', ... index=["logs-*"], ... ) >>> found = client.detection_engine.find_rules( ... filter='alert.attributes.name: "Suspicious login"' ... ) >>> client.detection_engine.delete_rule(id=rule.body["id"])
Managing Detection Rules
from kibana import Kibana client = Kibana("http://localhost:5601", api_key="your_api_key") # Create a custom query rule (disabled) rule = client.detection_engine.create_rule( type="query", name="Suspicious login", description="Detects suspicious logins", severity="low", risk_score=21, query='user.name: "suspicious"', index=["logs-*"], interval="5m", from_="now-6m", enabled=False, ) # Read, patch and find rules fetched = client.detection_engine.get_rule(rule_id=rule.body["rule_id"]) client.detection_engine.patch_rule( rule_id=rule.body["rule_id"], tags=["triage"] ) found = client.detection_engine.find_rules( filter='alert.attributes.tags: "triage"', per_page=50 ) # Full update -- also how you toggle `enabled` on 9.4.3 client.detection_engine.update_rule( rule_id=rule.body["rule_id"], type="query", name="Suspicious login", description="Detects suspicious logins", severity="medium", risk_score=47, query='user.name: "suspicious"', enabled=True, ) # Delete it client.detection_engine.delete_rule(rule_id=rule.body["rule_id"])
Bulk Actions, Export and Import
# Add a tag to many rules at once client.detection_engine.bulk_action_rules( action="edit", query='alert.attributes.tags: "triage"', edit=[{"type": "add_tags", "value": ["reviewed"]}], ) # Export rules as NDJSON and import them back exported = client.detection_engine.export_rules( objects=[{"rule_id": "my-rule"}], exclude_export_details=True ) client.detection_engine.import_rules(file=list(exported), overwrite=True) # Install the Elastic prebuilt rules and Timeline templates status = client.detection_engine.get_prepackaged_rules_status() if status.body["rules_not_installed"]: client.detection_engine.install_prepackaged_rules()
Previewing Rules
Preview the alerts a rule would generate without creating it:
preview = client.detection_engine.preview_rule( type="query", name="Preview", description="Preview run", severity="low", risk_score=21, query='user.name: "suspicious"', index=["logs-*"], invocation_count=1, timeframe_end="2026-07-06T12:00:00.000Z", from_="now-6h", interval="1h", ) print(preview.body["previewId"], preview.body["logs"])
Working with Detection Alerts
# Search open alerts alerts = client.detection_engine.search_alerts( query={ "bool": { "filter": [ {"match": {"kibana.alert.workflow_status": "open"}} ] } }, size=10, ) # Close alerts, tag them, assign them alert_ids = [hit["_id"] for hit in alerts.body["hits"]["hits"]] if alert_ids: client.detection_engine.set_alert_status( status="closed", signal_ids=alert_ids ) client.detection_engine.set_alert_tags( ids=alert_ids, tags_to_add=["triaged"], tags_to_remove=[] ) client.detection_engine.set_alert_assignees( ids=alert_ids, add=["u_profile_uid"], remove=[] )
- __init__(client, default_space_id=None, validate_spaces=True)[source]¶
Initialize the DetectionEngineClient.
- Parameters:
Example
>>> detection_engine_client = DetectionEngineClient(kibana_client)
- get_privileges(*, space_id=None, validate_spaces=None)[source]¶
Get detection-engine privileges for the current user.
GET /api/detection_engine/privileges. Retrieves whether or not the user is authenticated, and the user’s Kibana space and index privileges, which determine if the user can create an index for the Elastic Security alerts generated by detection rules.- Parameters:
- Returns:
ObjectApiResponse with
username,has_all_requested,clusterandindexprivilege maps,is_authenticatedandhas_encryption_key.- Raises:
AuthenticationException – If authentication fails.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> privileges = client.detection_engine.get_privileges() >>> print(privileges.body["is_authenticated"]) True
- create_alerts_index(*, space_id=None, validate_spaces=None)[source]¶
Create an alerts index.
POST /api/detection_engine/index. Creates the.alerts-security.alerts-<space>index (alias) for detection alerts in the target space, if it does not already exist. The call is idempotent: it acknowledges even when the index already exists.- Parameters:
- Returns:
ObjectApiResponse with
{"acknowledged": true}on success.- Raises:
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient index privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = client.detection_engine.create_alerts_index() >>> print(result.body["acknowledged"]) True
- get_alerts_index(*, space_id=None, validate_spaces=None)[source]¶
Read the alerts index name.
GET /api/detection_engine/index. Reads the name of the alerts index for the target space (e.g..alerts-security.alerts-default) if it exists.- Parameters:
- Returns:
ObjectApiResponse with the index
nameandindex_mapping_outdated.- Raises:
NotFoundError – If the alerts index does not exist.
AuthenticationException – If authentication fails.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> index = client.detection_engine.get_alerts_index() >>> print(index.body["name"]) .alerts-security.alerts-default
- delete_alerts_index(*, space_id=None, validate_spaces=None)[source]¶
Delete an alerts index.
DELETE /api/detection_engine/index. Deletes the alerts index for the target space.Note: on Kibana 9.4.3 this endpoint only removes legacy
.siem-signals-<space>indices; when only the modern.alerts-security.alerts-<space>alias exists the server responds 404 (index: ".siem-signals-<space>" does not exist).- Parameters:
- Returns:
ObjectApiResponse with
{"acknowledged": true}on success.- Raises:
NotFoundError – If no deletable alerts index exists.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient index privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> client.detection_engine.delete_alerts_index( ... space_id="my-space" ... )
- create_rule(*, type, name, description, severity, risk_score, rule_id=None, actions=None, alert_suppression=None, anomaly_threshold=None, author=None, building_block_type=None, concurrent_searches=None, data_view_id=None, enabled=None, event_category_override=None, exceptions_list=None, false_positives=None, filters=None, from_=None, history_window_start=None, index=None, interval=None, investigation_fields=None, items_per_search=None, language=None, license=None, machine_learning_job_id=None, max_signals=None, meta=None, namespace=None, new_terms_fields=None, note=None, output_index=None, query=None, references=None, related_integrations=None, required_fields=None, response_actions=None, risk_score_mapping=None, rule_name_override=None, saved_id=None, setup=None, severity_mapping=None, tags=None, threat=None, threat_filters=None, threat_index=None, threat_indicator_path=None, threat_language=None, threat_mapping=None, threat_query=None, threshold=None, throttle=None, tiebreaker_field=None, timeline_id=None, timeline_title=None, timestamp_field=None, timestamp_override=None, timestamp_override_fallback_disabled=None, to=None, version=None, fields=None, space_id=None, validate_spaces=None)[source]¶
Create a detection rule.
POST /api/detection_engine/rules. Creates a new detection rule of typequery,saved_query,eql,esql,threshold,threat_match,machine_learningornew_terms. Required type-specific fields differ per type:query/languagefor EQL and ES|QL rules,saved_idfor saved-query rules,thresholdfor threshold rules,threat_index/threat_query/threat_mappingfor indicator-match rules,machine_learning_job_id/anomaly_thresholdfor ML rules andnew_terms_fields/history_window_startfor new-terms rules.- Parameters:
type (str) – Rule type:
query,saved_query,eql,esql,threshold,threat_match,machine_learningornew_terms.name (str) – A human-readable name for the rule.
description (str) – The rule’s description.
severity (str) – Severity level of alerts produced by the rule:
low,medium,highorcritical.risk_score (int) – A numerical representation of the alert’s severity from 0 to 100.
rule_id (str | None) – A stable unique identifier for the rule object (used across Kibana instances; distinct from the object
id). Generated by Kibana when unspecified.actions (list[dict[str, Any]] | None) – Actions to perform when the rule fires.
alert_suppression (dict[str, Any] | None) – Alert suppression configuration (e.g.
{"group_by": ["host.name"]}).anomaly_threshold (int | None) – Anomaly score threshold above which alerts are created (
machine_learningrules only).building_block_type (str | None) – Set to
defaultto mark alerts from this rule as building-block alerts.concurrent_searches (int | None) – Number of concurrent threat-indicator searches (
threat_matchrules only).data_view_id (str | None) – Data view ID the rule runs against (cannot be combined with
index).enabled (bool | None) – Whether the rule is enabled on creation.
event_category_override (str | None) – EQL event category field override (
eqlrules only).exceptions_list (list[dict[str, Any]] | None) – Exception containers associated with the rule (
id,list_id,namespace_type,type).false_positives (list[str] | None) – Common reasons why the rule may issue false-positive alerts.
filters (list[Any] | None) – Query and filter context array (Query DSL filters) used to define rule conditions.
from – Time from which data is analyzed each rule execution (date math, e.g.
"now-6m"). Sent as thefrombody field.history_window_start (str | None) – Start date for the new-terms history window (
new_termsrules only).interval (str | None) – Frequency of rule execution (e.g.
"5m").investigation_fields (dict[str, Any] | None) – Fields highlighted during investigation (e.g.
{"field_names": ["host.name"]}).items_per_search (int | None) – Number of documents per threat-indicator search (
threat_matchrules only).language (str | None) – Query language:
kuery,lucene,eqloresqldepending on the rule type.license (str | None) – The rule’s license.
machine_learning_job_id (str | list[str] | None) – Anomaly-detection job ID(s) (
machine_learningrules only).max_signals (int | None) – Maximum number of alerts the rule can create per execution (default 100).
meta (dict[str, Any] | None) – Placeholder for metadata about the rule; unvalidated and overwritten on each update.
namespace (str | None) – Alerts index namespace (has no effect on 9.x; alerts are written to the space-aware index).
new_terms_fields (list[str] | None) – Fields containing the new terms (
new_termsrules only).note (str | None) – Notes to help investigate alerts produced by the rule.
output_index (str | None) – (deprecated) Has no effect; alerts are written to the space-aware
.alerts-security.alerts-<space>index.query (str | None) – The query the rule runs (KQL/Lucene/EQL/ES|QL depending on
type/language).references (list[str] | None) – References to information relevant to the rule.
related_integrations (list[dict[str, Any]] | None) – Related integrations for the rule (
package,version, optionalintegration).required_fields (list[dict[str, Any]] | None) – ECS fields the rule needs to function.
response_actions (list[dict[str, Any]] | None) – Response actions to run when the rule fires (e.g. Osquery or Endpoint actions).
risk_score_mapping (list[dict[str, Any]] | None) – Overrides that map source-event field values to risk scores.
rule_name_override (str | None) – Source-event field used to override the rule’s name in alerts.
saved_id (str | None) – Saved-query ID the rule runs (required for
saved_queryrules).setup (str | None) – Setup guide with instructions on rule prerequisites.
severity_mapping (list[dict[str, Any]] | None) – Overrides that map source-event field values to severities.
tags (list[str] | None) – String array used to organize rules.
threat (list[dict[str, Any]] | None) – MITRE ATT&CK framework threat information.
threat_filters (list[Any] | None) – Query DSL filters applied to the threat-indicator index (
threat_matchrules only).threat_index (list[str] | None) – Threat-indicator indices (
threat_matchrules only).threat_indicator_path (str | None) – Path to the threat-indicator object (
threat_matchrules only).threat_language (str | None) – Query language for
threat_query(threat_matchrules only).threat_mapping (list[dict[str, Any]] | None) – Field mappings between source events and threat indicators (
threat_matchrules only).threat_query (str | None) – Query run against the threat-indicator index (
threat_matchrules only).threshold (dict[str, Any] | None) – Threshold configuration (
field,value, optionalcardinality;thresholdrules only).throttle (str | None) – (deprecated) Action frequency shorthand; use the per-action
frequencyobject instead.tiebreaker_field (str | None) – Tiebreaker field for EQL sequences (
eqlrules only).timeline_id (str | None) – Timeline template ID used when investigating alerts.
timeline_title (str | None) – Timeline template title (required when
timeline_idis set).timestamp_field (str | None) – Timestamp field for event ordering (
eqlrules only).timestamp_override (str | None) – Field used instead of
@timestampwhen executing the rule.timestamp_override_fallback_disabled (bool | None) – Disable fallback to
@timestampwhen the override field is missing.to (str | None) – End of the time range analyzed each execution (date math, default
"now").version (int | None) – The rule’s version number (defaults to 1).
fields (dict[str, Any] | None) – Additional body fields merged into the request verbatim, for spec fields without a named parameter.
space_id (str | None) – Optional space ID to create the rule in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the created rule, including its generated
idandrule_id.- Raises:
BadRequestError – If the rule definition is invalid.
ConflictError – If a rule with the same
rule_idexists.AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> rule = client.detection_engine.create_rule( ... type="query", ... name="Suspicious login", ... description="Detects suspicious logins", ... severity="low", ... risk_score=21, ... query='user.name: "suspicious"', ... index=["logs-*"], ... interval="10m", ... from_="now-20m", ... ) >>> print(rule.body["rule_id"])
- get_rule(*, id=None, rule_id=None, space_id=None, validate_spaces=None)[source]¶
Retrieve a detection rule.
GET /api/detection_engine/rules. Retrieves a detection rule by its objectidor its stablerule_id; exactly one of the two must be provided.- Parameters:
- Returns:
ObjectApiResponse with the rule.
- Raises:
ValueError – If neither or both of
idandrule_idare given.NotFoundError – If the rule does not exist.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> rule = client.detection_engine.get_rule(rule_id="my-rule") >>> print(rule.body["name"])
- update_rule(*, type, name, description, severity, risk_score, id=None, rule_id=None, actions=None, alert_suppression=None, anomaly_threshold=None, author=None, building_block_type=None, concurrent_searches=None, data_view_id=None, enabled=None, event_category_override=None, exceptions_list=None, false_positives=None, filters=None, from_=None, history_window_start=None, index=None, interval=None, investigation_fields=None, items_per_search=None, language=None, license=None, machine_learning_job_id=None, max_signals=None, meta=None, namespace=None, new_terms_fields=None, note=None, output_index=None, query=None, references=None, related_integrations=None, required_fields=None, response_actions=None, risk_score_mapping=None, rule_name_override=None, saved_id=None, setup=None, severity_mapping=None, tags=None, threat=None, threat_filters=None, threat_index=None, threat_indicator_path=None, threat_language=None, threat_mapping=None, threat_query=None, threshold=None, throttle=None, tiebreaker_field=None, timeline_id=None, timeline_title=None, timestamp_field=None, timestamp_override=None, timestamp_override_fallback_disabled=None, to=None, version=None, fields=None, space_id=None, validate_spaces=None)[source]¶
Update a detection rule (full replacement).
PUT /api/detection_engine/rules. Updates a detection rule using theidorrule_idfield; one of the two must be provided. The whole rule definition is replaced: any field not supplied is reset to its default value (usepatch_rule()for partial updates).- Parameters:
type (str) – Rule type (see
create_rule()).name (str) – A human-readable name for the rule.
description (str) – The rule’s description.
severity (str) – Severity level of alerts produced by the rule.
risk_score (int) – A numerical representation of the alert’s severity from 0 to 100.
id (str | None) – The rule’s object identifier. Either
idorrule_idmust be provided.rule_id (str | None) – The rule’s stable signature identifier.
fields (dict[str, Any] | None) – Additional body fields merged into the request verbatim.
space_id (str | None) – Optional space ID the rule lives in.
validate_spaces (bool | None) – Override space validation setting for this operation.
All remaining keyword arguments are the rule-definition fields documented on
create_rule()and map one-to-one to the 9.4.3RuleUpdatePropsbody fields (from_is sent asfrom).- Returns:
ObjectApiResponse with the updated rule.
- Raises:
ValueError – If neither
idnorrule_idis given.NotFoundError – If the rule does not exist.
BadRequestError – If the rule definition is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> updated = client.detection_engine.update_rule( ... rule_id="my-rule", ... type="query", ... name="Suspicious login (updated)", ... description="Now with a better query", ... severity="medium", ... risk_score=47, ... query='user.name: "suspicious" and event.outcome: failure', ... )
- patch_rule(*, id=None, rule_id=None, type=None, name=None, description=None, severity=None, risk_score=None, actions=None, alert_suppression=None, anomaly_threshold=None, author=None, building_block_type=None, concurrent_searches=None, data_view_id=None, enabled=None, event_category_override=None, exceptions_list=None, false_positives=None, filters=None, from_=None, history_window_start=None, index=None, interval=None, investigation_fields=None, items_per_search=None, language=None, license=None, machine_learning_job_id=None, max_signals=None, meta=None, namespace=None, new_terms_fields=None, note=None, output_index=None, query=None, references=None, related_integrations=None, required_fields=None, response_actions=None, risk_score_mapping=None, rule_name_override=None, saved_id=None, setup=None, severity_mapping=None, tags=None, threat=None, threat_filters=None, threat_index=None, threat_indicator_path=None, threat_language=None, threat_mapping=None, threat_query=None, threshold=None, throttle=None, tiebreaker_field=None, timeline_id=None, timeline_title=None, timestamp_field=None, timestamp_override=None, timestamp_override_fallback_disabled=None, to=None, version=None, fields=None, space_id=None, validate_spaces=None)[source]¶
Patch a detection rule (partial update).
PATCH /api/detection_engine/rules. Updates specific fields of an existing detection rule using theidorrule_idfield; one of the two must be provided. Only the supplied fields are changed.Note: on Kibana 9.4.3 patching the
enabledfield is rejected with 403 (The current user does not have the permissions to edit the following fields: enabled) even for superusers; toggleenabledthroughupdate_rule()instead.- Parameters:
id (str | None) – The rule’s object identifier. Either
idorrule_idmust be provided.rule_id (str | None) – The rule’s stable signature identifier.
fields (dict[str, Any] | None) – Additional body fields merged into the request verbatim.
space_id (str | None) – Optional space ID the rule lives in.
validate_spaces (bool | None) – Override space validation setting for this operation.
All remaining keyword arguments are the rule-definition fields documented on
create_rule(); every one is optional here and maps one-to-one to the 9.4.3RulePatchPropsbody fields (from_is sent asfrom).- Returns:
ObjectApiResponse with the patched rule.
- Raises:
ValueError – If neither
idnorrule_idis given.NotFoundError – If the rule does not exist.
BadRequestError – If the patch payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> patched = client.detection_engine.patch_rule( ... rule_id="my-rule", ... tags=["triage", "linux"], ... )
- delete_rule(*, id=None, rule_id=None, space_id=None, validate_spaces=None)[source]¶
Delete a detection rule.
DELETE /api/detection_engine/rules. Deletes a detection rule by its objectidor its stablerule_id; exactly one of the two must be provided.- Parameters:
- Returns:
ObjectApiResponse with the deleted rule.
- Raises:
ValueError – If neither or both of
idandrule_idare given.NotFoundError – If the rule does not exist.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> client.detection_engine.delete_rule(rule_id="my-rule")
- find_rules(*, fields=None, filter=None, sort_field=None, sort_order=None, page=None, per_page=None, gaps_range_start=None, gaps_range_end=None, gap_fill_statuses=None, gap_auto_fill_scheduler_id=None, space_id=None, validate_spaces=None)[source]¶
List and paginate detection rules.
GET /api/detection_engine/rules/_find. Retrieves a paginated subset of detection rules; by default the first page with 20 rules sorted by creation date.- Parameters:
fields (list[str] | None) – Rule fields to return in the response.
filter (str | None) – KQL search filter over rule saved-object attributes, e.g.
'alert.attributes.name: "My rule"'.sort_field (str | None) – Field to sort by (e.g.
name,enabled,severity,risk_score,created_at,updated_at).sort_order (str | None) – Sort order:
ascordesc.page (int | None) – Page number (default 1).
per_page (int | None) – Rules per page (default 20).
gaps_range_start (str | None) – Gaps range start (used with gap filtering).
gaps_range_end (str | None) – Gaps range end (used with gap filtering).
gap_fill_statuses (list[str] | None) – Filter rules with gaps by gap-fill status:
unfilled,in_progress,filledorerror.gap_auto_fill_scheduler_id (str | None) – Gap auto-fill scheduler ID used to determine gap-fill status.
space_id (str | None) – Optional space ID to search rules in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with
page,perPage,totaland thedataarray of rules.- Raises:
BadRequestError – If the filter or sort options are invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> found = client.detection_engine.find_rules( ... filter='alert.attributes.tags: "linux"', ... sort_field="name", ... sort_order="asc", ... per_page=50, ... ) >>> print(found.body["total"])
- bulk_action_rules(*, action, ids=None, query=None, dry_run=None, edit=None, duplicate=None, run=None, fill_gaps=None, gaps_range_start=None, gaps_range_end=None, gap_fill_statuses=None, gap_auto_fill_scheduler_id=None, space_id=None, validate_spaces=None)[source]¶
Apply a bulk action to detection rules.
POST /api/detection_engine/rules/_bulk_action. Appliesenable,disable,delete,duplicate,export,run,fill_gapsoreditto multiple rules selected byidsor by a KQLquery. The edit action supports operations like adding/deleting tags or index patterns and changing schedules.Note: on Kibana 9.4.3 the
exportaction responds with NDJSON (parsed to a list) instead of a JSON summary. On the tested stack theenable,disable,runandfill_gapsactions were rejected withUSER_INSUFFICIENT_RULE_PRIVILEGESeven for superusers; toggleenabledthroughupdate_rule()instead.- Parameters:
action (str) – Bulk action to apply:
enable,disable,delete,duplicate,export,run,fill_gapsoredit.ids (list[str] | None) – Array of rule object
id``s (not ``rule_id``s) to apply the action to. Cannot be combined with ``query.query (str | None) – KQL query to select the rules to apply the action to.
dry_run (bool | None) – Validate the action and report per-rule outcomes without applying it (sent as the
dry_runquery parameter; not supported forexport).edit (list[dict[str, Any]] | None) – Array of edit operations (required for the
editaction), e.g.[{"type": "add_tags", "value": ["prod"]}].duplicate (dict[str, Any] | None) – Duplicate options (for the
duplicateaction):{"include_exceptions": bool, "include_expired_exceptions": bool}.run (dict[str, Any] | None) – Manual-run window (required for the
runaction):{"start_date": ..., "end_date": ...}.fill_gaps (dict[str, Any] | None) – Gap-fill window (required for the
fill_gapsaction):{"start_date": ..., "end_date": ...}.gaps_range_start (str | None) – Gaps range start (gap filtering, with
query).gaps_range_end (str | None) – Gaps range end (gap filtering, with
query).gap_fill_statuses (list[str] | None) – Filter rules with gaps by gap-fill status.
gap_auto_fill_scheduler_id (str | None) – Gap auto-fill scheduler ID used to determine gap-fill status.
space_id (str | None) – Optional space ID to apply the bulk action in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with
success,rules_countand anattributes.resultsbreakdown (updated,created,deleted,skipped) – or the NDJSON export payload for theexportaction.- Raises:
BadRequestError – If the bulk action payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = client.detection_engine.bulk_action_rules( ... action="edit", ... ids=[rule.body["id"]], ... edit=[{"type": "add_tags", "value": ["kbnpy"]}], ... ) >>> print(result.body["attributes"]["summary"])
- export_rules(*, objects=None, exclude_export_details=None, file_name=None, space_id=None, validate_spaces=None)[source]¶
Export detection rules as NDJSON.
POST /api/detection_engine/rules/_export. Exports detection rules to an NDJSON stream (one rule per line, plus an export-details line unless excluded). The parsed response body is a list of dicts that can be fed back toimport_rules(). Only custom rules can be exported; prebuilt rules are skipped.- Parameters:
objects (list[dict[str, Any]] | None) – Array of
{"rule_id": ...}descriptors selecting the rules to export (use the stablerule_id, not the objectid). Exports all rules when omitted.exclude_export_details (bool | None) – Exclude the export-details line at the end of the stream (default False).
file_name (str | None) – File name for the exported file (sent as the
file_namequery parameter; defaultexport.ndjson).space_id (str | None) – Optional space ID to export rules from.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse whose body is the parsed NDJSON list of exported rules (and the trailing export-details object unless excluded).
- Raises:
BadRequestError – If the export request is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> exported = client.detection_engine.export_rules( ... objects=[{"rule_id": "my-rule"}], ... exclude_export_details=True, ... ) >>> print(len(list(exported))) 1
- import_rules(*, file, overwrite=None, overwrite_exceptions=None, overwrite_action_connectors=None, as_new_list=None, filename='import.ndjson', space_id=None, validate_spaces=None)[source]¶
Import detection rules from an NDJSON export file.
POST /api/detection_engine/rules/_import. Imports detection rules (and their associated exception lists and action connectors) from an NDJSON file uploaded asmultipart/form-data. Rules are matched byrule_id; existing rules are only replaced whenoverwriteis True.- Parameters:
file (bytes | str | list[dict[str, Any]]) – NDJSON export content: raw
bytes/str, or a list of rule dicts (e.g. the parsed body returned byexport_rules()), which is NDJSON-encoded automatically.overwrite (bool | None) – Overwrite existing rules with the same
rule_id(default False).overwrite_exceptions (bool | None) – Overwrite existing exception lists with the same
list_id(default False).overwrite_action_connectors (bool | None) – Overwrite existing action connectors with the same
id(default False).as_new_list (bool | None) – Generate a new list ID for each imported exception list (default False).
filename (str) – Filename advertised in the multipart upload.
space_id (str | None) – Optional space ID to import the rules into.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
success,success_count,rules_count,errorsand the exceptions/action-connectors counterparts.- Return type:
ObjectApiResponse with the import summary
- Raises:
ValueError – If
fileis empty.BadRequestError – If the NDJSON payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
Example
>>> exported = client.detection_engine.export_rules( ... objects=[{"rule_id": "my-rule"}] ... ) >>> result = client.detection_engine.import_rules( ... file=list(exported), ... overwrite=True, ... ) >>> print(result.body["success"]) True
- get_prepackaged_rules_status(*, space_id=None, validate_spaces=None)[source]¶
Get the status of Elastic prebuilt rules and Timelines.
GET /api/detection_engine/rules/prepackaged/_status. Retrieves how many Elastic prebuilt detection rules and Timeline templates are installed, not installed, or outdated in the target space.- Parameters:
- Returns:
ObjectApiResponse with
rules_custom_installed,rules_installed,rules_not_installed,rules_not_updatedand thetimelines_*counterparts.- Raises:
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> status = client.detection_engine.get_prepackaged_rules_status() >>> print(status.body["rules_installed"])
- install_prepackaged_rules(*, space_id=None, validate_spaces=None)[source]¶
Install or update Elastic prebuilt rules and Timelines.
PUT /api/detection_engine/rules/prepackaged. Installs and updates the Elastic prebuilt detection rules and Timeline templates (downloading thesecurity_detection_engineFleet package on first use). The call is idempotent: already-installed and up-to-date assets are skipped.- Parameters:
- Returns:
ObjectApiResponse with
rules_installed,rules_updated,timelines_installedandtimelines_updatedcounts.- Raises:
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = client.detection_engine.install_prepackaged_rules() >>> print(result.body["rules_installed"])
- preview_rule(*, type, name, description, severity, risk_score, invocation_count, timeframe_end, enable_logged_requests=None, rule_id=None, actions=None, alert_suppression=None, anomaly_threshold=None, author=None, building_block_type=None, concurrent_searches=None, data_view_id=None, enabled=None, event_category_override=None, exceptions_list=None, false_positives=None, filters=None, from_=None, history_window_start=None, index=None, interval=None, investigation_fields=None, items_per_search=None, language=None, license=None, machine_learning_job_id=None, max_signals=None, meta=None, namespace=None, new_terms_fields=None, note=None, output_index=None, query=None, references=None, related_integrations=None, required_fields=None, response_actions=None, risk_score_mapping=None, rule_name_override=None, saved_id=None, setup=None, severity_mapping=None, tags=None, threat=None, threat_filters=None, threat_index=None, threat_indicator_path=None, threat_language=None, threat_mapping=None, threat_query=None, threshold=None, throttle=None, tiebreaker_field=None, timeline_id=None, timeline_title=None, timestamp_field=None, timestamp_override=None, timestamp_override_fallback_disabled=None, to=None, version=None, fields=None, space_id=None, validate_spaces=None)[source]¶
Preview the alerts a rule would generate.
POST /api/detection_engine/rules/preview. Runs a rule definition over a specified time range without creating the rule, and reports the execution logs (and, via the returnedpreviewId, the preview alerts written to the preview index).- Parameters:
type (str) – Rule type (see
create_rule()).name (str) – A human-readable name for the rule.
description (str) – The rule’s description.
severity (str) – Severity level of alerts produced by the rule.
risk_score (int) – A numerical representation of the alert’s severity from 0 to 100.
invocation_count (int) – Number of rule executions to simulate (sent as
invocationCount).timeframe_end (str) – End of the simulated execution timeframe, as an ISO date-time (sent as
timeframeEnd).enable_logged_requests (bool | None) – Log the Elasticsearch requests issued during the preview (query parameter).
fields (dict[str, Any] | None) – Additional body fields merged into the request verbatim.
space_id (str | None) – Optional space ID to run the preview in.
validate_spaces (bool | None) – Override space validation setting for this operation.
All remaining keyword arguments are the rule-definition fields documented on
create_rule()(from_is sent asfrom).- Returns:
ObjectApiResponse with the
previewId, per-invocationlogs(errors, warnings, duration) andisAborted.- Raises:
BadRequestError – If the rule definition is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> preview = client.detection_engine.preview_rule( ... type="query", ... name="Preview rule", ... description="Preview", ... severity="low", ... risk_score=21, ... query='user.name: "suspicious"', ... index=["logs-*"], ... invocation_count=1, ... timeframe_end="2026-07-06T12:00:00.000Z", ... from_="now-6h", ... interval="1h", ... ) >>> print(preview.body["previewId"])
- get_tags(*, space_id=None, validate_spaces=None)[source]¶
List all unique detection-rule tags.
GET /api/detection_engine/tags. Aggregates and returns all unique tags used by detection rules in the target space.- Parameters:
- Returns:
ObjectApiResponse whose body is the array of unique tag strings.
- Raises:
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> tags = client.detection_engine.get_tags() >>> print(list(tags))
- search_alerts(*, query=None, aggs=None, size=None, sort=None, fields=None, source=None, runtime_mappings=None, track_total_hits=None, space_id=None, validate_spaces=None)[source]¶
Find and/or aggregate detection alerts.
POST /api/detection_engine/signals/search. Searches the detection alerts (signals) index of the target space with an Elasticsearch query DSL body.- Parameters:
query (dict[str, Any] | None) – Elasticsearch query DSL to select alerts, e.g.
{"match_all": {}}.aggs (dict[str, Any] | None) – Elasticsearch aggregations to compute over the alerts.
size (int | None) – Maximum number of alerts to return.
sort (dict[str, Any] | list[Any] | str | None) – Elasticsearch sort specification (field name, dict, or a list of either).
fields (list[str] | None) – Fields to return via the search
fieldsoption.source (bool | str | list[str] | None) – The
_sourceoption: True/False, a field pattern, or a list of field patterns.runtime_mappings (dict[str, Any] | None) – Runtime field mappings for the search.
track_total_hits (bool | None) – Whether the exact total hit count is tracked.
space_id (str | None) – Optional space ID to search alerts in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the Elasticsearch search response (
hits,took,aggregations, …).- Raises:
BadRequestError – If the search body is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> results = client.detection_engine.search_alerts( ... query={ ... "bool": { ... "filter": [ ... {"match": {"kibana.alert.workflow_status": "open"}} ... ] ... } ... }, ... size=10, ... ) >>> print(results.body["hits"]["total"]["value"])
- set_alert_status(*, status, signal_ids=None, query=None, conflicts=None, reason=None, space_id=None, validate_spaces=None)[source]¶
Set the workflow status of detection alerts.
POST /api/detection_engine/signals/status. Sets the workflow status (open,acknowledgedorclosed) of detection alerts selected either by alert IDs or by an Elasticsearch query; exactly one ofsignal_idsandquerymust be provided.- Parameters:
status (str) – The new workflow status:
open,acknowledgedorclosed(in-progressis a deprecated alias ofacknowledged).signal_ids (list[str] | None) – List of alert ids (the alert document
_id/kibana.alert.uuid).query (dict[str, Any] | None) – Elasticsearch query DSL selecting the alerts to update.
conflicts (str | None) – Behavior on version conflicts when updating by query:
abort(default) orproceed.reason (str | None) – Reason for closing the alerts (only valid with
status="closed").space_id (str | None) – Optional space ID the alerts live in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the Elasticsearch update-by-query summary (
updated,total,failures, …).- Raises:
ValueError – If neither or both of
signal_idsandqueryare given.BadRequestError – If the payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = client.detection_engine.set_alert_status( ... status="closed", ... signal_ids=["6f37fdd4..."], ... ) >>> print(result.body["updated"])
- set_alert_tags(*, ids, tags_to_add, tags_to_remove, space_id=None, validate_spaces=None)[source]¶
Add and remove detection alert tags.
POST /api/detection_engine/signals/tags. Adds and/or removes tags on the given detection alerts in a single request.- Parameters:
tags_to_add (list[str]) – Tags to add to the alerts. A tag that is in both lists results in a no-op.
tags_to_remove (list[str]) – Tags to remove from the alerts.
space_id (str | None) – Optional space ID the alerts live in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the Elasticsearch update-by-query summary (
updated,total,failures, …).- Raises:
BadRequestError – If the payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = client.detection_engine.set_alert_tags( ... ids=["6f37fdd4..."], ... tags_to_add=["triage"], ... tags_to_remove=[], ... )
- set_alert_assignees(*, ids, add, remove, space_id=None, validate_spaces=None)[source]¶
Assign and unassign users from detection alerts.
POST /api/detection_engine/signals/assignees. Assigns and/or unassigns users (by user-profileuid) on the given detection alerts. Users need to activate their user profile by logging into Kibana at least once.- Parameters:
- Returns:
ObjectApiResponse with the Elasticsearch update-by-query summary (
updated,total,failures, …).- Raises:
BadRequestError – If the payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = client.detection_engine.set_alert_assignees( ... ids=["6f37fdd4..."], ... add=["u_myuserprofileuid"], ... remove=[], ... )
- create_alerts_migration(*, index, requests_per_second=None, size=None, slices=None, space_id=None, validate_spaces=None)[source]¶
Initiate a detection alert migration.
Deprecated since version 9.4: The legacy signals migration APIs are deprecated; modern
.alerts-security.alertsindices do not need migration.POST /api/detection_engine/signals/migration. Initiates the migration of legacy detection alerts (.siem-signals-*indices) to the current schema, one migration task per index.- Parameters:
index (list[str]) – Array of legacy signals index names to migrate.
requests_per_second (int | None) – Throttle for the migration task in sub-requests per second (Reindex
requests_per_second).size (int | None) – Number of alerts to migrate per batch (Reindex
source.size).slices (int | None) – Number of subtasks for the migration task (Reindex
slices).space_id (str | None) – Optional space ID the indices belong to.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with per-index
indicesresults (migration_id,migration_index).- Raises:
BadRequestError – If a migration prerequisite is unmet (e.g.
Cannot migrate due to the signals template being out of datewhen no legacy signals template exists).AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> migration = client.detection_engine.create_alerts_migration( ... index=[".siem-signals-default-000001"], ... )
- get_alerts_migration_status(*, from_, space_id=None, validate_spaces=None)[source]¶
Retrieve the status of detection alert migrations.
Deprecated since version 9.4: The legacy signals migration APIs are deprecated; modern
.alerts-security.alertsindices do not need migration.GET /api/detection_engine/signals/migration_status. Retrieves the migration status of detection alerts in indices containing alerts from the given time range.Note: on Kibana 9.4.3 this endpoint responds 404 (
undefined: undefined) when no legacy signals indices exist for the range.- Parameters:
- Returns:
ObjectApiResponse with per-index migration statuses.
- Raises:
NotFoundError – If no qualifying signals indices exist.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> status = client.detection_engine.get_alerts_migration_status( ... from_="now-30d", ... )
- finalize_alerts_migration(*, migration_ids, space_id=None, validate_spaces=None)[source]¶
Finalize detection alert migrations.
Deprecated since version 9.4: The legacy signals migration APIs are deprecated; modern
.alerts-security.alertsindices do not need migration.POST /api/detection_engine/signals/finalize_migration. Finalizes completed migrations of legacy detection alerts: swaps the alias to the migrated index and marks the migration as complete.- Parameters:
migration_ids (list[str]) – Array of migration IDs to finalize (as returned by
create_alerts_migration()).space_id (str | None) – Optional space ID the migrations belong to.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the finalized
migrationsstatuses.- Raises:
NotFoundError – If a migration ID does not exist.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> client.detection_engine.finalize_alerts_migration( ... migration_ids=["924f7c50-505f-11eb-ae0a-3fa2e626a51d"], ... )
- delete_alerts_migration(*, migration_ids, space_id=None, validate_spaces=None)[source]¶
Clean up detection alert migrations.
Deprecated since version 9.4: The legacy signals migration APIs are deprecated; modern
.alerts-security.alertsindices do not need migration.DELETE /api/detection_engine/signals/migration. Migrations are initiated per index; when a migration is stale or its results are no longer needed, this soft-deletes the migration saved object.- Parameters:
migration_ids (list[str]) – Array of migration IDs to clean up (as returned by
create_alerts_migration()).space_id (str | None) – Optional space ID the migrations belong to.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the cleaned-up
migrationsstatuses.- Raises:
NotFoundError – If a migration ID does not exist.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> client.detection_engine.delete_alerts_migration( ... migration_ids=["924f7c50-505f-11eb-ae0a-3fa2e626a51d"], ... )
AsyncDetectionEngineClient¶
Asynchronous version of the DetectionEngineClient for use with async/await syntax.
- class kibana._async.client.detection_engine.AsyncDetectionEngineClient(client, default_space_id=None, validate_spaces=True)[source]¶
Bases:
AsyncNamespaceClientAsync client for the Kibana Security Detections API.
Manages Elastic Security detection rules (create, read, update, delete, find, bulk actions, preview, export/import, prebuilt rule installation), detection alerts – also called signals – (search, status, tags, assignees, legacy signals migrations) and the
.alerts-security.alertsindex for a Kibana space.All Security Detections APIs are space-scoped: rules and alerts live in the space they were created in. Every method accepts an optional
space_idto target a specific space (Nonetargets the default space or the space the client is scoped to).Note: the rule-exceptions endpoint
POST /api/detection_engine/rules/{id}/exceptionsis exposed on theexception_listsnamespace, not here.Example
>>> from kibana import AsyncKibana >>> client = AsyncKibana("http://localhost:5601", api_key="...") >>> >>> # Create a custom query rule and find it >>> rule = await client.detection_engine.create_rule( ... type="query", ... name="Suspicious login", ... description="Detects suspicious logins", ... severity="low", ... risk_score=21, ... query='user.name: "suspicious"', ... index=["logs-*"], ... ) >>> found = await client.detection_engine.find_rules( ... filter='alert.attributes.name: "Suspicious login"' ... ) >>> await client.detection_engine.delete_rule(id=rule.body["id"])
Usage
The AsyncDetectionEngineClient provides the same methods as DetectionEngineClient but all methods are async and must be awaited:
from kibana import AsyncKibana import asyncio async def main(): async with AsyncKibana("http://localhost:5601") as client: rule = await client.detection_engine.create_rule( type="query", name="Async rule", description="Created asynchronously", severity="low", risk_score=21, query='user.name: "suspicious"', enabled=False, ) found = await client.detection_engine.find_rules( filter='alert.attributes.name: "Async rule"' ) await client.detection_engine.delete_rule( rule_id=rule.body["rule_id"] ) asyncio.run(main())
- __init__(client, default_space_id=None, validate_spaces=True)[source]¶
Initialize the AsyncDetectionEngineClient.
- Parameters:
client (AsyncKibana) – The parent AsyncKibana client instance to delegate requests to.
default_space_id (str | None) – Optional default space ID for all operations.
validate_spaces (bool) – Whether to validate space existence before space-scoped operations (default: True).
Example
>>> detection_engine_client = AsyncDetectionEngineClient(kibana_client)
- async get_privileges(*, space_id=None, validate_spaces=None)[source]¶
Get detection-engine privileges for the current user.
GET /api/detection_engine/privileges. Retrieves whether or not the user is authenticated, and the user’s Kibana space and index privileges, which determine if the user can create an index for the Elastic Security alerts generated by detection rules.- Parameters:
- Returns:
ObjectApiResponse with
username,has_all_requested,clusterandindexprivilege maps,is_authenticatedandhas_encryption_key.- Raises:
AuthenticationException – If authentication fails.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> privileges = await client.detection_engine.get_privileges() >>> print(privileges.body["is_authenticated"]) True
- async create_alerts_index(*, space_id=None, validate_spaces=None)[source]¶
Create an alerts index.
POST /api/detection_engine/index. Creates the.alerts-security.alerts-<space>index (alias) for detection alerts in the target space, if it does not already exist. The call is idempotent: it acknowledges even when the index already exists.- Parameters:
- Returns:
ObjectApiResponse with
{"acknowledged": true}on success.- Raises:
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient index privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = await client.detection_engine.create_alerts_index() >>> print(result.body["acknowledged"]) True
- async get_alerts_index(*, space_id=None, validate_spaces=None)[source]¶
Read the alerts index name.
GET /api/detection_engine/index. Reads the name of the alerts index for the target space (e.g..alerts-security.alerts-default) if it exists.- Parameters:
- Returns:
ObjectApiResponse with the index
nameandindex_mapping_outdated.- Raises:
NotFoundError – If the alerts index does not exist.
AuthenticationException – If authentication fails.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> index = await client.detection_engine.get_alerts_index() >>> print(index.body["name"]) .alerts-security.alerts-default
- async delete_alerts_index(*, space_id=None, validate_spaces=None)[source]¶
Delete an alerts index.
DELETE /api/detection_engine/index. Deletes the alerts index for the target space.Note: on Kibana 9.4.3 this endpoint only removes legacy
.siem-signals-<space>indices; when only the modern.alerts-security.alerts-<space>alias exists the server responds 404 (index: ".siem-signals-<space>" does not exist).- Parameters:
- Returns:
ObjectApiResponse with
{"acknowledged": true}on success.- Raises:
NotFoundError – If no deletable alerts index exists.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient index privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> await client.detection_engine.delete_alerts_index( ... space_id="my-space" ... )
- async create_rule(*, type, name, description, severity, risk_score, rule_id=None, actions=None, alert_suppression=None, anomaly_threshold=None, author=None, building_block_type=None, concurrent_searches=None, data_view_id=None, enabled=None, event_category_override=None, exceptions_list=None, false_positives=None, filters=None, from_=None, history_window_start=None, index=None, interval=None, investigation_fields=None, items_per_search=None, language=None, license=None, machine_learning_job_id=None, max_signals=None, meta=None, namespace=None, new_terms_fields=None, note=None, output_index=None, query=None, references=None, related_integrations=None, required_fields=None, response_actions=None, risk_score_mapping=None, rule_name_override=None, saved_id=None, setup=None, severity_mapping=None, tags=None, threat=None, threat_filters=None, threat_index=None, threat_indicator_path=None, threat_language=None, threat_mapping=None, threat_query=None, threshold=None, throttle=None, tiebreaker_field=None, timeline_id=None, timeline_title=None, timestamp_field=None, timestamp_override=None, timestamp_override_fallback_disabled=None, to=None, version=None, fields=None, space_id=None, validate_spaces=None)[source]¶
Create a detection rule.
POST /api/detection_engine/rules. Creates a new detection rule of typequery,saved_query,eql,esql,threshold,threat_match,machine_learningornew_terms. Required type-specific fields differ per type:query/languagefor EQL and ES|QL rules,saved_idfor saved-query rules,thresholdfor threshold rules,threat_index/threat_query/threat_mappingfor indicator-match rules,machine_learning_job_id/anomaly_thresholdfor ML rules andnew_terms_fields/history_window_startfor new-terms rules.- Parameters:
type (str) – Rule type:
query,saved_query,eql,esql,threshold,threat_match,machine_learningornew_terms.name (str) – A human-readable name for the rule.
description (str) – The rule’s description.
severity (str) – Severity level of alerts produced by the rule:
low,medium,highorcritical.risk_score (int) – A numerical representation of the alert’s severity from 0 to 100.
rule_id (str | None) – A stable unique identifier for the rule object (used across Kibana instances; distinct from the object
id). Generated by Kibana when unspecified.actions (list[dict[str, Any]] | None) – Actions to perform when the rule fires.
alert_suppression (dict[str, Any] | None) – Alert suppression configuration (e.g.
{"group_by": ["host.name"]}).anomaly_threshold (int | None) – Anomaly score threshold above which alerts are created (
machine_learningrules only).building_block_type (str | None) – Set to
defaultto mark alerts from this rule as building-block alerts.concurrent_searches (int | None) – Number of concurrent threat-indicator searches (
threat_matchrules only).data_view_id (str | None) – Data view ID the rule runs against (cannot be combined with
index).enabled (bool | None) – Whether the rule is enabled on creation.
event_category_override (str | None) – EQL event category field override (
eqlrules only).exceptions_list (list[dict[str, Any]] | None) – Exception containers associated with the rule (
id,list_id,namespace_type,type).false_positives (list[str] | None) – Common reasons why the rule may issue false-positive alerts.
filters (list[Any] | None) – Query and filter context array (Query DSL filters) used to define rule conditions.
from – Time from which data is analyzed each rule execution (date math, e.g.
"now-6m"). Sent as thefrombody field.history_window_start (str | None) – Start date for the new-terms history window (
new_termsrules only).interval (str | None) – Frequency of rule execution (e.g.
"5m").investigation_fields (dict[str, Any] | None) – Fields highlighted during investigation (e.g.
{"field_names": ["host.name"]}).items_per_search (int | None) – Number of documents per threat-indicator search (
threat_matchrules only).language (str | None) – Query language:
kuery,lucene,eqloresqldepending on the rule type.license (str | None) – The rule’s license.
machine_learning_job_id (str | list[str] | None) – Anomaly-detection job ID(s) (
machine_learningrules only).max_signals (int | None) – Maximum number of alerts the rule can create per execution (default 100).
meta (dict[str, Any] | None) – Placeholder for metadata about the rule; unvalidated and overwritten on each update.
namespace (str | None) – Alerts index namespace (has no effect on 9.x; alerts are written to the space-aware index).
new_terms_fields (list[str] | None) – Fields containing the new terms (
new_termsrules only).note (str | None) – Notes to help investigate alerts produced by the rule.
output_index (str | None) – (deprecated) Has no effect; alerts are written to the space-aware
.alerts-security.alerts-<space>index.query (str | None) – The query the rule runs (KQL/Lucene/EQL/ES|QL depending on
type/language).references (list[str] | None) – References to information relevant to the rule.
related_integrations (list[dict[str, Any]] | None) – Related integrations for the rule (
package,version, optionalintegration).required_fields (list[dict[str, Any]] | None) – ECS fields the rule needs to function.
response_actions (list[dict[str, Any]] | None) – Response actions to run when the rule fires (e.g. Osquery or Endpoint actions).
risk_score_mapping (list[dict[str, Any]] | None) – Overrides that map source-event field values to risk scores.
rule_name_override (str | None) – Source-event field used to override the rule’s name in alerts.
saved_id (str | None) – Saved-query ID the rule runs (required for
saved_queryrules).setup (str | None) – Setup guide with instructions on rule prerequisites.
severity_mapping (list[dict[str, Any]] | None) – Overrides that map source-event field values to severities.
tags (list[str] | None) – String array used to organize rules.
threat (list[dict[str, Any]] | None) – MITRE ATT&CK framework threat information.
threat_filters (list[Any] | None) – Query DSL filters applied to the threat-indicator index (
threat_matchrules only).threat_index (list[str] | None) – Threat-indicator indices (
threat_matchrules only).threat_indicator_path (str | None) – Path to the threat-indicator object (
threat_matchrules only).threat_language (str | None) – Query language for
threat_query(threat_matchrules only).threat_mapping (list[dict[str, Any]] | None) – Field mappings between source events and threat indicators (
threat_matchrules only).threat_query (str | None) – Query run against the threat-indicator index (
threat_matchrules only).threshold (dict[str, Any] | None) – Threshold configuration (
field,value, optionalcardinality;thresholdrules only).throttle (str | None) – (deprecated) Action frequency shorthand; use the per-action
frequencyobject instead.tiebreaker_field (str | None) – Tiebreaker field for EQL sequences (
eqlrules only).timeline_id (str | None) – Timeline template ID used when investigating alerts.
timeline_title (str | None) – Timeline template title (required when
timeline_idis set).timestamp_field (str | None) – Timestamp field for event ordering (
eqlrules only).timestamp_override (str | None) – Field used instead of
@timestampwhen executing the rule.timestamp_override_fallback_disabled (bool | None) – Disable fallback to
@timestampwhen the override field is missing.to (str | None) – End of the time range analyzed each execution (date math, default
"now").version (int | None) – The rule’s version number (defaults to 1).
fields (dict[str, Any] | None) – Additional body fields merged into the request verbatim, for spec fields without a named parameter.
space_id (str | None) – Optional space ID to create the rule in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the created rule, including its generated
idandrule_id.- Raises:
BadRequestError – If the rule definition is invalid.
ConflictError – If a rule with the same
rule_idexists.AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> rule = await client.detection_engine.create_rule( ... type="query", ... name="Suspicious login", ... description="Detects suspicious logins", ... severity="low", ... risk_score=21, ... query='user.name: "suspicious"', ... index=["logs-*"], ... interval="10m", ... from_="now-20m", ... ) >>> print(rule.body["rule_id"])
- async get_rule(*, id=None, rule_id=None, space_id=None, validate_spaces=None)[source]¶
Retrieve a detection rule.
GET /api/detection_engine/rules. Retrieves a detection rule by its objectidor its stablerule_id; exactly one of the two must be provided.- Parameters:
- Returns:
ObjectApiResponse with the rule.
- Raises:
ValueError – If neither or both of
idandrule_idare given.NotFoundError – If the rule does not exist.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> rule = await client.detection_engine.get_rule(rule_id="my-rule") >>> print(rule.body["name"])
- async update_rule(*, type, name, description, severity, risk_score, id=None, rule_id=None, actions=None, alert_suppression=None, anomaly_threshold=None, author=None, building_block_type=None, concurrent_searches=None, data_view_id=None, enabled=None, event_category_override=None, exceptions_list=None, false_positives=None, filters=None, from_=None, history_window_start=None, index=None, interval=None, investigation_fields=None, items_per_search=None, language=None, license=None, machine_learning_job_id=None, max_signals=None, meta=None, namespace=None, new_terms_fields=None, note=None, output_index=None, query=None, references=None, related_integrations=None, required_fields=None, response_actions=None, risk_score_mapping=None, rule_name_override=None, saved_id=None, setup=None, severity_mapping=None, tags=None, threat=None, threat_filters=None, threat_index=None, threat_indicator_path=None, threat_language=None, threat_mapping=None, threat_query=None, threshold=None, throttle=None, tiebreaker_field=None, timeline_id=None, timeline_title=None, timestamp_field=None, timestamp_override=None, timestamp_override_fallback_disabled=None, to=None, version=None, fields=None, space_id=None, validate_spaces=None)[source]¶
Update a detection rule (full replacement).
PUT /api/detection_engine/rules. Updates a detection rule using theidorrule_idfield; one of the two must be provided. The whole rule definition is replaced: any field not supplied is reset to its default value (usepatch_rule()for partial updates).- Parameters:
type (str) – Rule type (see
create_rule()).name (str) – A human-readable name for the rule.
description (str) – The rule’s description.
severity (str) – Severity level of alerts produced by the rule.
risk_score (int) – A numerical representation of the alert’s severity from 0 to 100.
id (str | None) – The rule’s object identifier. Either
idorrule_idmust be provided.rule_id (str | None) – The rule’s stable signature identifier.
fields (dict[str, Any] | None) – Additional body fields merged into the request verbatim.
space_id (str | None) – Optional space ID the rule lives in.
validate_spaces (bool | None) – Override space validation setting for this operation.
All remaining keyword arguments are the rule-definition fields documented on
create_rule()and map one-to-one to the 9.4.3RuleUpdatePropsbody fields (from_is sent asfrom).- Returns:
ObjectApiResponse with the updated rule.
- Raises:
ValueError – If neither
idnorrule_idis given.NotFoundError – If the rule does not exist.
BadRequestError – If the rule definition is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> updated = await client.detection_engine.update_rule( ... rule_id="my-rule", ... type="query", ... name="Suspicious login (updated)", ... description="Now with a better query", ... severity="medium", ... risk_score=47, ... query='user.name: "suspicious" and event.outcome: failure', ... )
- async patch_rule(*, id=None, rule_id=None, type=None, name=None, description=None, severity=None, risk_score=None, actions=None, alert_suppression=None, anomaly_threshold=None, author=None, building_block_type=None, concurrent_searches=None, data_view_id=None, enabled=None, event_category_override=None, exceptions_list=None, false_positives=None, filters=None, from_=None, history_window_start=None, index=None, interval=None, investigation_fields=None, items_per_search=None, language=None, license=None, machine_learning_job_id=None, max_signals=None, meta=None, namespace=None, new_terms_fields=None, note=None, output_index=None, query=None, references=None, related_integrations=None, required_fields=None, response_actions=None, risk_score_mapping=None, rule_name_override=None, saved_id=None, setup=None, severity_mapping=None, tags=None, threat=None, threat_filters=None, threat_index=None, threat_indicator_path=None, threat_language=None, threat_mapping=None, threat_query=None, threshold=None, throttle=None, tiebreaker_field=None, timeline_id=None, timeline_title=None, timestamp_field=None, timestamp_override=None, timestamp_override_fallback_disabled=None, to=None, version=None, fields=None, space_id=None, validate_spaces=None)[source]¶
Patch a detection rule (partial update).
PATCH /api/detection_engine/rules. Updates specific fields of an existing detection rule using theidorrule_idfield; one of the two must be provided. Only the supplied fields are changed.Note: on Kibana 9.4.3 patching the
enabledfield is rejected with 403 (The current user does not have the permissions to edit the following fields: enabled) even for superusers; toggleenabledthroughupdate_rule()instead.- Parameters:
id (str | None) – The rule’s object identifier. Either
idorrule_idmust be provided.rule_id (str | None) – The rule’s stable signature identifier.
fields (dict[str, Any] | None) – Additional body fields merged into the request verbatim.
space_id (str | None) – Optional space ID the rule lives in.
validate_spaces (bool | None) – Override space validation setting for this operation.
All remaining keyword arguments are the rule-definition fields documented on
create_rule(); every one is optional here and maps one-to-one to the 9.4.3RulePatchPropsbody fields (from_is sent asfrom).- Returns:
ObjectApiResponse with the patched rule.
- Raises:
ValueError – If neither
idnorrule_idis given.NotFoundError – If the rule does not exist.
BadRequestError – If the patch payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> patched = await client.detection_engine.patch_rule( ... rule_id="my-rule", ... tags=["triage", "linux"], ... )
- async delete_rule(*, id=None, rule_id=None, space_id=None, validate_spaces=None)[source]¶
Delete a detection rule.
DELETE /api/detection_engine/rules. Deletes a detection rule by its objectidor its stablerule_id; exactly one of the two must be provided.- Parameters:
- Returns:
ObjectApiResponse with the deleted rule.
- Raises:
ValueError – If neither or both of
idandrule_idare given.NotFoundError – If the rule does not exist.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> await client.detection_engine.delete_rule(rule_id="my-rule")
- async find_rules(*, fields=None, filter=None, sort_field=None, sort_order=None, page=None, per_page=None, gaps_range_start=None, gaps_range_end=None, gap_fill_statuses=None, gap_auto_fill_scheduler_id=None, space_id=None, validate_spaces=None)[source]¶
List and paginate detection rules.
GET /api/detection_engine/rules/_find. Retrieves a paginated subset of detection rules; by default the first page with 20 rules sorted by creation date.- Parameters:
fields (list[str] | None) – Rule fields to return in the response.
filter (str | None) – KQL search filter over rule saved-object attributes, e.g.
'alert.attributes.name: "My rule"'.sort_field (str | None) – Field to sort by (e.g.
name,enabled,severity,risk_score,created_at,updated_at).sort_order (str | None) – Sort order:
ascordesc.page (int | None) – Page number (default 1).
per_page (int | None) – Rules per page (default 20).
gaps_range_start (str | None) – Gaps range start (used with gap filtering).
gaps_range_end (str | None) – Gaps range end (used with gap filtering).
gap_fill_statuses (list[str] | None) – Filter rules with gaps by gap-fill status:
unfilled,in_progress,filledorerror.gap_auto_fill_scheduler_id (str | None) – Gap auto-fill scheduler ID used to determine gap-fill status.
space_id (str | None) – Optional space ID to search rules in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with
page,perPage,totaland thedataarray of rules.- Raises:
BadRequestError – If the filter or sort options are invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> found = await client.detection_engine.find_rules( ... filter='alert.attributes.tags: "linux"', ... sort_field="name", ... sort_order="asc", ... per_page=50, ... ) >>> print(found.body["total"])
- async bulk_action_rules(*, action, ids=None, query=None, dry_run=None, edit=None, duplicate=None, run=None, fill_gaps=None, gaps_range_start=None, gaps_range_end=None, gap_fill_statuses=None, gap_auto_fill_scheduler_id=None, space_id=None, validate_spaces=None)[source]¶
Apply a bulk action to detection rules.
POST /api/detection_engine/rules/_bulk_action. Appliesenable,disable,delete,duplicate,export,run,fill_gapsoreditto multiple rules selected byidsor by a KQLquery. The edit action supports operations like adding/deleting tags or index patterns and changing schedules.Note: on Kibana 9.4.3 the
exportaction responds with NDJSON (parsed to a list) instead of a JSON summary. On the tested stack theenable,disable,runandfill_gapsactions were rejected withUSER_INSUFFICIENT_RULE_PRIVILEGESeven for superusers; toggleenabledthroughupdate_rule()instead.- Parameters:
action (str) – Bulk action to apply:
enable,disable,delete,duplicate,export,run,fill_gapsoredit.ids (list[str] | None) – Array of rule object
id``s (not ``rule_id``s) to apply the action to. Cannot be combined with ``query.query (str | None) – KQL query to select the rules to apply the action to.
dry_run (bool | None) – Validate the action and report per-rule outcomes without applying it (sent as the
dry_runquery parameter; not supported forexport).edit (list[dict[str, Any]] | None) – Array of edit operations (required for the
editaction), e.g.[{"type": "add_tags", "value": ["prod"]}].duplicate (dict[str, Any] | None) – Duplicate options (for the
duplicateaction):{"include_exceptions": bool, "include_expired_exceptions": bool}.run (dict[str, Any] | None) – Manual-run window (required for the
runaction):{"start_date": ..., "end_date": ...}.fill_gaps (dict[str, Any] | None) – Gap-fill window (required for the
fill_gapsaction):{"start_date": ..., "end_date": ...}.gaps_range_start (str | None) – Gaps range start (gap filtering, with
query).gaps_range_end (str | None) – Gaps range end (gap filtering, with
query).gap_fill_statuses (list[str] | None) – Filter rules with gaps by gap-fill status.
gap_auto_fill_scheduler_id (str | None) – Gap auto-fill scheduler ID used to determine gap-fill status.
space_id (str | None) – Optional space ID to apply the bulk action in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with
success,rules_countand anattributes.resultsbreakdown (updated,created,deleted,skipped) – or the NDJSON export payload for theexportaction.- Raises:
BadRequestError – If the bulk action payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = await client.detection_engine.bulk_action_rules( ... action="edit", ... ids=[rule.body["id"]], ... edit=[{"type": "add_tags", "value": ["kbnpy"]}], ... ) >>> print(result.body["attributes"]["summary"])
- async export_rules(*, objects=None, exclude_export_details=None, file_name=None, space_id=None, validate_spaces=None)[source]¶
Export detection rules as NDJSON.
POST /api/detection_engine/rules/_export. Exports detection rules to an NDJSON stream (one rule per line, plus an export-details line unless excluded). The parsed response body is a list of dicts that can be fed back toimport_rules(). Only custom rules can be exported; prebuilt rules are skipped.- Parameters:
objects (list[dict[str, Any]] | None) – Array of
{"rule_id": ...}descriptors selecting the rules to export (use the stablerule_id, not the objectid). Exports all rules when omitted.exclude_export_details (bool | None) – Exclude the export-details line at the end of the stream (default False).
file_name (str | None) – File name for the exported file (sent as the
file_namequery parameter; defaultexport.ndjson).space_id (str | None) – Optional space ID to export rules from.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse whose body is the parsed NDJSON list of exported rules (and the trailing export-details object unless excluded).
- Raises:
BadRequestError – If the export request is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> exported = await client.detection_engine.export_rules( ... objects=[{"rule_id": "my-rule"}], ... exclude_export_details=True, ... ) >>> print(len(list(exported))) 1
- async import_rules(*, file, overwrite=None, overwrite_exceptions=None, overwrite_action_connectors=None, as_new_list=None, filename='import.ndjson', space_id=None, validate_spaces=None)[source]¶
Import detection rules from an NDJSON export file.
POST /api/detection_engine/rules/_import. Imports detection rules (and their associated exception lists and action connectors) from an NDJSON file uploaded asmultipart/form-data. Rules are matched byrule_id; existing rules are only replaced whenoverwriteis True.- Parameters:
file (bytes | str | list[dict[str, Any]]) – NDJSON export content: raw
bytes/str, or a list of rule dicts (e.g. the parsed body returned byexport_rules()), which is NDJSON-encoded automatically.overwrite (bool | None) – Overwrite existing rules with the same
rule_id(default False).overwrite_exceptions (bool | None) – Overwrite existing exception lists with the same
list_id(default False).overwrite_action_connectors (bool | None) – Overwrite existing action connectors with the same
id(default False).as_new_list (bool | None) – Generate a new list ID for each imported exception list (default False).
filename (str) – Filename advertised in the multipart upload.
space_id (str | None) – Optional space ID to import the rules into.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
success,success_count,rules_count,errorsand the exceptions/action-connectors counterparts.- Return type:
ObjectApiResponse with the import summary
- Raises:
ValueError – If
fileis empty.BadRequestError – If the NDJSON payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
Example
>>> exported = await client.detection_engine.export_rules( ... objects=[{"rule_id": "my-rule"}] ... ) >>> result = await client.detection_engine.import_rules( ... file=list(exported), ... overwrite=True, ... ) >>> print(result.body["success"]) True
- async get_prepackaged_rules_status(*, space_id=None, validate_spaces=None)[source]¶
Get the status of Elastic prebuilt rules and Timelines.
GET /api/detection_engine/rules/prepackaged/_status. Retrieves how many Elastic prebuilt detection rules and Timeline templates are installed, not installed, or outdated in the target space.- Parameters:
- Returns:
ObjectApiResponse with
rules_custom_installed,rules_installed,rules_not_installed,rules_not_updatedand thetimelines_*counterparts.- Raises:
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> status = await client.detection_engine.get_prepackaged_rules_status() >>> print(status.body["rules_installed"])
- async install_prepackaged_rules(*, space_id=None, validate_spaces=None)[source]¶
Install or update Elastic prebuilt rules and Timelines.
PUT /api/detection_engine/rules/prepackaged. Installs and updates the Elastic prebuilt detection rules and Timeline templates (downloading thesecurity_detection_engineFleet package on first use). The call is idempotent: already-installed and up-to-date assets are skipped.- Parameters:
- Returns:
ObjectApiResponse with
rules_installed,rules_updated,timelines_installedandtimelines_updatedcounts.- Raises:
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = await client.detection_engine.install_prepackaged_rules() >>> print(result.body["rules_installed"])
- async preview_rule(*, type, name, description, severity, risk_score, invocation_count, timeframe_end, enable_logged_requests=None, rule_id=None, actions=None, alert_suppression=None, anomaly_threshold=None, author=None, building_block_type=None, concurrent_searches=None, data_view_id=None, enabled=None, event_category_override=None, exceptions_list=None, false_positives=None, filters=None, from_=None, history_window_start=None, index=None, interval=None, investigation_fields=None, items_per_search=None, language=None, license=None, machine_learning_job_id=None, max_signals=None, meta=None, namespace=None, new_terms_fields=None, note=None, output_index=None, query=None, references=None, related_integrations=None, required_fields=None, response_actions=None, risk_score_mapping=None, rule_name_override=None, saved_id=None, setup=None, severity_mapping=None, tags=None, threat=None, threat_filters=None, threat_index=None, threat_indicator_path=None, threat_language=None, threat_mapping=None, threat_query=None, threshold=None, throttle=None, tiebreaker_field=None, timeline_id=None, timeline_title=None, timestamp_field=None, timestamp_override=None, timestamp_override_fallback_disabled=None, to=None, version=None, fields=None, space_id=None, validate_spaces=None)[source]¶
Preview the alerts a rule would generate.
POST /api/detection_engine/rules/preview. Runs a rule definition over a specified time range without creating the rule, and reports the execution logs (and, via the returnedpreviewId, the preview alerts written to the preview index).- Parameters:
type (str) – Rule type (see
create_rule()).name (str) – A human-readable name for the rule.
description (str) – The rule’s description.
severity (str) – Severity level of alerts produced by the rule.
risk_score (int) – A numerical representation of the alert’s severity from 0 to 100.
invocation_count (int) – Number of rule executions to simulate (sent as
invocationCount).timeframe_end (str) – End of the simulated execution timeframe, as an ISO date-time (sent as
timeframeEnd).enable_logged_requests (bool | None) – Log the Elasticsearch requests issued during the preview (query parameter).
fields (dict[str, Any] | None) – Additional body fields merged into the request verbatim.
space_id (str | None) – Optional space ID to run the preview in.
validate_spaces (bool | None) – Override space validation setting for this operation.
All remaining keyword arguments are the rule-definition fields documented on
create_rule()(from_is sent asfrom).- Returns:
ObjectApiResponse with the
previewId, per-invocationlogs(errors, warnings, duration) andisAborted.- Raises:
BadRequestError – If the rule definition is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> preview = await client.detection_engine.preview_rule( ... type="query", ... name="Preview rule", ... description="Preview", ... severity="low", ... risk_score=21, ... query='user.name: "suspicious"', ... index=["logs-*"], ... invocation_count=1, ... timeframe_end="2026-07-06T12:00:00.000Z", ... from_="now-6h", ... interval="1h", ... ) >>> print(preview.body["previewId"])
- async get_tags(*, space_id=None, validate_spaces=None)[source]¶
List all unique detection-rule tags.
GET /api/detection_engine/tags. Aggregates and returns all unique tags used by detection rules in the target space.- Parameters:
- Returns:
ObjectApiResponse whose body is the array of unique tag strings.
- Raises:
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> tags = await client.detection_engine.get_tags() >>> print(list(tags))
- async search_alerts(*, query=None, aggs=None, size=None, sort=None, fields=None, source=None, runtime_mappings=None, track_total_hits=None, space_id=None, validate_spaces=None)[source]¶
Find and/or aggregate detection alerts.
POST /api/detection_engine/signals/search. Searches the detection alerts (signals) index of the target space with an Elasticsearch query DSL body.- Parameters:
query (dict[str, Any] | None) – Elasticsearch query DSL to select alerts, e.g.
{"match_all": {}}.aggs (dict[str, Any] | None) – Elasticsearch aggregations to compute over the alerts.
size (int | None) – Maximum number of alerts to return.
sort (dict[str, Any] | list[Any] | str | None) – Elasticsearch sort specification (field name, dict, or a list of either).
fields (list[str] | None) – Fields to return via the search
fieldsoption.source (bool | str | list[str] | None) – The
_sourceoption: True/False, a field pattern, or a list of field patterns.runtime_mappings (dict[str, Any] | None) – Runtime field mappings for the search.
track_total_hits (bool | None) – Whether the exact total hit count is tracked.
space_id (str | None) – Optional space ID to search alerts in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the Elasticsearch search response (
hits,took,aggregations, …).- Raises:
BadRequestError – If the search body is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> results = await client.detection_engine.search_alerts( ... query={ ... "bool": { ... "filter": [ ... {"match": {"kibana.alert.workflow_status": "open"}} ... ] ... } ... }, ... size=10, ... ) >>> print(results.body["hits"]["total"]["value"])
- async set_alert_status(*, status, signal_ids=None, query=None, conflicts=None, reason=None, space_id=None, validate_spaces=None)[source]¶
Set the workflow status of detection alerts.
POST /api/detection_engine/signals/status. Sets the workflow status (open,acknowledgedorclosed) of detection alerts selected either by alert IDs or by an Elasticsearch query; exactly one ofsignal_idsandquerymust be provided.- Parameters:
status (str) – The new workflow status:
open,acknowledgedorclosed(in-progressis a deprecated alias ofacknowledged).signal_ids (list[str] | None) – List of alert ids (the alert document
_id/kibana.alert.uuid).query (dict[str, Any] | None) – Elasticsearch query DSL selecting the alerts to update.
conflicts (str | None) – Behavior on version conflicts when updating by query:
abort(default) orproceed.reason (str | None) – Reason for closing the alerts (only valid with
status="closed").space_id (str | None) – Optional space ID the alerts live in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the Elasticsearch update-by-query summary (
updated,total,failures, …).- Raises:
ValueError – If neither or both of
signal_idsandqueryare given.BadRequestError – If the payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = await client.detection_engine.set_alert_status( ... status="closed", ... signal_ids=["6f37fdd4..."], ... ) >>> print(result.body["updated"])
- async set_alert_tags(*, ids, tags_to_add, tags_to_remove, space_id=None, validate_spaces=None)[source]¶
Add and remove detection alert tags.
POST /api/detection_engine/signals/tags. Adds and/or removes tags on the given detection alerts in a single request.- Parameters:
tags_to_add (list[str]) – Tags to add to the alerts. A tag that is in both lists results in a no-op.
tags_to_remove (list[str]) – Tags to remove from the alerts.
space_id (str | None) – Optional space ID the alerts live in.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the Elasticsearch update-by-query summary (
updated,total,failures, …).- Raises:
BadRequestError – If the payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = await client.detection_engine.set_alert_tags( ... ids=["6f37fdd4..."], ... tags_to_add=["triage"], ... tags_to_remove=[], ... )
- async set_alert_assignees(*, ids, add, remove, space_id=None, validate_spaces=None)[source]¶
Assign and unassign users from detection alerts.
POST /api/detection_engine/signals/assignees. Assigns and/or unassigns users (by user-profileuid) on the given detection alerts. Users need to activate their user profile by logging into Kibana at least once.- Parameters:
- Returns:
ObjectApiResponse with the Elasticsearch update-by-query summary (
updated,total,failures, …).- Raises:
BadRequestError – If the payload is invalid.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> result = await client.detection_engine.set_alert_assignees( ... ids=["6f37fdd4..."], ... add=["u_myuserprofileuid"], ... remove=[], ... )
- async create_alerts_migration(*, index, requests_per_second=None, size=None, slices=None, space_id=None, validate_spaces=None)[source]¶
Initiate a detection alert migration.
Deprecated since version 9.4: The legacy signals migration APIs are deprecated; modern
.alerts-security.alertsindices do not need migration.POST /api/detection_engine/signals/migration. Initiates the migration of legacy detection alerts (.siem-signals-*indices) to the current schema, one migration task per index.- Parameters:
index (list[str]) – Array of legacy signals index names to migrate.
requests_per_second (int | None) – Throttle for the migration task in sub-requests per second (Reindex
requests_per_second).size (int | None) – Number of alerts to migrate per batch (Reindex
source.size).slices (int | None) – Number of subtasks for the migration task (Reindex
slices).space_id (str | None) – Optional space ID the indices belong to.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with per-index
indicesresults (migration_id,migration_index).- Raises:
BadRequestError – If a migration prerequisite is unmet (e.g.
Cannot migrate due to the signals template being out of datewhen no legacy signals template exists).AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> migration = await client.detection_engine.create_alerts_migration( ... index=[".siem-signals-default-000001"], ... )
- async get_alerts_migration_status(*, from_, space_id=None, validate_spaces=None)[source]¶
Retrieve the status of detection alert migrations.
Deprecated since version 9.4: The legacy signals migration APIs are deprecated; modern
.alerts-security.alertsindices do not need migration.GET /api/detection_engine/signals/migration_status. Retrieves the migration status of detection alerts in indices containing alerts from the given time range.Note: on Kibana 9.4.3 this endpoint responds 404 (
undefined: undefined) when no legacy signals indices exist for the range.- Parameters:
- Returns:
ObjectApiResponse with per-index migration statuses.
- Raises:
NotFoundError – If no qualifying signals indices exist.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> status = await client.detection_engine.get_alerts_migration_status( ... from_="now-30d", ... )
- async finalize_alerts_migration(*, migration_ids, space_id=None, validate_spaces=None)[source]¶
Finalize detection alert migrations.
Deprecated since version 9.4: The legacy signals migration APIs are deprecated; modern
.alerts-security.alertsindices do not need migration.POST /api/detection_engine/signals/finalize_migration. Finalizes completed migrations of legacy detection alerts: swaps the alias to the migrated index and marks the migration as complete.- Parameters:
migration_ids (list[str]) – Array of migration IDs to finalize (as returned by
create_alerts_migration()).space_id (str | None) – Optional space ID the migrations belong to.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the finalized
migrationsstatuses.- Raises:
NotFoundError – If a migration ID does not exist.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> await client.detection_engine.finalize_alerts_migration( ... migration_ids=["924f7c50-505f-11eb-ae0a-3fa2e626a51d"], ... )
- async delete_alerts_migration(*, migration_ids, space_id=None, validate_spaces=None)[source]¶
Clean up detection alert migrations.
Deprecated since version 9.4: The legacy signals migration APIs are deprecated; modern
.alerts-security.alertsindices do not need migration.DELETE /api/detection_engine/signals/migration. Migrations are initiated per index; when a migration is stale or its results are no longer needed, this soft-deletes the migration saved object.- Parameters:
migration_ids (list[str]) – Array of migration IDs to clean up (as returned by
create_alerts_migration()).space_id (str | None) – Optional space ID the migrations belong to.
validate_spaces (bool | None) – Override space validation setting for this operation.
- Returns:
ObjectApiResponse with the cleaned-up
migrationsstatuses.- Raises:
NotFoundError – If a migration ID does not exist.
AuthenticationException – If authentication fails.
AuthorizationException – If insufficient privileges.
SpaceNotFoundError – If the space doesn’t exist and validation is enabled.
- Return type:
Example
>>> await client.detection_engine.delete_alerts_migration( ... migration_ids=["924f7c50-505f-11eb-ae0a-3fa2e626a51d"], ... )