# Authentication

All HTTP requests sent to the Offer API must be signed with a special signature. The signature must be provided in the `Authorization` header. In order to generate signature partners need to have a valid API key and a secret signing key. Please note, a new signature must be generated for every request.

## Generate HMAC Signature

Offers API uses [HMAC-based](https://en.wikipedia.org/wiki/HMAC) authentication.

To authenticate API request the client application needs to perform the following steps:

1. Prepare request data for signing.
2. Sign data using one of the HMAC algorithms such as **`SHA1`** (dprecated), **`SHA256`** , **`SHA384`** or **`SHA512`** algorithms.
3. Encode the signature using **`Base64`** encoding.
4. URL encode the result of the previous step.
5. Prepare **`Authorization`** header containing the Base64 and URL encoded signature string, API Key and the algorithm used, for example **`hmac-sha512`**.

{% hint style="warning" %}
Please note the date string to be signed should be in [RFC 822 Section 5.1 format](https://datatracker.ietf.org/doc/html/rfc822#section-5.1) e.g. Thu, 04 Nov 2021 18:07:11 GMT

The date must be padded e.g. 04.
{% endhint %}

{% hint style="warning" %}
Please note the signature must be a base64 encoded strictly matching RFC 4648. Some programming languages will URL safe base64 encode which will replace the "+" and "/" characters with "-" and "\_" respectively. This will cause a "Signature string does not match!" error.
{% endhint %}

Below you can see an example code implementing these steps, this code can be used as a pre-request script in Postman.

{% tabs %}
{% tab title="Python" %}
{% code expandable="true" %}

```python
import requests
# Module defined below
from auth import SignatureAuth

# Prodivded by the assigned Client Solutions Engineer (CSE)
API_KEY = ""
API_SECRET = ""

def _apply_auth(request):
    request.headers.update(
        SignatureAuth(API_KEY,
                      API_SECRET).sign()
    )
    return request

session = requests.Session()
request = requests.Request('POST', url, json=payload, headers=headers)
response = session.send(_apply_auth(request.prepare()))

print(response.status_code)
    
# auth.py
"""
Authentication related module.
"""
from __future__ import unicode_literals
​
from base64 import b64encode
from hashlib import sha512
import hmac
from urllib.parse import quote
​
from datetime import datetime
from time import mktime
from wsgiref.handlers import format_date_time
​
def http_date():
    now = datetime.utcnow()
    return format_date_time(mktime(now.timetuple()))
​
​
class SignatureAuth:
    """Class for basic authentication support."""
​
    def __init__(self, key, secret):
        self._key = key
        self._secret = secret
        self._headers = None
​
    def create_signature(self, date):
        raw = 'date: {date}'.format(date=date)
        hashed = hmac.new(self._secret.encode('utf-8'), raw.encode('utf-8'), sha512).digest()
        return quote(b64encode(hashed), safe='')
​
    def build_signature(self, signature, key):
        template = ('Signature keyId="%(key)s",algorithm="hmac-sha512",'
                    'signature="%(signature)s"')
​
        return template % {
            'key': key,
            'signature': signature
        }
​
    def sign(self):
        date = http_date()
        auth = self.build_signature(signature=self.create_signature(date), key=self._key)
​
        return {
            'Date': date,
            'Authorization': auth,
            'X-Api-Key': self._key,
        }

```

{% endcode %}
{% endtab %}

{% tab title="JavaScript (Postman)" %}

```javascript
var apiKey = environment.api_key,
    apiSecret = environment.api_secret,
    date = (new Date()).toUTCString(),
    sigContent = 'date: ' + date,
    sig = CryptoJS.HmacSHA512(sigContent, apiSecret).toString(CryptoJS.enc.Base64),
    authHeader = 'Signature keyId="' + apiKey + '",algorithm="hmac-sha512",signature="' + encodeURIComponent(sig) + '"';

pm.environment.set("authHeader", authHeader);  // Authorization header
pm.environment.set("date", date);  // Date header
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

$apiKey = env('API_KEY'); // or however you access your environment variables
$apiSecret = env('API_SECRET');

$date = gmdate('D, d M Y H:i:s') . ' GMT';

$sigContent = 'date: ' . $date;

$sig = base64_encode(hash_hmac('sha512', $sigContent, $apiSecret, true));

$authHeader = sprintf(
    'Signature keyId="%s",algorithm="hmac-sha512",signature="%s"',
    $apiKey,
    urlencode($sig)
);

// Usage in HTTP headers:
// 'Authorization' => $authHeader
// 'Date' => $date
```

{% endtab %}

{% tab title="C#" %}

```csharp
using System;
using System.Web;
using System.Text;
using System.Security.Cryptography;

class Program {
    static void Main(string[] args) {
        String rfc1123DateString = DateTime.Now.ToString("R");
        String apiKey = "";
        String apiSecret = "";
	String signatureContentString = "date: " + rfc1123DateString;
	HMACSHA512 hmacsha512 = new HMACSHA512(Encoding.UTF8.GetBytes(apiSecret));
	byte[] bytes = hmacsha512.ComputeHash(Encoding.UTF8.GetBytes(signatureContentString));
	String signature = Convert.ToBase64String(bytes);
	String authHeader = "Signature keyId=\""+apiKey+"\",algorithm=\"hmac-sha512\",signature=\""+HttpUtility.UrlEncode(signatureString)+"\"";
	return authHeader;
    }
}
```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require "base64"
require "time"
require 'openssl'
require 'cgi/util'

def auth_header
  rfc1123_date_string = Time.now.httpdate
  api_key = ""
  api_secret = ""
  sig_content = "date: #{rfc1123_date_string}"
  sig = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), api_secret, sig_content)
  encoded_sig = Base64.strict_encode64(sig)
  "Signature keyId=\"#{api_key}\",algorithm=\"hmac-sha512\",signature=\"#{CGI.escape(encoded_sig)}\""
end
```

{% endtab %}
{% endtabs %}

## Testing API Keys

To streamline your integration process, the XCover API supports Test Keys that operate directly within the production environment. This "Single Environment" approach ensures that your integration behaves exactly the same way during testing as it will in live production, without the need to manage separate staging endpoints.

#### How it Works

When you use a Test API Key, the system automatically flags the transaction. This allows you to validate your integration end-to-end—from generating offers to binding policies—without triggering real financial transactions.

* Endpoint: Use the standard production URL.
* Identification: Transactions made with these keys are marked as `test` in our backend and your partner dashboard.
* Security: Even when using test keys, all requests must be signed using the same HMAC signature process described in the [Authentication](/offers/api/authentication.md) section.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://partner-docs.covergenius.com/offers/api/authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
