TimelineClient

Client for the Kibana Security Timeline API.

Timelines are the Security Solution’s workspace for investigating events and alerts. The Timeline APIs cover Timeline and Timeline-template CRUD, per-user draft Timelines, favorites, NDJSON export/import, prepackaged-Timeline installation, Timeline copies, investigation notes (/api/note) and pinned events (/api/pinned_event).

Timelines, notes and pinned events are space-scoped saved objects: a Timeline created in one space is not visible from another space. Every method accepts an optional space_id to target a specific space.

class kibana._sync.client.timeline.TimelineClient(client, default_space_id=None, validate_spaces=True)[source]

Bases: NamespaceClient

Client for the Kibana Security Timeline API.

Timelines are the Security Solution’s workspace for investigating events and alerts. This client covers the full Security Timeline API surface: Timeline and Timeline-template CRUD, per-user draft Timelines, favorites, NDJSON export/import, prepackaged-Timeline installation, Timeline copies, investigation notes (/api/note) and pinned events (/api/pinned_event).

All Timeline resources are space-scoped saved objects: a Timeline created in one space is not visible from another space. 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).

Example

>>> from kibana import Kibana
>>> client = Kibana("http://localhost:5601", api_key="...")
>>>
>>> # Create a Timeline and attach a note to it
>>> created = client.timeline.create(
...     timeline={"title": "Suspicious logons", "description": "..."}
... )
>>> timeline_id = created.body["savedObjectId"]
>>> client.timeline.create_note(
...     note={"timelineId": timeline_id, "note": "Check host-1 first"}
... )
>>>
>>> # Clean up
>>> client.timeline.delete(saved_object_ids=[timeline_id])

Creating and Managing Timelines

from kibana import Kibana

client = Kibana("http://localhost:5601", api_key="your_api_key")

# Create a Timeline
created = client.timeline.create(
    timeline={
        "title": "Suspicious logons",
        "description": "Investigating a suspicious logon burst",
        "dateRange": {
            "start": "2026-07-01T00:00:00.000Z",
            "end": "2026-07-02T00:00:00.000Z",
        },
    }
)
timeline_id = created.body["savedObjectId"]

# Get, update, list and delete
fetched = client.timeline.get(id=timeline_id)
client.timeline.update(
    timeline_id=timeline_id,
    version=fetched.body["version"],
    timeline={"title": "Suspicious logons (triaged)"},
)
found = client.timeline.get_all(search="Suspicious", page_size=10)
client.timeline.delete(saved_object_ids=[timeline_id])

Notes and Pinned Events

# Attach an investigation note to the Timeline
note = client.timeline.create_note(
    note={"timelineId": timeline_id, "note": "Check host-1 first"}
)
note_id = note.body["note"]["noteId"]

# Fetch the Timeline's notes, then delete them
notes = client.timeline.get_notes(saved_object_ids=timeline_id)
client.timeline.delete_notes(note_id=note_id)

# Pin an event (by its document _id) and unpin it again
pinned = client.timeline.pin_event(
    event_id="d3a1d35a3e84...", timeline_id=timeline_id
)
client.timeline.unpin_event(
    event_id="d3a1d35a3e84...",
    timeline_id=timeline_id,
    pinned_event_id=pinned.body["pinnedEventId"],
)

Export and Import

# Export Timelines as NDJSON (the parsed body is a list of dicts)
exported = client.timeline.export(
    file_name="timelines.ndjson", ids=[timeline_id]
)

# Import them back (multipart/form-data upload)
result = client.timeline.import_timelines(file=list(exported))
print(result.body["success"], result.body["timelines_installed"])

Drafts, Favorites, Copies and Prepackaged Timelines

# Per-user draft Timeline
draft = client.timeline.get_draft(timeline_type="default")
client.timeline.clean_draft(timeline_type="default")

# Toggle the favorite mark for the current user
client.timeline.favorite(timeline_id=timeline_id, timeline_type="default")

# Copy a Timeline (including notes and pinned events)
copy = client.timeline.copy(
    timeline_id_to_copy=timeline_id, timeline={"title": "Copy"}
)

# Install/update the Elastic prepackaged Timeline templates
client.timeline.install_prepackaged()
__init__(client, default_space_id=None, validate_spaces=True)[source]

Initialize the TimelineClient.

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

>>> timeline_client = TimelineClient(kibana_client)
create(*, timeline, status=None, template_timeline_id=None, template_timeline_version=None, timeline_id=None, timeline_type=None, version=None, space_id=None, validate_spaces=None)[source]

Create a Timeline or Timeline template.

POST /api/timeline. Creates a new saved Timeline or Timeline template from a SavedTimeline object (title, description, dateRange, columns, dataProviders, filters, …).

Parameters:
  • timeline (dict[str, Any]) – The SavedTimeline object describing the Timeline (e.g. {"title": ..., "description": ..., "dateRange": {"start": ..., "end": ...}}).

  • status (str | None) – Timeline status: "active", "draft" or "immutable".

  • template_timeline_id (str | None) – Unique identifier for the Timeline template (when creating a template).

  • template_timeline_version (int | None) – Timeline template version number.

  • timeline_id (str | None) – A unique identifier to assign to the Timeline.

  • timeline_type (str | None) – Type of Timeline: "default" or "template".

  • version (str | None) – Version of the Timeline.

  • space_id (str | None) – Optional space ID to create the Timeline in.

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

