API Documentation
Integrate your application with Wonderblogs by implementing two endpoints. Wonderblogs calls your API to fetch brand context before generating content, and pushes the finished article to your webhook when done.
Overview
Wonderblogs is an AI-powered content marketing engine. It generates high-quality blog posts on an automated schedule, using your brand context to stay on-voice and on-topic. The integration works through two HTTP endpoints that you implement:
| Method | Endpoint | Direction | Purpose |
|---|---|---|---|
| GET | targetServiceUrl | Wonderblogs → Your App | Fetch brand context before generating content |
| POST | targetWebhookUrl | Wonderblogs → Your App | Push the generated article to your system |
Both URLs are configured per site in your Settings page (under Content Platform). Wonderblogs sends an Authorization: Bearer header using the Target Authentication Key you configure in the API Keys section.
Authentication
All requests from Wonderblogs include an Authorization: Bearer <key> header when a Target Authentication Key is configured in your site settings. The key is encrypted at rest in the Wonderblogs database and only transmitted via HTTPS.
Authorization: Bearer your-secret-api-keyIf no Target Authentication Key is configured, Wonderblogs sends requests without an Authorization header. We strongly recommend generating a key for production use.
Your endpoint should:
- Extract the token from the
Authorizationheader. - Compare it against your stored secret.
- Return
401 Unauthorizedif the token is missing or invalid.
GET Brand Context Endpoint
Wonderblogs calls your targetServiceUrl with a GET request before each content generation run. Your endpoint must return a JSON object containing your brand identity, tone, instructions, content focus, and recently published articles.
Request
GET https://your-app.example.com/api/wonderblogs
Accept: application/json
Authorization: Bearer your-secret-api-keyResponse Schema
Return a 200 OK with Content-Type: application/json:
{
"brand_identity": "string (required, max 5,000 chars)",
"tone_of_voice": "string (required, max 5,000 chars)",
"instructions": "string (required, max 10,000 chars)",
"content_focus": "string | null (max 5,000 chars)",
"recent_articles": [
{
"title": "string (required, max 500 chars)",
"summary": "string (optional, max 2,000 chars)"
}
]
}Example Response
{
"brand_identity": "Acme Corp is a B2B developer tools company helping engineering teams ship faster. We're known for blunt, no-hype technical communication grounded in real benchmarks.",
"tone_of_voice": "Write like a smart colleague sharing over coffee — informal but precise. Avoid buzzwords. Use contractions. It's okay to be opinionated.",
"instructions": "Always include a practical code example. Target senior developers. Never mention competitor X by name. Keep articles under 2,000 words.",
"content_focus": "Kubernetes cost optimization, FinOps best practices, right-sizing workloads for cloud-native teams",
"recent_articles": [
{
"title": "Why We Moved to Arm64",
"summary": "Migration story covering cost savings and gotchas with AWS Graviton."
},
{
"title": "FinOps Maturity Model Explained"
}
]
}Validation Rules
- All five top-level fields are required. Use
""(empty string) if you have no value;content_focusmay benull. recent_articlesis an array of up to 50 items. Each item must have atitle;summaryis optional but recommended.- No additional properties are allowed on the root object or on article items. Unknown fields will cause validation to fail.
- If
content_focusisnullor empty and no topic override is provided, the run will be skipped.
POST Publish Article Endpoint
When a content generation run completes successfully and auto-publish is enabled, Wonderblogs sends the generated article to your targetWebhookUrl via POST. This endpoint is also used for manual re-pushes from the dashboard.
Request
POST https://your-app.example.com/api/wonderblogs
Content-Type: application/json
Authorization: Bearer your-secret-api-keyRequest Body Schema
{
"slug": "string (max 200 chars)",
"locale": "string (max 10 chars, e.g. 'en', 'de')",
"title": "string (max 500 chars — human-readable post title)",
"description": "string (max 2,000 chars — short summary for readers)",
"content": "string (Markdown content of the generated post)",
"author": "string (optional, max 255 chars — from site settings)",
"tags": ["string (max 20 tags, each max 100 chars)"],
"seo": {
"metaTitle": "string (max 200 chars)",
"metaDescription": "string (max 500 chars)",
"slug": "string (max 200 chars)"
},
"targetFocus": "string (optional — the content focus used for generation)",
"refinedAngle": "string (optional — the unique angle chosen by the AI)",
"coverImageUrl": "string (optional — URL or data URI of the AI-generated cover image)",
"sources": [
{ "url": "string (max 2,000 chars)", "title": "string (max 500 chars)" }
]
}Example Request
{
"slug": "right-sizing-kubernetes-workloads",
"locale": "en",
"title": "Right-Sizing Kubernetes Workloads: Stop Overpaying for Idle Pods",
"description": "Most teams overprovision by 60%. Learn a practical methodology using real kubectl metrics to right-size your workloads and cut cloud costs.",
"content": "## Why Most Teams Overprovision\n\nThe default approach to Kubernetes resource requests is generous...\n\n## Step 1: Measure Actual Usage\n\n```bash\nkubectl top pods --all-namespaces\n```\n\n...",
"author": "Acme Engineering",
"tags": ["kubernetes", "finops", "cost-optimization", "cloud-native"],
"seo": {
"metaTitle": "Right-Sizing Kubernetes Workloads: A Practical Guide",
"metaDescription": "Learn how to measure actual resource usage and right-size your Kubernetes workloads to cut cloud costs by up to 60%.",
"slug": "right-sizing-kubernetes-workloads"
},
"targetFocus": "Kubernetes cost optimization",
"refinedAngle": "Practical right-sizing methodology using real kubectl metrics",
"coverImageUrl": "https://images.example.com/kubernetes-costs.webp",
"sources": [
{ "url": "https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/", "title": "Managing Resources for Containers" },
{ "url": "https://www.cncf.io/blog/2024/03/finops-kubernetes/", "title": "FinOps for Kubernetes Workloads" }
]
}Expected Response
Return any 2xx status code to confirm receipt. Wonderblogs does not inspect the response body. If your endpoint returns a non-2xx status, the post is saved locally with status READY_TO_PUSH and can be re-pushed manually from the dashboard.
Field Reference
Context Response Fields (GET)
| Field | Type | Max Length | Description |
|---|---|---|---|
| brand_identity | string | 5,000 | Prose description of your company — who you are, what you do, what makes you distinctive. Think elevator pitch, not tagline. |
| tone_of_voice | string | 5,000 | Voice personality guidance — how content should sound. Describe style, register, attitude. |
| instructions | string | 10,000 | Directives for the AI: content rules, formatting, topics to emphasize or avoid, audience assumptions. |
| content_focus | string | null | 5,000 | Current thematic priority driving topic selection. If null/empty, the run is skipped unless a topic override is provided. |
| recent_articles | array | 50 items | Recently published articles for uniqueness checks. Most recent first. Each item has a required title (max 500 chars) and optional summary (max 2,000 chars). |
Publish Payload Fields (POST)
| Field | Type | Required | Description |
|---|---|---|---|
| slug | string | Yes | URL-friendly slug (max 200 chars). |
| locale | string | Yes | Locale/language code from site settings (max 10 chars, e.g. "en", "de"). |
| title | string | Yes | Human-readable post title (max 500 chars). |
| description | string | Yes | Short summary/description for readers (max 2,000 chars). |
| content | string | Yes | Full Markdown content of the generated blog post. |
| author | string | No | Author name from site settings (max 255 chars). |
| tags | string[] | Yes | Up to 20 SEO/categorization tags (each max 100 chars). |
| seo.metaTitle | string | Yes | SEO page title (max 200 chars). |
| seo.metaDescription | string | Yes | SEO meta description (max 500 chars). |
| seo.slug | string | Yes | URL-friendly slug (max 200 chars). |
| targetFocus | string | No | The content focus / topic used for generation (max 5,000 chars). |
| refinedAngle | string | No | The unique angle chosen by the AI's uniqueness agent (max 5,000 chars). |
| coverImageUrl | string | No | URL or data URI of the AI-generated cover image. |
| sources | Array<{url, title}> | No | Up to 20 structured sources referenced in the post. Each item has a url (max 2,000 chars) and title (max 500 chars). |
Error Codes
Your endpoints should return standard HTTP status codes. Here is how Wonderblogs interprets them:
| Status | Meaning | Wonderblogs Behavior |
|---|---|---|
| 200–299 | Success | Context accepted / article delivery confirmed. |
| 401 | Unauthorized | Run marked FAILED. Check your API key configuration. |
| 4xx | Client error | Context fetch: run marked FAILED. Publish: post saved as READY_TO_PUSH for manual retry. |
| 5xx | Server error | Same as 4xx. Fix the issue and use the Re-Push button in the dashboard. |
Quick Start
Get up and running in three steps:
- Install the adapter package in your project:
npm install @wonderblogs/target-adapter - Create a route handler using one of the framework adapters (see integration guides below).
- Configure your site in the Wonderblogs dashboard:
- Set Target Service URL to your GET endpoint.
- Set Target Webhook URL to your POST endpoint (can be the same URL if using the adapter).
- Set an API Key shared between Wonderblogs and your endpoint.
@wonderblogs/target-adapter Package
The official adapter package provides Zod schemas, TypeScript types, validation helpers, and ready-made route handlers for popular frameworks. It is the single source of truth for the target API contract.
| Import Path | What It Provides |
|---|---|
| @wonderblogs/target-adapter | Schemas, types, validation helpers, OpenAPI generator |
| @wonderblogs/target-adapter/nextjs | createWonderblogsHandler() — Next.js App Router adapter |
| @wonderblogs/target-adapter/express | createWonderblogsMiddleware() — Express/Connect adapter |
| @wonderblogs/target-adapter/openapi | generateOpenApiSpec() — programmatic OpenAPI 3.0 generation |
Next.js Integration
The Next.js adapter creates both GET and POST route handlers from a single configuration object. Drop it into any App Router route file:
import { createWonderblogsHandler } from "@wonderblogs/target-adapter/nextjs";
import { db } from "@/lib/db";
export const { GET, POST } = createWonderblogsHandler({
apiKey: process.env.WONDERBLOGS_API_KEY!,
getContext: async () => ({
brand_identity: "Acme Corp — developer tools for engineering teams.",
tone_of_voice: "Informal, precise, opinionated. Avoid buzzwords.",
instructions: "Include code examples. Target senior developers.",
content_focus: "API design best practices",
recent_articles: await db.query.posts.findMany({
columns: { title: true, summary: true },
orderBy: (posts, { desc }) => [desc(posts.createdAt)],
limit: 20,
}),
}),
onPublish: async (payload) => {
await db.insert(posts).values({
slug: payload.slug,
locale: payload.locale,
title: payload.title,
description: payload.description,
content: payload.content,
author: payload.author,
tags: payload.tags,
});
},
});The adapter handles authentication, request validation, and error responses automatically. Both endpoints share the same URL — the adapter dispatches based on the HTTP method.
Express Integration
The Express adapter provides Connect-compatible middleware that handles both GET and POST on the mounted path:
import express from "express";
import { createWonderblogsMiddleware } from "@wonderblogs/target-adapter/express";
const app = express();
app.use(express.json());
app.use(
"/api/wonderblogs",
createWonderblogsMiddleware({
apiKey: process.env.WONDERBLOGS_API_KEY!,
getContext: async () => ({
brand_identity: "Your brand description",
tone_of_voice: "Your tone preferences",
instructions: "Your content guidelines",
content_focus: "Your current topic focus",
recent_articles: [],
}),
onPublish: async (payload) => {
console.log("Received article:", payload.title);
// Save to your database
},
})
);
app.listen(3000);Manual Integration
If you use a framework without an official adapter, install the package for types and validation only:
npm install @wonderblogs/target-adapterThen implement the two endpoints yourself, using the exported schemas for validation:
import {
contextResponseSchema,
publishPayloadSchema,
type ContextResponse,
type PublishPayload,
} from "@wonderblogs/target-adapter";
// Validate your GET response before returning
const context: ContextResponse = contextResponseSchema.parse({
brand_identity: "...",
tone_of_voice: "...",
instructions: "...",
content_focus: "...",
recent_articles: [],
});
// Validate incoming POST payload
function handlePublish(body: unknown) {
const payload: PublishPayload = publishPayloadSchema.parse(body);
// Process the article...
}For any language other than TypeScript/JavaScript, refer to the OpenAPI spec below to generate client/server stubs.
Post Generation API
The Post Generation API allows external applications to trigger on-demand blog post generation. Provide a topic and Wonderblogs will run its full AI workflow — from research to writing to SEO — and return the finished post.
Authentication
Uses the same per-site API keys as the Image API. Create a key from Dashboard > Settings > API Keys and include it in the Authorization header.
Generate Post
POST /api/v1/posts/generate
{
"topic": "AI trends transforming healthcare in 2026",
"callback_url": "https://yoursite.com/webhooks/post-ready"
}| Field | Type | Required | Description |
|---|---|---|---|
| topic | string | Yes | Topic or angle for the blog post (3–500 chars). |
| callback_url | string | No | HTTPS URL for webhook delivery on completion. If omitted, poll the run status endpoint. |
Response (202 Accepted)
{
"run_id": "a1b2c3d4-...",
"status": "pending",
"site_id": "a1b2c3d4-...",
"poll_url": "/api/v1/posts/runs/{runId}"
}Poll Run Status
GET /api/v1/posts/runs/{runId}
{
"run_id": "a1b2c3d4-...",
"status": "completed",
"post": {
"title": "AI Trends Transforming Healthcare in 2026",
"slug": "ai-trends-transforming-healthcare-2026",
"content": "## Introduction\n\nArtificial intelligence is...",
"meta_title": "AI Trends in Healthcare 2026 — A Comprehensive Guide",
"meta_description": "Explore how AI is reshaping diagnostics...",
"tags": ["ai", "healthcare", "technology"],
"image_url": "https://..."
},
"created_at": "2026-03-08T12:00:00Z",
"completed_at": "2026-03-08T12:05:30Z"
}Possible status values: pending, running, completed, failed, skipped.
Webhook Callback
If you provide a callback_url, Wonderblogs will POST the result on completion (up to 3 retries with exponential backoff). The payload matches the poll response format.
Example: cURL
curl -X POST https://www.wonderblogs.org/api/v1/posts/generate \
-H "Authorization: Bearer wb_live_a3f2_..." \
-H "Content-Type: application/json" \
-d '{
"topic": "AI trends transforming healthcare in 2026",
"callback_url": "https://yoursite.com/webhooks/post"
}'curl https://www.wonderblogs.org/api/v1/posts/runs/{runId} \
-H "Authorization: Bearer wb_live_a3f2_..."Rate Limits
Post generation requests are rate-limited to 5 requests per minute per API key. Monthly run quotas are plan-based (see Plans & Limits below). Runs triggered via the API count toward the same monthly run limit as dashboard and cron runs.
Image Generation API
The Image Generation API allows external applications to generate AI-powered cover images for blog posts. Send a blog post title and content, and Wonderblogs will generate a brand-aligned image using its 5-stage image pipeline (distill, brief, synthesize, generate, evaluate).
Authentication
Create a per-site API key from Dashboard > Settings > API Keys. Include it in the Authorization header:
Authorization: Bearer wb_live_a3f2_xxxxxxxxxxxxxxxxxxxxxxxxEach API key is scoped to a single site. Keys are shown only once on creation and stored as SHA-256 hashes. Revoke keys from the settings page at any time.
Generate Image
POST /api/v1/images/generate
{
"title": "How AI is Transforming Healthcare",
"content": "Full blog post content or summary...",
"callback_url": "https://yoursite.com/webhooks/image-ready"
}| Field | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | Blog post title (max 1,000 chars). |
| content | string | Yes | Blog post content or summary (max 50,000 chars). |
| callback_url | string | No | HTTPS URL for webhook delivery on completion. If omitted, poll the job status endpoint. |
Response (202 Accepted)
{
"job_id": "a1b2c3d4-...",
"status": "pending",
"site_id": "a1b2c3d4-...",
"poll_url": "/api/v1/images/jobs/{jobId}"
}Poll Job Status
GET /api/v1/images/jobs/{jobId}
{
"job_id": "a1b2c3d4-...",
"status": "completed",
"image_url": "https://...",
"prompt": "A serene healthcare scene...",
"brief": { ... },
"evaluation": { ... },
"created_at": "2026-03-08T12:00:00Z",
"completed_at": "2026-03-08T12:01:30Z"
}Possible status values: pending, processing, completed, failed.
Webhook Callback
If you provide a callback_url, Wonderblogs will POST the result on completion (up to 3 retries with exponential backoff). The payload is HMAC-signed with the same mechanism as article publishing.
{
"event": "image.completed",
"job_id": "a1b2c3d4-...",
"site_id": "...",
"status": "completed",
"image_url": "https://...",
"prompt": "...",
"brief": { ... },
"evaluation": { ... },
"created_at": "2026-03-08T12:00:00Z",
"completed_at": "2026-03-08T12:01:30Z"
}Example: cURL
curl -X POST https://www.wonderblogs.org/api/v1/images/generate \
-H "Authorization: Bearer wb_live_a3f2_..." \
-H "Content-Type: application/json" \
-d '{
"title": "How AI is Transforming Healthcare",
"content": "Artificial intelligence is revolutionizing...",
"callback_url": "https://yoursite.com/webhooks/image"
}'curl https://www.wonderblogs.org/api/v1/images/jobs/{jobId} \
-H "Authorization: Bearer wb_live_a3f2_..."Rate Limits
API requests are rate-limited to 10 requests per minute per API key. Monthly quotas are plan-based (see Plans & Limits below).
Plans & Limits
Wonderblogs enforces plan-based limits on content generation runs and image generation requests per month:
| Plan | Max Runs / Month | API Images / Month | Dashboard Images / Month | Price |
|---|---|---|---|---|
| Free | 5 | 10 | 20 | $0 |
| Pro | 100 | 200 | 500 | $29/month |
Runs are per-account (shared across all sites). Image quotas are per-site. A "run" is one complete execution of the AI content generation workflow, producing one blog post.
Workflow Overview
Each content generation run follows a 7-step AI pipeline. Understanding the workflow helps you provide better context data:
| Step | Name | What Happens |
|---|---|---|
| 0 | Context Sync | Fetches brand context from your GET endpoint and loads local post history. |
| 1 | Uniqueness | Refines a unique angle from content focus + your recent articles to avoid duplicates. |
| 2 | Deep Research | Web search + summarization into a reference document (can be disabled per site). |
| 3–4 | Writer / Evaluator Loop | Generates a draft, evaluates quality, and loops up to maxAttempts times until the evaluator approves. |
| 5 | SEO & Tags | Generates metaTitle, metaDescription, slug, and categorization tags. |
| 6 | Save & Publish | Saves the post to the Wonderblogs database and pushes to your POST webhook. |
The quality of your brand_identity, tone_of_voice, and instructions directly impacts the quality of generated content. The more specific and detailed your context, the better the results.
OpenAPI Specification
The full OpenAPI 3.0 specification is available in the @wonderblogs/target-adapter package. You can use it to generate client/server stubs for any language, import into Swagger UI, or use with API testing tools like Postman.
# Via npm (after installing the adapter)
npx wonderblogs-openapi > openapi.json
# Or import programmatically
import { generateOpenApiSpec } from "@wonderblogs/target-adapter/openapi";
const spec = generateOpenApiSpec();The spec is also committed at packages/target-adapter/openapi.json in the Wonderblogs repository for reference.
Support
If you need help with your integration or encounter issues, reach out to us:
- Email: support@wonderblogs.org
- Help Center: wonderblogs.org/help
For detailed information about data handling and security, see our Privacy Policy and Terms of Service.