Overview
Manage webhook triggers for n8n workflows, including URL generation, authentication, and signature verification.
Base URL: https://api.so1.io/v1/n8n/webhooks
Register Webhook
Endpoint
Request Body
Workflow to attach webhook
Webhook URL path (e.g., /deploy, /github-push)
HTTP method: GET, POST, PUT, PATCH, DELETE
Authentication configuration
Auth type: none, apiKey, hmac, basic, oauth
Header name for API key (e.g., X-API-Key)
Secret for HMAC signature verification
Header containing HMAC signature
responseMode
string
default:"onReceived"
Response timing: onReceived (immediate) or lastNode (wait for completion)
Example Request
curl -X POST https://api.so1.io/v1/n8n/webhooks \
-H "Authorization: Bearer so1_key_abc123xyz" \
-H "Content-Type: application/json" \
-d '{
"workflowId": "deploy-notification",
"path": "/deploy",
"method": "POST",
"authentication": {
"type": "apiKey",
"apiKeyHeader": "X-API-Key",
"apiKeyValue": "secret-api-key-123"
},
"responseMode": "onReceived"
}'
Response
{
"success": true,
"data": {
"webhookId": "wh-abc123",
"workflowId": "deploy-notification",
"url": "https://n8n.so1.io/webhook/deploy",
"method": "POST",
"authentication": {
"type": "apiKey",
"apiKeyHeader": "X-API-Key"
},
"active": true,
"createdAt": "2024-03-10T15:30:00Z"
}
}
Get Webhook
Endpoint
GET /v1/n8n/webhooks/{webhookId}
Response
{
"success": true,
"data": {
"webhookId": "wh-abc123",
"workflowId": "deploy-notification",
"workflowName": "Deploy Notification",
"url": "https://n8n.so1.io/webhook/deploy",
"method": "POST",
"authentication": {
"type": "apiKey",
"apiKeyHeader": "X-API-Key"
},
"responseMode": "onReceived",
"active": true,
"statistics": {
"totalRequests": 1247,
"successfulRequests": 1235,
"failedRequests": 12,
"averageResponseTime": 0.3,
"lastTriggered": "2024-03-10T15:25:00Z"
},
"createdAt": "2024-03-10T15:30:00Z"
}
}
List Webhooks
Endpoint
Query Parameters
Response
{
"success": true,
"data": {
"webhooks": [
{
"webhookId": "wh-abc123",
"workflowId": "deploy-notification",
"url": "https://n8n.so1.io/webhook/deploy",
"method": "POST",
"active": true,
"totalRequests": 1247,
"lastTriggered": "2024-03-10T15:25:00Z"
}
// ... more webhooks
],
"pagination": {
"total": 47,
"limit": 20,
"hasMore": true
}
}
}
Update Webhook
Endpoint
PUT /v1/n8n/webhooks/{webhookId}
Request Body
All fields optional - only provided fields are updated.
Updated authentication settings
Activate/deactivate webhook
Response
{
"success": true,
"data": {
"webhookId": "wh-abc123",
"updatedAt": "2024-03-10T16:00:00Z"
}
}
Delete Webhook
Endpoint
DELETE /v1/n8n/webhooks/{webhookId}
Response
{
"success": true,
"data": {
"webhookId": "wh-abc123",
"deletedAt": "2024-03-10T16:00:00Z"
}
}
Test Webhook
Send a test request to verify webhook configuration.
Endpoint
POST /v1/n8n/webhooks/{webhookId}/test
Request Body
Additional headers (including auth headers)
Example Request
curl -X POST https://api.so1.io/v1/n8n/webhooks/wh-abc123/test \
-H "Authorization: Bearer so1_key_abc123xyz" \
-H "Content-Type: application/json" \
-d '{
"data": {
"service": "api-gateway",
"environment": "staging"
},
"headers": {
"X-API-Key": "secret-api-key-123"
}
}'
Response
{
"success": true,
"data": {
"testExecutionId": "exec-test123",
"webhookResponse": {
"status": 200,
"body": {
"message": "Workflow triggered successfully"
}
},
"workflowResult": {
"status": "success",
"duration": 2.3
}
}
}
Get Webhook Logs
Retrieve webhook request logs for debugging.
Endpoint
GET /v1/n8n/webhooks/{webhookId}/logs
Query Parameters
Number of log entries (1-500)
Filter by status: success, failed, rejected
Response
{
"success": true,
"data": {
"webhookId": "wh-abc123",
"logs": [
{
"timestamp": "2024-03-10T15:30:00Z",
"method": "POST",
"sourceIp": "203.0.113.42",
"status": "success",
"responseTime": 0.3,
"executionId": "exec-abc123"
},
{
"timestamp": "2024-03-10T15:25:00Z",
"method": "POST",
"sourceIp": "203.0.113.43",
"status": "rejected",
"reason": "Invalid API key",
"responseTime": 0.1
}
// ... more logs
],
"pagination": {
"limit": 50,
"hasMore": true
}
}
}
Webhook Security Best Practices
1. Always Use Authentication
Never expose webhooks without authentication:// ❌ Bad: No authentication
const webhook = {
path: '/deploy',
method: 'POST',
authentication: { type: 'none' }
};
// ✅ Good: API key authentication
const webhook = {
path: '/deploy',
method: 'POST',
authentication: {
type: 'apiKey',
apiKeyHeader: 'X-API-Key',
apiKeyValue: process.env.WEBHOOK_SECRET
}
};
2. Verify HMAC Signatures
For external services (GitHub, Stripe, etc.), verify HMAC signatures:import crypto from 'crypto';
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// In n8n Function node:
const body = JSON.stringify($json);
const signature = $node["Webhook"].context["headerData"]["x-hub-signature-256"];
const secret = $credentials.githubWebhookSecret;
if (!verifyWebhookSignature(body, signature, secret)) {
throw new Error('Invalid webhook signature');
}
3. Implement Rate Limiting
Protect against webhook abuse:// Configure webhook with rate limiting
const webhook = await client.n8n.webhooks.register({
workflowId: 'user-signup',
path: '/signup',
method: 'POST',
rateLimit: {
windowMs: 60000, // 1 minute
maxRequests: 10,
keyBy: 'ip' // Rate limit by source IP
}
});
SO1 webhooks are HTTPS-only, but ensure external webhooks also use HTTPS:// ✅ Good: HTTPS callback URL
const webhook = {
callbackUrl: 'https://your-app.com/webhooks/so1'
};
// ❌ Bad: HTTP callback (rejected)
const webhook = {
callbackUrl: 'http://your-app.com/webhooks/so1'
};
5. Log and Monitor Webhooks
Track webhook activity:// Get webhook statistics
const stats = await client.n8n.webhooks.getStatistics('wh-abc123');
console.log('Webhook health:');
console.log(` Success rate: ${stats.successRate}%`);
console.log(` Average response time: ${stats.averageResponseTime}ms`);
console.log(` Failed requests (last 24h): ${stats.failedRequests24h}`);
// Set up alerts for failures
if (stats.failedRequests24h > 10) {
await sendAlert('High webhook failure rate detected');
}
Common Patterns
GitHub Webhook Integration
const githubWebhook = await client.n8n.webhooks.register({
workflowId: 'github-ci-cd',
path: '/github-push',
method: 'POST',
authentication: {
type: 'hmac',
hmacSecret: process.env.GITHUB_WEBHOOK_SECRET,
hmacHeader: 'X-Hub-Signature-256',
hmacAlgorithm: 'sha256'
}
});
// GitHub will send:
// POST https://n8n.so1.io/webhook/github-push
// X-Hub-Signature-256: sha256=abc123...
// Body: { "ref": "refs/heads/main", ... }
Stripe Webhook Integration
const stripeWebhook = await client.n8n.webhooks.register({
workflowId: 'payment-processing',
path: '/stripe-events',
method: 'POST',
authentication: {
type: 'hmac',
hmacSecret: process.env.STRIPE_WEBHOOK_SECRET,
hmacHeader: 'Stripe-Signature',
hmacAlgorithm: 'sha256'
}
});
// Stripe will send:
// POST https://n8n.so1.io/webhook/stripe-events
// Stripe-Signature: t=1234567890,v1=abc123...
// Body: { "type": "payment_intent.succeeded", "data": {...} }
Custom API Webhook
const apiWebhook = await client.n8n.webhooks.register({
workflowId: 'api-notifications',
path: '/api-events',
method: 'POST',
authentication: {
type: 'apiKey',
apiKeyHeader: 'X-API-Key',
apiKeyValue: crypto.randomBytes(32).toString('hex')
},
responseMode: 'lastNode' // Return workflow result
});
// Clients call:
// POST https://n8n.so1.io/webhook/api-events
// X-API-Key: your-api-key
// Body: { "event": "user.created", "data": {...} }
//
// Response includes workflow result:
// { "success": true, "notificationSent": true }