Wonderblogs
FeaturesHow It WorksPricingBlogAPI DocsHelp
Log InStart Free
Wonderblogs

AI Content Marketing Engine. Research, write, and publish blog posts on autopilot.

Product

  • Features
  • Pricing
  • Blog
  • API Docs
  • Help Center

Legal

  • Terms of Service
  • Privacy Policy
  • Imprint

Company

  • SKAJ Ventures GmbH
  • support@wonderblogs.org

© 2026 SKAJ Ventures GmbH. All rights reserved.

TermsPrivacyImprint

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.

On this page

  • Overview
  • Authentication
  • GET: Brand Context
  • POST: Publish Article
  • Field Reference
  • Error Codes
  • Quick Start
  • Adapter Package
  • Next.js Integration
  • Express Integration
  • Manual Integration
  • Post Generation API
  • Post Rewrite API
  • Post Translation API
  • Image Generation API
  • Image API Authentication
  • Plans & Limits
  • Workflow Overview
  • OpenAPI Spec
  • Support

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:

MethodEndpointDirectionPurpose
GETtargetServiceUrlWonderblogs → Your AppFetch brand context before generating content
POSTtargetWebhookUrlWonderblogs → Your AppPush 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.

Integration Lifecycle

Wonderblogs→GETyour-app/api/wonderblogsfetch brand context
Your App←200{ brand_identity, tone_of_voice, instructions, ... }
  AI pipeline: research → write → evaluate → SEO → image
Wonderblogs→POSTyour-app/api/wonderblogspush article
Your App←200article accepted

v1 API Async Flow

When using the Wonderblogs v1 API to trigger generation from your systems, the flow is asynchronous:

Your App→POST/api/v1/posts/generatetrigger run
Wonderblogs←202{ run_id, poll_url }
Your App→GET/api/v1/posts/runs/{runId}poll status
Wonderblogs←200{ status: "completed", post: { ... } }
  Or receive a callback webhook if callback_url was provided

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.

Request header
Authorization: Bearer your-secret-api-key

If 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:

  1. Extract the token from the Authorization header.
  2. Compare it against your stored secret.
  3. Return 401 Unauthorized if 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-key

Response Schema

Return a 200 OK with Content-Type: application/json:

Response body
{
  "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)"
    }
  ],
  "visual_identity": {
    "color_palette":          ["string (max 10 items)"],
    "visual_style":           "string (max 100 chars)",
    "image_mood":             ["string (max 10 items)"],
    "banned_visual_elements": ["string (max 20 items)"],
    "reference_description":  "string (max 2,000 chars)",
    "image_output": {
      "aspect_ratio":       "string (optional)",
      "quality":            "string (optional)",
      "output_format":      "string (optional)",
      "compression":        "number (optional, 0-100)",
      "max_file_size_bytes": "number (optional)",
      "background":         "string (optional)"
    }
  }
}

Example Response

200 OK (application/json)
{
  "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"
    }
  ],
  "visual_identity": {
    "color_palette": ["#1A73E8", "#2C2116"],
    "visual_style": "flat-illustration",
    "image_mood": ["Professional", "Optimistic"],
    "banned_visual_elements": ["stock photos", "generic icons"],
    "reference_description": "Clean, modern tech aesthetic with geometric shapes"
  }
}

Validation Rules

  • All five top-level fields are required. Use "" (empty string) if you have no value; content_focus may be null.
  • recent_articles is an array of up to 50 items. Each item must have a title; summary is optional but recommended.
  • visual_identity is optional. When omitted, Wonderblogs uses the site's stored visual identity settings.
  • No additional properties are allowed on the root object or on article items. Unknown fields will cause validation to fail.
  • If content_focus is null or 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-key

Request Body Schema

Request body
{
  "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, public URL or relative Wonderblogs API path for the cover image)",
  "sources": [
    { "url": "string (max 2,000 chars)", "title": "string (max 500 chars)" }
  ]
}

