---
title: Authenticate with Deployment API
slug: dxp/docs/authentication
docTags: 
createdAt: 2026-07-30T20:33:07.109Z
---

The Deployment API for Optimizely Digital Experience Platform (DXP) authenticates each user request using a pair of client keys and a client secret.

You can create one or more credentials with the self-service option in the DXP management portal and associate them with DXP environments. Associating a single credential to one or more environments simplifies the authentication process, providing flexibility for API users.

## Add API credentials

You can add one or more credentials to deploy through API for each environment you can deploy.

You can add an API credential or retrieve existing credentials on the **API** tab in the DXP Management Portal.

1. Open the **API** tab. A list of existing credentials displays.

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/17H90Ac2J-UdRbOrEySNn_7553b26-image.png)

2. Click **Add API credentials**.
3. Enter the name for the credential, select applicable permissions associated with environments, and click **Save** to add an API credential.
   The **Edge logs** permission is associated with the get edge logs location function, and the other permissions are associated with each environment by the same name. The  **General** environment has resources that are shared by the **Integration**, **Preproduction**, and **Production** environments. **ADE**'s are optional environments. See [DXP environments](docId\:nkd5j5cDfZKtxIoCNqnn5).

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/e8Z55NDtgRvx8H0_UjKv6_3f71f7f-image.png)

:::hint{type="info"}
**Note**
You can add a duplicate credential for the same combination of permissions by using the **Name** credential as an informatory field in such instances. Also, you must select at least one permission for adding a credential.

When deploying code from a source environment to a target using Deployment API, the credentials supplied by an API request should have access to both source and target environments. For example, when promoting code from a Preproduction environment to Production, the supplied credentials should have been created by selecting **Preproduction** and **Production** in the **Add API Credentials** screen (above).
:::

Added credentials display in the credentials list. The API secret value is only shown once when the credential is added until the next page refresh happens. When you refresh the page, the credential secret is removed.

![](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/40Z2r1jt_u8SyBsXc2xuA_a015991eabcb236ac1b4cd687d3cb8b6b40ee61a56e81881afe651eb035f6858-image.png)

4. Each credential's has the icons to perform operations such as **Copy API Key**, **Copy API Secret**, and **Delete API Credential**.

:::hint{type="warning"}
**Important**
If you lose the API secret or did not copy it as mentioned in the previous step, delete the credential and add a credential.
:::

## HMAC computation

Before issuing a request, the client must compute a hash-based message authentication code (HMAC) that is unique to that request. The HMAC is computed as follows:

1. A message is assembled by concatenating the following parameters:
   - **API Key** – This is a unique identifier provided to the client upon platform registration.
   - **HTTP request method** – GET, POST, DELETE, and so on, as uppercase.
   - **HTTP request target** – Original [request target.](https://tools.ietf.org/html/rfc7230#section-5.3)
   - **Timestamp** – Time at which the request was created, UTC in milliseconds from Unix epoch.
   - **Nonce** – A random, unique identifier generated by the client.
   - **MD5 hash of the HTTP request body**.
2. The message is hashed using a [SHA256-based HMAC algorithm](https://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha256%28v=vs.110%29.aspx) to produce a signature. The hashing mechanism uses the API secret as a cryptographic key.

:::hint{type="info"}
**Note**
The secret is never communicated across the Internet.
:::

3. The bytes representing the signature are converted to a base64 encoded string.

## Authorization header

Each request must include an "Authorization" HTTP header, which includes the computed HMAC and other supporting parameters. The value of the header must be in the following format.

`epi-hmac <api-key>:<timestamp>:<nonce>:<hmac>`

The parameters comprising this header include:

- `<api-key>` – This is a unique identifier provided to the client upon platform registration.
- `<timestamp>` –Time the request was created; UTC in milliseconds from Unix epoch.
- `<nonce>` – A random, unique identifier generated by the client.
- `<hmac>` – The signature computed for the header.

## Sample code to request Hmac

Postman Pre-Request Script

```javascript
var crypto = require("crypto-js");
var sdk = require('postman-collection');
// This script uses 2 variables.
//
// EPTSKey
// EPTSSecret
//
var method = pm.request.method;
var key = pm.variables.get("EPTSKey");
var secret = CryptoJS.enc.Base64.parse(pm.variables.get("EPTSSecret"));
var target = new sdk.Url(request.url).getPathWithQuery();
var timestamp = (new Date()).getTime();
var nonce = Math.random().toString(36).substring(7);
var body = "";
if( pm.request.body )
{
    body = pm.request.body.raw;
}
var bodybase64 = crypto.MD5(body).toString(CryptoJS.enc.Base64);
var hmac = crypto.HmacSHA256(key + method + target + timestamp + nonce + bodybase64, secret);
var base64hmac = CryptoJS.enc.Base64.stringify(hmac);
var header = "epi-hmac " + key + ":" + timestamp +":" + nonce + ":" + base64hmac;
pm.request.headers.add(header, "Authorization")
```

For C#

```csharp
var hmacAlgorithm = new HMACSHA256();
var md5 = MD5.Create();

// Set the secret the HMAC algorithm uses for computing the signature
hmacAlgorithm.Key = Convert.FromBase64String(clientSecret);

// Define the different parts that make up the HMAC signature
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var nonce = Guid.NewGuid().ToString("N");
var target = new Uri(apiUrl).PathAndQuery;

// Define the HTTP request payload that will be tacked on to the signature

byte[] bodyBytes = null;
if (body != null) {
  bodyBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(body));
} else {
  bodyBytes = Encoding.UTF8.GetBytes("");
}
var bodyHashBytes = md5.ComputeHash(bodyBytes);
var hashBody = Convert.ToBase64String(bodyHashBytes);

// Combine all the parts into a signature message
var message = $ "{clientKey}{method.ToString().ToUpper()}{target}{timestamp}{nonce}{hashBody}";
var messageBytes = Encoding.UTF8.GetBytes(message);

// Define the HMAC signature from the message
var signatureHash = hmacAlgorithm.ComputeHash(messageBytes);
var signature = Convert.ToBase64String(signatureHash);

// Define the authorization header for the HTTP request
var authorization = $ "epi-hmac {clientKey}:{timestamp}:{nonce}:{signature}";
```
