Signature Verification

Primitive signs every webhook request so you can verify it came from us. This prevents attackers from sending fake webhooks to your endpoint.

The signature header

Every webhook includes a Primitive-Signature header with this format:

t=1734523200,v1=5257a869e7ecebeda32aff1deadbeef951cad7e77a0e56ff536d0ce8e108d8bd
  • t - Unix timestamp when the signature was generated
  • v1 - HMAC-SHA256 signature

Verifying with the SDK

The easiest path is still to use your SDK's high-level webhook helper. Reach for these lower-level verification helpers when you want to inspect the signature before parsing the payload.

Node.js uses WebhookVerificationError for structured verification failures.

import { verifyWebhookSignature, WebhookVerificationError } from '@primitivedotdev/sdk';
try {
verifyWebhookSignature({
rawBody,
signatureHeader: request.headers.get('Primitive-Signature') ?? '',
secret: process.env.PRIMITIVE_WEBHOOK_SECRET!,
});
// Signature is valid
} catch (error) {
if (error instanceof WebhookVerificationError) {
console.error('Verification failed:', error.code);
}
throw error;
}

Manual verification

If you are not using the SDK, the verification flow is the same in every language:

  1. Parse the header and extract t and v1.
  2. Reject timestamps older than 5 minutes to limit replay attacks.
  3. Compute an HMAC-SHA256 signature of {timestamp}.{rawBody} using your webhook secret.
  4. Compare the provided and expected signatures with a timing-safe comparison.
  5. Always use the exact raw request body, never re-serialized JSON.

Finding your webhook secret

Your webhook secret is in the Webhooks section of your dashboard. Store it securely in PRIMITIVE_WEBHOOK_SECRET or an equivalent secret manager value, and never commit it to source control.

Rotating your secret

You can rotate your webhook secret from the dashboard at any time. When you rotate, the old secret is immediately invalidated. Update your webhook handlers before rotating to avoid verification failures.

Error codes

Verification failures use stable error codes across the SDKs:

CodeDescription
INVALID_SIGNATURE_HEADERMissing or malformed Primitive-Signature header
TIMESTAMP_OUT_OF_RANGETimestamp is too old (possible replay attack)
SIGNATURE_MISMATCHSignature doesn't match expected value
MISSING_SECRETNo webhook secret was provided