Documentation
Everything you need to integrate TrafficNinja into your stack — REST API reference and WordPress plugin guide.
API Integration
The TrafficNinja REST API lets you programmatically manage websites, categories, themes, and sync generated articles to your platform. All endpoints are prefixed with /api/v1/.
Base URL
https://trafficninja.io/api/v1Authentication
TrafficNinja uses Bearer token authentication. Your API key is generated automatically during onboarding. Find it in your dashboard under Settings → Integration Settings.
Copy your API key from Dashboard → Settings → Integration Settings and pass it as a Bearer token in every request.
Use your API key in every request:
curl https://trafficninja.io/api/v1/websites \
-H "Authorization: Bearer {your-api-key}" \
-H "Accept: application/json"Core Endpoints
Websites
/api/v1/websitesList all websites Auth/api/v1/websitesCreate a website Auth/api/v1/websites/{id}Get a website Auth/api/v1/websites/{id}Update a website Auth/api/v1/websites/{id}Delete a website AuthPosts
/api/v1/postsList posts Auth/api/v1/posts/{id}Get post AuthOptional query filters: website_id (integer), statuses[] (published|draft|archived|deleted), title (partial match), date_from / date_to (YYYY-MM-DD)
GET /api/v1/posts?website_id=1&statuses[]=published&title=seo&date_from=2026-01-01&date_to=2026-04-30
Authorization: Bearer {your-api-key}Example: Create a website
POST /api/v1/websites
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "My Blog",
"url": "https://myblog.com",
"industry": "technology",
"country": "US",
"language": "en"
}{
"id": 42,
"name": "My Blog",
"url": "https://myblog.com",
"status": "active",
"created_at": "2026-04-10T12:00:00Z"
}WordPress Plugin Endpoints
These endpoints are consumed by the WordPress plugin using a per-site WordPress API Key (generated in the dashboard). Pass it via the X-API-Key header:
X-API-Key: {your-wordpress-api-key}/api/v1/wordpress/connection-testVerify API key + connectivity/api/v1/wordpress/content-queueFetch articles ready to publish/api/v1/wordpress/content/{id}Get full article contentContent queue item shape
{
"id": 99,
"title": "10 Ways to Boost Local SEO",
"slug": "10-ways-boost-local-seo",
"content": "<h2>...</h2><p>...</p>",
"meta_description": "Learn how to dominate local search...",
"focus_keyword": "local SEO tips",
"json_ld": "{"@context":"https://schema.org",...}",
"locale": "en",
"categories": ["SEO", "Marketing"],
"scheduled_for": "2026-04-11T08:00:00Z"
}Outbound Webhooks
TrafficNinja can POST a signed JSON payload to a URL of your choice whenever a post changes state. Configure one webhook URL per website — no polling required.
Configuring a Webhook
Set a webhook URL via the API or from the website settings in your dashboard. When you save a URL for the first time a signing secret is automatically generated and returned. Store it securely — you will need it to verify incoming requests.
/api/v1/websites/{id}/settings/webhookSet or clear webhook URL Auth/api/v1/websites/{id}/settings/webhook/regenerate-secretRotate signing secret AuthPUT /api/v1/websites/42/settings/webhook
Authorization: Bearer {your-api-key}
Content-Type: application/json
{ "webhook_url": "https://yoursite.com/hooks/trafficninja" }
→ 200 OK
{
"data": {
"webhook_url": "https://yoursite.com/hooks/trafficninja",
"webhook_secret": "abc123...64chars",
"has_webhook": true
}
}Events
post.publishedA post status changed to published (auto-publish or manual).post.archivedA post status changed to archived.post.content_editedThe title or body of a published, draft, or archived post was edited.Payload Shape
Every delivery is an HTTP POST with Content-Type: application/json. The post object mirrors the GET /api/v1/posts/{id} response.
{
"event": "post.published",
"timestamp": "2026-04-18T10:30:00Z",
"website_id": 42,
"post": {
"id": 99,
"title": "10 Ways to Boost Local SEO",
"slug": "10-ways-boost-local-seo",
"status": "published",
"language": "en-US",
"meta_description": "Learn how to dominate local search...",
"seo_score": 94,
"word_count": 2300,
"published_at": "2026-04-18T10:29:58Z",
...
}
}Verifying Signatures
Each request includes an X-Webhook-Signature header containing sha256= followed by an HMAC-SHA256 hex digest of the raw request body, signed with your webhook secret. Always verify this before processing the payload.
// Node.js verification example
const crypto = require('crypto');
function verifySignature(rawBody, secret, signatureHeader) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody) // use the raw request body bytes
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}// PHP verification example
function verifySignature(string $rawBody, string $secret, string $signatureHeader): bool {
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
return hash_equals($expected, $signatureHeader);
}Delivery & Retries
Error Handling
All errors return JSON with a consistent shape:
{
"message": "The given data was invalid.",
"errors": {
"email": ["The email field is required."]
}
}400Bad Request — validation failed401Unauthorized — missing or invalid token403Forbidden — insufficient permissions404Not Found — resource does not exist422Unprocessable Entity — business logic error429Too Many Requests — rate limited500Server Error — try again later