Verify an incoming webhook payload and signature. This method validates that the webhook request is authentic by: 1. Validating the webhook timestamp is within the tolerance window 2. Verifying the HMAC-SHA256 signature using the correct algorithm 3. Parsing
(
self,
*,
id: str,
payload: str,
secret: str,
signature: str,
timestamp: str,
tolerance: int = 300,
)
| 1188 | return _SubcriptionBuilder(client=self._client).connect(timeout=timeout) |
| 1189 | |
| 1190 | def verify_webhook( |
| 1191 | self, |
| 1192 | *, |
| 1193 | id: str, |
| 1194 | payload: str, |
| 1195 | secret: str, |
| 1196 | signature: str, |
| 1197 | timestamp: str, |
| 1198 | tolerance: int = 300, |
| 1199 | ) -> VerifyWebhookResult: |
| 1200 | """ |
| 1201 | Verify an incoming webhook payload and signature. |
| 1202 | |
| 1203 | This method validates that the webhook request is authentic by: |
| 1204 | 1. Validating the webhook timestamp is within the tolerance window |
| 1205 | 2. Verifying the HMAC-SHA256 signature using the correct algorithm |
| 1206 | 3. Parsing the payload and detecting the webhook version (V1, V2, or V3) |
| 1207 | |
| 1208 | :param id: The webhook message ID from the 'webhook-id' header (format: 'msg_xxx') |
| 1209 | :param payload: The raw webhook payload as a string (request body) |
| 1210 | :param secret: The webhook secret used to sign the payload (from Composio dashboard) |
| 1211 | :param signature: The signature from the 'webhook-signature' header (format: 'v1,base64EncodedSignature') |
| 1212 | :param timestamp: The webhook timestamp from the 'webhook-timestamp' header (Unix seconds) |
| 1213 | :param tolerance: Maximum allowed age of the webhook in seconds (default: 300 = 5 minutes). |
| 1214 | Set to 0 to disable timestamp validation. |
| 1215 | :return: VerifyWebhookResult containing version, normalized payload, and raw payload |
| 1216 | :raises WebhookSignatureVerificationError: If the signature verification fails |
| 1217 | :raises WebhookPayloadError: If the payload cannot be parsed or is invalid |
| 1218 | |
| 1219 | Example: |
| 1220 | # In a Flask webhook handler |
| 1221 | @app.route('/webhook', methods=['POST']) |
| 1222 | def webhook(): |
| 1223 | try: |
| 1224 | result = composio.triggers.verify_webhook( |
| 1225 | id=request.headers.get('webhook-id', ''), |
| 1226 | payload=request.get_data(as_text=True), |
| 1227 | signature=request.headers.get('webhook-signature', ''), |
| 1228 | timestamp=request.headers.get('webhook-timestamp', ''), |
| 1229 | secret=os.environ['COMPOSIO_WEBHOOK_SECRET'], |
| 1230 | ) |
| 1231 | |
| 1232 | # Process the verified payload |
| 1233 | print(f"Version: {result['version']}") |
| 1234 | print(f"Received trigger: {result['payload']['trigger_slug']}") |
| 1235 | return 'OK', 200 |
| 1236 | except WebhookSignatureVerificationError: |
| 1237 | return 'Unauthorized', 401 |
| 1238 | """ |
| 1239 | # Validate timestamp if tolerance is set |
| 1240 | if tolerance > 0: |
| 1241 | self._validate_webhook_timestamp_header(timestamp, tolerance) |
| 1242 | |
| 1243 | # Verify signature using the correct algorithm |
| 1244 | self._verify_webhook_signature( |
| 1245 | webhook_id=id, |
| 1246 | webhook_timestamp=timestamp, |
| 1247 | payload=payload, |