{"id":3280,"library":"standardwebhooks","title":"Standard Webhooks","description":"Standard Webhooks is a Python library for securely handling webhooks conforming to the Standard Webhooks specification. It provides functionalities for signature verification, content encryption, and replay protection, ensuring the authenticity and integrity of incoming webhook payloads. The current version is 1.0.1, with active development and maintenance.","status":"active","version":"1.0.1","language":"en","source_language":"en","source_url":"https://github.com/standardwebhooks/python-standard-webhooks","tags":["webhooks","security","signature-verification","encryption","replay-protection","spec"],"install":[{"cmd":"pip install standardwebhooks","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Used for cryptographic operations like signature verification and encryption.","package":"cryptography","optional":false},{"reason":"Used for JSON Web Signatures (JWS) and JSON Web Encryption (JWE) components of the specification.","package":"python-jose","optional":false}],"imports":[{"note":"The primary Webhook class is directly available from the top-level package.","wrong":"import standardwebhooks.Webhook","symbol":"Webhook","correct":"from standardwebhooks import Webhook"},{"note":"Common error class for handling failed webhook verifications.","symbol":"WebhookVerificationError","correct":"from standardwebhooks import WebhookVerificationError"},{"note":"Common error class for handling failed webhook signing.","symbol":"WebhookSigningError","correct":"from standardwebhooks import WebhookSigningError"}],"quickstart":{"code":"import os\nfrom standardwebhooks import Webhook, WebhookVerificationError\n\n# In a real application, the secret should be securely loaded from environment variables or a secret store.\n# It MUST be bytes.\nWEBHOOK_SECRET = os.environ.get('STANDARDWEBHOOKS_SECRET', 'whsec_testsecretforlocaldevelopmentonly').encode('utf-8')\n\n# Example incoming webhook data (replace with actual request data)\nheaders = {\n    'Webhook-Id': 'msg_00000000000000000000000000',\n    'Webhook-Timestamp': '2024-04-10T12:00:00Z',\n    'Webhook-Signature': 'v1,sig_00000000000000000000000000',\n    'Content-Type': 'application/json'\n}\nbody = b'{\"key\": \"value\"}' # Body must be bytes\n\n# Initialize the Webhook handler with your secret\nwebhook = Webhook(WEBHOOK_SECRET)\n\ntry:\n    # Verify the incoming webhook\n    # In a web framework, you would pass request.headers and request.body\n    verified_data = webhook.verify(headers=headers, body=body)\n    print(\"Webhook verified successfully!\")\n    print(\"Payload:\", verified_data)\nexcept WebhookVerificationError as e:\n    print(f\"Webhook verification failed: {e}\")\n    # Important: Log the error but do not expose details to the client.\n    # Return a 400 or 401 status code.\nexcept Exception as e:\n    print(f\"An unexpected error occurred: {e}\")\n\n# To simulate a successful verification, you'd need a valid signature for the given secret, body, id, and timestamp.\n# The example above uses placeholder values for demonstration.","lang":"python","description":"This quickstart demonstrates how to initialize the `Webhook` class with a secret and verify an incoming webhook request. It shows the expected input types (headers as dict, body as bytes) and how to handle potential `WebhookVerificationError` exceptions, which are critical for secure webhook processing. Remember to load your secret securely from environment variables or a secret manager and ensure it's provided as bytes."},"warnings":[{"fix":"Ensure your secret is explicitly encoded to bytes, e.g., `os.environ.get('MY_SECRET').encode('utf-8')`.","message":"The webhook secret must be provided as a `bytes` object when initializing the `Webhook` class. Providing a `str` will result in a `TypeError` or unexpected behavior during signature verification.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always wrap your `webhook.verify()` calls in a `try...except WebhookVerificationError` block and return an appropriate error response (e.g., HTTP 400 or 401) without processing the payload.","message":"It is crucial to handle `WebhookVerificationError` exceptions. If this exception is raised, the incoming webhook is invalid, tampered with, or expired. Ignoring this error can lead to security vulnerabilities.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure your web framework passes the raw request body (e.g., `request.body` in Flask/Django, `await request.body()` in FastAPI) directly to `webhook.verify()`.","message":"The `webhook.verify()` method expects the raw request body as `bytes`. Do not pass a decoded string or a parsed JSON object, as this will prevent correct signature verification.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}