Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mavera.io/llms.txt

Use this file to discover all available pages before exploring further.

Scenario

Full round-trip: generate a brand-voice-consistent article with Mavera using an existing brand voice and persona, then publish it directly back to WordPress as a draft. This pipeline covers content ideation through to draft creation with proper auth, categories, and metadata.

Architecture

Code

import os, json, requests
from base64 import b64encode

WP, WP_USER, WP_PASS = os.environ["WORDPRESS_URL"], os.environ["WORDPRESS_USER"], os.environ["WORDPRESS_APP_PASSWORD"]
MV = os.environ["MAVERA_API_KEY"]
MB = "https://app.mavera.io/api/v1"
MH = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
wp_token = b64encode(f"{WP_USER}:{WP_PASS}".encode()).decode()
WP_H = {"Authorization": f"Basic {wp_token}", "Content-Type": "application/json"}

voices = requests.get(f"{MB}/brand-voices", headers=MH).json()
voice_id = voices.get("brand_voices", voices.get("data", []))[0]["id"]
personas = requests.get(f"{MB}/personas", headers=MH).json()
persona_id = personas.get("personas", personas.get("data", []))[0]["id"]
print(f"Voice: {voice_id} | Persona: {persona_id}")

gen = requests.post(f"{MB}/responses", json={
    "model": "mavera-default", "brand_voice_id": voice_id, "persona_id": persona_id,
    "input": [
        {"role": "system", "content": "Content writer. Return JSON: title, body (HTML with h2/p/ul tags), excerpt (2 sentences), suggested_category."},
        {"role": "user", "content": "Write a 600-word article about building a personal brand on LinkedIn in 2026. Include actionable tips, trends, and a strong hook."},
    ],
    "response_format": {"type": "json_object"},
}, headers=MH)
gen.raise_for_status()
article = json.loads(gen.json()["choices"][0]["message"]["content"])
print(f"Generated: {article['title']}")

cats_resp = requests.get(f"{WP}/wp-json/wp/v2/categories", params={"search": article.get("suggested_category", ""), "per_page": 5})
cat_id = cats_resp.json()[0]["id"] if cats_resp.ok and cats_resp.json() else 1

post_resp = requests.post(f"{WP}/wp-json/wp/v2/posts", json={
    "title": article["title"], "content": article["body"],
    "excerpt": article.get("excerpt", ""), "status": "draft", "categories": [cat_id],
}, headers=WP_H)
post_resp.raise_for_status()
post = post_resp.json()
print(f"Draft created: {post['link']} (ID: {post['id']}, status: {post['status']})")

Example Output

{
  "id": 1247,
  "title": { "rendered": "LinkedIn Personal Branding in 2026: 7 Tactics That Actually Work" },
  "status": "draft",
  "link": "https://blog.example.com/?p=1247",
  "excerpt": {
    "rendered": "Your LinkedIn profile isn't a resume — it's a landing page. Here's how to turn it into a magnet for the opportunities you actually want."
  },
  "categories": [14],
  "date": "2026-03-17T10:42:15"
}

Error Handling

Write operations require Basic auth. Ensure you’re encoding username:application_password (not your login password) with base64. Application Passwords contain spaces — include them. If you regenerated the password, the old one is revoked immediately. Test with: curl -u "user:xxxx xxxx xxxx" https://yoursite.com/wp-json/wp/v2/users/me.
The authenticated user must have the publish_posts capability (Editor or Administrator role). Contributors can create posts but not publish them. The code sets status: "draft" which requires the edit_posts capability — Author role or above.