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: NamespaceClient

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.alerts index 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_id to target a specific space (None targets the default space or the space the client is scoped to).

Note: the rule-exceptions endpoint POST /api/detection_engine/rules/{id}/exceptions is exposed on the exception_lists namespace, 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:
  • client (Kibana) – The parent Kibana 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 = 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:
  • space_id (str | None) – Optional space ID to check privileges in.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with username, has_all_requested, cluster and index privilege maps, is_authenticated and has_encryption_key.

Raises:
Return type:

ObjectApiResponse[Any]

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:
  • space_id (str | None) – Optional space ID to create the alerts index for.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with {"acknowledged": true} on success.

Raises:
Return type:

ObjectApiResponse[Any]

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:
  • space_id (str | None) – Optional space ID to read the alerts index for.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with the index name and index_mapping_outdated.

Raises:
Return type:

ObjectApiResponse[Any]

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:
  • space_id (str | None) – Optional space ID to delete the alerts index for.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with {"acknowledged": true} on success.

Raises:
Return type:

ObjectApiResponse[Any]

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 type query, saved_query, eql, esql, threshold, threat_match, machine_learning or new_terms. Required type-specific fields differ per type: query/language for EQL and ES|QL rules, saved_id for saved-query rules, threshold for threshold rules, threat_index/threat_query/ threat_mapping for indicator-match rules, machine_learning_job_id/anomaly_threshold for ML rules and new_terms_fields/history_window_start for new-terms rules.

Parameters:
  • type (str) – Rule type: query, saved_query, eql, esql, threshold, threat_match, machine_learning or new_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, high or critical.

  • 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_learning rules only).

  • author (list[str] | None) – The rule’s author(s).

  • building_block_type (str | None) – Set to default to mark alerts from this rule as building-block alerts.

  • concurrent_searches (int | None) – Number of concurrent threat-indicator searches (threat_match rules 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 (eql rules 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 the from body field.

  • history_window_start (str | None) – Start date for the new-terms history window (new_terms rules only).

  • index (list[str] | None) – Indices the rule runs against.

  • 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_match rules only).

  • language (str | None) – Query language: kuery, lucene, eql or esql depending 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_learning rules 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_terms rules 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, optional integration).

  • 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_query rules).

  • 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_match rules only).

  • threat_index (list[str] | None) – Threat-indicator indices (threat_match rules only).

  • threat_indicator_path (str | None) – Path to the threat-indicator object (threat_match rules only).

  • threat_language (str | None) – Query language for threat_query (threat_match rules only).

  • threat_mapping (list[dict[str, Any]] | None) – Field mappings between source events and threat indicators (threat_match rules only).

  • threat_query (str | None) – Query run against the threat-indicator index (threat_match rules only).

  • threshold (dict[str, Any] | None) – Threshold configuration (field, value, optional cardinality; threshold rules only).

  • throttle (str | None) – (deprecated) Action frequency shorthand; use the per-action frequency object instead.

  • tiebreaker_field (str | None) – Tiebreaker field for EQL sequences (eql rules only).

  • timeline_id (str | None) – Timeline template ID used when investigating alerts.

  • timeline_title (str | None) – Timeline template title (required when timeline_id is set).

  • timestamp_field (str | None) – Timestamp field for event ordering (eql rules only).

  • timestamp_override (str | None) – Field used instead of @timestamp when executing the rule.

  • timestamp_override_fallback_disabled (bool | None) – Disable fallback to @timestamp when 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 id and rule_id.

Raises:
Return type:

ObjectApiResponse[Any]

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 object id or its stable rule_id; exactly one of the two must be provided.

Parameters:
  • id (str | None) – The rule’s object identifier (UUID generated by Kibana).

  • rule_id (str | None) – The rule’s stable signature identifier.

  • space_id (str | None) – Optional space ID to read the rule from.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with the rule.

Raises:
Return type:

