[role="xpack"]
[[security-api-query-api-key]]
=== Query API key information API

++++
<titleabbrev>Query API key information</titleabbrev>
++++

Retrieves information for API keys with <<query-dsl,Query DSL>>
in a <<paginate-search-results,paginated>> fashion.

[[security-api-query-api-key-request]]
==== {api-request-title}

`GET /_security/_query/api_key`

`POST /_security/_query/api_key`

[[security-api-query-api-key-prereqs]]
==== {api-prereq-title}

* To use this API, you must have at least the `manage_own_api_key` or the `read_security`
cluster privileges.
* If you have only the `manage_own_api_key` privilege, this API returns only
the API keys that you own. If you have the `read_security`, `manage_api_key` or greater
privileges (including `manage_security`), this API returns all API keys
regardless of ownership.

[[security-api-query-api-key-desc]]
==== {api-description-title}

Use this API to retrieve the API keys created with the
<<security-api-create-api-key,create API key API>> in a paginated manner.
You can optionally filter the results with a query.

[[security-api-query-api-key-query-params]]
==== {api-path-parms-title}

`with_limited_by`::
(Optional, Boolean) A boolean flag to return the snapshot of the owner user's role descriptors
associated with the API key. An API key's actual permission is the intersection of
its <<api-key-role-descriptors,assigned role descriptors>> and the owner user's role descriptors
(effectively limited by it). An API key cannot retrieve any API key's limited-by role descriptors
(including itself) unless it has `manage_api_key` or higher privileges.

[[security-api-query-api-key-request-body]]
==== {api-request-body-title}

You can specify the following parameters in the request body:

`query`::
(Optional, string) A <<query-dsl,query>> to filter which API keys to return.
The query supports a subset of query types, including
<<query-dsl-match-all-query,`match_all`>>, <<query-dsl-bool-query,`bool`>>,
<<query-dsl-term-query,`term`>>, <<query-dsl-terms-query,`terms`>>, <<query-dsl-ids-query,`ids`>>,
<<query-dsl-prefix-query,`prefix`>>, <<query-dsl-wildcard-query,`wildcard`>>, <<query-dsl-exists-query,`exists`>>,
and <<query-dsl-range-query,`range`>>.
+
You can query the following public values associated with an API key.
+
.Valid values for `query`
[%collapsible%open]
====
`id`::
ID of the API key. Note `id` must be queried with the <<query-dsl-ids-query,`ids`>> query.

`name`::
Name of the API key.

`creation`::
Creation time of the API key in milliseconds.

`expiration`::
Expiration time of the API key in milliseconds.

`invalidated`::
Indicates whether the API key is invalidated. If `true`, the key is invalidated.
Defaults to `false`.

`invalidation`::
Invalidation time of the API key in milliseconds. This field is only set for invalidated API keys.

`username`::
Username of the API key owner.

`realm`::
Realm name of the API key owner.

`metadata`::
Metadata field associated with the API key, such as `metadata.my_field`. Because
metadata is stored as a <<flattened,flattened>> field type, all fields act like
`keyword` fields when querying and sorting.

NOTE: You cannot query the role descriptors of an API key.
====

include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=from]
+
By default, you cannot page through more than 10,000 hits using the `from` and
`size` parameters. To page through more hits, use the
<<search-after,`search_after`>> parameter.

`size`::
(Optional, integer) The number of hits to return. Must not be negative and defaults to `10`.
+
By default, you cannot page through more than 10,000 hits using the `from` and
`size` parameters. To page through more hits, use the
<<search-after,`search_after`>> parameter.

`sort`::
(Optional, object) <<sort-search-results,Sort definition>>. Other than `id`,
all public fields of an API key are eligible for sorting. In addition, sort can
also be applied to the `_doc` field to sort by index order.

`search_after`::
(Optional, array) <<search-after,Search after>> definition.


[[security-api-query-api-key-response-body]]
==== {api-response-body-title}

This API returns the following top level fields:

`total`::
The total number of API keys found.