Returns:

ObjectApiResponse containing the created Timeline, including its savedObjectId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> created = client.timeline.create(
...     timeline={
...         "title": "My investigation",
...         "description": "Investigating a suspicious logon",
...     }
... )
>>> print(created.body["savedObjectId"])
get(*, id=None, template_timeline_id=None, space_id=None, validate_spaces=None)[source]

Get Timeline or Timeline template details.

GET /api/timeline. Gets the details of an existing saved Timeline (by id) or Timeline template (by template_timeline_id).

NOTE: the live Kibana 9.4.3 server returns HTTP 500 (“please provide id or template_timeline_id”) when neither parameter is given, so this client requires at least one of them.

Parameters:
  • id (str | None) – The savedObjectId of the Timeline to retrieve.

  • template_timeline_id (str | None) – The ID of the Timeline template to retrieve.

  • space_id (str | None) – Optional space ID to get the Timeline from.

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

Returns:

ObjectApiResponse containing the Timeline, including its savedObjectId, version and all SavedTimeline fields.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> timeline = client.timeline.get(id="15c1929b-...-56e234cc7c4e")
>>> print(timeline.body["title"])
get_all(*, only_user_favorite=None, timeline_type=None, sort_field=None, sort_order=None, page_size=None, page_index=None, search=None, status=None, space_id=None, validate_spaces=None)[source]

Get Timelines or Timeline templates.

GET /api/timelines. Gets a list of all saved Timelines or Timeline templates, with optional filtering, sorting and pagination.

Parameters:
  • only_user_favorite (bool | str | None) – If true, only Timelines marked as favorites by the current user are returned.

  • timeline_type (str | None) – Filter by type: "default" or "template".

  • sort_field (str | None) – Field to sort by: "title", "description", "updated" or "created".

  • sort_order (str | None) – Sort order: "asc" or "desc".

  • page_size (int | str | None) – How many results are returned per page.

  • page_index (int | str | None) – How many pages are skipped (1-based page number).

  • search (str | None) – Search for Timelines by their title.

  • status (str | None) – Filter by status: "active", "draft" or "immutable".

  • space_id (str | None) – Optional space ID to list Timelines from.

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

Returns:

ObjectApiResponse containing timeline (the list of Timelines) and totalCount, plus favorite/template count summaries.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> found = client.timeline.get_all(
...     search="investigation", page_size=10, page_index=1
... )
>>> print(found.body["totalCount"])
update(*, timeline_id, version, timeline, space_id=None, validate_spaces=None)[source]

Update a Timeline.

PATCH /api/timeline. Updates an existing Timeline or Timeline template. You can update the title, description, date range, data providers and any other SavedTimeline field.

Parameters:
  • timeline_id (str) – The savedObjectId of the Timeline or Timeline template being updated.

  • version (str | None) – The version of the Timeline being updated (from a previous read; may be None).

  • timeline (dict[str, Any]) – The SavedTimeline object with the updated fields.

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the updated Timeline with its new version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> current = client.timeline.get(id=timeline_id)
>>> updated = client.timeline.update(
...     timeline_id=timeline_id,
...     version=current.body["version"],
...     timeline={"title": "Renamed investigation"},
... )
delete(*, saved_object_ids, search_ids=None, space_id=None, validate_spaces=None)[source]

Delete Timelines or Timeline templates.

DELETE /api/timeline. Deletes one or more Timelines or Timeline templates by their saved object IDs (maximum 100 per call).

Parameters:
  • saved_object_ids (list[str]) – The list of savedObjectId values of the Timelines or Timeline templates to delete.

  • search_ids (list[str] | None) – Saved search IDs that should be deleted alongside the Timelines.

  • space_id (str | None) – Optional space ID the Timelines live in.

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

Returns:

ObjectApiResponse with an empty body on success.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> client.timeline.delete(
...     saved_object_ids=["15c1929b-...-56e234cc7c4e"]
... )
resolve(*, id=None, template_timeline_id=None, space_id=None, validate_spaces=None)[source]

Resolve a saved Timeline or Timeline template.

GET /api/timeline/resolve. Like get(), but uses the saved objects resolve semantics: the response wraps the Timeline in a timeline key together with an outcome (exactMatch, aliasMatch or conflict) so callers can follow legacy-URL aliases after migrations.

Parameters:
  • id (str | None) – The ID of the Timeline to resolve.

  • template_timeline_id (str | None) – The ID of the Timeline template to resolve.

  • space_id (str | None) – Optional space ID to resolve the Timeline in.

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

Returns:

ObjectApiResponse containing the resolved timeline object and the resolve outcome.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> resolved = client.timeline.resolve(id=timeline_id)
>>> print(resolved.body["timeline"]["title"])
copy(*, timeline_id_to_copy, timeline, space_id=None, validate_spaces=None)[source]

Copy a Timeline or Timeline template.

POST /api/timeline/_copy. Copies an existing Timeline or Timeline template (including its notes and pinned events) and returns the copy.

NOTE: the 9.4.3 OpenAPI spec documents this operation as GET, but the live server only registers POST and restricts the route to internal callers; this client sends the x-elastic-internal-origin header the route requires.

