Skip to main content
This page covers verifying ongoing webhook payloads. For initial endpoint verification when creating a webhook, see Callback URI Verification.
Always verify that webhook payloads actually came from Smartcar before processing them. Every webhook includes an SC-Signature header containing an HMAC-SHA256 signature of the payload.

Why Verification Matters

Without signature verification:
  • Anyone could send fake webhook payloads to your endpoint
  • Malicious actors could inject false vehicle data
  • You have no guarantee the payload came from Smartcar
Signature verification ensures:
  • The payload was sent by Smartcar
  • The payload wasn’t tampered with in transit
  • You can safely process the data

How Signature Verification Works

  1. Smartcar creates an HMAC-SHA256 hash of the raw request body using your Application Management Token as the secret key
  2. The hash is sent in the SC-Signature header
  3. You recreate the hash using the same secret and compare it to the received signature
  4. If they match, the payload is authentic and unmodified

Quick Implementation

Use our SDKs for automatic signature verification:
Our backend SDKs have helper methods that return true if the payload is valid.
smartcar.verifyPayload(
    application_management_token,
    sc_signature_header, 
    raw_webhook_body
);

Manual Implementation

If you’re not using an SDK, implement signature verification manually:
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, managementToken) {
  // Create HMAC hash of the raw body
  const hmac = crypto
    .createHmac('sha256', managementToken)
    .update(payload)
    .digest('hex');
  
  // Securely compare (prevents timing attacks)
  return crypto.timingSafeEqual(
    Buffer.from(hmac),
    Buffer.from(signature)
  );
}

// Important: Use raw body parser
app.post('/webhooks/smartcar', 
  express.raw({ type: 'application/json' }), 
  (req, res) => {
    // Get the signature from headers
    const signature = req.headers['sc-signature'];
    
    // Get the raw body
    const rawBody = req.body.toString();
    
    // Verify signature
    if (!verifyWebhookSignature(rawBody, signature, MANAGEMENT_TOKEN)) {
      return res.status(401).json({ error: 'Invalid signature' });
    }
    
    // Now safe to process
    const payload = JSON.parse(rawBody);
    processWebhook(payload);
    res.status(200).json({ status: 'received' });
  }
);
Critical: You must verify the signature against the raw request body before parsing it as JSON. Many frameworks automatically parse JSON, which can alter the body and break signature verification.

Best Practices

Never skip signature verification, even in development. It’s your only guarantee that payloads are authentic.
Verify against the raw request body before JSON parsing. Parsed JSON may have different whitespace/ordering that breaks verification.
Return 401 Unauthorized for invalid signatures. Don’t process the payload or return 200.
Store your Application Management Token securely (environment variables, secrets manager). Never commit it to source control.

Next Steps