Example Request

POST (application/json)
{
  "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)

FieldTypeMax LengthDescription
brand_identitystring5,000Prose description of your company: who you are, what you do, what makes you distinctive. Think elevator pitch, not tagline.
tone_of_voicestring5,000Voice personality guidance: how content should sound. Describe style, register, attitude.
instructionsstring10,000Directives for the AI: content rules, formatting, topics to emphasize or avoid, audience assumptions.
content_focusstring | null5,000Current thematic priority driving topic selection. If null/empty, the run is skipped unless a topic override is provided.
recent_articlesarray50 itemsRecently published articles for uniqueness checks. Most recent first. Each item has a required title (max 500 chars) and optional summary (max 2,000 chars).
visual_identityobjectn/aOptional visual identity preferences for AI-generated cover images. When omitted, Wonderblogs uses the site's stored visual identity.
visual_identity.color_palettestring[]10 itemsBrand colors as hex codes or names, e.g. ["#1A73E8", "navy"].
visual_identity.visual_stylestring100Preferred image style: flat-illustration, 3d-render, photorealistic, watercolor, line-art, isometric, abstract, collage, minimalist, retro.
visual_identity.image_moodstring[]10 itemsDesired emotional qualities, e.g. ["Professional", "Optimistic"].
visual_identity.banned_visual_elementsstring[]20 itemsVisual elements to avoid in generated images.
visual_identity.reference_descriptionstring2,000Free-text description of the ideal visual direction.
visual_identity.image_outputobjectn/aOptional technical output settings for generated images.
visual_identity.image_output.aspect_ratiostring10Desired aspect ratio: 16:9, 3:2, 4:3, 1:1, 4:5, 3:4, 2:3, 9:16.
visual_identity.image_output.qualitystring10Generation quality: low, medium, high.
visual_identity.image_output.output_formatstring10Output format: webp, png, jpeg.
visual_identity.image_output.compressionnumber0–100Compression quality for lossy formats (webp/jpeg).
visual_identity.image_output.max_file_size_bytesnumber10,485,760Maximum file size in bytes. 0 = no limit.
visual_identity.image_output.backgroundstring20Background mode: opaque, transparent, auto.

Publish Payload Fields (POST)

FieldTypeRequiredDescription
slugstringYesURL-friendly slug (max 200 chars).
localestringYesLocale/language code from site settings (max 10 chars, e.g. "en", "de").
titlestringYesHuman-readable post title (max 500 chars).
descriptionstringYesShort summary/description for readers (max 2,000 chars).
contentstringYesFull Markdown content of the generated blog post.
authorstringNoAuthor name from site settings (max 255 chars).
tagsstring[]YesUp to 20 SEO/categorization tags (each max 100 chars).
seo.metaTitlestringYesSEO page title (max 200 chars).
seo.metaDescriptionstringYesSEO meta description (max 500 chars).
seo.slugstringYesURL-friendly slug (max 200 chars).
targetFocusstringNoThe content focus / topic used for generation (max 5,000 chars).
refinedAnglestringNoThe unique angle chosen by the AI's uniqueness agent (max 5,000 chars).
coverImageUrlstringNoPublic URL or relative Wonderblogs API path for the AI-generated cover image. Relative paths (e.g. /api/v1/images/download/post/{postId}) require Bearer token authentication to download.
sourcesArray<{url, title}>NoUp to 20 structured sources referenced in the post. Each item has a url (max 2,000 chars) and title (max 500 chars).

Error Codes

Target API (your endpoints)

Your endpoints should return standard HTTP status codes. Here is how Wonderblogs interprets them:

StatusMeaningWonderblogs Behavior
200–299SuccessContext accepted / article delivery confirmed.
401UnauthorizedRun marked FAILED. Check your API key configuration.
4xxClient errorContext fetch: run marked FAILED. Publish: post saved as READY_TO_PUSH for manual retry.
5xxServer errorSame as 4xx. Fix the issue and use the Re-Push button in the dashboard.

Wonderblogs v1 API (error responses)

All error responses from the Wonderblogs v1 API use the format { "error": "..." }. Validation errors may include a details array with Zod issue objects.

StatusWhenExample Response Body
400Invalid JSON, validation error, non-HTTPS callback{ "error": "Invalid request body", "details": [...] }
401Missing or invalid/revoked/expired API key{ "error": "Invalid or expired API key" }
404Run/job not found or not owned by this key's site{ "error": "Run not found" }
429Per-minute rate limit or monthly plan quota{ "error": "Rate limit exceeded. Max 5 requests per minute." }
500Unhandled server error{ "error": "Internal server error" }

Quick Start

Get up and running in three steps:

  1. Install the adapter package in your project:
    npm install @wonderblogs/target-adapter
  2. Create a route handler using one of the framework adapters (see integration guides below).
  3. 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 PathWhat It Provides
@wonderblogs/target-adapterSchemas, types, validation helpers, OpenAPI generator
@wonderblogs/target-adapter/nextjscreateWonderblogsHandler(), Next.js App Router adapter
@wonderblogs/target-adapter/expresscreateWonderblogsMiddleware(), Express/Connect adapter
@wonderblogs/target-adapter/openapigenerateOpenApiSpec(), 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:

app/api/wonderblogs/route.ts
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:

server.ts
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-adapter

Then implement the two endpoints yourself, using the exported schemas for validation:

Validation example
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 (research, writing, and 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

Request body
{
  "topic": "AI trends transforming healthcare in 2026",
  "language": "de",
  "callback_url": "https://yoursite.com/webhooks/post-ready"
}
FieldTypeRequiredDescription
topicstringYesTopic or angle for the blog post (3–500 chars).
languagestringNoOverride the output language for this run. If omitted, uses the primary language from the site's brand context. One of: en, de, fr, es, it, pt, nl.
callback_urlstringNoHTTPS URL for webhook delivery on completion. If omitted, poll the run status endpoint.

Response (202 Accepted)

Response body
{
  "run_id": "a1b2c3d4-...",
  "status": "pending",
  "poll_url": "/api/v1/posts/runs/{runId}"
}

Poll Run Status

GET /api/v1/posts/runs/{runId}

Response (completed)
{
  "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 Complete 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 when the run finishes. Delivery uses up to 3 retries with exponential backoff (1s, 2s, 4s), 30-second timeout per attempt. 4xx responses stop retries immediately. When the site has a Target API Key configured, callbacks include X-Wonderblogs-Signature and X-Wonderblogs-Timestamp HMAC signature headers.

Callback payload: run.completed
{
  "event": "run.completed",
  "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",
    "meta_description": "Explore how AI is reshaping diagnostics...",
    "tags": ["ai", "healthcare", "technology"],
    "image_url": "https://..."
  }
}
Callback payload: run.failed
{
  "event": "run.failed",
  "run_id": "a1b2c3d4-...",
  "status": "failed",
  "error": "Draft failed evaluation after 3 attempts"
}
Callback payload: run.skipped
{
  "event": "run.skipped",
  "run_id": "a1b2c3d4-...",
  "status": "skipped",
  "error": "No content focus available"
}

Example: cURL

Generate a post
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"
  }'
Poll for status
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 blog post quotas are plan-based (see Plans & Limits below). Generations triggered via the API count toward the same monthly blog post limit as dashboard and cron activity.

Post Rewrite API

The Post Rewrite API allows external applications to submit existing blog post content for rewriting. Wonderblogs rewrites the content using the site's brand context and writing instructions, then returns the rewritten post. Image generation is not performed for rewrites.

Rewrite Post

POST /api/v1/posts/rewrite

Request body
{
  "existing_content": "# My Old Blog Post\n\nThe full markdown content...",
  "topic": "Optional topic override",
  "language": "fr",
  "existing_slug": "my-old-blog-post",
  "external_id": "your-internal-id-123",
  "research": false,
  "callback_url": "https://yoursite.com/webhooks/post-ready"
}
FieldTypeRequiredDescription
existing_contentstringYesFull markdown content to rewrite (100–30,000 chars). HTML is stripped automatically.
topicstringNoTopic override (3–500 chars). If omitted, extracted from content focus.
languagestringNoOverride the output language for this run. If omitted, uses the primary language from the site's brand context. One of: en, de, fr, es, it, pt, nl.
existing_slugstringNoPreserve this slug in the rewritten post (max 200 chars).
external_idstringNoYour internal ID for matching updates (max 500 chars). Echoed in the publish payload.
researchbooleanNoWhether to run fresh web research (default: false).
callback_urlstringNoHTTPS URL for webhook delivery on completion.

Response (202 Accepted)

Same response format as /posts/generate. Use the same /api/v1/posts/runs/{runId} endpoint to poll for status.

Response body
{
  "run_id": "a1b2c3d4-...",
  "status": "pending",
  "poll_url": "/api/v1/posts/runs/{runId}"
}

Rewrite Pipeline

Rewrites follow a reduced pipeline compared to new post generation:

  • Context Sync: same brand context and writing instructions
  • Uniqueness: skipped (topic defined by existing content)
  • Research: optional (only when research: true)
  • Writer/Evaluator: rewrites the content, freely restructuring based on brand guidelines
  • SEO & Tags: generated fresh (slug preserved if existing_slug provided)
  • Cover Image: skipped (use the Image API separately if needed)
  • Publish: same webhook delivery with action: "update"

Publish Payload Differences

When a rewrite is published to your webhook, the payload includes two additional fields:

  • action: "update", indicating this is a rewrite, not a new post
  • externalId, your external_id echoed back for matching

Example: cURL

Rewrite a post
curl -X POST https://www.wonderblogs.org/api/v1/posts/rewrite \
  -H "Authorization: Bearer wb_live_a3f2_..." \
  -H "Content-Type: application/json" \
  -d '{
    "existing_content": "# My Old Post\n\nContent to rewrite...",
    "external_id": "post-456",
    "existing_slug": "my-old-post",
    "research": false
  }'

