diff --git a/x-pack/docs/en/rest-api/security/get-api-keys.asciidoc b/x-pack/docs/en/rest-api/security/get-api-keys.asciidoc
index dce3f48370028..e0dcf8801536a 100644
--- a/x-pack/docs/en/rest-api/security/get-api-keys.asciidoc
+++ b/x-pack/docs/en/rest-api/security/get-api-keys.asciidoc
@@ -179,7 +179,7 @@ A successful call returns a JSON structure that contains the information of one
{
"api_keys": [ <1>
{
- "id": "dGhpcyBpcyBub3QgYSByZWFsIHRva2VuIGJ1dCBpdCBpcyBvbmx5IHRlc3QgZGF0YS4gZG8gbm90IHRyeSB0byByZWFkIHRva2VuIQ==", <2>
+ "id": "0GF5GXsBCXxz2eDxWwFN", <2>
"name": "hadoop_myuser_key", <3>
"creation": 1548550550158, <4>
"expiration": 1548551550158, <5>
@@ -191,7 +191,7 @@ A successful call returns a JSON structure that contains the information of one
}
},
{
- "id": "api-key-id-2",
+ "id": "6wHJmcQpReKBa42EHV5SBw",
"name": "api-key-name-2",
"creation": 1548550550158,
"invalidated": false,
diff --git a/x-pack/docs/en/rest-api/security/query-api-key.asciidoc b/x-pack/docs/en/rest-api/security/query-api-key.asciidoc
new file mode 100644
index 0000000000000..1a293c0f912bd
--- /dev/null
+++ b/x-pack/docs/en/rest-api/security/query-api-key.asciidoc
@@ -0,0 +1,334 @@
+[role="xpack"]
+[[security-api-query-api-key]]
+=== Query API key information API
+
+++++
+Query API key information
+++++
+
+Retrieves information for API keys with <>
+in a <> 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` cluster
+privilege.
+* If you have only the `manage_own_api_key` privilege, this API returns only
+the API keys that you own. If you have the `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
+<> in a paginated manner.
+You can optionally filter the results with a query.
+
+[[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 <> to filter which API keys to return.
+The query supports a subset of query types, including
+<>, <>,
+<>, <>, <>,
+<>, <>, and <>.
++
+You can query all public information associated with an API key, including the
+following values.
++
+.Valid values for `query`
+[%collapsible%open]
+====
+`id`::
+ID of the API key. Note `id` must be queried with the <> 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`.
+
+`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 <> field type, all fields act like
+`keyword` fields when querying and sorting.
+====
+
+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
+<> 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
+<> parameter.
+
+`sort`::
+(Optional, object) <>. 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) <> 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"
+ }
+ },
+ {
+ "id": "oEvrGXsB8w290t5683TI",
+ "name": "my-api-key-2",
+ "creation": 1628227498953,
+ "expiration": 1628313898953,
+ "invalidated": false,
+ "username": "elastic",
+ "realm": "reserved",
+ "metadata": {
+ "letter": "b"
+ }
+ }
+ ]
+}
+----
+// NOTCONSOLE
+
+<1> The list of API keys that were retrieved for this request
+
+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"
+}
+----
+// TESTRESPONSE[s/VuaCfGcBCdbkQm-e5aOx/$body.id/]
+// TESTRESPONSE[s/ui2lp2axTNmsyakw9tvNnw/$body.api_key/]
+
+Use the information from the response to retrieve the API key by ID:
+
+[source,console]
+----
+GET /_security/_query/api_key
+{
+ "query": {
+ "ids": {
+ "values": [
+ "VuaCfGcBCdbkQm-e5aOx"
+ ]
+ }
+ }
+}
+----
+// TEST[s/VuaCfGcBCdbkQm-e5aOx/$body.id/]
+// TEST[continued]
+
+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]
+----
+{
+ "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 <> 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"
+ },
+ "_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"
+ },
+ "_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` <> as defined in the request
+<2> The second sort value is the API key name