Parameters:
  • timeline_id_to_copy (str) – The savedObjectId of the Timeline to copy.

  • timeline (dict[str, Any]) – The SavedTimeline object applied to the copy (e.g. a new title).

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the copied Timeline, including its new savedObjectId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> copy = client.timeline.copy(
...     timeline_id_to_copy=timeline_id,
...     timeline={"title": "Copy of my investigation"},
... )
>>> print(copy.body["savedObjectId"])
get_draft(*, timeline_type, space_id=None, validate_spaces=None)[source]

Get the draft Timeline or Timeline template for the current user.

GET /api/timeline/_draft. Gets the details of the current user’s draft Timeline (or Timeline template). If the user doesn’t have a draft Timeline, an empty draft Timeline is created and returned.

Parameters:
  • timeline_type (str) – The type of draft Timeline: "default" or "template".

  • space_id (str | None) – Optional space ID to get the draft Timeline from.

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

Returns:

ObjectApiResponse containing the draft Timeline, including its savedObjectId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> draft = client.timeline.get_draft(timeline_type="default")
>>> print(draft.body["status"])
draft
clean_draft(*, timeline_type, space_id=None, validate_spaces=None)[source]

Create a clean draft Timeline or Timeline template.

POST /api/timeline/_draft. Creates a clean draft Timeline (or Timeline template) for the current user. If the user already has a draft Timeline, the existing draft is cleared and returned.

Parameters:
  • timeline_type (str) – The type of draft Timeline to create: "default" or "template".

  • space_id (str | None) – Optional space ID to create the draft Timeline in.

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

Returns:

ObjectApiResponse containing the (cleared) draft Timeline, including its savedObjectId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> draft = client.timeline.clean_draft(timeline_type="default")
>>> print(draft.body["savedObjectId"])
export(*, file_name, ids=None, space_id=None, validate_spaces=None)[source]

Export Timelines as an NDJSON file.

POST /api/timeline/_export. Exports the given Timelines as NDJSON (application/ndjson): one Timeline per line. The parsed response body is a list of Timeline dicts that can be passed straight to import_timelines().

Parameters:
  • file_name (str) – The name of the file to export (query parameter used for the Content-Disposition of the download).

  • ids (list[str] | None) – The savedObjectId values of the Timelines to export (1 to 1000 IDs).

  • space_id (str | None) – Optional space ID to export the Timelines from.

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

Returns:

ObjectApiResponse whose body is the parsed NDJSON list of exported Timelines.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> exported = client.timeline.export(
...     file_name="timelines.ndjson", ids=[timeline_id]
... )
>>> print(len(list(exported)))
1
import_timelines(*, file, is_immutable=None, filename='timelines.ndjson', space_id=None, validate_spaces=None)[source]

Import Timelines from an NDJSON export file.

POST /api/timeline/_import. Imports Timelines from an NDJSON file produced by export(), uploaded as multipart/form-data (the content type the live server requires).

Parameters:
  • file (bytes | str | list[dict[str, Any]]) – NDJSON export content: raw bytes/str, or a list of Timeline dicts (e.g. the parsed body returned by export()), which is NDJSON-encoded automatically.

  • is_immutable (bool | str | None) – Whether the imported Timelines should be immutable (sent as the isImmutable form field; booleans are encoded as "true"/"false").

  • filename (str) – Filename advertised in the multipart upload; must have an .ndjson extension.

  • space_id (str | None) – Optional space ID to import the Timelines into.

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

Returns:

success, success_count, timelines_installed, timelines_updated and an errors array.

Return type:

ObjectApiResponse containing the import result

Raises:

Example

>>> exported = client.timeline.export(
...     file_name="timelines.ndjson", ids=[timeline_id]
... )
>>> result = client.timeline.import_timelines(file=list(exported))
>>> print(result.body["success"])
install_prepackaged(*, timelines_to_install=None, timelines_to_update=None, prepackaged_timelines=None, space_id=None, validate_spaces=None)[source]

Install or update prepackaged Timelines.

POST /api/timeline/_prepackaged. Installs or updates the Elastic prepackaged Timeline templates. When called with the default empty lists, the server computes which prepackaged Timelines are missing or outdated and installs/updates them.

Parameters:
  • timelines_to_install (list[dict[str, Any]] | None) – Timelines to install (ImportTimelines objects). Defaults to an empty list.

  • timelines_to_update (list[dict[str, Any]] | None) – Timelines to update (ImportTimelines objects). Defaults to an empty list.

  • prepackaged_timelines (list[dict[str, Any]] | None) – The currently installed prepackaged Timelines (TimelineSavedToReturnObject objects). Defaults to an empty list.

  • space_id (str | None) – Optional space ID to install the Timelines into.

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

Returns:

success, success_count, timelines_installed, timelines_updated and an errors array.

Return type:

ObjectApiResponse containing the install result

Raises:

Example

>>> result = client.timeline.install_prepackaged()
>>> print(result.body["timelines_installed"])
favorite(*, timeline_id, template_timeline_id=None, template_timeline_version=None, timeline_type=None, space_id=None, validate_spaces=None)[source]

Favorite (or unfavorite) a Timeline for the current user.