Rate Limits

Rewrite requests share the same rate limit as post generation: 5 requests per minute per API key. Rewrites count toward the same monthly blog post limit as all other generations.

Post Translation API

The Post Translation API allows external applications to submit existing blog post content for translation into a target language. Wonderblogs translates the content while preserving structure and SEO metadata, then returns the translated post. Image generation is not performed for translations.

Translate Post

POST /api/v1/posts/translate

Request body
{
  "existing_content": "# My Blog Post\n\nThe full markdown content...",
  "target_language": "de",
  "topic": "Optional topic for SEO metadata",
  "existing_slug": "my-blog-post",
  "external_id": "your-internal-id-123",
  "callback_url": "https://yoursite.com/webhooks/post-ready"
}
FieldTypeRequiredDescription
existing_contentstringYesFull markdown content to translate (100–30,000 chars). HTML is stripped automatically.
target_languagestringYesTarget language code. One of: en, de, fr, es, it, pt, nl.
topicstringNoOptional topic for SEO metadata generation (3–500 chars).
existing_slugstringNoCurrent slug of the post (max 200 chars).
external_idstringNoYour platform's ID for the post (max 500 chars). Echoed in the publish payload.
callback_urlstringNoHTTPS URL for webhook delivery on completion.

Response (202 Accepted)

