Authentication
Authorization
To authorize a request, you must use the API key obtained earlier from your merchant panel. This key ensures secure communication between your server and our platform.
When making API requests, include the API key in the request header using the x-api-key field.
Example Header:
"x-api-key": "your-api-key-value"
Example Request:
POST /example/endpoint HTTP/1.1
Host: api.bitzone.space
Content-Type: application/json
x-api-key: your-api-key-value
{
"field1": "value1",
"field2": "value2"
}
Ensure your API key is kept secure and never exposed publicly. If you believe your key has been compromised, generate a new one through the merchant panel immediately.
Signature Verification
To ensure security and confirm that webhook requests are genuinely sent by our platform, you must verify the request signature. The signature is provided in the x-signature header
Overview
- Obtain the request body (as a raw JSON string).
- Extract the signature from the
x-signatureheader. - Generate the signature using your API key.
- Compare the signatures using a secure method.
Signature Generation Algorithm
The signature is generated using the HMAC-SHA256 algorithm. It is calculated based on:
- The request body (unaltered), and
- Your API key.
Examples
Signature Verification Function
- JavaScript
- TypeScript
- Python
- Java
- PHP
- Ruby
- Go
const crypto = require('crypto');
/**
* Verifies the webhook signature.
* @param {string} apiKey - Your API key.
* @param {string} requestBody - The raw request body (unaltered).
* @param {string} receivedSignature - The signature from the `x-signature` header.
* @returns {boolean} true if the signatures match; otherwise, false.
*/
function verifyWebhookSignature(apiKey, requestBody, receivedSignature) {
// Generate the computed signature
const computedSignature = crypto
.createHmac('sha256', apiKey) // Create an HMAC using SHA256
.update(requestBody) // Update it with the request body
.digest('hex'); // Convert the result to a hex string
// Compare the signatures securely
return crypto.timingSafeEqual(
Buffer.from(receivedSignature, 'hex'),
Buffer.from(computedSignature, 'hex')
);
}
module.exports = { verifyWebhookSignature };
import * as crypto from 'crypto';
/**
* Verifies the webhook signature.
* @param apiKey - Your API key.
* @param requestBody - The raw request body (unaltered).
* @param receivedSignature - The signature from the `x-signature` header.
* @returns true if the signatures match; otherwise, false.
*/
function verifyWebhookSignature(
apiKey: string,
requestBody: string,
receivedSignature: string
): boolean {
// Generate the computed signature
const computedSignature = crypto
.createHmac('sha256', apiKey) // Create an HMAC using SHA256
.update(requestBody) // Update it with the request body
.digest('hex'); // Convert the result to a hex string
// Compare the signatures securely
return crypto.timingSafeEqual(
Buffer.from(receivedSignature, 'hex'),
Buffer.from(computedSignature, 'hex')
);
}
import hmac
import hashlib
from typing import Any
def verify_webhook_signature(api_key: str, request_body: str, received_signature: str) -> bool:
"""
Verifies the webhook signature.
Args:
api_key (str): Your API key.
request_body (str): The raw request body (unaltered).
received_signature (str): The signature from the `x-signature` header.
Returns:
bool: True if the signatures match, otherwise False.
"""
# Generate the computed signature
computed_signature = hmac.new(
key=api_key.encode(),
msg=request_body.encode(),
digestmod=hashlib.sha256
).hexdigest()
# Compare the signatures securely
return hmac.compare_digest(computed_signature, received_signature)
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
public class WebhookVerifier {
/**
* Verifies the webhook signature.
*
* @param apiKey Your API key.
* @param requestBody The raw request body (unaltered).
* @param receivedSignature The signature from the `x-signature` header.
* @return true if the signatures match, otherwise false.
*/
public static boolean verifyWebhookSignature(String apiKey, String requestBody, String receivedSignature) {
try {
// Generate the computed signature
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(apiKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
mac.init(secretKey);
byte[] computedBytes = mac.doFinal(requestBody.getBytes(StandardCharsets.UTF_8));
String computedSignature = bytesToHex(computedBytes);
// Compare the signatures securely
return MessageDigest.isEqual(computedSignature.getBytes(), receivedSignature.getBytes());
} catch (Exception e) {
throw new RuntimeException("Error verifying signature", e);
}
}
// Helper function to convert bytes to hex
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
hexString.append(String.format("%02x", b));
}
return hexString.toString();
}
}
/**
* Verifies the webhook signature.
*
* @param string $apiKey Your API key.
* @param string $requestBody The raw request body (unaltered).
* @param string $receivedSignature The signature from the `x-signature` header.
* @return bool true if the signatures match, otherwise false.
*/
function verifyWebhookSignature(string $apiKey, string $requestBody, string $receivedSignature): bool {
// Generate the computed signature
$computedSignature = hash_hmac('sha256', $requestBody, $apiKey);
// Compare the signatures securely
return hash_equals($computedSignature, $receivedSignature);
}
require 'openssl'
# Verifies the webhook signature.
# @param api_key [String] Your API key.
# @param request_body [String] The raw request body (unaltered).
# @param received_signature [String] The signature from the `x-signature` header.
# @return [Boolean] true if the signatures match, otherwise false.
def verify_webhook_signature(api_key, request_body, received_signature)
# Generate the computed signature
computed_signature = OpenSSL::HMAC.hexdigest('sha256', api_key, request_body)
# Compare the signatures securely
return Rack::Utils.secure_compare(computed_signature, received_signature)
end
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"strings"
)
// verifyWebhookSignature verifies the webhook signature.
// apiKey: Your API key.
// requestBody: The raw request body (unaltered).
// receivedSignature: The signature from the `x-signature` header.
// returns: true if the signatures match, otherwise false.
func verifyWebhookSignature(apiKey, requestBody, receivedSignature string) bool {
// Generate the computed signature
mac := hmac.New(sha256.New, []byte(apiKey))
mac.Write([]byte(requestBody))
computedSignature := hex.EncodeToString(mac.Sum(nil))
// Compare the signatures securely
return hmac.Equal([]byte(receivedSignature), []byte(computedSignature))
}
Usage Example
- JavaScript
- TypeScript
- Python
- PHP
- Java
- Ruby
- Go
const apiKey = 'your_api_key'; // Your API key
const requestBody = '{"event":"payment","data":{"amount":100,"currency":"USD"}}'; // Example request body
const receivedSignature = 'd3b07384d113edec49eaa6238ad5ff00'; // Signature from the x-signature header
if (verifyWebhookSignature(apiKey, requestBody, receivedSignature)) {
console.log('Signature is valid. The request is authenticated!');
} else {
console.log('Invalid signature. The request may be forged.');
}
const apiKey = 'your_api_key'; // Your API key
const requestBody = '{"event":"payment","data":{"amount":100,"currency":"USD"}}'; // Example request body
const receivedSignature = 'd3b07384d113edec49eaa6238ad5ff00'; // Signature from the x-signature header
if (verifyWebhookSignature(apiKey, requestBody, receivedSignature)) {
console.log('Signature is valid. The request is authenticated!');
} else {
console.log('Invalid signature. The request may be forged.');
}
api_key = 'your_api_key' # Your API key
request_body = '{"event":"payment","data":{"amount":100,"currency":"USD"}}' # Example request body
received_signature = 'd3b07384d113edec49eaa6238ad5ff00' # Signature from the x-signature header
if verify_webhook_signature(api_key, request_body, received_signature):
print('Signature is valid. The request is authenticated!')
else:
print('Invalid signature. The request may be forged.')
$apiKey = 'your_api_key'; // Your API key
$requestBody = '{"event":"payment","data":{"amount":100,"currency":"USD"}}'; // Example request body
$receivedSignature = 'd3b07384d113edec49eaa6238ad5ff00'; // Signature from the x-signature header
if (verifyWebhookSignature($apiKey, $requestBody, $receivedSignature)) {
echo 'Signature is valid. The request is authenticated!';
} else {
echo 'Invalid signature. The request may be forged.';
}
String apiKey = "your_api_key"; // Your API key
String requestBody = "{\"event\":\"payment\",\"data\":{\"amount\":100,\"currency\":\"USD\"}}"; // Example request body
String receivedSignature = "d3b07384d113edec49eaa6238ad5ff00"; // Signature from the x-signature header
if (verifyWebhookSignature(apiKey, requestBody, receivedSignature)) {
System.out.println("Signature is valid. The request is authenticated!");
} else {
System.out.println("Invalid signature. The request may be forged.");
}
api_key = 'your_api_key' # Your API key
request_body = '{"event":"payment","data":{"amount":100,"currency":"USD"}}' # Example request body
received_signature = 'd3b07384d113edec49eaa6238ad5ff00' # Signature from the x-signature header
if verify_webhook_signature(api_key, request_body, received_signature)
puts 'Signature is valid. The request is authenticated!'
else
puts 'Invalid signature. The request may be forged.'
end
package main
import "fmt"
func main() {
apiKey := "your_api_key" // Your API key
requestBody := `{"event":"payment","data":{"amount":100,"currency":"USD"}}` // Example request body
receivedSignature := "d3b07384d113edec49eaa6238ad5ff00" // Signature from the x-signature header
if verifyWebhookSignature(apiKey, requestBody, receivedSignature) {
fmt.Println("Signature is valid. The request is authenticated!")
} else {
fmt.Println("Invalid signature. The request may be forged.")
}
}
FAQs
Q: What algorithm is used for signature generation?
A: HMAC-SHA256 is used.
Q: What should I do if the signature doesn't match?
A: Reject the request and respond with an HTTP status code 401 Unauthorized.
By following the above steps, you can securely validate the authenticity of webhook requests.