`count`::
The number of API keys returned in the response.

`api_keys`::
A list of API key information.

[[security-api-query-api-key-example]]
==== {api-examples-title}

The following request lists all API keys, assuming you have the
`manage_api_key` privilege:

[source,console]
----
GET /_security/_query/api_key
----

A successful call returns a JSON structure that contains the information
retrieved from one or more API keys:

[source,js]
----
{
  "total": 3,
  "count": 3,
  "api_keys": [ <1>
    {
      "id": "nkvrGXsB8w290t56q3Rg",
      "name": "my-api-key-1",
      "creation": 1628227480421,
      "expiration": 1629091480421,
      "invalidated": false,
      "username": "elastic",
      "realm": "reserved",
      "metadata": {
        "letter": "a"
      },
      "role_descriptors": { <2>
        "role-a": {
          "cluster": [
            "monitor"
          ],
          "indices": [
            {
              "names": [
                "index-a"
              ],
              "privileges": [
                "read"
              ],
              "allow_restricted_indices": false
            }
          ],
          "applications": [ ],
          "run_as": [ ],
          "metadata": { },
          "transient_metadata": {
            "enabled": true
          }
        }
      }
    },
    {
      "id": "oEvrGXsB8w290t5683TI",
      "name": "my-api-key-2",
      "creation": 1628227498953,
      "expiration": 1628313898953,
      "invalidated": false,
      "username": "elastic",
      "realm": "reserved",
      "metadata": {
        "letter": "b"
      },
      "role_descriptors": { } <3>
    }
  ]
}
----
// NOTCONSOLE

<1> The list of API keys that were retrieved for this request
<2> The role descriptors that are assigned to this API key when it was <<api-key-role-descriptors,created>>
or last <<security-api-update-api-key-api-key-role-descriptors,updated>>. Note the API key's
effective permissions are an intersection of its assigned privileges and the point-in-time snapshot of
the owner user's permissions.
<3> An empty role descriptors means the API key inherits the owner user's permissions.

If you create an API key with the following details:

[source,console]
----
POST /_security/api_key
{
  "name": "application-key-1",
  "metadata": { "application": "my-application"}
}
----

A successful call returns a JSON structure that provides
API key information. For example:

[source,console-result]
----
{
  "id": "VuaCfGcBCdbkQm-e5aOx",
  "name": "application-key-1",
  "api_key": "ui2lp2axTNmsyakw9tvNnw",
  "encoded": "VnVhQ2ZHY0JDZGJrUW0tZTVhT3g6dWkybHAyYXhUTm1zeWFrdzl0dk5udw=="
}
----
// TESTRESPONSE[s/VuaCfGcBCdbkQm-e5aOx/$body.id/]
// TESTRESPONSE[s/ui2lp2axTNmsyakw9tvNnw/$body.api_key/]
// TESTRESPONSE[s/VnVhQ2ZHY0JDZGJrUW0tZTVhT3g6dWkybHAyYXhUTm1zeWFrdzl0dk5udw==/$body.encoded/]

Use the information from the response to retrieve the API key by ID:

[source,console]
----
GET /_security/_query/api_key?with_limited_by=true
{
  "query": {
    "ids": {
      "values": [
        "VuaCfGcBCdbkQm-e5aOx"
      ]
    }
  }
}
----
// TEST[s/VuaCfGcBCdbkQm-e5aOx/$body.id/]
// TEST[continued]

A successful call returns a JSON structure for API key information including its limited-by role descriptors:

