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

You maintain curated Shopify collections (e.g., “Summer Essentials”). You pull all products from a target collection, use their existing descriptions to create a Mavera brand voice, then generate fresh marketing copy — product descriptions, social posts, email subject lines — with voice consistency across the entire collection.

Architecture

Code

import os, requests, time

STORE = os.environ["SHOPIFY_STORE"]
TOKEN = os.environ["SHOPIFY_ACCESS_TOKEN"]
MV = os.environ["MAVERA_API_KEY"]
SH = f"https://{STORE}.myshopify.com/admin/api/2024-10/graphql.json"
SH_H = {"X-Shopify-Access-Token": TOKEN, "Content-Type": "application/json"}
MB = "https://app.mavera.io/api/v1"
MH = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
HANDLE = "summer-essentials"

QUERY = """query ($handle: String!) {
  collectionByHandle(handle: $handle) { title
    products(first: 50) { edges { node { title descriptionHtml productType
      priceRangeV2 { minVariantPrice { amount currencyCode } }
    }}}
  }
}"""

resp = requests.post(SH, json={"query": QUERY, "variables": {"handle": HANDLE}}, headers=SH_H)
resp.raise_for_status()
coll = resp.json()["data"]["collectionByHandle"]
products = [e["node"] for e in coll["products"]["edges"]]
print(f"Collection: {coll['title']}{len(products)} products")

samples = [p["descriptionHtml"] for p in products if p.get("descriptionHtml")][:10]
voice_resp = requests.post(f"{MB}/brand-voices", json={"name": f"Shopify — {HANDLE}", "samples": samples}, headers=MH)
voice_resp.raise_for_status()
voice_id = voice_resp.json()["id"]
print(f"Brand voice: {voice_id}")

for p in products:
    price = p["priceRangeV2"]["minVariantPrice"]
    gen = requests.post(f"{MB}/generations", json={
        "brand_voice_id": voice_id,
        "prompt": f"Write: 1) 2-sentence product description 2) Instagram caption with hashtags 3) Email subject line\n\nProduct: {p['title']}\nType: {p['productType']}\nPrice: {price['amount']} {price['currencyCode']}\nCurrent: {p.get('descriptionHtml', 'N/A')}",
    }, headers=MH)
    gen.raise_for_status()
    print(f"\n--- {p['title']} ---\n{gen.json()['text']}")
    time.sleep(0.3)

Example Output

Collection: Summer Essentials — 24 products
Brand voice: bv_9c4e2a1f

--- Linen Breeze Shirt ---
1. Lightweight linen that breathes from morning coffee to sunset cocktails. Relaxed fit with mother-of-pearl buttons.
2. Your summer uniform, perfected. The Linen Breeze Shirt in sea salt. #SummerEssentials #LinenLife
3. The shirt that makes summer effortless — now in 4 new colors

Error Handling

If collectionByHandle returns null, the handle doesn’t exist or is unpublished. Verify in Shopify Admin → Products → Collections → URL handle. Handles are case-sensitive and use hyphens. Query collections(first: 10) to list available handles.
Mavera requires at least 3 text samples to create a brand voice. If your collection has fewer products with descriptions, combine from multiple collections or add sample copy manually.