Same response format as /posts/generate. Use the same /api/v1/posts/runs/{runId} endpoint to poll for status.

Response body
{
  "run_id": "a1b2c3d4-...",
  "status": "pending",
  "poll_url": "/api/v1/posts/runs/{runId}"
}

Example: cURL

Translate a post
curl -X POST https://www.wonderblogs.org/api/v1/posts/translate \
  -H "Authorization: Bearer wb_live_a3f2_..." \
  -H "Content-Type: application/json" \
  -d '{
    "existing_content": "# My Post\n\nContent to translate...",
    "target_language": "de",
    "external_id": "post-789",
    "existing_slug": "my-post"
  }'

Rate Limits

Translation requests share the same rate limit as post generation: 5 requests per minute per API key. Translations count toward the same monthly blog post limit as all other generations.

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:

Request header
Authorization: Bearer wb_live_a3f2_xxxxxxxxxxxxxxxxxxxxxxxx

Each 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

Request body
{
  "title": "How AI is Transforming Healthcare",
  "content": "Full blog post content or summary...",
  "callback_url": "https://yoursite.com/webhooks/image-ready"
}
FieldTypeRequiredDescription
titlestringYesBlog post title (max 1,000 chars).
contentstringYesBlog post content or summary (max 50,000 chars).
callback_urlstringNoHTTPS URL for webhook delivery on completion. If omitted, poll the job status endpoint.