ObjectApiResponse[Any]

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 the id or rule_id field; one of the two must be provided. The whole rule definition is replaced: any field not supplied is reset to its default value (use patch_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 id or rule_id must 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.3 RuleUpdateProps body fields (from_ is sent as from).

Returns:

ObjectApiResponse with the updated rule.

Raises:
Return type:

ObjectApiResponse[Any]

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 the id or rule_id field; one of the two must be provided. Only the supplied fields are changed.

Note: on Kibana 9.4.3 patching the enabled field is rejected with 403 (The current user does not have the permissions to edit the following fields: enabled) even for superusers; toggle enabled through update_rule() instead.

Parameters:
  • id (str | None) – The rule’s object identifier. Either id or rule_id must 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.3 RulePatchProps body fields (from_ is sent as from).

Returns:

ObjectApiResponse with the patched rule.

Raises:
Return type:

ObjectApiResponse[Any]

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 object id or its stable rule_id; exactly one of the two must be provided.

Parameters:
  • id (str | None) – The rule’s object identifier (UUID generated by Kibana).

  • rule_id (str | None) – The rule’s stable signature identifier.

  • space_id (str | None) – Optional space ID to delete the rule from.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with the deleted rule.

Raises:
Return type:

ObjectApiResponse[Any]

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: asc or desc.

  • 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, filled or error.

  • 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, total and the data array of rules.

Raises:
Return type:

ObjectApiResponse[Any]

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. Applies enable, disable, delete, duplicate, export, run, fill_gaps or edit to multiple rules selected by ids or by a KQL query. The edit action supports operations like adding/deleting tags or index patterns and changing schedules.

Note: on Kibana 9.4.3 the export action responds with NDJSON (parsed to a list) instead of a JSON summary. On the tested stack the enable, disable, run and fill_gaps actions were rejected with USER_INSUFFICIENT_RULE_PRIVILEGES even for superusers; toggle enabled through update_rule() instead.

Parameters:
  • action (str) – Bulk action to apply: enable, disable, delete, duplicate, export, run, fill_gaps or edit.

  • 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_run query parameter; not supported for export).

  • edit (list[dict[str, Any]] | None) – Array of edit operations (required for the edit action), e.g. [{"type": "add_tags", "value": ["prod"]}].

  • duplicate (dict[str, Any] | None) – Duplicate options (for the duplicate action): {"include_exceptions": bool, "include_expired_exceptions": bool}.

  • run (dict[str, Any] | None) – Manual-run window (required for the run action): {"start_date": ..., "end_date": ...}.

  • fill_gaps (dict[str, Any] | None) – Gap-fill window (required for the fill_gaps action): {"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_count and an attributes.results breakdown (updated, created, deleted, skipped) – or the NDJSON export payload for the export action.

Raises:
Return type:

ObjectApiResponse[Any]

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 to import_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 stable rule_id, not the object id). 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_name query parameter; default export.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:
Return type:

ObjectApiResponse[Any]

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 as multipart/form-data. Rules are matched by rule_id; existing rules are only replaced when overwrite is 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 by export_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, errors and the exceptions/action-connectors counterparts.

Return type:

ObjectApiResponse with the import summary

Raises:

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:
  • space_id (str | None) – Optional space ID to read the status for.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with rules_custom_installed, rules_installed, rules_not_installed, rules_not_updated and the timelines_* counterparts.

Raises:
Return type:

ObjectApiResponse[Any]

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 the security_detection_engine Fleet package on first use). The call is idempotent: already-installed and up-to-date assets are skipped.

Parameters:
  • space_id (str | None) – Optional space ID to install the prebuilt content in.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with rules_installed, rules_updated, timelines_installed and timelines_updated counts.

Raises:
Return type:

ObjectApiResponse[Any]

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 returned previewId, 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 as from).

Returns:

ObjectApiResponse with the previewId, per-invocation logs (errors, warnings, duration) and isAborted.

Raises:
Return type:

ObjectApiResponse[Any]

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:
  • space_id (str | None) – Optional space ID to list tags from.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse whose body is the array of unique tag strings.

Raises:
Return type:

ObjectApiResponse[Any]

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 fields option.

  • source (bool | str | list[str] | None) – The _source option: 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:
Return type:

ObjectApiResponse[Any]

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, acknowledged or closed) of detection alerts selected either by alert IDs or by an Elasticsearch query; exactly one of signal_ids and query must be provided.