PATCH /api/timeline/_favorite. Toggles the favorite status of a Timeline or Timeline template for the current user: calling it once marks the Timeline as a favorite, calling it again removes the favorite mark. All four body fields are required by the API but may be null.

Parameters:
  • timeline_id (str | None) – The savedObjectId of the Timeline (may be None when favoriting a template by its template ID).

  • template_timeline_id (str | None) – The Timeline template ID.

  • template_timeline_version (int | None) – The Timeline template version.

  • timeline_type (str | None) – The type of Timeline: "default" or "template".

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the Timeline’s savedObjectId, new version and the favorite entries (empty after an unfavorite call).

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> result = client.timeline.favorite(
...     timeline_id=timeline_id, timeline_type="default"
... )
>>> print(result.body["favorite"][0]["userName"])
create_note(*, note, space_id=None, validate_spaces=None)[source]

Add a note to a Timeline.

PATCH /api/note. Creates a new note attached to a Timeline. To attach the note to a specific event or alert, set note["eventId"] to that event’s document _id; omit eventId for a timeline-wide note. Requires the Timeline and Notes write privilege (notes_write).

Parameters:
  • note (dict[str, Any]) – The BareNote payload. Must include timelineId; may include note (the text) and eventId.

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the persisted note under the note key, including its noteId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> created = client.timeline.create_note(
...     note={"timelineId": timeline_id, "note": "Look at host-1"}
... )
>>> print(created.body["note"]["noteId"])
update_note(*, note_id, note, version=None, space_id=None, validate_spaces=None)[source]

Update an existing note.

PATCH /api/note. Updates an existing note by its saved object ID. Optionally pass version (from a previous read) for optimistic concurrency control. Requires the Timeline and Notes write privilege (notes_write).

Parameters:
  • note_id (str) – The savedObjectId of the note to update.

  • note (dict[str, Any]) – The BareNote payload with the changed fields. Must include timelineId.

  • version (str | None) – Saved object version string from a previous read.

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the persisted note under the note key, including its noteId and new version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> updated = client.timeline.update_note(
...     note_id=note_id,
...     note={"timelineId": timeline_id, "note": "Updated text"},
...     version=note_version,
... )
get_notes(*, document_ids=None, saved_object_ids=None, page=None, per_page=None, search=None, sort_field=None, sort_order=None, filter=None, created_by_filter=None, associated_filter=None, space_id=None, validate_spaces=None)[source]

Get notes.

GET /api/note. Returns Security Timeline notes. The server has three mutually exclusive query modes:

  1. document_ids set: returns notes whose eventId matches the given event document _id value(s); pagination is not applied.

  2. saved_object_ids set: returns notes linked to the given Timeline saved object ID(s); pagination is not applied.

  3. Neither set: lists notes with saved-objects find semantics using page, per_page, search, sort_field, sort_order, filter, created_by_filter and associated_filter.

Requires the Timeline and Notes read privilege (notes_read).

Parameters:
  • document_ids (str | list[str] | None) – Event document _id value(s) to match against each note’s eventId.

  • saved_object_ids (str | list[str] | None) – Timeline savedObjectId value(s); returns notes that reference those Timelines.

  • page (int | str | None) – Page number for list mode (default 1).

  • per_page (int | str | None) – Page size for list mode (default 10).

  • search (str | None) – Search string (list mode only).

  • sort_field (str | None) – Field to sort by (list mode only).

  • sort_order (str | None) – Sort order, "asc" or "desc" (list mode only).

  • filter (str | None) – KQL filter string interpreted by the saved-objects layer (list mode only).

  • created_by_filter (str | None) – Kibana user profile UID; returns notes created by that user (list mode only).

  • associated_filter (str | None) – Restricts notes by how they relate to a Timeline and/or event: "all", "document_only", "saved_object_only", "document_and_saved_object" or "orphan" (list mode only).

  • space_id (str | None) – Optional space ID to get the notes from.

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

Returns:

ObjectApiResponse containing notes and totalCount.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> notes = client.timeline.get_notes(
...     saved_object_ids=timeline_id
... )
>>> print(notes.body["totalCount"])
delete_notes(*, note_id=None, note_ids=None, space_id=None, validate_spaces=None)[source]

Delete one or more notes.

DELETE /api/note. Deletes notes by saved object ID. Pass either note_id (single delete) or note_ids (bulk delete) — exactly one of the two. Requires the Timeline and Notes write privilege (notes_write).

Parameters:
  • note_id (str | None) – Saved object ID of the single note to delete.

  • note_ids (list[str] | None) – Saved object IDs of the notes to delete.

  • space_id (str | None) – Optional space ID the notes live in.

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

Returns:

ObjectApiResponse with an empty body on success.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> client.timeline.delete_notes(note_id="709f99c6-...-8e174e")
>>> client.timeline.delete_notes(note_ids=["id-1", "id-2"])
pin_event(*, event_id, timeline_id, space_id=None, validate_spaces=None)[source]

Pin an event to a Timeline.

PATCH /api/pinned_event. Pins an event to an existing Timeline so it stays visible during the investigation.

