Skip to main content

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

POST /v1/n8n/webhooks

Request Body

workflowId
string
required
Workflow to attach webhook
path
string
required
Webhook URL path (e.g., /deploy, /github-push)
method
string
required
HTTP method: GET, POST, PUT, PATCH, DELETE
authentication
object
Authentication configuration
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

GET /v1/n8n/webhooks

Query Parameters

workflowId
string
Filter by workflow
active
boolean
Filter by active status
method
string
Filter by HTTP method
limit
number
default:"20"
Results per page (1-100)

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.
path
string
Updated webhook path
method
string
Updated HTTP method
authentication
object
Updated authentication settings
active
boolean
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

data
object
required
Test payload
headers
object
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

limit
number
default:"50"
Number of log entries (1-500)
status
string
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

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
  }
};
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');
}
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'
};
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 }