Parameters:
  • status (str) – The new workflow status: open, acknowledged or closed (in-progress is a deprecated alias of acknowledged).

  • 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) or proceed.

  • 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:
Return type:

ObjectApiResponse[Any]

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:
  • ids (list[str]) – List of alert ids to update.

  • 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:
Return type:

ObjectApiResponse[Any]

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-profile uid) on the given detection alerts. Users need to activate their user profile by logging into Kibana at least once.

Parameters:
  • ids (list[str]) – List of alert ids to update.

  • add (list[str]) – User profile uid values to assign. A uid that is in both lists results in a no-op.

  • remove (list[str]) – User profile uid values to unassign.

  • 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:
Return type:

ObjectApiResponse[Any]

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.alerts indices 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 indices results (migration_id, migration_index).

Raises:
Return type:

ObjectApiResponse[Any]

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.alerts indices 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:
  • from – Maximum age of qualifying detection alerts, as date math (e.g. "now-30d"); sent as the from query parameter.

  • 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 migration statuses.

Raises:
Return type:

ObjectApiResponse[Any]

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.alerts indices 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 migrations statuses.

Raises:
Return type:

ObjectApiResponse[Any]

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.alerts indices 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 migrations statuses.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> client.detection_engine.delete_alerts_migration(
...     migration_ids=["924f7c50-505f-11eb-ae0a-3fa2e626a51d"],
... )
perform_request(method, path, *, params=None, headers=None, body=None)

Perform an HTTP request via the parent client with space context enhancement.

Parameters:
  • method (str) – HTTP method (GET, POST, PUT, DELETE, etc.)

  • path (str) – API endpoint path

  • params (dict[str, Any] | None) – Query parameters

  • headers (dict[str, str] | None) – Request headers

  • body (dict[str, Any] | None) – Request body

Returns:

API response

Raises:

ApiError – If the API returns an error response (enhanced with space context)

Return type:

ObjectApiResponse[Any]

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: AsyncNamespaceClient

Async 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.alerts index 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_id to target a specific space (None targets the default space or the space the client is scoped to).

Note: the rule-exceptions endpoint POST /api/detection_engine/rules/{id}/exceptions is exposed on the exception_lists namespace, 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:
  • space_id (str | None) – Optional space ID to check privileges in.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with username, has_all_requested, cluster and index privilege maps, is_authenticated and has_encryption_key.

Raises:
Return type:

ObjectApiResponse[Any]

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:
  • space_id (str | None) – Optional space ID to create the alerts index for.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with {"acknowledged": true} on success.

Raises:
Return type:

ObjectApiResponse[Any]

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:
  • space_id (str | None) – Optional space ID to read the alerts index for.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with the index name and index_mapping_outdated.

Raises:
Return type:

ObjectApiResponse[Any]

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:
  • space_id (str | None) – Optional space ID to delete the alerts index for.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with {"acknowledged": true} on success.

Raises:
Return type:

ObjectApiResponse[Any]

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 type query, saved_query, eql, esql, threshold, threat_match, machine_learning or new_terms. Required type-specific fields differ per type: query/language for EQL and ES|QL rules, saved_id for saved-query rules, threshold for threshold rules, threat_index/threat_query/ threat_mapping for indicator-match rules, machine_learning_job_id/anomaly_threshold for ML rules and new_terms_fields/history_window_start for new-terms rules.

