How to import Kibana saved objects

Importing Kibana saved objects lets you move dashboards, data views, saved searches, and other workspace assets between environments without rebuilding them by hand. A clean import path keeps dashboards reproducible across development, staging, and production when the same views need to be promoted into another Kibana space or deployment.

Kibana stores these assets as saved object documents and imports them from a file created by the Saved Objects export API or the Saved Objects page in the web UI. The import endpoint accepts an NDJSON file as multipart form data, runs the saved-object migrations needed for the current version, and can either overwrite matching objects or create new copies with regenerated IDs.

Current Kibana releases import saved objects only into the same version, a newer minor on the same major, or the next major. The account performing the import needs the Saved Objects Management Kibana privilege, import requests must include the kbn-xsrf header, and large files are still limited by savedObjects.maxImportExportSize and savedObjects.maxImportPayloadBytes. When objects are imported into another space or as new copies, Kibana can assign different IDs, which can break weak links such as Markdown links that still point to old dashboard URLs.

Steps to import Kibana saved objects:

  1. Confirm the target Kibana endpoint is reachable and note its version before importing.
    $ curl --silent --show-error --fail \
      --user 'kibana_import:password' \
      --cacert /etc/kibana/certs/http-ca.crt \
      'https://kibana.example.net:5601/api/status' | jq '{version: .version.number, status: .status.overall.level}'
    {
      "version": "9.3.2",
      "status": "available"
    }

    Importing works only into the same Kibana version, a newer minor on the same major, or the next major. Add the configured base path before /api/ when Kibana is published behind a reverse proxy, such as https://kibana.example.net:5601/kibana/api/status.

  2. Inspect the exported file and confirm it contains newline-delimited saved object documents.
    $ head -n 2 saved-objects.ndjson
    {"attributes":{"description":"Imported dashboard example","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"hidePanelTitles\":false}","panelsJSON":"[]","timeRestore":false,"title":"Ops overview"},"coreMigrationVersion":"8.8.0","created_at":"2026-04-02T13:52:47.850Z","id":"ops-overview","managed":false,"references":[],"type":"dashboard","typeMigrationVersion":"10.3.0","updated_at":"2026-04-02T13:52:47.850Z","version":"WzYsMV0="}
    {"attributes":{"allowHidden":false,"allowNoIndex":true,"fieldAttrs":"{}","fieldFormatMap":"{}","fields":"[]","name":"Ops import logs","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"@timestamp","title":"ops-import-*"},"coreMigrationVersion":"8.8.0","created_at":"2026-04-02T13:52:48.104Z","id":"388b3515-36a8-4d0d-84a6-ca7785b3499e","managed":false,"references":[],"type":"index-pattern","typeMigrationVersion":"8.0.0","updated_at":"2026-04-02T13:52:48.104Z","version":"WzcsMV0="}

    Use a file exported from Kibana rather than hand-editing the NDJSON. The saved objects APIs still use the saved object type index-pattern for data views in export and import payloads.

  3. Import the file into the target space.
    $ curl --silent --show-error --fail \
      --user 'kibana_import:password' \
      --cacert /etc/kibana/certs/http-ca.crt \
      --header 'kbn-xsrf: true' \
      --form file=@saved-objects.ndjson \
      'https://kibana.example.net:5601/s/ops-import/api/saved_objects/_import?overwrite=true' | jq '{success: .success, successCount: .successCount, successResults: [.successResults[] | {type: .type, id: .id, title: .meta.title}]}'
    {
      "success": true,
      "successCount": 2,
      "successResults": [
        {
          "type": "dashboard",
          "id": "ops-overview",
          "title": "Ops overview"
        },
        {
          "type": "index-pattern",
          "id": "388b3515-36a8-4d0d-84a6-ca7785b3499e",
          "title": "Ops import logs"
        }
      ]
    }

    Using overwrite=true replaces matching objects in the target space. Use createNewCopies=true when you need side-by-side copies instead, but do not combine it with overwrite or compatibilityMode.

    Use compatibilityMode=true only when Kibana reports import compatibility problems, and replace --user with an Authorization: ApiKey header when automation already standardizes on API key authentication.

  4. Query the imported objects and confirm Kibana stored them in the target space.
    $ curl --silent --show-error --fail \
      --user 'kibana_import:password' \
      --cacert /etc/kibana/certs/http-ca.crt \
      'https://kibana.example.net:5601/s/ops-import/api/saved_objects/_find?type=dashboard&search_fields=title&search=Ops%20overview&per_page=1' | jq '{total: .total, saved_objects: [.saved_objects[] | {id: .id, type: .type, title: .attributes.title}]}'
    {
      "total": 1,
      "saved_objects": [
        {
          "id": "ops-overview",
          "type": "dashboard",
          "title": "Ops overview"
        }
      ]
    }

    If the import response reports success: false, inspect the errors array for conflict or missing_references details. Objects are created only after Kibana can resolve every import error for that object set.

  5. Open Stack ManagementSaved Objects in the target space and confirm the imported dashboard or related objects appear with the expected names.

    Current Kibana imports overwrite matching objects by default in the web UI. Use Create new objects with random IDs only when you explicitly want copies with new IDs, and check dashboard links afterward because ID changes can break weak links.