Response (202 Accepted)

Response body
{
  "job_id": "a1b2c3d4-...",
  "status": "pending",
  "poll_url": "/api/v1/images/jobs/{jobId}"
}

Poll Job Status

GET /api/v1/images/jobs/{jobId}

Response (completed)
{
  "job_id": "a1b2c3d4-...",
  "status": "completed",
  "image_url": "https://...",
  "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 when the job finishes. Delivery uses up to 3 retries with exponential backoff (1s, 2s, 4s), 30-second timeout per attempt. 4xx responses stop retries immediately. When the site has a Target API Key configured, callbacks include X-Wonderblogs-Signature and X-Wonderblogs-Timestamp HMAC signature headers.

Callback payload: image.completed
{
  "event": "image.completed",
  "job_id": "a1b2c3d4-...",
  "status": "completed",
  "image_url": "https://...",
  "created_at": "2026-03-08T12:00:00Z",
  "completed_at": "2026-03-08T12:01:30Z"
}
Callback payload: image.failed
{
  "event": "image.failed",
  "job_id": "a1b2c3d4-...",
  "status": "failed",
  "error": "Image generation failed",
  "created_at": "2026-03-08T12:00:00Z",
  "completed_at": "2026-03-08T12:01:00Z"
}

Example: cURL

Generate an image
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"
  }'
Poll for status
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 sites, blog post generation, and image generation requests per month:

PlanSitesBlog Posts / MonthImages / MonthPrice
Free1525$0
Pro350150$29/month
Expert10200500$99/month

Blog post and image quotas are per-account (shared across all sites). Site limits determine how many connected platforms you can create. One blog post unit is one complete execution of the AI content generation workflow. Rewrites count as regular blog post units toward the same monthly limit. Images generated via the API and the dashboard share a single monthly quota.

Workflow Overview

Each content generation run follows a 7-step AI pipeline. Understanding the workflow helps you provide better context data:

StepNameWhat Happens
0Context SyncFetches brand context from your GET endpoint and loads local post history.
1UniquenessRefines a unique angle from content focus + your recent articles to avoid duplicates.
2Deep ResearchWeb search + summarization into a reference document (can be disabled per site).
3–4Writer / Evaluator LoopGenerates a draft, evaluates quality, and loops up to maxAttempts times until the evaluator approves.
5SEO & TagsGenerates metaTitle, metaDescription, slug, and categorization tags.
6Save & PublishSaves 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.

Rewrite Variant

When using the Post Rewrite API, the pipeline is reduced: the Uniqueness step is skipped (the topic is defined by the existing content), Research is optional (default off), and Cover Image generation is skipped. The Writer receives the original content and rewrites it according to your brand guidelines.

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.

Generate or access the spec
# 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.