Overview
This guide explains how the Python WordPress adapter transforms structured JSON content into fully rendered WordPress posts. Weâll explore how the adapter converts blocks into HTML, uploads media, authenticates using Basic Auth with application passwords, creates posts through the REST API (/wp-json/wp/v2/posts), assigns featured images, and surfaces operational errors clearly for production reliability.
Structured JSON as the Source of Truth
The adapter accepts structured JSON representing content blocks (headings, paragraphs, lists, quotes, code blocks, callouts, dividers, etc.). Each block is normalized and rendered into WordPress-compatible HTML before submission. This separation ensures content logic remains independent of presentation and allows consistent rendering across publishing targets.
def render_block(block):
block_type = block.get("type")
if block_type == "heading":
level = block.get("level", 2)
return f"<h{level}>{block['content']}</h{level}>"
if block_type == "paragraph":
return f"<p>{block['content']}</p>"
if block_type == "list":
tag = "ol" if block.get("ordered") else "ul"
items = "".join(f"<li>{item}</li>" for item in block.get("items", []))
return f"<{tag}>{items}</{tag}>"
if block_type == "quote":
return f"<blockquote>{block['content']}</blockquote>"
if block_type == "divider":
return "<hr />"
raise ValueError(f"Unsupported block type: {block_type}")
The adapter iterates through all blocks, concatenates the rendered HTML, and produces a single HTML payload that is sent to WordPress as the post content.
Authentication with Application Passwords
The adapter authenticates using WordPress Application Passwords via Basic Auth. This approach avoids session cookies and enables secure server-to-server publishing. Credentials are encoded in base64 and attached to every API request.
import base64
import requests
credentials = f"{username}:{application_password}"
token = base64.b64encode(credentials.encode()).decode()
headers = {
"Authorization": f"Basic {token}",
"Content-Type": "application/json"
}
Always store application passwords securely (e.g., environment variables or secret managers). Never hard-code credentials in source files.
Uploading Media and Handling Featured Images
When a block references a local or remote image, the adapter uploads the asset to the WordPress media endpoint (/wp-json/wp/v2/media). The returned media ID is then injected into the post as either inline HTML or as the featured image.
def upload_media(file_path):
with open(file_path, "rb") as f:
response = requests.post(
f"{site_url}/wp-json/wp/v2/media",
headers={
"Authorization": headers["Authorization"],
"Content-Disposition": f"attachment; filename={file_path}"
},
files={"file": f}
)
if response.status_code != 201:
raise RuntimeError(f"Media upload failed: {response.text}")
return response.json()["id"]
After uploading, the adapter assigns the returned media ID to the featured_media field when creating the post. This ensures the image appears as the official featured image in WordPress themes.
Creating Posts via the REST API
Once HTML content and media IDs are prepared, the adapter submits the post to /wp-json/wp/v2/posts. The payload includes title, slug, status, content, and optionally featured_media.
post_data = {
"title": title,
"slug": slug,
"status": "draft",
"content": rendered_html,
"featured_media": featured_media_id
}
response = requests.post(
f"{site_url}/wp-json/wp/v2/posts",
headers=headers,
json=post_data
)
if response.status_code != 201:
raise RuntimeError(f"Post creation failed: {response.status_code} {response.text}")
Clear Operational Error Handling
The adapter surfaces operational errors clearly by validating HTTP status codes and returning structured error messages. Instead of failing silently, it raises descriptive exceptions that include response codes and API messages. This makes debugging authentication failures (401), permission issues (403), validation errors (400), and server errors (500) straightforward.
Production publishing pipelines must fail loudly and descriptively. Silent failures create broken editorial workflows.
End-to-End Flow Summary
- Accept structured JSON content.
- Render each block into WordPress-compatible HTML.
- Upload referenced media files to the media endpoint.
- Capture returned media IDs for inline usage and featured images.
- Authenticate using Basic Auth with application passwords.
- Create a draft post via /wp-json/wp/v2/posts.
- Validate responses and surface errors clearly.
By encapsulating rendering, authentication, media handling, and error management, the Python WordPress adapter provides a reliable bridge between structured content systems and WordPress publishing workflows. This design keeps content structured, publishing deterministic, and operational issues transparent.