Authentication

Most Variational API calls require the request to be authenticated by an HMAC-SHA256 signature generated using an API Key and an API Secret. You can obtain those by generating API credentials for your company in the UI's settings pages.

Required Headers

All requests to Variational API endpoints requiring authentication must include 3 headers:

  • X-Request-Timestamp-Ms: Unix timestamp of the request (in milliseconds)

  • X-Variational-Key: client API key

  • X-Variational-Signature: a signature derived from the timestamp, client API key, secret, some of the request parameters and payload

For example:

curl --request GET \
     --url 'https://api.testnet.variational.io/v1/addresses' \
     --header 'X-Request-Timestamp-Ms: 1707254051670' \
     --header 'X-Variational-Key: dfeee8ee-bb76-4194-9570-32f163a0d342' \
     --header 'X-Variational-Signature: e120b1c6cbd7dcf2d465a8ba8431421d46da17cb031c02bb810104654a5d1918'

Time Accuracy

For security, we require that the timestamp you specify on the request does not differ from the current time on our API servers by more than 5 seconds.

You can access the Variational API server time using the /status endpoint: https://api.testnet.variational.io/v1/status (doesn't require authentication)

Generating a Signature

A signature is generated by writing an authentication message to a byte buffer and signing it with HMAC-SHA256. The message is an ascii-encoded string consisting of the following values divided by pipe | symbols:

{API_KEY}|{TIMESTAMP_MS}|{HTTP_METHOD}|{URL_PATH_AND_QUERY}

For example,

dfeee8ee-bb76-4194-9570-32f163a0d342|1707254051670|GET|/v1/addresses?company=30db7747-66b7-4182-a744-87c6cd899fbf

For endpoints expecting a request payload, the exact bytes of the HTTP request body must be appended to the authentication message buffer following another pipe symbol:

dfeee8ee-bb76-4194-9570-32f163a0d342|1707254051670|POST|/v1/addresses/new|{"address":"0x4264f4cbe7f50eded6a653cd4148a52cf1fd89e6"}

Python Code Examples

import time
import hmac
import hashlib

API_KEY = "dfeee8ee-bb76-4194-9570-32f163a0d342"
API_SECRET = bytes.fromhex("a432e5f89fea81fb7647c02191fb07c7c8012bae5b44bd9c30ca0320356de919")

timestamp_ms = int(time.time() * 1000)  # 1707254051670
method = "GET"
url_qs = "/v1/addresses?company=30db7747-66b7-4182-a744-87c6cd899fbf"
message_bytes = f"{API_KEY}|{timestamp_ms}|{method}|{url_qs}".encode()
signature = hmac.new(API_SECRET, message_bytes, hashlib.sha256).hexdigest()

print(signature)  # 1f2f1b99d87a6656d56f8b17d0c6e8609f31c7ca1899e473e0ea86804849e4d0

For requests with a JSON payload:

import time
import hmac
import hashlib
import json

API_KEY = "dfeee8ee-bb76-4194-9570-32f163a0d342"
API_SECRET = bytes.fromhex(
    "a432e5f89fea81fb7647c02191fb07c7c8012bae5b44bd9c30ca0320356de919")

timestamp_ms = int(time.time() * 1000)  # 1707254051670
method = "POST"
url_qs = "/v1/addresses/new"
message_bytes = bytearray(f"{API_KEY}|{timestamp_ms}|{method}|{url_qs}".encode())

payload = {"address": "0x4264f4cbe7f50eded6a653cd4148a52cf1fd89e6"}
message_bytes.extend(b"|")
message_bytes.extend(json.dumps(payload).encode())

signature = hmac.new(API_SECRET, message_bytes, hashlib.sha256).hexdigest()

print(signature)  # 5213ecad43045ec0945206de00de82156605b302ed1d08e48bccb0f873137ec1

Python SDK

The provided Python SDK Client takes care of request signing for you:

from variational import Client, TESTNET

client = Client(API_KEY, API_SECRET, base_url=TESTNET)
print(client.get_addresses().result[0]["address"])
# 0x4264f4cbe7f50eded6a653cd4148a52cf1fd89e6

If you prefer to construct the requests manually, a helper function for request signing is available:

import requests
import pprint
from variational import sign_prepared_request


url = "https://api.testnet.variational.io/v1/addresses?company=30db7747-66b7-4182-a744-87c6cd899fbf"
req = requests.Request(method="GET", url=url).prepare()
sign_prepared_request(req, API_KEY, API_SECRET)

pprint.pprint(dict(req.headers))
# ({'X-Request-Timestamp-Ms': '1707255962176',)
# ( 'X-Variational-Key': 'dfeee8ee-bb76-4194-9570-32f163a0d342',)
# ( 'X-Variational-Signature': '6f78cee1d521717d45497835232701cd02f8b7bef03ca34966100abc2258d292'})

resp = requests.Session().send(req)
print(resp.status_code)  # 200

Last updated