Skip to main content
It is critical to verify that incoming requests to your webhook were sent by Authsignal, and to reject any that were not. The recommended approach is to use an Authsignal Server SDK to handle the incoming request.
const authsignal = new Authsignal({ apiSecretKey: "YOUR_SERVER_API_SECRET_KEY" });

// Obtain raw request body and signature header
// For example using Express (https://expressjs.com/)
const payload = req.body;
const sig = req.headers["X-Signature-V2"];

const event = authsignal.webhook.constructEvent(payload, sig);
var authsignal = new AuthsignalClient("YOUR_SERVER_API_SECRET_KEY");

// Obtain raw request body and signature header
var payload = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
var sig = Request.Headers["X-Signature-V2"];

var webhookEvent = authsignal.Webhook.ConstructEvent(payload, sig);
AuthsignalClient authsignal = new AuthsignalClient("YOUR_SERVER_API_SECRET_KEY");

// Obtain raw request body and signature header
// For example using the Spark framework (http://sparkjava.com)
String payload = request.body();
String sig = request.headers("X-Signature-V2");

WebhookEvent event = authsignal.webhook.constructEvent(payload, sig);
authsignal = Authsignal::Client.new(api_secret_key: 'YOUR_SERVER_API_SECRET_KEY')

# Obtain raw request body and signature header
payload = request.body.read
sig = request.headers['X-Signature-V2']

event = authsignal.webhook.construct_event(payload, sig)
from authsignal import AuthsignalClient

authsignal = AuthsignalClient(api_secret_key="YOUR_SERVER_API_SECRET_KEY")

# Obtain raw request body and signature header
payload = request.get_data(as_text=True)
sig = request.headers.get("X-Signature-V2")

event = authsignal.webhook.construct_event(payload, sig)
$authsignal = new Authsignal\Client('YOUR_SERVER_API_SECRET_KEY');

// Obtain raw request body and signature header
$payload = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_SIGNATURE_V2'];

$event = $authsignal->webhook()->constructEvent($payload, $sig);
webhook := NewWebhook("YOUR_SERVER_API_SECRET_KEY")

// Obtain raw request body and signature header
payload := string(body)
sig := r.Header.Get("X-Signature-V2")

event, err := webhook.ConstructEventWithDefaultTolerance(payload, sig)
By passing the raw request body along with the X-Signature-V2 header to the SDK, it verifies that the request is valid and constructs the event for you to handle.
The Authsignal SDK requires the raw body of the request to verify the signature. If you’re using a framework, make sure it doesn’t manipulate the raw body, as this will cause the signature verification to fail.

Replay protection

The Authsignal Server SDKs reject events older than 5 minutes by default. Customize the window by passing a tolerance value (in minutes).
const payload = req.body;
const sig = req.headers["X-Signature-V2"];
const tolerance = 10;

const event = authsignal.webhook.constructEvent(payload, sig, tolerance);
var payload = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
var sig = Request.Headers["X-Signature-V2"];
var tolerance = 10;

var webhookEvent = authsignal.Webhook.ConstructEvent(payload, sig, tolerance);
String payload = request.body();
String sig = request.headers("X-Signature-V2");
int tolerance = 10;

WebhookEvent event = authsignal.webhook.constructEvent(payload, sig, tolerance);
payload = request.body.read
sig = request.headers['X-Signature-V2']
tolerance = 10

event = authsignal.webhook.construct_event(payload, sig, tolerance)
payload = request.get_data(as_text=True)
sig = request.headers.get("X-Signature-V2")
tolerance = 10

event = authsignal.webhook.construct_event(payload, sig, tolerance)
$payload = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_SIGNATURE_V2'];
$tolerance = 10;

$event = $authsignal->webhook()->constructEvent($payload, $sig, $tolerance);
payload := string(body)
sig := r.Header.Get("X-Signature-V2")
tolerance := 10

event, err := webhook.ConstructEvent(payload, sig, tolerance)