Parameters:
  • event_id (str) – The _id of the event document to pin.

  • timeline_id (str) – The savedObjectId of the Timeline to pin the event to.

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the pinned event, including its pinnedEventId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> pinned = client.timeline.pin_event(
...     event_id="d3a1d35a3e84...", timeline_id=timeline_id
... )
>>> print(pinned.body["pinnedEventId"])
unpin_event(*, event_id, timeline_id, pinned_event_id, space_id=None, validate_spaces=None)[source]

Unpin an event from a Timeline.

PATCH /api/pinned_event. Unpins an event from a Timeline by passing the pinnedEventId returned when the event was pinned.

Parameters:
  • event_id (str) – The _id of the event document to unpin.

  • timeline_id (str) – The savedObjectId of the Timeline the event is pinned to.

  • pinned_event_id (str) – The savedObjectId of the pinned event to unpin (returned by pin_event()).

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing {"unpinned": true} on success.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> result = client.timeline.unpin_event(
...     event_id="d3a1d35a3e84...",
...     timeline_id=timeline_id,
...     pinned_event_id=pinned_event_id,
... )
>>> print(result.body["unpinned"])
True
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]

AsyncTimelineClient

Asynchronous version of the TimelineClient for use with async/await syntax.

class kibana._async.client.timeline.AsyncTimelineClient(client, default_space_id=None, validate_spaces=True)[source]

Bases: AsyncNamespaceClient

Async client for the Kibana Security Timeline API.

Timelines are the Security Solution’s workspace for investigating events and alerts. This client covers the full Security Timeline API surface: Timeline and Timeline-template CRUD, per-user draft Timelines, favorites, NDJSON export/import, prepackaged-Timeline installation, Timeline copies, investigation notes (/api/note) and pinned events (/api/pinned_event).

All Timeline resources are space-scoped saved objects: a Timeline created in one space is not visible from another space. 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).

Example

>>> from kibana import AsyncKibana
>>> client = AsyncKibana("http://localhost:5601", api_key="...")
>>>
>>> # Create a Timeline and attach a note to it
>>> created = await client.timeline.create(
...     timeline={"title": "Suspicious logons", "description": "..."}
... )
>>> timeline_id = created.body["savedObjectId"]
>>> await client.timeline.create_note(
...     note={"timelineId": timeline_id, "note": "Check host-1 first"}
... )
>>>
>>> # Clean up
>>> await client.timeline.delete(saved_object_ids=[timeline_id])

Usage

The AsyncTimelineClient provides the same methods as TimelineClient 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:
        # Create a Timeline (async)
        created = await client.timeline.create(
            timeline={"title": "Async investigation"}
        )
        timeline_id = created.body["savedObjectId"]

        # Attach a note (async)
        await client.timeline.create_note(
            note={"timelineId": timeline_id, "note": "async note"}
        )

        # Clean up (async)
        await client.timeline.delete(saved_object_ids=[timeline_id])

asyncio.run(main())
__init__(client, default_space_id=None, validate_spaces=True)[source]

Initialize the AsyncTimelineClient.

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

>>> timeline_client = AsyncTimelineClient(kibana_client)
async create(*, timeline, status=None, template_timeline_id=None, template_timeline_version=None, timeline_id=None, timeline_type=None, version=None, space_id=None, validate_spaces=None)[source]

Create a Timeline or Timeline template.

POST /api/timeline. Creates a new saved Timeline or Timeline template from a SavedTimeline object (title, description, dateRange, columns, dataProviders, filters, …).

Parameters:
  • timeline (dict[str, Any]) – The SavedTimeline object describing the Timeline (e.g. {"title": ..., "description": ..., "dateRange": {"start": ..., "end": ...}}).

  • status (str | None) – Timeline status: "active", "draft" or "immutable".

  • template_timeline_id (str | None) – Unique identifier for the Timeline template (when creating a template).

  • template_timeline_version (int | None) – Timeline template version number.

  • timeline_id (str | None) – A unique identifier to assign to the Timeline.

  • timeline_type (str | None) – Type of Timeline: "default" or "template".

  • version (str | None) – Version of the Timeline.

  • space_id (str | None) – Optional space ID to create the Timeline in.

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

Returns:

ObjectApiResponse containing the created Timeline, including its savedObjectId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> created = await client.timeline.create(
...     timeline={
...         "title": "My investigation",
...         "description": "Investigating a suspicious logon",
...     }
... )
>>> print(created.body["savedObjectId"])
async get(*, id=None, template_timeline_id=None, space_id=None, validate_spaces=None)[source]

Get Timeline or Timeline template details.

GET /api/timeline. Gets the details of an existing saved Timeline (by id) or Timeline template (by template_timeline_id).

NOTE: the live Kibana 9.4.3 server returns HTTP 500 (“please provide id or template_timeline_id”) when neither parameter is given, so this client requires at least one of them.

Parameters:
  • id (str | None) – The savedObjectId of the Timeline to retrieve.

  • template_timeline_id (str | None) – The ID of the Timeline template to retrieve.

  • space_id (str | None) – Optional space ID to get the Timeline from.

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

Returns:

ObjectApiResponse containing the Timeline, including its savedObjectId, version and all SavedTimeline fields.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> timeline = await client.timeline.get(id="15c1929b-...-56e234cc7c4e")
>>> print(timeline.body["title"])
async get_all(*, only_user_favorite=None, timeline_type=None, sort_field=None, sort_order=None, page_size=None, page_index=None, search=None, status=None, space_id=None, validate_spaces=None)[source]

