clay-webhooks-events
Implement Clay webhook receivers and HTTP API column callbacks for real-time data flow. Use when setting up webhook endpoints, handling enrichment callbacks from Clay, or building event-driven integrations with Clay tables. Trigger with phrases like "clay webhook", "clay events", "clay callback", "handle clay data", "clay notifications", "clay HTTP API column".
What this skill does
# Clay Webhooks & Events
## Overview
Clay's event-driven architecture has two webhook patterns: (1) **Inbound webhooks** -- you POST data into Clay tables via unique webhook URLs, and (2) **Outbound HTTP API columns** -- Clay POSTs enriched data to your endpoint after enrichment completes. This skill covers both patterns with production-ready handlers.
## Prerequisites
- Clay table with webhook source configured (for inbound)
- Clay table with HTTP API enrichment column (for outbound)
- HTTPS endpoint accessible from the internet
- Familiarity with Express.js or similar framework
## Instructions
### Step 1: Inbound Webhook -- Send Data into Clay
Every Clay table has a unique webhook URL. When you POST JSON to this URL, a new row appears in the table.
```typescript
// src/clay/inbound.ts — send data into Clay tables
class ClayInboundWebhook {
constructor(
private webhookUrl: string,
private submissionCount: number = 0,
private readonly LIMIT: number = 50_000,
) {}
async sendRow(data: Record<string, unknown>): Promise<void> {
if (this.submissionCount >= this.LIMIT) {
throw new Error(`Webhook exhausted (${this.LIMIT} submissions). Create a new webhook in Clay.`);
}
const res = await fetch(this.webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!res.ok) {
throw new Error(`Clay webhook failed: ${res.status} ${res.statusText}`);
}
this.submissionCount++;
}
async sendBatch(rows: Record<string, unknown>[], delayMs = 200): Promise<{ sent: number; failed: number }> {
let sent = 0, failed = 0;
for (const row of rows) {
try {
await this.sendRow(row);
sent++;
} catch {
failed++;
}
await new Promise(r => setTimeout(r, delayMs));
}
return { sent, failed };
}
}
// Usage
const webhook = new ClayInboundWebhook(process.env.CLAY_WEBHOOK_URL!);
await webhook.sendRow({
email: '[email protected]',
domain: 'acme.com',
first_name: 'Jane',
last_name: 'Doe',
source: 'website-form',
});
```
### Step 2: Outbound Callback -- Receive Enriched Data from Clay
Clay's HTTP API enrichment column POSTs data to your endpoint after enrichment runs. Set up a handler:
```typescript
// src/clay/outbound-handler.ts — receive enriched data from Clay
import express from 'express';
import crypto from 'crypto';
const app = express();
app.use(express.json({ limit: '1mb' }));
// Signature verification middleware
function verifyClaySignature(req: any, res: any, next: any) {
const signature = req.headers['x-clay-signature'];
const secret = process.env.CLAY_WEBHOOK_SECRET;
if (secret && signature) {
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' });
}
}
next();
}
// Main callback endpoint
app.post('/api/clay/enriched', verifyClaySignature, async (req, res) => {
// Respond 200 immediately — Clay expects fast response
res.json({ received: true, timestamp: new Date().toISOString() });
// Process enriched data async
try {
await processEnrichedLead(req.body);
} catch (err) {
console.error('Failed to process enriched lead:', err);
}
});
interface EnrichedLead {
email?: string;
first_name?: string;
last_name?: string;
company_name?: string;
job_title?: string;
employee_count?: number;
industry?: string;
linkedin_url?: string;
icp_score?: number;
personalized_opener?: string;
}
async function processEnrichedLead(lead: EnrichedLead): Promise<void> {
// Route based on ICP score
if (lead.icp_score && lead.icp_score >= 80 && lead.email) {
await pushToOutreachSequence(lead);
} else if (lead.icp_score && lead.icp_score >= 50) {
await addToNurtureCampaign(lead);
} else {
console.log(`Low-score lead skipped: ${lead.email} (score: ${lead.icp_score})`);
}
}
```
### Step 3: Configure the HTTP API Column in Clay
In your Clay table, add an HTTP API enrichment column:
1. **+ Add Column > HTTP API**
2. **Method**: POST
3. **URL**: `https://your-app.com/api/clay/enriched`
4. **Headers**:
- `Content-Type: application/json`
- `X-Clay-Signature: {{shared-secret-hash}}` (optional)
5. **Body** (map Clay columns to your schema):
```json
{
"email": "{{Work Email}}",
"first_name": "{{first_name}}",
"last_name": "{{last_name}}",
"company_name": "{{Company Name}}",
"job_title": "{{Job Title}}",
"employee_count": "{{Employee Count}}",
"industry": "{{Industry}}",
"linkedin_url": "{{LinkedIn URL}}",
"icp_score": "{{ICP Score}}",
"personalized_opener": "{{Personalized Opener}}"
}
```
1. **Conditional run**: `ISNOTEMPTY(Work Email) AND ICP Score >= 50`
2. **Auto-run on new rows**: ON
### Step 4: Idempotent Processing
Clay may retry failed HTTP API calls. Ensure idempotent handling:
```typescript
// src/clay/idempotency.ts
const processedSet = new Set<string>();
function getIdempotencyKey(lead: EnrichedLead): string {
return crypto.createHash('sha256')
.update(`${lead.email}:${lead.company_name}:${Date.now().toString().slice(0, -4)}`)
.digest('hex');
}
async function processIdempotent(lead: EnrichedLead): Promise<boolean> {
const key = getIdempotencyKey(lead);
if (processedSet.has(key)) {
console.log(`Duplicate callback skipped: ${lead.email}`);
return false;
}
processedSet.add(key);
await processEnrichedLead(lead);
return true;
}
```
### Step 5: Integration with External Services
```typescript
// src/clay/integrations.ts — push enriched leads to downstream tools
// Zapier webhook trigger
async function triggerZapier(lead: EnrichedLead): Promise<void> {
await fetch(process.env.ZAPIER_WEBHOOK_URL!, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(lead),
});
}
// Slack notification for high-value leads
async function notifySlack(lead: EnrichedLead): Promise<void> {
if (!lead.icp_score || lead.icp_score < 90) return;
await fetch(process.env.SLACK_WEBHOOK_URL!, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: `Hot lead from Clay: ${lead.first_name} ${lead.last_name} (${lead.job_title}) at ${lead.company_name} - ICP Score: ${lead.icp_score}`,
}),
});
}
```
## Error Handling
| Issue | Cause | Solution |
|-------|-------|----------|
| Webhook returns 404 | URL expired or table deleted | Re-create webhook in Clay table |
| HTTP API column shows error | Your endpoint unreachable | Verify HTTPS URL is publicly accessible |
| Duplicate callbacks | Clay retried failed request | Implement idempotency (Step 4) |
| Webhook 50K limit hit | High volume usage | Create new webhook on same table |
| Callback timeout | Slow processing | Respond 200 immediately, process async |
## Resources
- [Clay University -- Webhook Integration Guide](https://university.clay.com/docs/webhook-integration-guide)
- [Clay University -- HTTP API Integration](https://university.clay.com/docs/http-api-integration-overview)
- Clay University -- Using Clay as an API
## Next Steps
For performance optimization, see `clay-performance-tuning`.
Related in Backend & APIs
jfrog
IncludedInteract with the JFrog Platform via the JFrog CLI and REST/GraphQL APIs. Use this skill when the user wants to manage Artifactory repositories, upload or download artifacts, manage builds, configure permissions, manage users and groups, work with access tokens, configure JFrog CLI servers, search artifacts, manage properties, set up replication, manage JFrog Projects, run security audits or scans, look up CVE details, query exposures scan results from JFrog Advanced Security, manage release bundles and lifecycle operations, aggregate or export platform data, or perform any JFrog Platform administration task. Also use when the user mentions jf, jfrog, artifactory, xray, distribution, evidence, apptrust, onemodel, graphql, workers, mission control, curation, advanced security, exposures, or any JFrog product name.
cupynumeric-migration-readiness
IncludedPre-migration readiness assessor for porting NumPy to cuPyNumeric. Use BEFORE substantial porting work begins when the user asks whether code will scale on GPU, whether they should migrate to cuPyNumeric, which NumPy patterns transfer cleanly, what must be refactored before porting, or mentions pre-port assessment, scaling analysis, or refactor planning. Inspect the user's source code, look up NumPy usage, cross-reference the cuPyNumeric API support manifest, and distinguish distributed-scaling-friendly patterns from blockers such as unsupported APIs, scalar synchronization, host round-trips, Python/object-heavy control flow, shape/data-dependent branching, and in-place mutation hazards. Produce a verdict of READY, LIGHT REFACTOR, SIGNIFICANT REFACTOR, or NOT RECOMMENDED, with concrete refactor pointers.
alibabacloud-data-agent-skill
IncludedInvoke Alibaba Cloud Apsara Data Agent for Analytics via CLI to perform natural language-driven data analysis on enterprise databases. Data Agent for Analytics is an intelligent data analysis agent developed by Alibaba Cloud Database team for enterprise users. It automatically completes requirement analysis, data understanding, analysis insights, and report generation based on natural language descriptions. This tool supports: discovering data resources (instances/databases/tables) managed in DMS, initiating query or deep analysis sessions, real-time progress tracking, and retrieving analysis conclusions and generated reports. Use this Skill when users need to query databases, analyze data trends, generate data reports, ask questions in natural language, or mention "Data Agent", "data analysis", "database query", "SQL analysis", "data insights".
token-optimizer
IncludedReduce OpenClaw token usage and API costs through smart model routing, heartbeat optimization, budget tracking, and native 2026.2.15 features (session pruning, bootstrap size limits, cache TTL alignment). Use when token costs are high, API rate limits are being hit, or hosting multiple agents at scale. The 4 executable scripts (context_optimizer, model_router, heartbeat_optimizer, token_tracker) are local-only — no network requests, no subprocess calls, no system modifications. Reference files (PROVIDERS.md, config-patches.json) document optional multi-provider strategies that require external API keys and network access if you choose to use them. See SECURITY.md for full breakdown.
resend-cli
IncludedUse this skill when the task is specifically about operating Resend from an AI agent, terminal session, or CI job via the official resend CLI: installing/authenticating the CLI, sending/listing/updating/cancelling emails, batch sends, domains and DNS, webhooks and local listeners, inbound receiving, contacts, topics, segments, broadcasts, templates, API keys, profiles, or debugging Resend CLI/API failures. Trigger on mentions of Resend CLI, `resend`, `resend doctor`, `resend emails send`, `resend domains`, `resend webhooks listen`, `resend emails receiving`, or agent-friendly terminal automation.
alibabacloud-odps-maxframe-coding
IncludedUse this skill for MaxFrame SDK development and documentation navigation on Alibaba Cloud MaxCompute (ODPS). Helps answer MaxFrame API, concept, official example, and supported pandas API questions; create data processing programs; read/write MaxCompute tables; debug jobs (remote or local); and build custom DPE runtime images. Trigger when users mention MaxFrame, MaxCompute with MaxFrame, ODPS table processing, DPE runtime, MaxFrame docs/examples, DataFrame/Tensor operations, or GPU runtime setup. Works for both English and Chinese queries about Alibaba Cloud data processing with MaxFrame.