How to create an Elasticsearch API key

Elasticsearch API keys let applications and automation authenticate without reusing a user password. Issuing a dedicated key per integration makes rotation, revocation, and privilege scoping easier when a pipeline, script, or host needs access to the cluster.

The security API creates keys through POST /_security/api_key. A request can set a name, expiration, metadata, and role_descriptors block, while the response returns the id, one-time api_key secret, and the prebuilt encoded value for an Authorization: ApiKey header. When role_descriptors is omitted or empty, the key inherits a point-in-time snapshot of the authenticated user's current permissions.

Current Elastic documentation states that the API key service is enabled automatically, and creating a key requires an authenticated principal with at least the manage_own_api_key cluster privilege. The returned secret is shown only once, so it must be stored immediately. On secured clusters, use the normal authenticated HTTPS endpoint for the target cluster. Elastic also documents that requests authenticated with an existing API key can only create a derived key without privileges, so a normal user credential is the safer default for scoped key creation.

Steps to create an Elasticsearch API key:

  1. Set the cluster URL used by the API calls.
    $ export ELASTICSEARCH_URL="https://elasticsearch.example.net:9200"

    Replace the URL with the authenticated HTTPS endpoint used by the target cluster.

  2. Create an API key with an expiration, metadata, and scoped privileges.
    $ curl --silent --show-error --fail \ \
      --user elastic:password \
      --header "Content-Type: application/json" \
      --request POST "$ELASTICSEARCH_URL/_security/api_key?pretty" \
      --data '{
      "name": "logs-reader",
      "expiration": "30d",
      "metadata": {
        "application": "support-portal",
        "environment": {
          "name": "production"
        }
      },
      "role_descriptors": {
        "logs_reader": {
          "indices": [
            {
              "names": ["logs-*"],
              "privileges": ["read", "view_index_metadata"]
            }
          ]
        }
      }
    }'
    {
      "id" : "VuaCf5cB2hLyd1kR3Y8x",
      "name" : "logs-reader",
      "expiration" : 1772784000000,
      "api_key" : "Dr8Q5w8yQnG6mQ1lYcYl7Q",
      "encoded" : "VnVhQ2Y1Y0IyaEx5ZDFrUjNZOHg6RHI4UTV3OHlRbkcybVExbFljWWw3UQ=="
    }

    Literal passwords on the command line can leak through shell history and process listings. Use a protected shell, a temporary credential flow, or a prompting workflow when handling real administrator credentials.

    If role_descriptors is omitted, the API key inherits a point-in-time snapshot of the authenticated user's current permissions. Assigned privileges are always limited by the authenticated user's effective permissions.

    Elastic's current API documentation notes that requests authenticated with an existing API key can create only a derived key without privileges. Use a user credential when a new key needs its own scoped role_descriptors.

  3. Export the returned encoded value for HTTP requests that send an Authorization: ApiKey header.
    $ export ELASTIC_API_KEY="VnVhQ2Y1Y0IyaEx5ZDFrUjNZOHg6RHI4UTV3OHlRbkcybVExbFljWWw3UQ=="

    The api_key secret is returned only at creation time and cannot be retrieved again later from Elasticsearch.

    Tools that expect the raw id:api_key form, such as Filebeat and Logstash, should use the separate id and api_key fields instead of the pre-encoded value.

  4. Verify the new credential authenticates successfully against Elasticsearch.
    $ curl --silent --show-error --fail \ \
      --header "Authorization: ApiKey $ELASTIC_API_KEY" \
      "$ELASTICSEARCH_URL/_security/_authenticate?pretty"
    {
      "username" : "elastic",
      "authentication_type" : "api_key",
      "api_key" : {
        "id" : "VuaCf5cB2hLyd1kR3Y8x",
        "name" : "logs-reader",
        "managed_by" : "elasticsearch"
      }
    ##### snipped #####
    }

    A successful response confirms Elasticsearch accepts the key and identifies which API key was used for the request.

  5. Test the API key against the intended index pattern or API before handing it to an application.
    $ curl --silent --show-error --fail \ \
      --header "Authorization: ApiKey $ELASTIC_API_KEY" \
      "$ELASTICSEARCH_URL/logs-*/_count?pretty"
    {
      "count" : 42,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      }
    }

    Use a verification request that matches the privileges granted to the key. Authentication success alone does not prove the key can access the intended indices or APIs.