--- title: Manage API keys programmatically slug: '82' canonical_url: https://docs.coveo.com/en/82/ collection: manage-an-organization source_format: adoc --- # Manage API keys programmatically Developers working on a Coveo-powered deployment may require _API keys_ to interact programmatically with the [Coveo Platform](https://docs.coveo.com/en/186/). The following are typical situations in which an API key is required: * A developer is working on a [search interface](https://docs.coveo.com/en/2741/) that can show both public and secured content. They need an API key to implement [search token authentication](https://docs.coveo.com/en/56/). * A developer is building a [custom connector](https://docs.coveo.com/en/1702#custom-built-connectors) that uses the [Push API](https://docs.coveo.com/en/68/) to [index](https://docs.coveo.com/en/204/) content behind a firewall. They need an API key to [authenticate](https://docs.coveo.com/en/2120/) Push API calls. This article explains how to [create](#create-an-api-key-programmatically) and [rotate](#rotate-an-api-key-programmatically) API keys programmatically. ## Create an API key programmatically This section explains how to use the [Create API key](https://platform.cloud.coveo.com/docs?urls.primaryName=AuthorizationServer#/Api%20Keys/rest_organizations_paramId_apikeys_post) operation and provides some [examples](#examples). > **Tip** > > You can also [create API keys](https://docs.coveo.com/en/1718#create-an-api-key) in the [Coveo Administration Console](https://docs.coveo.com/en/183/) on the [**API Keys**](https://platform.cloud.coveo.com/admin/#/orgid/organization/api-access/) ([platform-ca](https://platform-ca.cloud.coveo.com/admin/#/orgid/organization/api-access/) | [platform-eu](https://platform-eu.cloud.coveo.com/admin/#/orgid/organization/api-access/) | [platform-au](https://platform-au.cloud.coveo.com/admin/#/orgid/organization/api-access/)) page. ### Creation request overview To create an API key with certain [privileges](https://docs.coveo.com/en/228/) in a specific [Coveo organization](https://docs.coveo.com/en/185/), make the following request to the Coveo Authorization Server API: ```http POST https://platform.cloud.coveo.com/rest/organizations//apikeys?apiKeyTemplateId= HTTP/1.1 ​ Accept: application/json Content-Type: application/json Authorization: Bearer ``` where: * `` is the [ID of the target Coveo organization](https://docs.coveo.com/en/148/). * `` is the [API key template](#api-key-templates) with the right set of [privileges](https://docs.coveo.com/en/228/) for your use case. To create a [custom API key](#custom-api-keys), omit this parameter from the request. * `` is an OAuth 2.0 [access token](https://docs.coveo.com/en/123/) with [administrative privileges](https://docs.coveo.com/en/109/) in your [Coveo organization](https://docs.coveo.com/en/185/). Coveo access tokens are valid for four hours. **Payload:** ```json { "description": "", <1> "displayName": "", <2> "allowedIps": [ * <3> ], "deniedIps": [ * <4> ], "lifetimeDuration": "", <5> "rotationEnabled": true <6> } ``` <1> (Optional) Replace `` with a string that indicates for whom, when, and for what purpose you're creating the API key. Although this is optional, you should include a detailed description to help manage the key in the future. <2> Replace `` with a name that summarizes the key's purpose. This is optional if you include an [API key template](#api-key-templates) in your request. If you omit the `apiKeyTemplateId` parameter to create a [custom API key](#custom-api-keys), the `displayName` is mandatory. <3> (Optional) Replace `*` with a list of IP addresses that should be able to use the API key. For more information, see [Allowed and denied IP addresses](#allowed-and-denied-ip-addresses). <4> (Optional) Replace `*` with a list of IP addresses that shouldn't be able to use the API key. For more information, see [Allowed and denied IP addresses](#allowed-and-denied-ip-addresses). <5> To set an expiration date for your key, replace `` with an [`ISO 8601^`](https://en.wikipedia.org/wiki/ISO_8601#Durations) formatted duration, such as `P30D` for 30 days. This is optional unless you use the **View all content** template, in which case you must set an expiration date of 1-14 days. <6> When set to `true` during key creation, the `rotationEnabled` option allows the API key to be [rotated programmatically](#rotate-an-api-key-programmatically). The body of a successful response (`201 Created`) contains information about the API key you just created. This response includes the following properties, among others: ```json { "id": "xxxxxxxxxxxxxxxxxxxxxxxxxx", <1> "value": "xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", <2> "organizationId": "", "displayName": "", "description": "", "privileges": [ <3> ... ], "createdDate": 1734516650656, "allowedIps": [], <4> "deniedIps": [], "apiKeyTemplateId": "", <5> "privacyLevel": "", <6> "status": "ENABLED", "expirationDate": 1737158399000, <7> "activationDate": 1734516650729, "rotationSecret": "coveo_apikey_rotation_v1_xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_xxxxxxxx" <8> } ``` <1> You can use the `id` property to edit or delete the API key. You can always [retrieve this value](https://docs.coveo.com/en/38/) after an API key has been created. <2> The `value` property contains the API key itself. > **Important** > > Copy the key immediately. > This is the only time you can see the `value` of an API key, and you'll never be able to retrieve it again. > > If you fail to save the `value`, or if you lose it, [delete the key](https://docs.coveo.com/en/80/) and create a new one. <3> If you created the key using an [API key template](#api-key-templates), the [privileges](https://docs.coveo.com/en/228/) are automatically assigned [based on the template](https://docs.coveo.com/en/1718#api-key-templates). If you created a [custom API key](#custom-api-keys), the [privileges](https://docs.coveo.com/en/228/) will match the values that you sent in the payload. <4> The `allowedIps` and `deniedIps` arrays will match the values that you sent in the payload. If you omitted these properties or passed empty arrays in the request, the response will include empty arrays. <5> If you created the key using a template, this will match the value that you sent in the request. If you created a custom key, this property won't appear in the response. <6> The privacy level is [based on the template](https://docs.coveo.com/en/1718#api-key-templates) that you used to create the API key. If you created a custom key, this will be `PRIVATE`. <7> This property will only appear in the response if you set an expiration date using `lifetimeDuration`. <8> This property will only appear in the response if you set `rotationEnabled` to `true`. Save this value because you'll need it to [rotate](#rotate-an-api-key-programmatically) your key in the future. ### API key templates Typically, you'll use an [API key template](https://docs.coveo.com/en/1718#api-key-templates) with predefined [privileges](https://docs.coveo.com/en/228/), in which case you must specify an `apiKeyTemplateId` in your request. You can also create a [custom API key](#custom-api-keys) that doesn't have any predefined [privileges](https://docs.coveo.com/en/228/). The following table lists the `apiKeyTemplateId` for each template: [%header,cols="2"] |=== |Template |`apiKeyTemplateId` |**Anonymous search** |`AnonymousSearch` |**Authenticated search** |`AuthenticatedSearch` |**Usage analytics** |`UsageAnalytics` |**Search pages** |`SearchPages` |**Anonymous Case Assist** |`AnonymousCaseAssist` |**Push API** |`PushDocument` |**View all content** |`ViewAllContent` |=== #### Custom API keys You can create a custom API key by omitting the `apiKeyTemplateId` from your request. In this case, you'll have to pass the list of [privileges](https://docs.coveo.com/en/1707/) that you want in the request body. See the [example section](#examples) for a sample custom API key request. > **Important** > > To prevent misuse, you can't grant any of the following [privileges](https://docs.coveo.com/en/228/) to a custom API key: > > * Search service > > ** [Execute queries](https://docs.coveo.com/en/1707#execute-queries-domain): Allowed > > ** [Impersonate](https://docs.coveo.com/en/1707#impersonate-domain-search): Allowed > > * Analytics service > > ** [Analytics data](https://docs.coveo.com/en/1707#analytics-data-domain): Push > > ** [Impersonate](https://docs.coveo.com/en/1707#impersonate-domain-Analytics): Allowed > > If you need these privileges, you can grant them using other [templates](https://docs.coveo.com/en/1718#api-key-templates). ### Allowed and denied IP addresses You can use the `allowedIps` and `deniedIps` properties to select which IP addresses can use an API key. The following table lists the results if both, one, or neither property is included in the payload. > **Tip** > > Passing an empty `allowedIps` or `deniedIps` array has the same result as omitting it from the payload. [%header,cols="~,~,~"] |=== |`allowedIps` |`deniedIps` |Result |Yes |Yes |Only the IP addresses in the `allowedIps` array can use the API key, unless they're also included in the `deniedIps` array. |Yes |No |Only the IP addresses in the `allowedIps` array can use the API key. |No |Yes |Any IP address can use the API key, except for those in the `deniedIps` array. |No |No |Any IP address can use the API key. |=== ### Examples . **Creating an API key for anonymous search:** ```http POST https://platform.cloud.coveo.com/rest/organizations/mycoveocloudv2organizationg8tp8wu3/apikeys?apiKeyTemplateId=AnonymousSearch HTTP/1.1 ​ Accept: application/json Content-Type: application/json Authorization: Bearer **********-****-****-****-************ ``` **Payload:** ```json { "description": "Created for Anonymous search on 2024-12-18.", "displayName": "Anonymous search key" } ``` **Successful response - 201 Created (excerpt):** ```json { "id": "wduuqg3ip2c3i3gpopapxhcgxe", "value": "xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "organizationId": "mycoveocloudv2organizationg8tp8wu3", "displayName": "Anonymous search key", "description": "Created for Anonymous search on 2024-12-18.", "privileges": [ { "targetDomain": "EXECUTE_QUERY", "targetId": "*", "owner": "SEARCH_API" }, { "type": "EDIT", "targetDomain": "ANALYTICS_DATA", "targetId": "*", "owner": "USAGE_ANALYTICS" } ], "createdDate": 1734516650656, "apiKeyTemplateId": "AnonymousSearch", "privacyLevel": "PUBLIC", "status": "ENABLED", "activationDate": 1734516650729 } ``` . **Creating a custom API key to view and edit sources:** ```http POST https://platform.cloud.coveo.com/rest/organizations/mycoveocloudv2organizationg8tp8wu3/apikeys HTTP/1.1 ​ Accept: application/json Content-Type: application/json Authorization: Bearer **********-****-****-****-************ ``` **Payload:** ```json { "description": "Created for Alice Smith on 2024-12-18 to view and edit sources.", "displayName": "Source Edit/View", "privileges": [ <1> { "owner": "PLATFORM", "targetDomain": "SOURCE", "type": "EDIT" }, { "owner": "PLATFORM", "targetDomain": "SOURCE", "type": "VIEW" } ] } ``` -- <1> For each [privilege](https://docs.coveo.com/en/228/) you include in the `privileges` array, specify a [valid `owner`, `targetDomain`, and `type` combination](https://docs.coveo.com/en/60#valid-owner-targetdomain-and-type-combinations). -- **Successful response - 201 Created (excerpt):** ```json { "id": "wduuqg3ip2c3i3gpopapxhcgxe", "value": "xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "organizationId": "mycoveocloudv2organizationg8tp8wu3", "displayName": "Source Edit/View", "description": "Created for Alice Smith on 2024-12-18 to view and edit sources.", "privileges": [ { "type": "EDIT", "targetDomain": "SOURCE", "targetId": "*", "owner": "PLATFORM" }, { "type": "VIEW", "targetDomain": "SOURCE", "targetId": "*", "owner": "PLATFORM" } ], "createdDate": 1734516650656, "privacyLevel": "PRIVATE", "status": "ENABLED", "activationDate": 1734516650729 } ``` ## Rotate an API key programmatically This section explains how to use the [Rotate API key](https://platform.cloud.coveo.com/docs?urls.primaryName=AuthorizationServer#/Api%20Keys/rest_organizations_paramId_apikeys_rotate_post) operation. When you [rotate](https://docs.coveo.com/en/p7sb0148/) an API key programmatically, the original key is automatically [set to expire](#rotation-and-api-key-expiration). Furthermore, you can only [rotate](https://docs.coveo.com/en/p7sb0148/) a given key once, because the [rotation](https://docs.coveo.com/en/p7sb0148/) secret becomes invalid afterward. > **Tip** > > You can also [rotate](https://docs.coveo.com/en/p7sb0148/) an API key by [creating a new key from an existing key](https://docs.coveo.com/en/1718#create-an-api-key-from-an-existing-key) in the [Coveo Administration Console](https://docs.coveo.com/en/183/) on the [**API Keys**](https://platform.cloud.coveo.com/admin/#/orgid/organization/api-access/) ([platform-ca](https://platform-ca.cloud.coveo.com/admin/#/orgid/organization/api-access/) | [platform-eu](https://platform-eu.cloud.coveo.com/admin/#/orgid/organization/api-access/) | [platform-au](https://platform-au.cloud.coveo.com/admin/#/orgid/organization/api-access/)) page. ### Rotation prerequisites You can [rotate](https://docs.coveo.com/en/p7sb0148/) an API key if it meets the following prerequisites: * When the key was created, the `rotationEnabled` field was set to `true`, and you retained the `rotationSecret` value that you received in the response. * The key that you want to [rotate](https://docs.coveo.com/en/p7sb0148/) hasn't been deleted and isn't deactivated or expired. > **Note** > > API keys with the `Soon to be deactivated`, `Soon to be expired`, or `Exposed` status can be [rotated](https://docs.coveo.com/en/p7sb0148/) programmatically. > > To [rotate](https://docs.coveo.com/en/p7sb0148/) a deactivated or expired key, [create a new key from your current key](https://docs.coveo.com/en/1718#create-an-api-key-from-an-existing-key) on the [**API Keys**](https://platform.cloud.coveo.com/admin/#/orgid/organization/api-access/) ([platform-ca](https://platform-ca.cloud.coveo.com/admin/#/orgid/organization/api-access/) | [platform-eu](https://platform-eu.cloud.coveo.com/admin/#/orgid/organization/api-access/) | [platform-au](https://platform-au.cloud.coveo.com/admin/#/orgid/organization/api-access/)) page of the [Coveo Administration Console](https://docs.coveo.com/en/183/). ### Rotation request overview To [rotate](https://docs.coveo.com/en/p7sb0148/) an API key, make the following request to the Authorization Server API: ```http POST https://platform.cloud.coveo.com/rest/organizations//apikeys/rotate HTTP/1.1 ​ Accept: application/json Content-Type: application/json Authorization: Bearer ``` where: * `` is the [ID of the target Coveo organization](https://docs.coveo.com/en/148/). * `` is the `value` of the API key that you want to [rotate](https://docs.coveo.com/en/p7sb0148/). > **Important** > > You must authenticate this request using the API key itself, not a Coveo [access token](https://docs.coveo.com/en/123/). **Payload:** ```json { "rotationSecret": "coveo_apikey_rotation_v1__", <1> "previousKeyExpirationPeriod": "P14D", <2> "newKeyExpirationPeriod": "P30D" <3> } ``` <1> This is the [rotation](https://docs.coveo.com/en/p7sb0148/) secret that was in the response when you created the original API key. <2> (Optional) After you [rotate](https://docs.coveo.com/en/p7sb0148/) an API key, the original key will [expire in 30 days or less](#rotation-and-api-key-expiration). Use `previousKeyExpirationPeriod` to set or change the expiration date of your original key. This must be in [`ISO 8601^`](https://en.wikipedia.org/wiki/ISO_8601#Durations) duration format, such as `P30D` for 30 days. <3> (Optional) The new API key won't have an expiration date by default, even if the original key had one. Use `newKeyExpirationPeriod` to set an expiration date of up to 1 year. This must be in [`ISO 8601^`](https://en.wikipedia.org/wiki/ISO_8601#Durations) duration format, such as `P1Y` for 1 year. The body of a successful response (`200 OK`) contains information about the new API key you created. This response includes the following properties, among others: ```json { "id": "xxxxxxxxxxxxxxxxxxxxxxxxxx", <1> "value": "xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "organizationId": "", "displayName": "", "description": "", "privileges": [ ... ], "createdDate": 1734516650656, "allowedIps": [], "deniedIps": [], "apiKeyTemplateId": "", "privacyLevel": "", "status": "ENABLED", "expirationDate": 1737158399000, <2> "activationDate": 1734516650729, "rotationSecret": "coveo_apikey_rotation_v1_xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_xxxxxxxx" <3> } ``` <1> The new API key will have a different `id` and `value` from the original key. Most of the other properties will be the same as those of the original key, and the new key will have the same privileges. <2> This property will only appear in the response if you set an expiration date using `newKeyExpirationPeriod`. <3> A new `rotationSecret` will let you [rotate](https://docs.coveo.com/en/p7sb0148/) this key in the future. ### Rotation and API key expiration When you [rotate](https://docs.coveo.com/en/p7sb0148/) an API key, the original key will be set to expire in 30 days or less, depending on its initial expiration date. You can use the `previousKeyExpirationPeriod` property in the request body to set a specific expiration date for the original key, as in the following table: [%header,cols="~,~,~"] |=== |Expiration date |Possible values for `previousKeyExpirationPeriod` |If you don't set `previousKeyExpirationPeriod` |None .2+.^|Between 1 day and 30 days. .2+.^|The original key expires in 30 days. |> 30 days |<= 30 days |Between 1 day and the existing expiration date. |The original key keeps its existing expiration date. |===