Parameters:
  • type (str) – Rule type: query, saved_query, eql, esql, threshold, threat_match, machine_learning or new_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, high or critical.

  • 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_learning rules only).

  • author (list[str] | None) – The rule’s author(s).

  • building_block_type (str | None) – Set to default to mark alerts from this rule as building-block alerts.

  • concurrent_searches (int | None) – Number of concurrent threat-indicator searches (threat_match rules 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 (eql rules 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 the from body field.

  • history_window_start (str | None) – Start date for the new-terms history window (new_terms rules only).

  • index (list[str] | None) – Indices the rule runs against.

  • 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_match rules only).

  • language (str | None) – Query language: kuery, lucene, eql or esql depending 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_learning rules 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_terms rules 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, optional integration).

  • 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_query rules).

  • 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_match rules only).

  • threat_index (list[str] | None) – Threat-indicator indices (threat_match rules only).

  • threat_indicator_path (str | None) – Path to the threat-indicator object (threat_match rules only).

  • threat_language (str | None) – Query language for threat_query (threat_match rules only).

  • threat_mapping (list[dict[str, Any]] | None) – Field mappings between source events and threat indicators (threat_match rules only).

  • threat_query (str | None) – Query run against the threat-indicator index (threat_match rules only).

  • threshold (dict[str, Any] | None) – Threshold configuration (field, value, optional cardinality; threshold rules only).

  • throttle (str | None) – (deprecated) Action frequency shorthand; use the per-action frequency object instead.

  • tiebreaker_field (str | None) – Tiebreaker field for EQL sequences (eql rules only).

  • timeline_id (str | None) – Timeline template ID used when investigating alerts.

  • timeline_title (str | None) – Timeline template title (required when timeline_id is set).

  • timestamp_field (str | None) – Timestamp field for event ordering (eql rules only).

  • timestamp_override (str | None) – Field used instead of @timestamp when executing the rule.

  • timestamp_override_fallback_disabled (bool | None) – Disable fallback to @timestamp when 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 id and rule_id.

Raises:
Return type:

ObjectApiResponse[Any]

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 object id or its stable rule_id; exactly one of the two must be provided.

Parameters:
  • id (str | None) – The rule’s object identifier (UUID generated by Kibana).

  • rule_id (str | None) – The rule’s stable signature identifier.

  • space_id (str | None) – Optional space ID to read the rule from.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with the rule.

Raises:
Return type:

ObjectApiResponse[Any]

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 the id or rule_id field; one of the two must be provided. The whole rule definition is replaced: any field not supplied is reset to its default value (use patch_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 id or rule_id must 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.3 RuleUpdateProps body fields (from_ is sent as from).

Returns:

ObjectApiResponse with the updated rule.

Raises:
Return type:

ObjectApiResponse[Any]

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 the id or rule_id field; one of the two must be provided. Only the supplied fields are changed.

Note: on Kibana 9.4.3 patching the enabled field is rejected with 403 (The current user does not have the permissions to edit the following fields: enabled) even for superusers; toggle enabled through update_rule() instead.

Parameters:
  • id (str | None) – The rule’s object identifier. Either id or rule_id must 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.3 RulePatchProps body fields (from_ is sent as from).

Returns:

ObjectApiResponse with the patched rule.

Raises:
Return type:

ObjectApiResponse[Any]

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 object id or its stable rule_id; exactly one of the two must be provided.

Parameters:
  • id (str | None) – The rule’s object identifier (UUID generated by Kibana).

  • rule_id (str | None) – The rule’s stable signature identifier.

  • space_id (str | None) – Optional space ID to delete the rule from.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with the deleted rule.

Raises:
Return type:

ObjectApiResponse[Any]

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: asc or desc.

  • 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, filled or error.

  • 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, total and the data array of rules.

Raises:
Return type:

ObjectApiResponse[Any]

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. Applies enable, disable, delete, duplicate, export, run, fill_gaps or edit to multiple rules selected by ids or by a KQL query. The edit action supports operations like adding/deleting tags or index patterns and changing schedules.

Note: on Kibana 9.4.3 the export action responds with NDJSON (parsed to a list) instead of a JSON summary. On the tested stack the enable, disable, run and fill_gaps actions were rejected with USER_INSUFFICIENT_RULE_PRIVILEGES even for superusers; toggle enabled through update_rule() instead.

Parameters:
  • action (str) – Bulk action to apply: enable, disable, delete, duplicate, export, run, fill_gaps or edit.

  • 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_run query parameter; not supported for export).

  • edit (list[dict[str, Any]] | None) – Array of edit operations (required for the edit action), e.g. [{"type": "add_tags", "value": ["prod"]}].

  • duplicate (dict[str, Any] | None) – Duplicate options (for the duplicate action): {"include_exceptions": bool, "include_expired_exceptions": bool}.

  • run (dict[str, Any] | None) – Manual-run window (required for the run action): {"start_date": ..., "end_date": ...}.

  • fill_gaps (dict[str, Any] | None) – Gap-fill window (required for the fill_gaps action): {"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_count and an attributes.results breakdown (updated, created, deleted, skipped) – or the NDJSON export payload for the export action.

Raises:
Return type:

ObjectApiResponse[Any]

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 to import_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 stable rule_id, not the object id). 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_name query parameter; default export.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:
Return type:

