Clay Security Basics
Overview
Security best practices for Clay API keys, tokens, and access control.
Prerequisites
- Clay SDK installed
- Understanding of environment variables
- Access to Clay dashboard
Instructions
Step 1: Configure Environment Variables
# .env (NEVER commit to git) CLAY_API_KEY=sk_live_*** CLAY_SECRET=*** # .gitignore .env .env.local .env.*.local
Step 2: Implement Secret Rotation
# 1. Generate new key in Clay dashboard # 2. Update environment variable export CLAY_API_KEY="new_key_here" # 3. Verify new key works curl -H "Authorization: Bearer ${CLAY_API_KEY}" \ https://api.clay.com/health # 4. Revoke old key in dashboard
Step 3: Apply Least Privilege
| Environment | Recommended Scopes |
|---|---|
| Development | read:* |
| Staging | read:*, write:limited |
| Production | Only required scopes |
Output
- Secure API key storage
- Environment-specific access controls
- Audit logging enabled
Error Handling
| Security Issue | Detection | Mitigation |
|---|---|---|
| Exposed API key | Git scanning | Rotate immediately |
| Excessive scopes | Audit logs | Reduce permissions |
| Missing rotation | Key age check | Schedule rotation |
Examples
Service Account Pattern
const clients = { reader: new ClayClient({ apiKey: process.env.CLAY_READ_KEY, }), writer: new ClayClient({ apiKey: process.env.CLAY_WRITE_KEY, }), };
Webhook Signature Verification
import crypto from 'crypto'; function verifyWebhookSignature( payload: string, signature: string, secret: string ): boolean { const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex'); return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); }
Security Checklist
- API keys in environment variables
-
.envfiles in.gitignore - Different keys for dev/staging/prod
- Minimal scopes per environment
- Webhook signatures validated
- Audit logging enabled
Audit Logging
interface AuditEntry { timestamp: Date; action: string; userId: string; resource: string; result: 'success' | 'failure'; metadata?: Record<string, any>; } async function auditLog(entry: Omit<AuditEntry, 'timestamp'>): Promise<void> { const log: AuditEntry = { ...entry, timestamp: new Date() }; // Log to Clay analytics await clayClient.track('audit', log); // Also log locally for compliance console.log('[AUDIT]', JSON.stringify(log)); } // Usage await auditLog({ action: 'clay.api.call', userId: currentUser.id, resource: '/v1/resource', result: 'success', });
Resources
Next Steps
For production deployment, see clay-prod-checklist.