Generic Webhook Integration
The Generic Webhook integration allows you to connect iContentForge to any custom content management system, static site generator, or internal application. By providing a simple endpoint URL, you can receive fully generated articles as structured JSON payloads, enabling complete flexibility for your publishing pipeline.
Configuration
To set up a Generic Webhook, navigate to your project's Settings > CMS Integration and select "Generic Webhook" from the connector list.
Generic Webhook configuration screen in iContentForge
You will need to configure two primary settings:
- Endpoint URL: The full HTTPS URL of your server that will receive the webhook POST requests.
- Secret Key: A shared secret used to cryptographically sign each webhook payload, allowing your server to verify the request originated from iContentForge.
Your endpoint URL must use HTTPS. iContentForge will not send webhooks to insecure HTTP endpoints for security reasons. Ensure your server has a valid SSL certificate.
Webhook Payload Format
When an article's status changes to ready (or published if configured), iContentForge sends a POST request to your endpoint. The request body is a JSON object with the following structure:
{
"event": "article.published",
"projectId": "proj_abc123",
"article": {
"id": "art_xyz789",
"title": "The Complete Guide to Programmatic SEO",
"slug": "complete-guide-programmatic-seo",
"content": "<h1>The Complete Guide...</h1><p>Programmatic SEO is...</p>",
"excerpt": "An introduction to scaling content creation with data and automation.",
"status": "published",
"meta": {
"description": "Learn how programmatic SEO can automate and scale your content strategy for higher rankings.",
"keywords": ["programmatic seo", "content automation", "seo scaling"]
},
"author": "iContentForge AI",
"publishedAt": "2024-01-15T10:30:00.000Z",
"categories": ["SEO", "Content Strategy"],
"tags": ["automation", "scale"]
}
}
Payload Field Reference
| Field | Type | Description |
|---|---|---|
event | String | The triggering event. Common values: article.ready, article.published, article.updated. |
projectId | String | The unique ID of the iContentForge project this article belongs to. |
article.id | String | The unique internal ID of the article. |
article.title | String | The full title of the generated article. |
article.slug | String | The URL-friendly slug derived from the title. |
article.content | String | The full HTML content of the article, ready for publishing. |
article.excerpt | String | A short summary of the article content. |
article.status | String | The final status of the article (ready or published). |
article.meta | Object | Contains SEO meta tags like description and keywords. |
article.author | String | The author name as configured in the project settings. |
article.publishedAt | String (ISO 8601) | The scheduled date and time for publication. |
article.categories | Array | A list of categories assigned to the article. |
article.tags | Array | A list of tags assigned to the article. |
Security & Signature Verification
To prevent spoofing, iContentForge signs every webhook request using an HMAC-SHA256 signature. The signature is included in the X-iCF-Signature HTTP header. Your server must verify this signature using the Secret Key you configured.
The signature is generated from the raw request body string. You must compute the HMAC of this raw body and compare it to the value in the header.
Verification Example (Node.js)
import crypto from 'crypto';
export async function handleWebhook(req, res) {
const secret = process.env.ICF_WEBHOOK_SECRET; // Your configured Secret Key
const signature = req.headers['x-icf-signature'];
const rawBody = JSON.stringify(req.body); // Get the raw JSON string
// Compute the expected signature
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
// Compare signatures in a timing-safe manner
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature))) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Signature is valid, process the article...
console.log('Received article:', req.body.article.title);
res.status(200).json({ received: true });
}
Verification Example (Python)
import hashlib
import hmac
import json
from flask import request, jsonify
def handle_webhook():
secret = os.environ.get('ICF_WEBHOOK_SECRET').encode() # Your configured Secret Key
signature = request.headers.get('X-iCF-Signature')
raw_body = request.get_data(as_text=True) # Get the raw request body as string
# Compute the expected signature
expected_signature = hmac.new(secret, msg=raw_body.encode(), digestmod=hashlib.sha256).hexdigest()
# Compare signatures (use hmac.compare_digest for timing safety)
if not hmac.compare_digest(signature, expected_signature):
return jsonify({'error': 'Invalid signature'}), 401
# Signature is valid, process the article...
data = json.loads(raw_body)
print(f"Received article: {data['article']['title']}")
return jsonify({'received': True}), 200
Always use a timing-safe comparison function (like crypto.timingSafeEqual in Node.js or hmac.compare_digest in Python) to verify the HMAC signature. This prevents timing attacks that could compromise your secret key.
Handling & Retry Logic
Your endpoint should return a 2xx HTTP status code (e.g., 200 OK) upon successful receipt and processing of the payload. If iContentForge receives a 4xx or 5xx error, it will retry the webhook delivery with an exponential backoff for up to 24 hours.
For testing, you can use a service like webhook.site to generate a temporary endpoint URL and inspect the payload structure before implementing your own server.
Next Steps
- Learn how to structure your content with the Silo Radar for internal linking.
- Understand the full article generation workflow.
- Explore other direct CMS Integrations like WordPress and Shopify.