[source,js]
--------------------------------------------------
{
  "api_keys": [
    {
      "id": "VuaCfGcBCdbkQm-e5aOx",
      "name": "application-key-1",
      "creation": 1548550550158,
      "expiration": 1548551550158,
      "invalidated": false,
      "username": "myuser",
      "realm": "native1",
      "metadata": {
        "application": "my-application"
      },
      "role_descriptors": { },
      "limited_by": [ <1>
        {
          "role-power-user": {
            "cluster": [
              "monitor"
            ],
            "indices": [
              {
                "names": [
                  "*"
                ],
                "privileges": [
                  "read"
                ],
                "allow_restricted_indices": false
              }
            ],
            "applications": [ ],
            "run_as": [ ],
            "metadata": { },
            "transient_metadata": {
              "enabled": true
            }
          }
        }
      ]
    }
  ]
}
--------------------------------------------------
// NOTCONSOLE
<1> The owner user's permissions associated with the API key.
It is a point-in-time snapshot captured at <<security-api-create-api-key,creation>> and
subsequent <<security-api-update-api-key,updates>>. An API key's
effective permissions are an intersection of its assigned privileges and
the owner user's permissions.

You can also retrieve the API key by name:

[source,console]
----
GET /_security/_query/api_key
{
  "query": {
    "term": {
      "name": {
        "value": "application-key-1"
      }
    }
  }
}
----
// TEST[continued]

Use a `bool` query to issue complex logical conditions and use
`from`, `size`, `sort` to help paginate the result:

[source,js]
----
GET /_security/_query/api_key
{
  "query": {
    "bool": {
      "must": [
        {
          "prefix": {
            "name": "app1-key-" <1>
          }
        },
        {
          "term": {
            "invalidated": "false" <2>
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "name": "app1-key-01" <3>
          }
        }
      ],
      "filter": [
        {
          "wildcard": {
            "username": "org-*-user" <4>
          }
        },
        {
          "term": {
            "metadata.environment": "production" <5>
          }
        }
      ]
    }
  },
  "from": 20, <6>
  "size": 10, <7>
  "sort": [ <8>
    { "creation": { "order": "desc", "format": "date_time" } },
    "name"
  ]
}
----
// NOTCONSOLE

<1> The API key name must begin with `app1-key-`
<2> The API key must still be valid
<3> The API key name must not be `app1-key-01`
<4> The API key must be owned by a username of the <<query-dsl-wildcard-query,wildcard>> pattern `org-*-user`
<5> The API key must have the metadata field `environment` that has the value of `production`
<6> The offset to begin the search result is the 20th (zero-based index) API key
<7> The page size of the response is 10 API keys
<8> The result is first sorted by `creation` date in descending order, then by name in ascending order

The response contains a list of matched API keys along with their sort values:

[source,js]
----
{
  "total": 100,
  "count": 10,
  "api_keys": [
    {
      "id": "CLXgVnsBOGkf8IyjcXU7",
      "name": "app1-key-79",
      "creation": 1629250154811,
      "invalidated": false,
      "username": "org-admin-user",
      "realm": "native1",
      "metadata": {
        "environment": "production"
      },
      "role_descriptors": { },
      "_sort": [
        "2021-08-18T01:29:14.811Z",  <1>
        "app1-key-79"  <2>
      ]
    },
    {
      "id": "BrXgVnsBOGkf8IyjbXVB",
      "name": "app1-key-78",
      "creation": 1629250153794,
      "invalidated": false,
      "username": "org-admin-user",
      "realm": "native1",
      "metadata": {
        "environment": "production"
      },
      "role_descriptors": { },
      "_sort": [
        "2021-08-18T01:29:13.794Z",
        "app1-key-78"
      ]
    },
    ...
  ]
}
----
// NOTCONSOLE

<1> The first sort value is creation time, which is displayed in `date_time` <<mapping-date-format,format>> as defined in the request
<2> The second sort value is the API key name

You can use the following request to retrieve all valid API keys, i.e. not invalidated and not expired:
[source,js]
----
GET /_security/_query/api_key
{
  "query": {
    "bool": {
      "must": {
        "term": {
          "invalidated": false  <1>
        }
      },
      "should": [  <2>
        {
          "range": {
            "expiration": {
              "gte": "now"
            }
          }
        },
        {
          "bool": {
            "must_not": {
              "exists": {
                "field": "expiration"
              }
            }
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}
----
// NOTCONSOLE

<1> Matching API keys must not be invalidated
<2> Matching API keys must be either not expired or does not have an expiration date
