You're viewing **Apigee Edge** documentation.  
[Go to the
**Apigee X** documentation](http://cloud.google.com/apigee/docs/api-platform/reference/policies/verify-api-key-policy). info
![](https://docs.apigee.com/static/api-platform/images/icon_policy_security.jpg)

## What

The Verify API Key policy lets you enforce verification of API keys at runtime, letting only
apps with approved API keys access your APIs. This policy ensures that API keys are valid, have
not been revoked, and are approved to consume the specific resources associated with your API
products.

## Samples

### Key in query param

```
<VerifyAPIKey name="APIKeyVerifier">
    <APIKey ref="request.queryparam.apikey" />
</VerifyAPIKey>
```

In this example, the policy expects to find the API key in a flow variable called
`request.queryparam.apikey`. The variable `request.queryparam.{name}`
is a standard Edge flow variable that is populated with the value of a query param passed
in the client request.

The following `curl` command passes the API key in a query param:

```
curl http://myorg-test.apigee.net/mocktarget?apikey=IEYRtW2cb7A5Gs54A1wKElECBL65GVls
```

> [!NOTE]
> While allowed, it's generally a poor practice to pass the API key in a query parameter. The reason is because query params can appear in the browser history and network logs, which presents a possible security risk. A better practice is to place the API key in a header, which will not appear in log files. See the "KEY IN HEADER" example on the next tab.

### Key in header

```
<VerifyAPIKey name="APIKeyVerifier">
    <APIKey ref="request.header.x-apikey" />
</VerifyAPIKey>
```

In this example, the policy expects to find the API key in a flow variable called
`request.header.x-apikey`. The variable `request.header.{name}`
is a standard Edge flow variable that is populated with the value of a header passed
in the client request.

The following cURL shows how to pass the API key in a header:

```
curl "http://myorg-test.apigee.net/mocktarget" -H "x-apikey:IEYRtW2cb7A5Gs54A1wKElECBL65GVls"
```

> [!NOTE]
> It's a good practice to pass the API key in a header rather than in a query parameter. The reason is because headers do not appear in the browser history or network logs, which could present a possible security risk.

### Key in variable

```
<VerifyAPIKey name="APIKeyVerifier">
    <APIKey ref="requestAPIKey.key"/>
</VerifyAPIKey>
```

The policy can reference any variable that contains the key. The policy in this example
extracts the API key from a variable named requestAPIKey.key.

How that variable is populated is up to you. For example, you could use the Extract
Variables policy to populate requestAPIKey.key from a query parameter
named myKey, as shown
below:

```
<ExtractVariables async="false" continueOnError="false" enabled="true" name="SetAPIKeyVar">
    <Source>request</Source>
    <QueryParam name="myKey">
        <Pattern ignoreCase="true">{key}</Pattern>
    </QueryParam>
    <VariablePrefix>requestAPIKey</VariablePrefix>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
```

### Access policy flow variables

```
<AssignMessage async="false" continueOnError="false" enabled="true" name="accessverifyvars">
    <AssignVariable>
        <Name>devFirstName</Name>
        <Ref>verifyapikey.verify-api-key.developer.firstName</Ref>
        <Value>ErrorOnCopy</Value>
    </AssignVariable>
    <AssignVariable>
        <Name>devLastName</Name>
        <Ref>verifyapikey.verify-api-key.developer.lastName</Ref>
        <Value>ErrorOnCopy</Value>
    </AssignVariable>
    <AssignVariable>
        <Name>devEmail</Name>
        <Ref>verifyapikey.verify-api-key.developer.email</Ref>
        <Value>ErrorOnCopy</Value>
    </AssignVariable>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>
```

Edge automatically populates a set of flow variables when executing the Verify API Key
policy for a valid API key. You can use these variables to access information such as the app
name, app ID, and information about the developer or company who registered the app. In the
example above, you use the Assign Message policy to access the developer's first name, last
name, and email address after the Verify API Key executes.

These variables are all prefixed by:

```
verifyapikey.{policy_name}
```

In this example, the Verify API key policy name is "verify-api-key". Therefore, you reference
the first name of the developer making the request by accessing the
variable `verifyapikey.verify-api-key.developer.firstName.`

### Learn Edge

> [!NOTE]
> **Sample:** **Learn by doing!**   
> The [Secure the proxy with an API key](https://github.com/apigee/api-platform-samples/tree/master/learn-edge/apikey-security-1) example secures an API proxy with an API key, and the [Remove the apikey query parameter](https://github.com/apigee/api-platform-samples/tree/master/learn-edge/apikey-security-2) shows you how to remove the API key from the request to prevent it from being passed to the backend target (a best practice). Just clone the repository and follow the instructions in the README files.

*** ** * ** ***

## About the Verify API Key policy

When a developer registers an app on Edge, Edge automatically generates a consumer key and
secret pair. You can see the app's consumer key and secret pair in the Edge UI or access them
from the Edge API.

> [!NOTE]
> **Note:** API keys go by many names. You may see them referred to as 'API keys', 'app keys', and 'consumer keys'. All of these names are synonymous.

At the time of app registration, the developer selects one or more *API products* to
associate with the app, where an API product is a collection of*resources*
accessible through API proxies. The developer then passes the API key (consumer key) as part of
every request to an API in an API product associated with the app. See [Publishing overview](https://docs.apigee.com/api-platform/publish/publishing-overview) for more.

API keys can be used as authentication tokens, or they can be used to obtain OAuth access
tokens. In OAuth, API keys are referred to as "client id". The names can be used interchangeably.
See [OAuth home](https://docs.apigee.com/api-platform/security/oauth/oauth-home) for more.

Edge automatically populates a set of flow variables when executing the Verify API Key policy.
See [Flow
variables](https://docs.apigee.com/api-platform/reference/policies/verify-api-key-policy#variables) below for more.

## Element Reference

Following are elements and attributes you can configure on this policy:

```
<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-API-Key-1">
    <DisplayName>Custom label used in UI</DisplayName>
    <APIKey ref="variable_containing_api_key"/>
</VerifyAPIKey>
```

## \<VerifyAPIKey\> attributes

The following example shows the attributes on the `<VerifyAPIKey>` tag:

```
<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-API-Key-1">
```

The following table describes attributes that are common to all policy parent elements:

| Attribute | Description | Default | Presence |
|---|---|---|---|
| `name` | The internal name of the policy. The value of the `name` attribute can contain letters, numbers, spaces, hyphens, underscores, and periods. This value cannot exceed 255 characters. Optionally, use the `<DisplayName>` element to label the policy in the management UI proxy editor with a different, natural-language name. | N/A | Required |
| `continueOnError` | Set to `false` to return an error when a policy fails. This is expected behavior for most policies. Set to `true` to have flow execution continue even after a policy fails. | false | Optional |
| `enabled` | Set to `true` to enforce the policy. Set to `false` to *turn off* the policy. The policy will not be enforced even if it remains attached to a flow. | true | Optional |
| `async` | This attribute is deprecated. | false | Deprecated |

## \<DisplayName\> element

Use in addition to the `name` attribute to label the policy in the
management UI proxy editor with a different, natural-language name.

```
<DisplayName>Policy Display Name</DisplayName>
```

| Default | N/A If you omit this element, the value of the policy's `name` attribute is used. |
| Presence | Optional |
| Type | String |
|---|---|

## \<APIKey\> element

This element specifies the flow variable that contains the API key. Typically, the client sends the API key
in a query parameter, HTTP header or a form parameter. For example, if the key is sent in a header
called `x-apikey`, the key will be found in the variable: `request.header.x-apikey`

| Default | NA |
| Presence | Required |
| Type | String |
|---|---|

### Attributes

The following table describes the attributes of the `<APIKey>` element

| Attribute | Description | Default | Presence |
|---|---|---|---|
| ref | A reference to the variable that contains the API key. Only one location is allowed per policy. | N/A | Required |

> [!NOTE]
> It's a good practice to pass the API key in a header or form parameter rather than in a query parameter. The reason is because query parameters can show up in browser histories and network logs, which could present a possible security risk.

### Examples

In these examples, the key is passed in parameters and a header called `x-apikey`.

As a query parameter:

```
<VerifyAPIKey name="APIKeyVerifier">
    <APIKey ref="request.queryparam.x-apikey"/>
</VerifyAPIKey>
```

As an HTTP header:

```
<VerifyAPIKey name="APIKeyVerifier">
    <APIKey ref="request.header.x-apikey"/>
</VerifyAPIKey>
```

As an HTTP form parameter:

```
<VerifyAPIKey name="APIKeyVerifier">
    <APIKey ref="request.formparam.x-apikey"/>
</VerifyAPIKey>
```

## Schemas

> [!NOTE]
> **Sample:** See our [GitHub
> repository](https://github.com/apigee/api-platform-samples/tree/master/schemas/policy) samples for the most recent schemas.

## Flow variables

When a Verify API Key policy is enforced on a valid API key, Edge populates a set of flow
variables. These variables are available to policies or code executed later in the flow, and are
often used to perform custom processing based on attributes of the API key such as the app name,
the API product used to authorize the key, or custom attributes of the API key.

The policy populates several different types of flow variables, including:

- General
- App
- Developer
- Company
- Analytics

Each type of flow variable has a different prefix. All variables are scalars except those
specifically indicated as arrays.

### General flow variables

The following table lists the general flow variables populated by the Verify API Key policy.
These variables are all prefixed by:

```
verifyapikey.{policy_name}
```

For example: `verifyapikey.{policy_name}.client_id`

The available variables include:

| Variable | Description |
|---|---|
| `client_id` | The consumer key (aka API key or app key) supplied by the requesting app. |
| `client_secret` | The consumer secret associated with the consumer key. |
| `redirection_uris` | Any redirect URIs in the request. |
| `developer.app.id` | The ID of the developer app making the request. > [!NOTE] > **Note:** Do not use the `developer.app.id` variable for any of the following purposes: > - [identifier for the Quota policy](https://docs.apigee.com/api-platform/reference/policies/quota-policy#identifierelement) > - [Key Value Map (KVM) keys](https://docs.apigee.com/api-platform/cache/key-value-maps) > - Identifiers sent to targets to be used in backend business logic > This ID is generated internally by Apigee and is not guaranteed to stay the same over time. For example, Apigee could change the format or length of this variable. |
| `developer.app.name` | The app name of the developer app making the request. |
| `developer.id` | The ID of the developer registered as the owner of the requesting app. > [!NOTE] > **Note:** Do not use the `developer.id` variable for any of the following purposes: > - [Quota Identifier](https://docs.apigee.com/api-platform/reference/policies/quota-policy#identifierelement) > - [KVM keys](https://docs.apigee.com/api-platform/cache/key-value-maps) > - Identifiers sent to targets to be used in backend business logic > This ID is generated internally by Apigee and is not guaranteed to stay the same over time. For example, Apigee could change the format or length of this variable. |
| `developer.{custom_attrib_name}` | Any custom attributes derived from the app key profile |
| `DisplayName` | The value of the policy's \<DisplayName\> attribute. |
| `failed` | Set to "true" when API Key validation fails. |
| `{custom_app_attrib}` | Any custom attribute derived from the app profile. Specify the name of the custom attribute. > [!NOTE] > **Note:** If the App custom attribute and App key custom attribute have the same name, then App key custom attribute will take precedence. |
| `apiproduct.name*` | The name of the API product used to validate the request. |
| `apiproduct.{custom_attrib_name}*` | Any custom attribute derived from the API product profile. |
| `apiproduct.developer.quota.limit*` | The quota limit set on the API product, if any. |
| `apiproduct.developer.quota.interval*` | The quota interval set on the API product, if any. |
| `apiproduct.developer.quota.timeunit*` | The quota time unit set on the API product, if any. |
| \* API product variables are populated automatically if the API products are configured with valid environment, proxies, and resources (derived from the `proxy.pathsuffix`). For instructions on setting up API products, see [Using the Edge management API to Publish APIs](https://docs.apigee.com/api-platform/publish/using-edge-management-api-publish-apis). ||

### App flow variables

The following flow variables containing information about the app are populated by the policy.
These variables are all prefixed by:

`verifyapikey.{policy_name}.app`.

For example:

`verifyapikey.{policy_name}.app.name`

The available variables include:

| Variable | Description |
|---|---|
| `name` | The name of the app. |
| `id` | The ID of the app. |
| `accessType` | Unused by Apigee. |
| `callbackUrl` | The callback URL of the app. Typically used only for OAuth. |
| `DisplayName` | The app's display name. |
| `status` | The app status, such as 'approved' or 'revoked'. |
| `apiproducts` | An array containing the list of API products associated with the app. |
| `appFamily` | Any app family containing the app, or "default". |
| `appParentStatus` | The status of the app's parent, such as 'active' or 'inactive' |
| `appType` | The app type, as either "Company" or "Developer". |
| `appParentId` | The ID of the parent app. |
| `created_at` | The date/time stamp when the app was created. |
| `created_by` | The email address of the developer who created the app. |
| `last_modified_at` | The date/time stamp when the app was last updated. |
| `last_modified_by` | The email address of the developer who last updated the app. |
| `{app_custom_attributes}` | Any custom app attribute. Specify the name of the custom attribute. |

### **Developer flow variables**

The following flow variables containing information about the developer are populated by the
policy. These variables are all prefixed by:

```
verifyapikey.{policy_name}.developer
```

> [!NOTE]
> **Note:** If the `verifyapikey.{policy_name}.app.appType` flow variable is "Developer", then developer attributes are populated. If `app.appType` is "Company", then company attributes are populated.

For example:

`verifyapikey.{policy_name}.developer.id`

The available variables include:

| Variable | Description |
|---|---|
| `id` | Returns {org_name}@@@{developer_id} |
| `userName` | The developer's user name. |
| `firstName` | The developer's first name. |
| `lastName` | The developer's last name. |
| `email` | The developer's email address. |
| `status` | The developer's status, as active, inactive, or login_lock. |
| `apps` | An array of apps associated with the developer. |
| `created_at` | The date/time stamp when the developer was created. |
| `created_by` | The email address of the user who created the developer. |
| `last_modified_at` | The date/time stamp when the developer was last modified. |
| `last_modified_by` | The email address of the user who modified the developer. |
| `{developer_custom_attributes}` | Any custom developer attribute. Specify the name of the custom attribute. |
| `Company` | The name of the company, if any, associated with the developer. |

### Company flow variables

The following flow variables containing information about the company are populated by the
policy. These variables are all prefixed by:

```
verifyapikey.{policy_name}.company
```

> [!NOTE]
> **Note:** If the `verifyapikey.{policy_name}.app.appType` is "Company", then company attributes are populated. If `app.appType` is "Developer", then developer attributes are populated.

For example:

```
verifyapikey.{policy_name}.company.name
```

The available variables include:

| Variable | Description |
|---|---|
| `name` | The company name. |
| `displayName` | The display name of the company. |
| `id` | The company ID. > [!NOTE] > **Note:** Do not use the `company.id` variable for any of the following purposes: > - [Quota Identifier](https://docs.apigee.com/api-platform/reference/policies/quota-policy#identifierelement) > - [KVM keys](https://docs.apigee.com/api-platform/cache/key-value-maps) > - Identifiers sent to targets to be used in backend business logic > This ID is generated internally by Apigee and is not guaranteed to stay the same over time. For example, Apigee could change the format or length of this variable. |
| `apps` | An array containing the list of company apps. |
| `appOwnerStatus` | The status of the app owner, as active, inactive, or login_lock. |
| `created_at` | The date/time stamp when the company was created. |
| `created_by` | The email address of the user who created the company. |
| `last_modified_at` | The date/time stamp when the company was last modified. |
| `last_modified_by` | The email address of the user who last modified the company. |
| `{company_custom_attributes}` | Any custom company attribute. Specify the name of the custom attribute. |

### Analytics variables

The following variables are automatically populated in Analytics when a Verify API Key policy
is enforced for a valid API key. These variables are only populated by the Verify API Key
policy and the OAuth policies.

The variables and values can be used as dimensions to build Analytics reports to gain
visibility into consumption patterns by developers and apps.

- apiproduct.name
- developer.app.name
- client_id
- developer.id

## Error reference


This section describes the fault codes and error messages that are returned and fault variables that are set by Edge when this policy triggers an error.
This information is important to know if you are developing fault rules to
handle faults. To learn more, see [What you need to know
about policy errors](https://docs.apigee.com/api-platform/fundamentals/what-you-need-know-about-policy-errors) and [Handling
faults](https://docs.apigee.com/api-platform/fundamentals/fault-handling).

### Runtime errors

These errors can occur when the policy executes.

> [!IMPORTANT]
> **Tip:** Use [API Monitoring](https://docs.apigee.com/api-monitoring) to investigate fault codes and diagnose issues faster. See [Set up a policy fault code alert](https://docs.apigee.com/api-monitoring/alerts-notifications#fault-code-alert) for an example. See [Fault code reference](https://docs.apigee.com/api-monitoring/fault-codes) for a complete list of all fault codes that you can handle with API Monitoring.

| Fault code | HTTP status | Cause |
|---|---|---|
| `keymanagement.service.CompanyStatusNotActive` | 401 | The Company associated with the Developer App that has the API key you are using has an inactive status. When a Company's status is set to inactive, you cannot access the developers or apps associated with that Company. An org admin can change a Company's status using the management API. See [Set the Status of a Company](https://docs.apigee.com/management/apis/put/organizations/{org_name}/companies/{company_name}-0). |
| `keymanagement.service.DeveloperStatusNotActive` | 401 | The developer who created the Developer App that has the API key you are using has an inactive status. When an App Developer's status is set to inactive, any Developer Apps created by that developer are deactivated. An admin user with appropriate permissions (such as Organization Administrator) can change a developer's status in the following ways: - Management API: [Set Developer Status](https://docs.apigee.com/management/apis/post/organizations/{org_name}/developers/{developer_email_or_id}) - Management UI: In [Register app developers](https://docs.apigee.com/api-platform/publish/adding-developers-your-api-product), see the instructions for deactivating (and activating) a developer. |
| `keymanagement.service.invalid_client-app_not_approved` | 401 | The Developer App associated with the API key is revoked. A revoked app cannot access any API products and cannot invoke any API managed by Apigee Edge. An org admin can change the status of a Developer App using the management API. See [Approve or Revoke Developer App](https://docs.apigee.com/management/apis/post/organizations/{org_name}/developers/{developer_email_or_id}/apps/{app_name}). |
| `oauth.v2.FailedToResolveAPIKey` | 401 | The policy expects to find the API key in a variable that is specified in the policy's [\<APIKey\> element](https://docs.apigee.com/api-platform/reference/policies/verify-api-key-policy#apikey). This error arises when the expected variable does not exist (it cannot be resolved). |
| `oauth.v2.InvalidApiKey` | 401 | An API key was received by Edge, but it is invalid. When Edge looks up the key in its database, it must exactly match the on that was sent in the request. If the API worked previously, make sure the key was not regenerated. If the key was regenerated, you will see this error if you try to use the old key. For details, see [Register apps and manage API keys](https://docs.apigee.com/api-platform/publish/creating-apps-surface-your-api). |
| `oauth.v2.InvalidApiKeyForGivenResource` | 401 | An API key was received by Edge, and it is valid; however, it does not match an approved key in the Developer App associated with your API proxy through a Product. |

> [!NOTE]
> **Note:** Currently Edge does not report the `ApiKeyNotApproved` error accurately. Instead, if a key is not approved (its status is set to "revoked" or "pending"), you will get the FailedToResolveAPIKey error instead. For more information and a possible workaround, see [this post on the Apigee Community](https://discuss.google.dev/t/verify-api-key-not-reporting-api-key-not-approved/1705).

### Deployment errors

These errors can occur when you deploy a proxy containing this policy.

| Error name | Cause |
|---|---|
| `SpecifyValueOrRefApiKey` | The `<APIKey>` element does not have a value or key specified. |

### Fault variables

These variables are set when a runtime error occurs. For more information, see [What you need to know
about policy errors](https://docs.apigee.com/api-platform/fundamentals/what-you-need-know-about-policy-errors).

| Variables | Where | Example |
|---|---|---|
| `fault.name="fault_name"` | <var translate="no">fault_name</var> is the name of the fault, as listed in the [Runtime errors](https://docs.apigee.com/api-platform/reference/policies/verify-api-key-policy#runtime-errors) table above. The fault name is the last part of the fault code. | `fault.name Matches "FailedToResolveAPIKey"` |
| `oauthV2.policy_name.failed` | <var translate="no">policy_name</var> is the user-specified name of the policy that threw the fault. | `oauthV2.VK-VerifyAPIKey.failed = true` |

### Example error responses

> [!NOTE]
> **Note:** For error handling, the best practice is to trap the `errorcode` part of the error response. Do not rely on the text in the `faultstring`, because it could change.

```
{
   "fault":{
      "faultstring":"Invalid ApiKey",
      "detail":{
         "errorcode":"oauth.v2.InvalidApiKey"
      }
   }
}
```

```
{
   "fault":{
      "detail":{
         "errorcode":"keymanagement.service.DeveloperStatusNotActive"
      },
      "faultstring":"Developer Status is not Active"
   }
}
```

### Example fault rule

```
<FaultRule name="FailedToResolveAPIKey">
    <Step>
        <Name>AM-FailedToResolveAPIKey</Name>
    </Step>
    <Condition>(fault.name Matches "FailedToResolveAPIKey") </Condition>
</FaultRule>
```

<br />

## Related topics

> [!NOTE]
> **Sample:** For working samples of API proxies, see the [Samples list](https://docs.apigee.com/api-platform/samples/samples-reference).