Introduction
Welcome to WP n8n Connector - the most powerful WordPress plugin for automating content publishing via API. This documentation will help you get up and running in minutes.
WP n8n Connector is a WordPress plugin that exposes a secure REST API endpoint, allowing you to create posts programmatically from external tools like n8n, Zapier, Make.com, or custom applications.
Key Features
SHA-256 hashed keys with expiration and IP whitelisting
Optimized for high-throughput API calls
Track every API request with detailed audit logs
Built-in protection against abuse
Installation
Install WP n8n Connector in just a few simple steps.
Method 1: Upload via WordPress Admin
- Download the plugin ZIP file from your Lemon Squeezy account
- Go to
WordPress Admin → Plugins → Add New - Click "Upload Plugin" button
- Choose the ZIP file and click "Install Now"
- Click "Activate Plugin"
Method 2: FTP Upload
- Extract the plugin ZIP file
- Upload the folder to
/wp-content/plugins/ - Go to
WordPress Admin → Plugins - Activate WP n8n Connector
You'll see a new "n8n API" menu in your WordPress admin sidebar.
Quick Start
Get your first post created via API in under 2 minutes.
Step 1: Create an API Key
Navigate to WordPress Admin → n8n API and create your first API key:
1. Click "Create New API Key"
2. Enter a name (e.g., "My n8n Workflow")
3. Set request limit (e.g., 1000)
4. Click "Create Key"
5. ⚠️ Copy and save the key - it won't be shown again!
Step 2: Make Your First API Call
Use this simple cURL command to create your first post:
curl -X POST https://yoursite.com/wp-json/n8n/v1/publish \
-H "Content-Type: application/json" \
-H "X-API-Key: n8n_your_api_key_here" \
-d '{
"title": "My First API Post",
"content": "<p>Hello from the API!</p>",
"status": "draft"
}'
Step 3: Check the Response
{
"success": true,
"post_id": 123,
"post_url": "https://yoursite.com/?p=123",
"edit_url": "https://yoursite.com/wp-admin/post.php?post=123&action=edit",
"status": "draft"
}
You've just created your first post via API. Check your WordPress drafts to see it!
Requirements
| Requirement | Version |
|---|---|
| WordPress | 5.0 or higher |
| PHP | 7.4 or higher |
| MySQL | 5.6 or higher |
| HTTPS | Required (SSL certificate) |
| REST API | Must be enabled |
Creating API Keys
API keys are used to authenticate requests to your WordPress site. Each key can have its own limits, expiration, and IP restrictions.
Creating a New Key
- Go to
WordPress Admin → n8n API - Fill in the "Create New API Key" form:
| Field | Description | Required |
|---|---|---|
| Client Name | Identifier for this key (max 100 chars) | ✅ Yes |
| Request Limit | Total allowed requests (1 - 1,000,000) | ✅ Yes |
| Expires In | Days until expiration (0 = never) | ❌ No |
| IP Whitelist | Comma-separated IPs or CIDR ranges | ❌ No |
Your full API key is only displayed once at creation. Store it securely - if lost, you'll need to create a new one.
Managing API Keys
Viewing Keys
All your keys are listed in the dashboard with the following info:
- Key Prefix - First 12 characters for identification
- Usage - Number of requests made
- Limit - Maximum allowed requests
- Status - Active, Revoked, or Expired
- Last Used - When the key was last used
Revoking a Key
To disable a key without deleting it:
- Find the key in the dashboard
- Click "Revoke"
- Confirm the action
IP Whitelist
Restrict API access to specific IP addresses or networks for enhanced security.
Single IP Addresses
192.168.1.100, 203.0.113.50
CIDR Ranges
10.0.0.0/24, 192.168.1.0/16
Mixed Format
192.168.1.100, 10.0.0.0/24, 203.0.113.50
Key Expiration
Set keys to automatically expire after a specified number of days.
| Days | Use Case |
|---|---|
| 0 | Never expires (permanent keys) |
| 7 | Short-term testing |
| 30 | Monthly projects |
| 90 | Recommended rotation period |
| 365 | Annual contracts |
Authentication
All API requests must be authenticated using your API key in the request header.
Header Format
X-API-Key: n8n_your_api_key_here
Example Request
curl -X POST https://yoursite.com/wp-json/n8n/v1/publish \
-H "X-API-Key: n8n_abc123..." \
-H "Content-Type: application/json"
- Never share your API key publicly
- Never commit keys to version control
- Use environment variables in production
- Always use HTTPS when sending keys
Endpoints
Base URL: https://yoursite.com/wp-json/n8n/v1
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /publish |
Create a new post | ✅ |
| GET | /status |
Check API status | ❌ |
Create Post
Creates a new WordPress post with the provided data.
/wp-json/n8n/v1/publish
Request Headers
| Header | Value | Required |
|---|---|---|
X-API-Key |
Your API key | ✅ |
Content-Type |
application/json | ✅ |
Request Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
title |
string | ✅ | Post title (max 200 chars) |
content |
string | ✅ | Post content (HTML allowed, max 500KB) |
status |
string | ❌ | draft, publish, pending, private |
excerpt |
string | ❌ | Short description |
category |
string | ❌ | Category name (created if doesn't exist) |
tags |
string | ❌ | Comma-separated tags |
Example Request
{
"title": "How to Use Our API",
"content": "<p>This is the post content with <strong>HTML</strong></p>",
"status": "publish",
"excerpt": "A quick guide to our API",
"category": "Tutorials",
"tags": "api, tutorial, wordpress"
}
Success Response (200)
{
"success": true,
"post_id": 456,
"post_url": "https://yoursite.com/how-to-use-our-api/",
"edit_url": "https://yoursite.com/wp-admin/post.php?post=456&action=edit",
"status": "publish"
}
Error Response (400)
{
"code": "invalid",
"message": "Missing title or content",
"data": {
"status": 400
}
}
Status Check
Check if the API is operational. No authentication required.
/wp-json/n8n/v1/status
Example Request
curl https://yoursite.com/wp-json/n8n/v1/status
Response
{
"status": "ok",
"version": "5.0"
}
Response Codes
Our API uses standard HTTP response codes to indicate the success or failure of requests.
| Code | Meaning | Description |
|---|---|---|
| 200 | OK | Request was successful |
| 400 | Bad Request | Missing or invalid parameters |
| 401 | Unauthorized | API key is missing |
| 403 | Forbidden | Invalid/revoked/expired key, IP blocked, or HTTPS required |
| 413 | Payload Too Large | Content exceeds size limit |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Server Error | Something went wrong on our end |
Rate Limits
To ensure fair usage and prevent abuse, we enforce the following rate limits:
- Per API Key: Based on your configured limit
- Per IP Address: 60 requests per minute
Handling Rate Limits
When you exceed a rate limit, you'll receive a 429 response:
{
"code": "rate_limit",
"message": "Too many requests from your IP",
"data": {
"status": 429
}
}
Best Practices
- Implement exponential backoff for retries
- Cache responses when possible
- Monitor your usage in the admin dashboard
- Upgrade your plan if you need higher limits
cURL Example
curl -X POST https://yoursite.com/wp-json/n8n/v1/publish \
-H "Content-Type: application/json" \
-H "X-API-Key: n8n_your_api_key_here" \
-d '{
"title": "My New Post",
"content": "<p>Hello World!</p>",
"status": "publish",
"category": "News",
"tags": "tag1, tag2"
}'
JavaScript / Node.js
Using Fetch API
const createPost = async (postData) => {
try {
const response = await fetch('https://yoursite.com/wp-json/n8n/v1/publish', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.N8N_API_KEY
},
body: JSON.stringify(postData)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Post created:', data);
return data;
} catch (error) {
console.error('Error creating post:', error);
throw error;
}
};
// Usage
createPost({
title: 'Automated Post',
content: '<p>Content here</p>',
status: 'draft',
tags: 'automation, api'
});
Using Axios
const axios = require('axios');
const api = axios.create({
baseURL: 'https://yoursite.com/wp-json/n8n/v1',
headers: {
'X-API-Key': process.env.N8N_API_KEY,
'Content-Type': 'application/json'
}
});
async function publishPost(postData) {
try {
const { data } = await api.post('/publish', postData);
return data;
} catch (error) {
console.error(error.response?.data || error.message);
}
}
publishPost({
title: 'New Post via Axios',
content: '<p>Created with Axios</p>',
status: 'publish'
});
Python
import requests
import os
def create_post(title, content, status='draft', **kwargs):
url = 'https://yoursite.com/wp-json/n8n/v1/publish'
headers = {
'Content-Type': 'application/json',
'X-API-Key': os.getenv('N8N_API_KEY')
}
payload = {
'title': title,
'content': content,
'status': status,
**kwargs
}
try:
response = requests.post(url, json=payload, headers=headers, timeout=30)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
print(f'HTTP Error: {e}')
print(f'Response: {response.text}')
raise
except requests.exceptions.RequestException as e:
print(f'Request failed: {e}')
raise
# Usage
if __name__ == '__main__':
result = create_post(
title='Python Automated Post',
content='<p>Created via Python</p>',
status='publish',
category='Tech',
tags='python, api, automation'
)
print(f"Post created: {result['post_url']}")
PHP
<?php
function createPost($data) {
$url = 'https://yoursite.com/wp-json/n8n/v1/publish';
$apiKey = getenv('N8N_API_KEY');
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: ' . $apiKey
],
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
throw new Exception('cURL Error: ' . curl_error($ch));
}
curl_close($ch);
$result = json_decode($response, true);
if ($httpCode !== 200) {
throw new Exception('API Error: ' . ($result['message'] ?? 'Unknown error'));
}
return $result;
}
// Usage
try {
$post = createPost([
'title' => 'PHP Automated Post',
'content' => '<p>Created via PHP</p>',
'status' => 'publish',
'tags' => 'php, api'
]);
echo "Post created: " . $post['post_url'] . "\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
n8n Workflow Setup
Complete guide to setting up n8n workflow with our plugin.
Step 1: Add HTTP Request Node
- Open your n8n workflow
- Click "+" to add a new node
- Search for "HTTP Request"
- Select it
Step 2: Configure the Node
| Field | Value |
|---|---|
| Method | POST |
| URL | https://yoursite.com/wp-json/n8n/v1/publish |
| Authentication | Generic Credential Type → Header Auth |
| Header Name | X-API-Key |
| Header Value | Your API key |
| Body Content Type | JSON |
Step 3: Body JSON
{
"title": "{{ $json.title }}",
"content": "{{ $json.content }}",
"status": "draft",
"tags": "{{ $json.tags }}"
}
Use n8n expressions like {{ $json.fieldname }} to dynamically insert data from previous nodes.
Security Best Practices
API Key Management
- ✅ Store keys in environment variables, never in code
- ✅ Use different keys for different environments (dev, staging, prod)
- ✅ Rotate keys every 90 days
- ✅ Revoke unused keys immediately
- ✅ Use IP whitelisting when possible
- ✅ Set reasonable request limits
- ❌ Never commit keys to Git
- ❌ Never share keys via email or chat
- ❌ Never use the same key across multiple services
Network Security
- ✅ Always use HTTPS (required)
- ✅ Keep SSL certificates up to date
- ✅ Use a Web Application Firewall (WAF)
- ✅ Monitor logs regularly
Webhook Signatures
When using webhooks with our plugin, you can verify request authenticity using HMAC-SHA256 signatures.
Verifying Signatures (Node.js)
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
// Usage
const isValid = verifyWebhookSignature(
req.body,
req.headers['x-webhook-signature'],
process.env.WEBHOOK_SECRET
);
HTTPS Requirements
All API requests must be made over HTTPS. HTTP requests will be rejected.
If your site doesn't have SSL, get a free certificate from Let's Encrypt or contact your hosting provider.
Common Errors
🚫 "API key required"
Cause: The X-API-Key header is missing.
Solution: Add the header to your request.
🚫 "Invalid API key"
Cause: The key is wrong, doesn't exist, or has been revoked.
Solution: Check the key spelling and status in your dashboard.
🚫 "HTTPS connection required"
Cause: You're using HTTP instead of HTTPS.
Solution: Change http:// to https:// in your URL.
🚫 "Your IP is not authorized"
Cause: Your IP is not in the whitelist.
Solution: Add your IP in the key settings or remove the whitelist.
🚫 "API limit reached"
Cause: You've exceeded your request limit.
Solution: Increase the limit or create a new key.
🚫 "Too many requests from your IP"
Cause: Exceeded 60 requests/minute from your IP.
Solution: Slow down your requests or implement retry logic.
Debugging
Check API Logs
View detailed logs in WordPress Admin → n8n API → Logs:
- Timestamp of each request
- Key used
- IP address
- Status code
- Error messages
Test with Status Endpoint
First, verify the API is accessible:
curl https://yoursite.com/wp-json/n8n/v1/status
Enable Verbose Mode
curl -v -X POST https://yoursite.com/wp-json/n8n/v1/publish \
-H "X-API-Key: your_key" \
-H "Content-Type: application/json" \
-d '{"title":"Test","content":"Test"}'
Get Support
- Your WordPress version
- Plugin version
- The error message
- Relevant log entries
- Steps to reproduce the issue