Core Concepts
- Overview
- Infrastructure & Organization
- Data Structure
- Automation & Processing
Plugins
- Overview
- Docs
Advanced Guides
Embedding Flatfile
Webhook Examples
Standardized webhook patterns for Flatfile integrations
This file contains standardized webhook examples that can be referenced across all guides to ensure consistency.
Basic Webhook Setup
Environment Configuration
Copy
Ask AI
# Primary webhook endpoint
WEBHOOK_URL=https://your-app.com/webhook/flatfile
# Backup/testing endpoint (optional)
WEBHOOK_TEST_URL=https://webhook.site/your-unique-id
Webhook Request Patterns
Basic POST Request with Fetch
Copy
Ask AI
const webhookUrl = process.env.WEBHOOK_URL || "https://your-app.com/webhook/flatfile";
const response = await fetch(webhookUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"User-Agent": "Flatfile-Integration/1.0"
},
body: JSON.stringify({
event: "data_ready",
workbook: workbookData,
timestamp: new Date().toISOString()
})
});
if (!response.ok) {
throw new Error(`Webhook failed: ${response.status} ${response.statusText}`);
}
POST Request with Authentication
Copy
Ask AI
const webhookUrl = process.env.WEBHOOK_URL;
const apiKey = await event.secrets("WEBHOOK_API_KEY");
const response = await fetch(webhookUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`,
"X-Flatfile-Event": event.topic
},
body: JSON.stringify(payload)
});
Using Axios (Alternative)
Copy
Ask AI
import axios from "axios";
const webhookUrl = process.env.WEBHOOK_URL;
const response = await axios.post(webhookUrl, {
workbook,
sheets,
metadata: {
source: "flatfile",
timestamp: new Date().toISOString()
}
}, {
headers: {
"Content-Type": "application/json"
},
timeout: 30000 // 30 second timeout
});
Complete Webhook Integration Patterns
Workbook Action with Webhook
Copy
Ask AI
// Blueprint configuration
actions: [
{
operation: "submitToWebhook",
mode: "foreground",
label: "Submit to External System",
description: "Send data to your external system",
primary: true
}
]
// Listener implementation
listener.on(
"job:ready",
{ job: "workbook:submitToWebhook" },
async (event) => {
const { jobId, workbookId } = event.context;
try {
await api.jobs.ack(jobId, {
info: "Preparing data for submission...",
progress: 10
});
// Collect workbook data
const { data: workbook } = await api.workbooks.get(workbookId);
const { data: sheets } = await api.sheets.list({ workbookId });
const payload = {
workbook: {
...workbook,
sheets: await Promise.all(
sheets.map(async (sheet) => {
const { data: records } = await api.records.get(sheet.id);
return { ...sheet, records: records.records };
})
)
}
};
// Send to webhook
const webhookUrl = await event.secrets("WEBHOOK_URL");
const response = await fetch(webhookUrl, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
});
if (response.ok) {
await api.jobs.complete(jobId, {
outcome: {
message: `Data successfully submitted to ${webhookUrl}`
}
});
} else {
throw new Error(`Webhook returned ${response.status}`);
}
} catch (error) {
await api.jobs.fail(jobId, {
outcome: {
message: "Failed to submit data. Please check your webhook URL and try again."
}
});
}
}
);
Record Hook with Webhook
Copy
Ask AI
import { recordHook } from "@flatfile/plugin-record-hook";
listener.use(
recordHook("contacts", async (record, event) => {
try {
const webhookUrl = process.env.WEBHOOK_URL ||
await event.secrets("WEBHOOK_URL");
const response = await fetch(webhookUrl, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
action: "record_processed",
record: record.toJSON(),
sheet: event.context.sheetId
})
});
if (response.ok) {
record.addInfo("status", "Successfully sent to external system");
} else {
record.addError("status", "Failed to send to external system");
}
} catch (error) {
record.addError("status", "Webhook communication failed");
}
return record;
})
);
Webhook Testing Patterns
Using webhook.site for Testing
Copy
Ask AI
// For testing purposes - use webhook.site
const testWebhookUrl = "https://webhook.site/your-unique-id";
// In production, use your actual endpoint
const webhookUrl = process.env.NODE_ENV === "production"
? process.env.WEBHOOK_URL
: testWebhookUrl;
Local Development Testing
Copy
Ask AI
// Use ngrok or similar for local testing
const webhookUrl = process.env.WEBHOOK_URL ||
"https://your-ngrok-url.ngrok.io/webhook/flatfile";
Error Handling Best Practices
Comprehensive Error Handling
Copy
Ask AI
async function sendWebhook(url, payload, retries = 3) {
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Attempt": attempt.toString()
},
body: JSON.stringify(payload),
timeout: 30000
});
if (response.ok) {
return await response.json();
}
if (response.status >= 400 && response.status < 500) {
// Client error - don't retry
throw new Error(`Client error: ${response.status}`);
}
// Server error - retry
if (attempt === retries) {
throw new Error(`Server error after ${retries} attempts: ${response.status}`);
}
} catch (error) {
if (attempt === retries) {
throw error;
}
// Wait before retry (exponential backoff)
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
}
}
}
Security Considerations
- Always use HTTPS for webhook URLs
- Validate webhook signatures when possible
- Use authentication tokens for sensitive endpoints
- Implement proper error handling to avoid exposing sensitive information
- Set reasonable timeouts to prevent hanging requests
- Use environment variables for URLs and credentials
On this page
- Basic Webhook Setup
- Environment Configuration
- Webhook Request Patterns
- Basic POST Request with Fetch
- POST Request with Authentication
- Using Axios (Alternative)
- Complete Webhook Integration Patterns
- Workbook Action with Webhook
- Record Hook with Webhook
- Webhook Testing Patterns
- Using webhook.site for Testing
- Local Development Testing
- Error Handling Best Practices
- Comprehensive Error Handling
- Security Considerations
Assistant
Responses are generated using AI and may contain mistakes.