ObjectApiResponse[Any]

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 as multipart/form-data. Rules are matched by rule_id; existing rules are only replaced when overwrite is 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 by export_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, errors and the exceptions/action-connectors counterparts.

Return type:

ObjectApiResponse with the import summary

Raises:

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:
  • space_id (str | None) – Optional space ID to read the status for.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with rules_custom_installed, rules_installed, rules_not_installed, rules_not_updated and the timelines_* counterparts.

Raises:
Return type:

ObjectApiResponse[Any]

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 the security_detection_engine Fleet package on first use). The call is idempotent: already-installed and up-to-date assets are skipped.

Parameters:
  • space_id (str | None) – Optional space ID to install the prebuilt content in.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse with rules_installed, rules_updated, timelines_installed and timelines_updated counts.

Raises:
Return type:

ObjectApiResponse[Any]

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 returned previewId, 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 as from).

Returns:

ObjectApiResponse with the previewId, per-invocation logs (errors, warnings, duration) and isAborted.

Raises:
Return type:

ObjectApiResponse[Any]

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:
  • space_id (str | None) – Optional space ID to list tags from.

  • validate_spaces (bool | None) – Override space validation setting for this operation.

Returns:

ObjectApiResponse whose body is the array of unique tag strings.

Raises:
Return type:

ObjectApiResponse[Any]

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 fields option.

  • source (bool | str | list[str] | None) – The _source option: 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:
Return type:

ObjectApiResponse[Any]

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, acknowledged or closed) of detection alerts selected either by alert IDs or by an Elasticsearch query; exactly one of signal_ids and query must be provided.

Parameters:
  • status (str) – The new workflow status: open, acknowledged or closed (in-progress is a deprecated alias of acknowledged).

  • 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) or proceed.

  • 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:
Return type:

ObjectApiResponse[Any]

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:
  • ids (list[str]) – List of alert ids to update.

  • 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:
Return type:

ObjectApiResponse[Any]

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-profile uid) on the given detection alerts. Users need to activate their user profile by logging into Kibana at least once.

Parameters:
  • ids (list[str]) – List of alert ids to update.

  • add (list[str]) – User profile uid values to assign. A uid that is in both lists results in a no-op.

  • remove (list[str]) – User profile uid values to unassign.

  • 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:
Return type:

ObjectApiResponse[Any]

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.alerts indices 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 indices results (migration_id, migration_index).

Raises:
Return type:

ObjectApiResponse[Any]

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.alerts indices 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:
  • from – Maximum age of qualifying detection alerts, as date math (e.g. "now-30d"); sent as the from query parameter.

  • 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 migration statuses.

Raises:
Return type:

ObjectApiResponse[Any]

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.alerts indices 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 migrations statuses.

Raises:
Return type:

ObjectApiResponse[Any]

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.alerts indices 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 migrations statuses.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> await client.detection_engine.delete_alerts_migration(
...     migration_ids=["924f7c50-505f-11eb-ae0a-3fa2e626a51d"],
... )
async perform_request(method, path, *, params=None, headers=None, body=None)

Perform an async HTTP request via the parent client with space context enhancement.

Parameters:
  • method (str) – HTTP method (GET, POST, PUT, DELETE, etc.)

  • path (str) – API endpoint path

  • params (dict[str, Any] | None) – Query parameters

  • headers (dict[str, str] | None) – Request headers

  • body (dict[str, Any] | None) – Request body

Returns:

API response

Raises:

ApiError – If the API returns an error response (enhanced with space context)

Return type:

ObjectApiResponse[Any]