Get Timelines or Timeline templates.

GET /api/timelines. Gets a list of all saved Timelines or Timeline templates, with optional filtering, sorting and pagination.

Parameters:
  • only_user_favorite (bool | str | None) – If true, only Timelines marked as favorites by the current user are returned.

  • timeline_type (str | None) – Filter by type: "default" or "template".

  • sort_field (str | None) – Field to sort by: "title", "description", "updated" or "created".

  • sort_order (str | None) – Sort order: "asc" or "desc".

  • page_size (int | str | None) – How many results are returned per page.

  • page_index (int | str | None) – How many pages are skipped (1-based page number).

  • search (str | None) – Search for Timelines by their title.

  • status (str | None) – Filter by status: "active", "draft" or "immutable".

  • space_id (str | None) – Optional space ID to list Timelines from.

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

Returns:

ObjectApiResponse containing timeline (the list of Timelines) and totalCount, plus favorite/template count summaries.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> found = await client.timeline.get_all(
...     search="investigation", page_size=10, page_index=1
... )
>>> print(found.body["totalCount"])
async update(*, timeline_id, version, timeline, space_id=None, validate_spaces=None)[source]

Update a Timeline.

PATCH /api/timeline. Updates an existing Timeline or Timeline template. You can update the title, description, date range, data providers and any other SavedTimeline field.

Parameters:
  • timeline_id (str) – The savedObjectId of the Timeline or Timeline template being updated.

  • version (str | None) – The version of the Timeline being updated (from a previous read; may be None).

  • timeline (dict[str, Any]) – The SavedTimeline object with the updated fields.

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the updated Timeline with its new version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> current = await client.timeline.get(id=timeline_id)
>>> updated = await client.timeline.update(
...     timeline_id=timeline_id,
...     version=current.body["version"],
...     timeline={"title": "Renamed investigation"},
... )
async delete(*, saved_object_ids, search_ids=None, space_id=None, validate_spaces=None)[source]

Delete Timelines or Timeline templates.

DELETE /api/timeline. Deletes one or more Timelines or Timeline templates by their saved object IDs (maximum 100 per call).

Parameters:
  • saved_object_ids (list[str]) – The list of savedObjectId values of the Timelines or Timeline templates to delete.

  • search_ids (list[str] | None) – Saved search IDs that should be deleted alongside the Timelines.

  • space_id (str | None) – Optional space ID the Timelines live in.

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

Returns:

ObjectApiResponse with an empty body on success.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> await client.timeline.delete(
...     saved_object_ids=["15c1929b-...-56e234cc7c4e"]
... )
async resolve(*, id=None, template_timeline_id=None, space_id=None, validate_spaces=None)[source]

Resolve a saved Timeline or Timeline template.

GET /api/timeline/resolve. Like get(), but uses the saved objects resolve semantics: the response wraps the Timeline in a timeline key together with an outcome (exactMatch, aliasMatch or conflict) so callers can follow legacy-URL aliases after migrations.

Parameters:
  • id (str | None) – The ID of the Timeline to resolve.

  • template_timeline_id (str | None) – The ID of the Timeline template to resolve.

  • space_id (str | None) – Optional space ID to resolve the Timeline in.

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

Returns:

ObjectApiResponse containing the resolved timeline object and the resolve outcome.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> resolved = await client.timeline.resolve(id=timeline_id)
>>> print(resolved.body["timeline"]["title"])
async copy(*, timeline_id_to_copy, timeline, space_id=None, validate_spaces=None)[source]

Copy a Timeline or Timeline template.

POST /api/timeline/_copy. Copies an existing Timeline or Timeline template (including its notes and pinned events) and returns the copy.

NOTE: the 9.4.3 OpenAPI spec documents this operation as GET, but the live server only registers POST and restricts the route to internal callers; this client sends the x-elastic-internal-origin header the route requires.

Parameters:
  • timeline_id_to_copy (str) – The savedObjectId of the Timeline to copy.

  • timeline (dict[str, Any]) – The SavedTimeline object applied to the copy (e.g. a new title).

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the copied Timeline, including its new savedObjectId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> copy = await client.timeline.copy(
...     timeline_id_to_copy=timeline_id,
...     timeline={"title": "Copy of my investigation"},
... )
>>> print(copy.body["savedObjectId"])
async get_draft(*, timeline_type, space_id=None, validate_spaces=None)[source]

Get the draft Timeline or Timeline template for the current user.

GET /api/timeline/_draft. Gets the details of the current user’s draft Timeline (or Timeline template). If the user doesn’t have a draft Timeline, an empty draft Timeline is created and returned.

Parameters:
  • timeline_type (str) – The type of draft Timeline: "default" or "template".

  • space_id (str | None) – Optional space ID to get the draft Timeline from.

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

Returns:

ObjectApiResponse containing the draft Timeline, including its savedObjectId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> draft = await client.timeline.get_draft(timeline_type="default")
>>> print(draft.body["status"])
draft
async clean_draft(*, timeline_type, space_id=None, validate_spaces=None)[source]

