Install
openclaw skills install @leooooooow/wordpress-blog-publisherUse this skill whenever the user wants to publish, update, or batch-upload blog content to a WordPress site via the REST API. Handles auth, markdown conversion, image uploads, scheduling, and writing permalink back to upstream systems.
openclaw skills install @leooooooow/wordpress-blog-publisherThis skill turns an AI agent into a reliable publisher for WordPress sites via the REST API (/wp-json/wp/v2/*). Designed for batch SEO content workflows, it handles authentication, markdown-to-HTML conversion, media uploads, post scheduling, and status writeback to upstream systems like Airtable, Bitable, or Google Sheets.
| Decision | Strong Choice | Acceptable | Weak / Avoid |
|----------|---------------|------------||--------------|
| Auth method | Application Password (HTTP Basic) | JWT token | Login password (never) |
| Content format | Markdown → HTML (convert first) | Raw HTML | Raw markdown (WP won't render it) |
| Batch approach | Dry-run first post, confirm, then batch | Process all with logs | Process all without validation |
| Image handling | Upload to WP media library, rewrite src | External CDN links | Local file paths |
| Post status | publish or future (scheduled) | draft for review | private (unless intentional) |
| Error handling | Log and continue on non-critical errors | Stop on all errors | Silent fail |
| Permalink writeback | Write to upstream system after publish | Log to file | No writeback |
Required credentials:
site_url: e.g., https://example.com (no trailing slash)username: WP admin usernameapp_password: Application Password from WP Admin → Users → Profile → Application PasswordsAuth header:
Authorization: Basic base64(username:app_password)
Test connection:
GET {site_url}/wp-json/wp/v2/users/me
If 200, auth is working. If 401, check Application Password setup. If 403, user lacks publish_posts capability.
title, slug, categories, tags fields from it<pre><code>), tables, nested lists# H1 title (use as post title, not body content)WP requires numeric IDs, not names:
GET {site_url}/wp-json/wp/v2/categories?search=seo&per_page=5
Cache the ID map for the batch to avoid repeated lookups.
POST {site_url}/wp-json/wp/v2/media
Headers:
Content-Disposition: attachment; filename="image.jpg"
Content-Type: image/jpeg
Body: [binary image data]
POST {site_url}/wp-json/wp/v2/posts
{
"title": "Your Post Title",
"content": "<p>HTML content here</p>",
"slug": "your-post-slug",
"status": "publish",
"categories": [12, 34],
"tags": [56, 78],
"featured_media": 1234,
"date_gmt": "2025-06-15T09:00:00"
}
Response includes "link" — the live permalink. Save this.
After each successful publish, write permalink and timestamp back:
permalink and wp_status fields{slug, wp_post_id, permalink, published_at} to CSV/JSON[3/20] Published: /seo-guide-2025 ✓20 published, 1 failed (see log)Status = "Ready to Publish" from Airtablestatus: "future" and date_gmt staggered by 1 day eachGET /wp-json/wp/v2/posts?slug={slug}&status=any to find post IDPOST /wp-json/wp/v2/posts/{id} with updated contentdate instead of date_gmt — always use UTC.references/api-reference.md — WP REST API endpoints quick referencereferences/markdown-to-html-rules.md — Conversion rules and edge casesassets/wp-publish-checklist.md — Pre-publish and post-publish quality checklist