Webhook Integration

How to Integrate Your Blog with Our Webhook Service
This comprehensive guide will walk you through setting up webhook integration between your blog and our service. When enabled, our service will automatically send new blog posts to your specified webhook endpoint, including images as base64 data if configured in your settings.
What You'll Need
- API Key: Your authentication token for securing webhook requests
- Webhook Endpoint URL: The URL where we'll send POST requests with your blog data
- A server/backend: To receive and process the webhook data
Webhook Request Format
Our service sends webhook requests with the following structure:
HTTP Headers
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
Request Body
{
"title": "Your Blog Post Title",
"content": "The full content of your blog post...", //HTML Format
"image": "4AAQSkZJRgABAQEAYABgAAD..." // Optional, if image generation enabled
}
Implementation Examples
Node.js with Express
const express = require('express');
const app = express();
// Middleware to parse JSON
app.use(express.json({ limit: '50mb' })); // Increase limit for base64 images
// Webhook endpoint
app.post('/webhook/blog-post', (req, res) => {
// Verify API key
const authHeader = req.headers.authorization;
const expectedApiKey = process.env.YOUR_API_KEY;
if (!authHeader || authHeader !== `Bearer ${expectedApiKey}`) {
return res.status(401).json({ error: 'Unauthorized' });
}
const { title, content, image } = req.body;
console.log('Received blog post:', title);
// Process the blog post data
processBlogPost({ title, content, image });
res.status(200).json({ success: true, message: 'Blog post received' });
});
function processBlogPost({ title, content, image }) {
// Save to database
// Send notifications
// Process image if provided
if (image) {
// Image is WebP base64 encoded, you can save it or process it
console.log('Received image data');
}
}
app.listen(3000, () => {
console.log('Webhook server running on port 3000');
});
Python with Flask
from flask import Flask, request, jsonify
import os
import base64
import json
app = Flask(__name__)
@app.route('/webhook/blog-post', methods=['POST'])
def handle_blog_webhook():
# Verify API key
auth_header = request.headers.get('Authorization')
expected_api_key = f"Bearer {os.getenv('YOUR_API_KEY')}"
if not auth_header or auth_header != expected_api_key:
return jsonify({'error': 'Unauthorized'}), 401
data = request.get_json()
title = data.get('title')
content = data.get('content')
image = data.get('image')
print(f'Received blog post: {title}')
# Process the blog post
process_blog_post(title, content, image)
return jsonify({'success': True, 'message': 'Blog post received'})
def process_blog_post(title, content, image):
# Save to database
# Send notifications
if image:
# Process base64 image
try:
# Decode base64 image
image_data = base64.b64decode(image)
# Save image file
with open(f'images/{title.replace(" ", "_")}.webp', 'wb') as f:
f.write(image_data)
except Exception as e:
print(f'Error processing image: {e}')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
PHP
<?php
// webhook.php
// Get the raw POST data
$json = file_get_contents('php://input');
$data = json_decode($json, true);
// Verify API key
$headers = getallheaders();
$authHeader = isset($headers['Authorization']) ? $headers['Authorization'] : '';
$expectedApiKey = 'Bearer ' . $_ENV['YOUR_API_KEY'];
if ($authHeader !== $expectedApiKey) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
exit;
}
$title = $data['title'] ?? '';
$content = $data['content'] ?? '';
$image = $data['image'] ?? '';
error_log("Received blog post: " . $title);
// Process the blog post
processBlogPost($title, $content, $image);
// Return success response
http_response_code(200);
echo json_encode(['success' => true, 'message' => 'Blog post received']);
function processBlogPost($title, $content, $image) {
// Save to database
// Example: Insert into MySQL
/*
$pdo = new PDO('mysql:host=localhost;dbname=blog', $username, $password);
$stmt = $pdo->prepare('INSERT INTO posts (title, content, created_at) VALUES (?, ?, NOW())');
$stmt->execute([$title, $content]);
*/
// Process image if provided
if (!empty($image)) {
// Decode and save image
$imageData = base64_decode($image);
$filename = 'images/' . str_replace(' ', '_', $title) . '.webp';
file_put_contents($filename, $imageData);
}
}
?>
Java with Spring Boot
@RestController
@RequestMapping("/webhook")
public class WebhookController {
@Value("${your.api.key}")
private String expectedApiKey;
@PostMapping("/blog-post")
public ResponseEntity<Map<String, Object>> handleBlogPost(
@RequestHeader("Authorization") String authHeader,
@RequestBody BlogPostWebhook blogPost) {
// Verify API key
String expectedAuth = "Bearer " + expectedApiKey;
if (!expectedAuth.equals(authHeader)) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("error", "Unauthorized");
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorResponse);
}
System.out.println("Received blog post: " + blogPost.getTitle());
// Process the blog post
processBlogPost(blogPost);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("message", "Blog post received");
return ResponseEntity.ok(response);
}
private void processBlogPost(BlogPostWebhook blogPost) {
// Save to database
// Process image if provided
if (blogPost.getImage() != null && !blogPost.getImage().isEmpty()) {
try {
String imageData = blogPost.getImage();
// Decode base64 image
byte[] decodedImage = Base64.getDecoder().decode(imageData);
// Save image file
String filename = "images/" + blogPost.getTitle().replaceAll(" ", "_") + ".jpg";
Files.write(Paths.get(filename), decodedImage);
} catch (Exception e) {
System.err.println("Error processing image: " + e.getMessage());
}
}
}
}
// BlogPostWebhook.java
public class BlogPostWebhook {
private String title;
private String content;
private String image;
// Getters and setters
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
public String getImage() { return image; }
public void setImage(String image) { this.image = image; }
}
Go
package main
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
)
type BlogPostWebhook struct {
Title string `json:"title"`
Content string `json:"content"`
Image string `json:"image,omitempty"`
}
func main() {
http.HandleFunc("/webhook/blog-post", handleBlogPost)
fmt.Println("Webhook server running on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func handleBlogPost(w http.ResponseWriter, r *http.Request) {
// Verify API key
authHeader := r.Header.Get("Authorization")
expectedApiKey := "Bearer " + os.Getenv("YOUR_API_KEY")
if authHeader != expectedApiKey {
w.WriteHeader(http.StatusUnauthorized)
json.NewEncoder(w).Encode(map[string]string{"error": "Unauthorized"})
return
}
// Parse request body
body, err := ioutil.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
var blogPost BlogPostWebhook
if err := json.Unmarshal(body, &blogPost); err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
fmt.Printf("Received blog post: %s\n", blogPost.Title)
// Process the blog post
processBlogPost(blogPost)
// Return success response
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"success": true,
"message": "Blog post received",
})
}
func processBlogPost(blogPost BlogPostWebhook) {
// Save to database
// Process image if provided
// Decode base64 image
decodedImage, err := base64.StdEncoding.DecodeString(imageData)
if err != nil {
log.Printf("Error decoding image: %v", err)
return
}
// Save image file
filename := fmt.Sprintf("images/%s.jpg", strings.ReplaceAll(blogPost.Title, " ", "_"))
if err := ioutil.WriteFile(filename, decodedImage, 0644); err != nil {
log.Printf("Error saving image: %v", err)
}
}
}
Setting Up Your Webhook
Step 1: Choose Your Implementation
Select one of the above implementations based on your preferred programming language and framework.
Step 2: Deploy Your Webhook Endpoint
Deploy your webhook handler to a publicly accessible server. Popular options include:
- Vercel: Great for Node.js applications
- Heroku: Supports multiple languages
- AWS Lambda: Serverless option
- Digital Ocean: VPS hosting
- Your own server: Self-hosted solution
Step 3: Configure Environment Variables
Set up your API key as an environment variable:
YOUR_API_KEY=your_secret_api_key_here
Step 4: Test Your Endpoint
You can test your webhook endpoint using curl:
curl -X POST https://your-domain.com/webhook/blog-post \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key_here" \
-d '{
"title": "Test Blog Post",
"content": "This is a test blog post content...",
"image": "4AAQSkZJRgABAQEAYABgAAD..."
}'
Step 5: Configure Our Service
In our service settings:
- Enter your Webhook URL (e.g.,
https://your-domain.com/webhook/blog-post
) - Enter your API Key for authentication
- Enable Generate an image for each blog post in Content Settings, if you want an image generated and sent as base64
- Save your settings
Security Best Practices
API Key Security
- Use a strong, randomly generated API key
- Store API keys as environment variables, never in code
- Rotate API keys regularly
- Use different API keys for different environments (development, staging, production)
Endpoint Security
- Always validate the Authorization header
- Use HTTPS for your webhook endpoint
- Implement rate limiting to prevent abuse
- Log webhook requests for monitoring and debugging
Data Validation
- Validate incoming JSON structure
- Sanitize content before storing in database
- Validate image data if processing base64 images
- Implement proper error handling
Handling Images
When image base64 encoding is enabled, images are sent in the following format:
"4AAQSkZJRgABAQEAYABgAAD..."
Processing Base64 Images
- Decode: Convert base64 string to binary data
- Save: Write binary data to file or upload to cloud storage
- Optimize: Consider resizing or compressing images
Troubleshooting
Common Issues
401 Unauthorized
- Check that your API key is correct
- Ensure the Authorization header format is
Bearer YOUR_API_KEY
- Verify your API key environment variable is set
Webhook Not Receiving Data
- Verify your webhook URL is publicly accessible
- Check that your endpoint accepts POST requests
- Ensure your server is running and listening on the correct port
Image Processing Errors
- Increase request body size limits for base64 images
- Handle malformed base64 data gracefully
- Check file system permissions for image saving
Debugging Tips
- Enable detailed logging in your webhook handler
- Test with sample payloads using curl or Postman
- Monitor your server logs for error messages
Your webhook integration is now complete! Our service will automatically send your blog posts to your specified endpoint whenever new content is generated.