Authentication
The Veryfi API supports two ways to authenticate your requests. Both identify your account with the same Client Header and (optionally) the same signature headers; they differ only in the credential you place in the Authorization header.
Choosing an authentication method
Authentication methods
Bearer API keysRecommended
Client-scoped keys sent as `Authorization: Bearer `, available as **full-access** or **scoped** keys. A key belongs to your account (not a single user), and can be limited to specific routes and given an expiry. See [Bearer API keys](/api/getting-started/authentication/bearer-keys) and [Bearer API Key Management](/api/getting-started/authentication/bearer-key-management).
Standard API keysLegacy
The original per-user keys sent as `Authorization: apikey USERNAME:API_KEY`. Still fully supported. See [Standard API keys](/api/getting-started/authentication/standard-keys) and [Standard API Key Management](/api/getting-started/authentication/standard-key-management).
New integrations should prefer Bearer API keys (full-access or scoped) for tighter, per-key access control. Both methods use the same CLIENT-ID header and, where required, the same request signature.
Credentials
To access the Veryfi API programmatically you configure your client with the correct credentials. You can find and manage all of them on the web in the Keys section of Settings (API Auth Credentials):
CLIENT_IDandCLIENT_SECRET— identify your account and sign requests. Shared by both authentication methods.ENVIRONMENT_URL— the base URL for your requests (see Environment URL).- Standard API keys — your
UsernameandAPI Key(see Standard API keys). - Bearer API keys — client-scoped keys (full-access or scoped) you create and manage (see Bearer API keys).
Client Header
The Client Header identifies the partner (i.e. you) making requests to the Veryfi API. It is required for every request, regardless of which key format you use.
CLIENT-ID: "CLIENT_ID"
Environment URL
To make a request to Veryfi you need a URL made of two parts: ENVIRONMENT_URL and ENDPOINT_URL. Check the documentation for the endpoint that best fits your business needs.
https://api.veryfi.com/
Signature and Timestamp Headers
Requests to Veryfi's endpoints can include X-Veryfi-Request-Signature and X-Veryfi-Request-Timestamp headers as an additional layer of authentication, regardless of which key format you use. A user encodes a POST request with the CLIENT_SECRET signature; Veryfi validates the signature against the one on file.
UTF-8 Encoding
Every string passed to and from the API needs to be UTF-8 encoded. For maximum compatibility, normalize to Unicode Normalization Form C (NFC) before UTF-8 encoding.
Signatures are valid for 30 minutes from the time of generation.
X-Veryfi-Request-Signature: "Generated Signature"
X-Veryfi-Request-Timestamp value is a Unix Timestamp in milliseconds (ms) since epoch. Since CLIENT_SECRET is essential to the application's password, it automatically does the signing when using a Veryfi SDK.
X-Veryfi-Request-Timestamp: "Unix Timestamp"
Refer to the code examples below for a demonstration of how the value of the X-Veryfi-Request-Signature header is generated.
Code Samples
- Javascript
- Python
- Java
- Bash
const crypto = require('crypto')
function customSerialize(value) {
if (typeof value === 'object' && value !== null) {
if (Array.isArray(value)) {
return `[${value.map(customSerialize).join(', ')}]`
} else {
let nestedParts = []
for (const [nestedKey, nestedValue] of Object.entries(value)) {
nestedParts.push(`${nestedKey}: ${customSerialize(nestedValue)}`)
}
return `{${nestedParts.join(', ')}}`
}
}
return JSON.stringify(value)
}
function serializePayload(payload) {
let parts = []
for (const [key, value] of Object.entries(payload)) {
parts.push(`${key}:${customSerialize(value)}`)
}
return parts.join(',')
}
function createSignature(secret, payload, timestamp) {
let payloadStr = `timestamp:${timestamp},${serializePayload(payload)}`
console.log('Payload string:', payloadStr)
const hmac = crypto.createHmac('sha256', secret)
hmac.update(payloadStr)
return hmac.digest('base64')
}
const dt = new Date()
const utcSeconds = Math.floor(dt.getTime() / 1000)
const timestampMillisecond = utcSeconds * 1000
const requestPayload = {}
const clientSecret = ''
const signature = createSignature(
clientSecret,
requestPayload,
timestampMillisecond
)
console.log(signature)
const headers = {
'X-VERYFI-REQUEST-TIMESTAMP': timestampMillisecond.toString(),
'X-VERYFI-REQUEST-SIGNATURE': signature,
'CLIENT-ID': 'vrfKOMO1xSEM0AWNtKRpdemouT5M1Di8xxudemo',
// Standard (legacy) key. To use a Bearer API key (full-access or scoped) instead:
// AUTHORIZATION: 'Bearer vrfk_your_api_key',
AUTHORIZATION: 'apikey api_demo:4b1c01e8ce48ba08832cc299d808demo',
}
console.log(headers)
import base64
import calendar
import datetime
import hashlib
import hmac
from typing import Dict
dt = datetime.datetime.utcnow()
utc_seconds = calendar.timegm(dt.utctimetuple())
timestamp_millisecond = utc_seconds * 1000
request_payload = {}
client_secret = ""
def create_signature(secret: str, payload: Dict, timestamp: float) -> str:
payload_str = f"timestamp:{timestamp}"
for k, v in payload.items():
payload_str = f"{payload_str},{k}:{v}"
tmp_signature = hmac.new(
bytes(secret, "utf-8"), msg=bytes(payload_str, "utf-8"), digestmod=hashlib.sha256
).digest()
return str(base64.b64encode(tmp_signature), "utf-8").strip()
signature = create_signature(client_secret, request_payload, timestamp_millisecond)
headers = {
"X-VERYFI-REQUEST-TIMESTAMP": timestamp_millisecond,
"X-VERYFI-REQUEST-SIGNATURE": signature,
"CLIENT-ID": "vrfKOMO1xSEM0AWNtKRpdemouT5M1Di8xxudemo",
# Standard (legacy) key. To use a Bearer API key (full-access or scoped) instead:
# "AUTHORIZATION": "Bearer vrfk_your_api_key",
"AUTHORIZATION": "apikey api_demo:4b1c01e8ce48ba08832cc299d808demo",
}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;
public String getSignature() {
String clientSecret = "CLIENT_SECRET";
String userId = "USER_ID";
// Build signature
Date date = new Date();
long timeStamp = date.getTime();
String message = "timestamp:" + timeStamp + ",user_id:" + userId;
SecretKeySpec keySpec = new SecretKeySpec(clientSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
Mac mac;
try {
mac = Mac.getInstance("HmacSHA256");
} catch (NoSuchAlgorithmException e) {
return e.getMessage();
}
try {
mac.init(keySpec);
} catch (InvalidKeyException e) {
return e.getMessage();
}
byte[] rawHmac = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
String base64SignatureEncoded = Base64.getEncoder().encodeToString(rawHmac);
return base64SignatureEncoded;
}
CLIENT_SECRET="CLIENT_SECRET"
user_id="USER_ID"
# Sign the request
timestamp=$(( $(date +%s) * 1000 ))
payload_to_sign="timestamp:${timestamp},user_id:${user_id}"
base64_signature=$(echo -n ${payload_to_sign} | openssl sha256 -hmac ${CLIENT_SECRET} -binary | base64)
API Keys Access Permissions
Veryfi provides additional control for Admin users when granting access to API Keys for safety and security reasons.
Admin users with access to API Keys can only grant API Keys to other Admins. API Keys are not available to non-Admin team members. Visit Managing my team workspace to learn more about managing team members.