Claude-code-plugins-plus-skills clay-deploy-integration
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/clay-pack/skills/clay-deploy-integration" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-clay-deploy-integration && rm -rf "$T"
manifest:
plugins/saas-packs/clay-pack/skills/clay-deploy-integration/SKILL.mdsource content
Clay Deploy Integration
Overview
Deploy applications that integrate with Clay (webhook receivers, enrichment processors, CRM sync services) to production platforms. Clay itself is a hosted SaaS -- you deploy the code that interacts with Clay, not Clay itself. The critical requirement is a publicly accessible HTTPS endpoint for Clay's HTTP API columns to call back to.
Prerequisites
- Application code that handles Clay webhooks or HTTP API callbacks
- Platform CLI installed (vercel, gcloud, or docker)
- Clay webhook URL and/or API key stored securely
- HTTPS endpoint accessible from the public internet
Instructions
Step 1: Vercel Deployment (Serverless)
Best for: Webhook receivers, small-scale enrichment handlers.
# Set Clay secrets in Vercel vercel env add CLAY_WEBHOOK_URL production vercel env add CLAY_API_KEY production vercel env add CLAY_WEBHOOK_SECRET production # Deploy vercel --prod
// api/clay/callback.ts — Vercel serverless function import type { VercelRequest, VercelResponse } from '@vercel/node'; import crypto from 'crypto'; export default async function handler(req: VercelRequest, res: VercelResponse) { if (req.method !== 'POST') return res.status(405).end(); // Validate webhook signature const signature = req.headers['x-clay-signature'] as string; const secret = process.env.CLAY_WEBHOOK_SECRET!; const expected = crypto.createHmac('sha256', secret) .update(JSON.stringify(req.body)) .digest('hex'); if (!crypto.timingSafeEqual(Buffer.from(signature || ''), Buffer.from(expected))) { return res.status(401).json({ error: 'Invalid signature' }); } // Process enriched data from Clay HTTP API column const enrichedLead = req.body; console.log('Received enriched lead:', { email: enrichedLead.email, company: enrichedLead.company_name, score: enrichedLead.icp_score, }); // Push to CRM, database, or outreach tool await processLead(enrichedLead); return res.status(200).json({ status: 'processed' }); }
Step 2: Cloud Run Deployment (Container)
Best for: High-volume enrichment pipelines, CRM sync services.
# Dockerfile FROM node:20-slim WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY dist/ ./dist/ EXPOSE 8080 ENV PORT=8080 CMD ["node", "dist/index.js"]
# Build and deploy to Cloud Run gcloud builds submit --tag gcr.io/$PROJECT_ID/clay-handler gcloud run deploy clay-handler \ --image gcr.io/$PROJECT_ID/clay-handler \ --platform managed \ --region us-central1 \ --allow-unauthenticated \ --set-secrets "CLAY_API_KEY=clay-api-key:latest,CLAY_WEBHOOK_SECRET=clay-webhook-secret:latest" \ --min-instances 1 \ --max-instances 10
Step 3: Docker Compose (Self-Hosted)
Best for: On-premise deployments, development staging.
# docker-compose.yml version: '3.8' services: clay-handler: build: . ports: - "3000:3000" environment: - CLAY_WEBHOOK_URL=${CLAY_WEBHOOK_URL} - CLAY_API_KEY=${CLAY_API_KEY} - CLAY_WEBHOOK_SECRET=${CLAY_WEBHOOK_SECRET} - DATABASE_URL=${DATABASE_URL} restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3
Step 4: Configure Clay to Call Your Deployed Endpoint
Once deployed, update your Clay table's HTTP API column:
- Get your deployment URL (e.g.,
or Cloud Run URL)https://clay-handler.vercel.app - In Clay table, edit the HTTP API column
- Set URL to:
https://your-deployment.com/api/clay/callback - Test on a single row before enabling auto-run
Step 5: Health Check Endpoint
// src/health.ts — health check that verifies Clay connectivity app.get('/health', async (req, res) => { const checks: Record<string, string> = { server: 'ok', clay_webhook: 'unknown', database: 'unknown', }; // Check Clay webhook reachability try { const webhookTest = await fetch(process.env.CLAY_WEBHOOK_URL!, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ _health_check: true }), }); checks.clay_webhook = webhookTest.ok ? 'ok' : `error: ${webhookTest.status}`; } catch { checks.clay_webhook = 'unreachable'; } const allHealthy = Object.values(checks).every(v => v === 'ok'); res.status(allHealthy ? 200 : 503).json({ status: allHealthy ? 'healthy' : 'degraded', checks }); });
Step 6: Production Environment Variables
# Required for all deployments CLAY_WEBHOOK_URL=https://app.clay.com/api/v1/webhooks/your-id CLAY_WEBHOOK_SECRET=your-shared-secret # Optional (Enterprise only) CLAY_API_KEY=clay_ent_your_key # Application-specific DATABASE_URL=postgresql://... CRM_API_KEY=your-crm-key PORT=3000
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Clay can't reach callback | Endpoint not public HTTPS | Verify URL is accessible, check firewall |
| Cold start timeout | Serverless function too slow | Set min-instances=1 on Cloud Run |
| Missing secrets in deploy | Env vars not configured | Add via platform CLI before deploying |
| Health check fails | Clay webhook URL invalid | Re-copy webhook URL from Clay table |
Resources
Next Steps
For webhook handling patterns, see
clay-webhooks-events.