Clay Security Basics
Overview
Security best practices for Clay integrations covering API key management, webhook endpoint security, provider credential isolation, and lead data protection. Clay handles sensitive PII (emails, phone numbers, LinkedIn profiles) at scale, making security critical.
Prerequisites
- Clay account with admin access
- Understanding of environment variables and secrets management
- Access to deployment platform's secrets manager
Instructions
Step 1: Secure API Key Storage
# .env (NEVER commit to git)
CLAY_API_KEY=clay_ent_your_api_key_here
CLAY_WEBHOOK_URL=https://app.clay.com/api/v1/webhooks/your-id
# .gitignore — add these patterns
.env
.env.local
.env.*.local
*.key
For production, use your platform's secrets manager:
# GitHub Actions
gh secret set CLAY_API_KEY --body "clay_ent_your_key"
# Google Cloud Secret Manager
echo -n "clay_ent_your_key" | gcloud secrets create clay-api-key --data-file=-
# AWS Secrets Manager
aws secretsmanager create-secret \
--name clay/api-key \
--secret-string "clay_ent_your_key"
Step 2: Authenticate Incoming Webhook Callbacks
When Clay's HTTP API columns call your endpoint, validate the request origin:
// src/middleware/clay-auth.ts
import crypto from 'crypto';
const CLAY_WEBHOOK_SECRET = process.env.CLAY_WEBHOOK_SECRET!;
function verifyClayCallback(
payload: string,
signature: string | undefined
): boolean {
if (!signature || !CLAY_WEBHOOK_SECRET) return false;
const expected = crypto
.createHmac('sha256', CLAY_WEBHOOK_SECRET)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expected, 'hex')
);
}
// Express middleware
function clayAuthMiddleware(req: any, res: any, next: any) {
const signature = req.headers['x-clay-signature'] as string;
const rawBody = JSON.stringify(req.body);
if (!verifyClayCallback(rawBody, signature)) {
console.warn('Rejected unauthorized Clay callback from', req.ip);
return res.status(401).json({ error: 'Invalid signature' });
}
next();
}