Create a clean draft Timeline or Timeline template.

POST /api/timeline/_draft. Creates a clean draft Timeline (or Timeline template) for the current user. If the user already has a draft Timeline, the existing draft is cleared and returned.

Parameters:
  • timeline_type (str) – The type of draft Timeline to create: "default" or "template".

  • space_id (str | None) – Optional space ID to create the draft Timeline in.

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

Returns:

ObjectApiResponse containing the (cleared) draft Timeline, including its savedObjectId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> draft = await client.timeline.clean_draft(timeline_type="default")
>>> print(draft.body["savedObjectId"])
async export(*, file_name, ids=None, space_id=None, validate_spaces=None)[source]

Export Timelines as an NDJSON file.

POST /api/timeline/_export. Exports the given Timelines as NDJSON (application/ndjson): one Timeline per line. The parsed response body is a list of Timeline dicts that can be passed straight to import_timelines().

Parameters:
  • file_name (str) – The name of the file to export (query parameter used for the Content-Disposition of the download).

  • ids (list[str] | None) – The savedObjectId values of the Timelines to export (1 to 1000 IDs).

  • space_id (str | None) – Optional space ID to export the Timelines from.

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

Returns:

ObjectApiResponse whose body is the parsed NDJSON list of exported Timelines.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> exported = await client.timeline.export(
...     file_name="timelines.ndjson", ids=[timeline_id]
... )
>>> print(len(list(exported)))
1
async import_timelines(*, file, is_immutable=None, filename='timelines.ndjson', space_id=None, validate_spaces=None)[source]

Import Timelines from an NDJSON export file.

POST /api/timeline/_import. Imports Timelines from an NDJSON file produced by export(), uploaded as multipart/form-data (the content type the live server requires).

Parameters:
  • file (bytes | str | list[dict[str, Any]]) – NDJSON export content: raw bytes/str, or a list of Timeline dicts (e.g. the parsed body returned by export()), which is NDJSON-encoded automatically.

  • is_immutable (bool | str | None) – Whether the imported Timelines should be immutable (sent as the isImmutable form field; booleans are encoded as "true"/"false").

  • filename (str) – Filename advertised in the multipart upload; must have an .ndjson extension.

  • space_id (str | None) – Optional space ID to import the Timelines into.

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

Returns:

success, success_count, timelines_installed, timelines_updated and an errors array.

Return type:

ObjectApiResponse containing the import result

Raises:

Example

>>> exported = await client.timeline.export(
...     file_name="timelines.ndjson", ids=[timeline_id]
... )
>>> result = await client.timeline.import_timelines(file=list(exported))
>>> print(result.body["success"])
async install_prepackaged(*, timelines_to_install=None, timelines_to_update=None, prepackaged_timelines=None, space_id=None, validate_spaces=None)[source]

Install or update prepackaged Timelines.

POST /api/timeline/_prepackaged. Installs or updates the Elastic prepackaged Timeline templates. When called with the default empty lists, the server computes which prepackaged Timelines are missing or outdated and installs/updates them.

Parameters:
  • timelines_to_install (list[dict[str, Any]] | None) – Timelines to install (ImportTimelines objects). Defaults to an empty list.

  • timelines_to_update (list[dict[str, Any]] | None) – Timelines to update (ImportTimelines objects). Defaults to an empty list.

  • prepackaged_timelines (list[dict[str, Any]] | None) – The currently installed prepackaged Timelines (TimelineSavedToReturnObject objects). Defaults to an empty list.

  • space_id (str | None) – Optional space ID to install the Timelines into.

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

Returns:

success, success_count, timelines_installed, timelines_updated and an errors array.

Return type:

ObjectApiResponse containing the install result

Raises:

Example

>>> result = await client.timeline.install_prepackaged()
>>> print(result.body["timelines_installed"])
async favorite(*, timeline_id, template_timeline_id=None, template_timeline_version=None, timeline_type=None, space_id=None, validate_spaces=None)[source]

Favorite (or unfavorite) a Timeline for the current user.

PATCH /api/timeline/_favorite. Toggles the favorite status of a Timeline or Timeline template for the current user: calling it once marks the Timeline as a favorite, calling it again removes the favorite mark. All four body fields are required by the API but may be null.

Parameters:
  • timeline_id (str | None) – The savedObjectId of the Timeline (may be None when favoriting a template by its template ID).

  • template_timeline_id (str | None) – The Timeline template ID.

  • template_timeline_version (int | None) – The Timeline template version.

  • timeline_type (str | None) – The type of Timeline: "default" or "template".

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the Timeline’s savedObjectId, new version and the favorite entries (empty after an unfavorite call).

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> result = await client.timeline.favorite(
...     timeline_id=timeline_id, timeline_type="default"
... )
>>> print(result.body["favorite"][0]["userName"])
async create_note(*, note, space_id=None, validate_spaces=None)[source]

Add a note to a Timeline.

PATCH /api/note. Creates a new note attached to a Timeline. To attach the note to a specific event or alert, set note["eventId"] to that event’s document _id; omit eventId for a timeline-wide note. Requires the Timeline and Notes write privilege (notes_write).

