Skip to main content

Webhook Security

Authenticate Optacy webhooks with HMAC SHA-256 signatures using your private API key.

Every webhook request must be validated so you only accept data from Optacy. The signature object on each request includes three fields:

  • a random token
  • a timestamp (milliseconds since January 1, 1970)
  • a signature: HMAC SHA-256 of the timestamp concatenated with the random token, keyed with your private API key from the Webhooks tab in the dashboard

How to authenticate

  1. Concatenate timestamp and token into a single string with no spaces.
  2. Compute HMAC SHA-256 of that string using your private API key.
  3. Compare the hex digest to the signature field in the request.
  4. If they match, accept the request; otherwise reject it.

Store and access your private API key securely, typically via an environment variable.

Ruby on Rails example

token = params["signature"]["random_token"]
timestamp = params["signature"]["timestamp"]
signature = params["signature"]["signature"]

signed_test_data = OpenSSL::HMAC.hexdigest(
  "SHA256",
  ENV["OPTACY_WEBHOOK_PRIVATE_API_TOKEN"],
  "#{timestamp}#{token}"
)

if signed_test_data == signature
  # the request is accepted
else
  raise "Optacy webhook did not authenticate"
end

Replay protection

You may reject timestamps older than a few minutes to mitigate replay attacks. Replay risk is already low over HTTPS; this check is optional and not shown in the example above.