Skip to main content
Security is critical when dealing with automated event notifications.

Digital Signature Verification

All webhook requests include a digital signature using the ED25519 algorithm. The signature is provided in the following HTTP header:
X-Partoo-Signature-v1: BASE64_SIGNATURE
To verify:
  1. Base64 decode the signature
  2. Recalculate the hash of the payload
  3. Use our public key to validate the signature
Use separate keys for production and sandbox environments.
Use different public keys depending on the environment:
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA0G9ciHL6XZQXuWq6W4dFLvwNEPWgcdtQgEVlBIwZWBQ=
-----END PUBLIC KEY-----
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEALsyvX2yVnG3ZKRIFfEvYk2nkzanoNgAqBSqdeNub4sM=
-----END PUBLIC KEY-----

Code Examples

Here are sample snippets to help you implement signature verification:
from base64 import b64decode
import binascii
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ed25519

# load public key from filesystem, you may adapt depending on your secret management framework
public_key = serialization.load_pem_public_key(open("/var/secrets/partoo.pub.pem"))

def validate_signature(request):
  if (signature:=request.headers.get("X-Partoo-Signature-v1")) is None:
    raise ValueError("Missing signature")

  # don't trust your inputs
  # will raise a subclass of ValueError if format is invalid
  decoded_signature = b64decode(signature, validate=True)

  # validate payload's signature
  try:
    public_key.verify(decoded_signature, request.body.encode())
  except Exception as e:
    raise ValueError("Invalid signature") from e

Shared Secret in URL

You may include a shared secret in your webhook URL: Examples:
https://my.integration.io/webhooks/partoo/9fa91de19/business_update
https://my.integration.io/webhooks/partoo/business_update?key=9fa91de19