Parameters:
  • note (dict[str, Any]) – The BareNote payload. Must include timelineId; may include note (the text) and eventId.

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the persisted note under the note key, including its noteId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> created = await client.timeline.create_note(
...     note={"timelineId": timeline_id, "note": "Look at host-1"}
... )
>>> print(created.body["note"]["noteId"])
async update_note(*, note_id, note, version=None, space_id=None, validate_spaces=None)[source]

Update an existing note.

PATCH /api/note. Updates an existing note by its saved object ID. Optionally pass version (from a previous read) for optimistic concurrency control. Requires the Timeline and Notes write privilege (notes_write).

Parameters:
  • note_id (str) – The savedObjectId of the note to update.

  • note (dict[str, Any]) – The BareNote payload with the changed fields. Must include timelineId.

  • version (str | None) – Saved object version string from a previous read.

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the persisted note under the note key, including its noteId and new version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> updated = await client.timeline.update_note(
...     note_id=note_id,
...     note={"timelineId": timeline_id, "note": "Updated text"},
...     version=note_version,
... )
async get_notes(*, document_ids=None, saved_object_ids=None, page=None, per_page=None, search=None, sort_field=None, sort_order=None, filter=None, created_by_filter=None, associated_filter=None, space_id=None, validate_spaces=None)[source]

Get notes.

GET /api/note. Returns Security Timeline notes. The server has three mutually exclusive query modes:

  1. document_ids set: returns notes whose eventId matches the given event document _id value(s); pagination is not applied.

  2. saved_object_ids set: returns notes linked to the given Timeline saved object ID(s); pagination is not applied.

  3. Neither set: lists notes with saved-objects find semantics using page, per_page, search, sort_field, sort_order, filter, created_by_filter and associated_filter.

Requires the Timeline and Notes read privilege (notes_read).

Parameters:
  • document_ids (str | list[str] | None) – Event document _id value(s) to match against each note’s eventId.

  • saved_object_ids (str | list[str] | None) – Timeline savedObjectId value(s); returns notes that reference those Timelines.

  • page (int | str | None) – Page number for list mode (default 1).

  • per_page (int | str | None) – Page size for list mode (default 10).

  • search (str | None) – Search string (list mode only).

  • sort_field (str | None) – Field to sort by (list mode only).

  • sort_order (str | None) – Sort order, "asc" or "desc" (list mode only).

  • filter (str | None) – KQL filter string interpreted by the saved-objects layer (list mode only).

  • created_by_filter (str | None) – Kibana user profile UID; returns notes created by that user (list mode only).

  • associated_filter (str | None) – Restricts notes by how they relate to a Timeline and/or event: "all", "document_only", "saved_object_only", "document_and_saved_object" or "orphan" (list mode only).

  • space_id (str | None) – Optional space ID to get the notes from.

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

Returns:

ObjectApiResponse containing notes and totalCount.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> notes = await client.timeline.get_notes(
...     saved_object_ids=timeline_id
... )
>>> print(notes.body["totalCount"])
async delete_notes(*, note_id=None, note_ids=None, space_id=None, validate_spaces=None)[source]

Delete one or more notes.

DELETE /api/note. Deletes notes by saved object ID. Pass either note_id (single delete) or note_ids (bulk delete) — exactly one of the two. Requires the Timeline and Notes write privilege (notes_write).

Parameters:
  • note_id (str | None) – Saved object ID of the single note to delete.

  • note_ids (list[str] | None) – Saved object IDs of the notes to delete.

  • space_id (str | None) – Optional space ID the notes live in.

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

Returns:

ObjectApiResponse with an empty body on success.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> await client.timeline.delete_notes(note_id="709f99c6-...-8e174e")
>>> await client.timeline.delete_notes(note_ids=["id-1", "id-2"])
async pin_event(*, event_id, timeline_id, space_id=None, validate_spaces=None)[source]

Pin an event to a Timeline.

PATCH /api/pinned_event. Pins an event to an existing Timeline so it stays visible during the investigation.

Parameters:
  • event_id (str) – The _id of the event document to pin.

  • timeline_id (str) – The savedObjectId of the Timeline to pin the event to.

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing the pinned event, including its pinnedEventId and version.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> pinned = await client.timeline.pin_event(
...     event_id="d3a1d35a3e84...", timeline_id=timeline_id
... )
>>> print(pinned.body["pinnedEventId"])
async unpin_event(*, event_id, timeline_id, pinned_event_id, space_id=None, validate_spaces=None)[source]

Unpin an event from a Timeline.

PATCH /api/pinned_event. Unpins an event from a Timeline by passing the pinnedEventId returned when the event was pinned.

Parameters:
  • event_id (str) – The _id of the event document to unpin.

  • timeline_id (str) – The savedObjectId of the Timeline the event is pinned to.

  • pinned_event_id (str) – The savedObjectId of the pinned event to unpin (returned by pin_event()).

  • space_id (str | None) – Optional space ID the Timeline lives in.

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

Returns:

ObjectApiResponse containing {"unpinned": true} on success.

Raises:
Return type:

ObjectApiResponse[Any]

Example

>>> result = await client.timeline.unpin_event(
...     event_id="d3a1d35a3e84...",
...     timeline_id=timeline_id,
...     pinned_event_id=pinned_event_id,
... )
>>> print(result.body["unpinned"])
True
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]