> For the complete documentation index, see [llms.txt](https://legacy-docs.usesmileid.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://legacy-docs.usesmileid.com/integration-options/rest-api/signing-your-api-request/generate-signature.md).

# Using Signature

{% hint style="warning" %}
If you use one of the supplied SDKs, there is no reason to use the code in the following section as the signature can be generated by calling the generate\_signature function.\
\
The generated signature has to be passed as a string in your request.
{% endhint %}

## **Overview**

To communicate with our system we require a unique signature on each request to ensure that both parties are who they say they are. This signature should be generated at the time of the job submission. To calculate your signature, you will need your `partner ID` and `API Key for Signature`, both of which are available on the [portal](https://portal.usesmileid.com/security-settings).

### **API Key for Signature**

<figure><img src="/files/Onn9otocG9DRavcQGjx2" alt=""><figcaption></figcaption></figure>

You can find and generate your an API key [here](https://portal.usesmileid.com/security-settings). The key is unique to each environment, so you will need a different key for the sandbox and production environments. You can rotate your API key any time, however your previous key will be immediately disabled.

{% hint style="info" %}
To access your API keys, go to the **Developer Tools** section of the portal, then select **Security Settings**. Under the Credentials section, you can view and manage your existing API keys or generate new production credentials.
{% endhint %}

### **Partner ID**

You will need to know your partner ID, to create the signature. Your partner ID can be viewed when logged into the [portal](https://portal.usesmileid.com/). To calculate your signature you will need to input your partner ID as a string, as explained below

Your partner ID: `085`

String Value of your partner ID: `"085"`

## **Generating the signature**

Follow the steps below to generate your signature

1. Create a timestamp in an ISO date format
2. Create a new hmac-sha256 hash function using [Signature API Key](https://portal.usesmileid.com/security-settings).
3. Update the function message with timestamp created in 1, your partner Id, and "sid\_request" string
4. Base64 encode the encrypted hash

**Example code for creating the signature**

{% tabs %}
{% tab title="Ruby" %}

```ruby
require 'openssl'
require 'time'
require 'base64'

timestamp = Time.now.to_s
api_key = '<API-Key>'
partner_id = '<partner-id>'
hmac = OpenSSL::HMAC.new(api_key, 'sha256')
hmac.update(timestamp) hmac.update(partner_id)
hmac.update("sid_request")

signature = Base64.strict_encode64(hmac.digest())
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
let crypto = require("crypto");
let timestamp = new Date().toISOString();
let api_key = "<API-Key>";
let partner_id = "<partner-id>";
let hmac = crypto.createHmac("sha256", api_key);

hmac.update(timestamp, "utf8");
hmac.update(partner_id, "utf8");
hmac.update("sid_request", "utf8");

let signature = hmac.digest().toString("base64");
```

{% endtab %}

{% tab title="Python" %}

```python
import base64
import hashlib
import hmac
from datetime import datetime, timezone

timestamp = datetime.now(timezone.utc).isoformat(timespec='milliseconds').replace('+00:00', 'Z')
api_key = "<API-Key>"
partner_id = "<partner-id>"
hmac_new = hmac.new(api_key.encode("utf-8"), digestmod=hashlib.sha256)
hmac_new.update(timestamp.encode("utf-8"))
hmac_new.update(str(partner_id).encode("utf-8"))
hmac_new.update("sid_request".encode("utf-8"))

calculated_signature = base64.b64encode(hmac_new.digest()).decode("utf-8")
```

{% endtab %}

{% tab title="PHP" %}

```php
$api_key = "<API-Key>";
$partner_id = "<partner-id>";
$timestamp = gmdate("Y-m-d\TH:i:s.v\Z"); // ISO 8601 format in UTC
$message = $timestamp.$partner_id."sid_request";
$signature = base64_encode(hash_hmac('sha256', $message, $api_key, true));
```

{% endtab %}

{% tab title="Java" %}

```java
String apiKey = "<API-Key>";
String partnerId = "<partner-id>";
Instant now = Instant.now();

DateTimeFormatter formatter = DateTimeFormatter
        .ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
        .withZone(ZoneOffset.UTC);

String timestamp = formatter.format(now);

Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(apiKey.getBytes(), "HmacSHA256"));
mac.update(timestamp.getBytes(StandardCharsets.UTF_8));
mac.update(partnerId.getBytes(StandardCharsets.UTF_8));
mac.update("sid_request".getBytes(StandardCharsets.UTF_8));
String signature = Base64.getEncoder().encodeToString(mac.doFinal());
```

{% endtab %}

{% tab title="C#" %}

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

namespace csharp_sample
{
    class Program
    {
        static void Main(string[] args)
        {
            string timeStamp = DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss.fffZ", System.Globalization.CultureInfo.InvariantCulture);
            string apiKey = "<API-Key>";
            string partnerID = "<partner-id>";
            string data = timeStamp + partnerID + "sid_request";

            UTF8Encoding utf8 = new UTF8Encoding();
            Byte[] key = utf8.GetBytes(apiKey);
            Byte[] message = utf8.GetBytes(data);

            HMACSHA256 hash = new HMACSHA256(key);
            var signature = hash.ComputeHash(message);

            Console.WriteLine("Signature: " + Convert.ToBase64String(signature));
	    Console.WriteLine("TimeStamp: " + timeStamp);

        }
    }
}
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"time"
)

func main() {
  const iso8601MillisLayout = "2006-01-02T15:04:05.000Z"
  
	timestamp := time.Now().UTC().Format(iso8601MillisLayout)
	apiKey := "<API-Key>"
	partnerID := "<partner-id>"

	h := hmac.New(sha256.New, []byte(apiKey))
	h.Write([]byte(timestamp))
	h.Write([]byte(partnerID))
	h.Write([]byte("sid_request"))

	signature := base64.StdEncoding.EncodeToString(h.Sum(nil))

	fmt.Println(signature)
	fmt.Println(timestamp)
}

```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
**Reminder:** You must pass the signature as a string in your request.\
Your timestamp should be a string in the ISO 8601 format "yyyy-MM-dd'T'HH:mm:ss.fffZ"
{% endhint %}

## **Confirming an incoming signature**

To verify the authenticity of the response received from your callback as genuinely originating from Smile ID, you can confirm the returned signature and timestamp. The sample codes provided below can be used to confirm the signature in the request:

**Example code for confirming the signature**

{% tabs %}
{% tab title="Ruby" %}

```ruby
require 'openssl'
require 'time'
require 'base64'

# Example inputs - replace these with actual received values
# The signature received in the callback response
received_signature = ""
# The actual timestamp received in the callback response
received_timestamp = ""

# Your partner ID
partner_id = ""
# Your api key for the environment in concern (sandbox / production)
api_key = ""

# Function to verify the signature
def confirm_signature(received_signature, received_timestamp, partner_id, api_key)
  hmac = OpenSSL::HMAC.new(api_key, 'sha256')
  hmac.update(received_timestamp)
  hmac.update(partner_id)
  hmac.update("sid_request")

  generated_signature = Base64.strict_encode64(hmac.digest)

  received_signature == generated_signature
end

# print out a confirmation status
is_signature_valid = confirm_signature(received_signature, received_timestamp, partner_id, api_key)
puts "Is the signature valid? #{is_signature_valid}"
```

{% endtab %}

{% tab title="Node.js" %}

```javascript
const crypto = require("crypto");

// Inputs received along with the request
let received_signature = ""; // The signature received in the callback response
let received_timestamp = ""; // The actual timestamp received in the callback response

let partner_id = ""; // Your partner ID
let api_key = ""; // Your api key for the environment in concern (sandbox / production)

function confirmSignature(
  received_signature,
  received_timestamp,
  partner_id,
  api_key
) {
  let hmac = crypto.createHmac("sha256", api_key);
  hmac.update(received_timestamp, "utf8");
  hmac.update(partner_id, "utf8");
  hmac.update("sid_request", "utf8");

  // Generate the signature based on received data
  let generated_signature = hmac.digest().toString("base64");

  // Compare the generated signature with the received signature
  return generated_signature === received_signature;
}

const is_signature_valid = confirmSignature(
  received_signature,
  received_timestamp,
  partner_id,
  api_key
);
console.log(`Is the signature valid? ${is_signature_valid}`);
```

{% endtab %}

{% tab title="Python" %}

```python
import base64
import hashlib
import hmac

# The signature received in the callback response
received_signature = ""
# The actual timestamp received in the callback response
received_timestamp = ""

# Your partner ID
partner_id = ""
# Your api key for the environment in concern (sandbox / production)
api_key = ""

def confirm_signature(received_signature, received_timestamp, partner_id, api_key):
    # Recreate the HMAC object with the same parameters
    hmac_new = hmac.new(api_key.encode("utf-8"), digestmod=hashlib.sha256)
    hmac_new.update(received_timestamp.encode("utf-8"))
    hmac_new.update(str(partner_id).encode("utf-8"))
    hmac_new.update("sid_request".encode("utf-8"))

    # Generate the signature again
    generated_signature = base64.b64encode(hmac_new.digest()).decode("utf-8")

    # Compare the provided signature with the generated one
    return hmac.compare_digest(received_signature, generated_signature)

# print out a confirmation status
is_signature_valid = confirm_signature(received_signature, received_timestamp, partner_id, api_key)
print(f"Is the signature valid? {is_signature_valid}")
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

// Assume these values are received with the request
$receivedSignature = ""; // The signature received in the callback response
$receivedTimestamp = ""; // The actual timestamp received in the callback response

$partnerId = ""; // Your partner ID
$apiKey = ""; // Your api key for the environment in concern (sandbox / production)

function confirmSignature(string $receivedSignature, string $receivedTimestamp, String $partnerId, string $apiKey): bool
{
    // Concatenate the received data to form the message
    $message = $receivedTimestamp . $partnerId . "sid_request";

    // Generate the HMAC hash of the message
    $generatedSignature = base64_encode(hash_hmac('sha256', $message, $apiKey, true));

    // Compare the received signature with the generated signature and return boolean response
    return ($generatedSignature === $receivedSignature);
}

//print out a confirmation status
$is_signature_valid = confirmSignature($receivedSignature, $receivedTimestamp, $partnerId, $apiKey) ? 'True' : 'False';
echo "Is the signature valid? ".$is_signature_valid;

```

{% endtab %}

{% tab title="Java" %}

```java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class ConfirmSignature {

    public static void main(String[] args) {
        String receivedSignature = ""; // The signature received in the callback response
        String receivedTimestamp = ""; // The actual timestamp received in the callback response
        String partnerId = ""; // Your partner ID
        String apiKey = ""; // Your api key for the environment in concern (sandbox / production)

        Boolean isSignatureValid = confirmSignature(receivedSignature, receivedTimestamp, partnerId, apiKey);
        System.out.println("Is the signature valid? " + isSignatureValid);
    }

    public static boolean confirmSignature(String receivedSignature, String receivedTimestamp, String partnerId,
            String apiKey) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(apiKey.getBytes(), "HmacSHA256"));
            mac.update(receivedTimestamp.getBytes(StandardCharsets.UTF_8));
            mac.update(partnerId.getBytes(StandardCharsets.UTF_8));
            mac.update("sid_request".getBytes(StandardCharsets.UTF_8));

            // Generate the signature based on received data
            String generatedSignature = Base64.getEncoder().encodeToString(mac.doFinal());

            // Compare the generated signature with the received signature
            return generatedSignature.equals(receivedSignature);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}

```

{% endtab %}

{% tab title="C#" %}

```csharp

using System;
using System.Security.Cryptography;
using System.Text;
using System.Linq;

public static bool confirmSignature(string receivedSignature, string receivedTimestamp, string partnerID, string apiKey)
{
    // Use the signature and timestamp from the response sent to you via the webhook
    // This method returns true if the signature is fine and has not been tampered with
    bool err = false;

    string data = receivedTimestamp + partnerID + "sid_request";

    UTF8Encoding utf8 = new UTF8Encoding();
    Byte[] key = utf8.GetBytes(apiKey);
    Byte[] message = utf8.GetBytes(data);

    HMACSHA256 hash = new HMACSHA256(key);
    var generatedSignature = hash.ComputeHash(message);

    byte[] oldSignature = System.Convert.FromBase64String(receivedSignature);

    err = !oldSignature.SequenceEqual(generatedSignature);
    return !err;

}
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
)

func confirmSignature(receivedSignature, receivedTimestamp, partnerID, apiKey string) bool {

	data := receivedTimestamp + partnerID + "sid_request"

	mac := hmac.New(sha256.New, []byte(apiKey))
	mac.Write([]byte(data))
	expectedMAC := mac.Sum(nil)

	decodedSignature, err := base64.StdEncoding.DecodeString(receivedSignature)
	if err != nil {
		return false // Invalid base64 input
	}

	return hmac.Equal(decodedSignature, expectedMAC)
}

func main() {
	valid := confirmSignature(
		"<received-signature-string>",
		"<received-timestamp-string>",
		"<partner-id>",
		"<api-key>",
	)
	fmt.Println("Signature valid:", valid)
}

```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
**Reminder:** You must pass the received signature, received timestamp, partner id and api key as strings.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://legacy-docs.usesmileid.com/integration-options/rest-api/signing-your-api-request/generate-signature.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
