Skip to main content

Secure API Key Usage Guide

Introduction​

Let's effectively learn what's needed to use API Keys in practice. We'll use Python as it's simple and easy to demonstrate the necessary implementation.

Essential Request Components​

  1. API Key - Your previously registered API Key
  2. Timestamp - Current timestamp
  3. Base Endpoint - The API main domain (e.g. https://api.sandbox.avenia.io:10952)
  4. HTTP Method - The verb defining the action (GET, POST, PUT, PATCH, DELETE)
  5. Request URI - The specific path after the base endpoint (e.g. /v2/auth/api-keys)
  6. Request Body (when applicable) - Data to be sent in JSON format

Initial Setup​

First, we'll import the necessary libraries for cryptography and making requests:

import time
import base64
import requests

from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

api_key = "00000000-0000-0000-0000-000000000000"
endpoint = "https://api.sandbox.avenia.io:10952/v2/account/account-info"
method = "GET"
request_uri = "/v2/account/account-info"
body = ""
timestamp = str(int(time.time() * 1000))

string_to_sign = timestamp + method + request_uri # + body if the request contains a body
info

string_to_sign is what the signature will actually consist of. Remember that if the request you're making has a body, this field must also be included.

request_uri If your request has parameters or the URI changes, it must also be included in the request_uri. For example:

/v2/account/account-info?foo=bar

Loading the Private Key​

Next, we need to load the private_key.pem file that should be in the same directory as the Python file, and serialize it as an actual private key using our cryptography library:

with open("private_key.pem", "rb") as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
)

Creating the Request Signature​

Now we'll build the request signature and return it as base64, using our private key:

signature = private_key.sign(
string_to_sign.encode("utf-8"),
padding.PKCS1v15(),
hashes.SHA256()
)
signature_base64 = base64.b64encode(signature).decode("utf-8")

Building the Request​

Finally, we'll construct the request headers which consist of:

  1. X-API-KEY - Your previously registered API Key
  2. X-API-Timestamp - Current timestamp
  3. X-API-Signature - The signature we created earlier in base64
print("Headers:")
print("X-API-Key:", api_key)
print("X-API-Timestamp:", timestamp)
print("X-API-Signature:", signature_base64)

headers = {
"X-API-Key": api_key,
"X-API-Timestamp": timestamp,
"X-API-Signature": signature_base64,
}

response = requests.get(endpoint, headers=headers)

print("Status:", response.status_code)
print("Response:", response.text)

Expected Output​

When running the complete code, you should see something like this:

Headers:
X-API-Key: 00000000-0000-0000-0000-000000000000
X-API-Timestamp: 1743107780606
X-API-Signature: eEnHoz2CWyMqFA/rx518ZF+y...

Status: 200
Response: {"id":"11111111-1111-1111-1111-111111111111" ... "createdAt":"2025-02-07T19:54:17.727744Z"}

Complete Code​

Here's the complete Python code for reference:

import time
import base64
import requests

from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

# Configuration
api_key = "00000000-0000-0000-0000-000000000000"
endpoint = "https://api.sandbox.avenia.io:10952/v2/account/account-info"
method = "GET"
request_uri = "/v2/account/account-info"
body = ""
timestamp = str(int(time.time() * 1000))

# Create string to sign
string_to_sign = timestamp + method + request_uri # + body if the request contains a body

# Load private key
with open("private_key.pem", "rb") as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
)

# Generate signature
signature = private_key.sign(
string_to_sign.encode("utf-8"),
padding.PKCS1v15(),
hashes.SHA256()
)
signature_base64 = base64.b64encode(signature).decode("utf-8")

# Prepare headers
headers = {
"X-API-Key": api_key,
"X-API-Timestamp": timestamp,
"X-API-Signature": signature_base64,
}

# Make the request
response = requests.get(endpoint, headers=headers)

# Print results
print("Status:", response.status_code)
print("Response:", response.text)