{"record":{"id":"0db859557f02220e","repo":"ComposioHQ/composio","slug":"no-webhook-timestamp-was-provided-please-pass-the","errorCode":null,"errorMessage":"No webhook timestamp was provided. Please pass the value of the 'webhook-timestamp' header.","messagePattern":"No webhook timestamp was provided\\. Please pass the value of the 'webhook-timestamp' header\\.","errorType":"exception","errorClass":"ComposioWebhookSignatureVerificationError","httpStatus":null,"severity":"error","filePath":"ts/packages/core/src/models/Triggers.ts","lineNumber":1253,"sourceCode":"      throw new ComposioWebhookSignatureVerificationError(\n        \"No signature header value was provided. Please pass the value of the 'webhook-signature' header.\"\n      );\n    }\n\n    if (secret.length === 0) {\n      throw new ComposioWebhookSignatureVerificationError(\n        'No webhook secret was provided. You can find your webhook secret in your Composio dashboard.'\n      );\n    }\n\n    if (webhookId.length === 0) {\n      throw new ComposioWebhookSignatureVerificationError(\n        \"No webhook ID was provided. Please pass the value of the 'webhook-id' header.\"\n      );\n    }\n\n    if (webhookTimestamp.length === 0) {\n      throw new ComposioWebhookSignatureVerificationError(\n        \"No webhook timestamp was provided. Please pass the value of the 'webhook-timestamp' header.\"\n      );\n    }\n\n    // Parse signature - may have multiple signatures prefixed with version (e.g., \"v1,base64sig\")\n    const signatures = signature.split(' ');\n    const v1Signatures: string[] = [];\n\n    for (const sig of signatures) {\n      const [version, value] = sig.split(',');\n      if (version === 'v1' && value) {\n        v1Signatures.push(value);\n      }\n    }\n\n    if (v1Signatures.length === 0) {\n      throw new ComposioWebhookSignatureVerificationError(\n        'No valid v1 signature found in the webhook-signature header. ' +","sourceCodeStart":1235,"sourceCodeEnd":1271,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/core/src/models/Triggers.ts#L1235-L1271","documentation":"Thrown when the 'webhook-timestamp' header is missing or empty during webhook signature verification. The timestamp is a component of the signed payload (msgId.timestamp.payload) and is also used for replay-attack tolerance checks, so it is mandatory. The library throws ComposioWebhookSignatureVerificationError rather than guessing a timestamp.","triggerScenarios":"Calling verifyWebhookSignature with webhookTimestamp set to '' — e.g. the 'webhook-timestamp' header was not read from the request, was renamed by the framework, or the request genuinely lacks it (very old webhook deliveries or non-Composio traffic hitting the endpoint).","commonSituations":"Header-name casing mismatches (Node lowercases, some platforms do not), proxies stripping custom headers, or sending the webhook endpoint a manually crafted/test payload without the Composio headers.","solutions":["Read and pass the 'webhook-timestamp' header exactly as received from Composio","Verify header names survive any proxy/gateway in front of your handler","Reject or 400 non-Composio requests before calling verification","In tests, generate a current Unix-seconds timestamp header value"],"exampleFix":"// before\nverify({ signature: req.headers['webhook-signature'], webhookId: req.headers['webhook-id'], webhookTimestamp: '' });\n// after\nverify({\n  signature: req.headers['webhook-signature'],\n  webhookId: req.headers['webhook-id'],\n  webhookTimestamp: req.headers['webhook-timestamp'],\n});","handlingStrategy":"validation","validationCode":"const ts = req.headers['webhook-timestamp'];\nif (typeof ts !== 'string' || ts.length === 0) {\n  return res.status(400).send('Missing webhook-timestamp header');\n}","typeGuard":"const isNonEmptyHeader = (v: unknown): v is string => typeof v === 'string' && v.length > 0;","tryCatchPattern":"try { verifyWebhookSignature(...); } catch (e) { if (e instanceof ComposioWebhookSignatureVerificationError) { logger.warn('webhook rejected', e.message); return res.status(400).end(); } throw e; }","preventionTips":["Validate presence of all three webhook headers before calling verify","Keep header names lowercase when reading from Node-style request objects","Log incoming headers in dev to catch proxy stripping"],"tags":["webhook","signature-verification","missing-header","typescript"],"backgroundTag":"webhook-signature-verification-failed","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}