Let’s be honest upfront: there is no “Perplexity Collections API.” That feature doesn’t exist in any official Perplexity documentation, changelog, or announcement as of early 2026. So instead of pretending otherwise and serving up a tutorial built on fiction, here’s something better — a real, working workflow that uses Perplexity’s actual tools to automate social media captions with brand voice and product context baked in.
What Perplexity does have is a solid REST API (accessible at api.perplexity.ai), a Python-compatible interface via standard HTTP requests, Spaces for organizing research context, and Pro Search that can pull live web data. Combine those with a bit of Python and a well-structured prompt system, and you get a caption generator that knows your product, matches your tone, and can process posts in batches. That’s the tutorial you’re getting today.
By the end of this, you’ll have a Python script that reads product descriptions and tone guidelines from local files, sends them to Perplexity’s API with a structured prompt, and outputs ready-to-post captions for Instagram, LinkedIn, and X — all without hallucinating a fake Collections endpoint.
What You’ll Actually Build
The workflow has three components. First, a context loader that reads your brand guidelines and product docs from plain text files. Second, a prompt builder that injects that context into a system prompt so every API call knows who you are and how you sound. Third, a batch processor that takes a list of products or campaign topics and outputs a JSON file of captions per platform. Simple, auditable, and easy to extend.
Requirements
You need a Perplexity API key — available at perplexity.ai/settings/api once you have a Pro or API plan. The API uses standard Bearer token authentication. On the Python side, you only need the requests library and json, both available via pip. No proprietary SDK required. The tutorial uses Python 3.10+, but anything 3.8+ should work fine.
Note 💡
Perplexity’s API currently exposes models including sonar, sonar-pro, sonar-reasoning, and sonar-reasoning-pro. For caption generation, sonar-pro gives you the best balance of instruction-following and creative output. sonar-reasoning is worth trying if you want the model to explicitly justify tone choices — useful for brand review workflows.
Step 1 — Set Up Your Context Files
Create a project folder with two plain text files. The first is brand_voice.txt — this is your tone guide. Write it the way you’d brief a copywriter: describe your brand personality, what words you avoid, your typical sentence length, whether you use emojis and how, and what emotional register you aim for. The second file is product_catalog.txt — a structured list of your products, their key features, and any claims you always want associated with them.
These files become your in-context RAG. You’re not indexing a vector database — you’re pasting the relevant context directly into the system prompt. For most brand guidelines (under 2,000 words) and product catalogs (under 50 SKUs), this fits easily within sonar-pro’s context window. If your catalog is massive, split it into category files and load only the relevant one per batch.
Pro tip ✅
Keep your brand_voice.txt under 800 words. Longer tone guides dilute signal — the model starts averaging across contradictory instructions. Be ruthless: three adjectives that describe your brand voice beat a paragraph of marketing philosophy every time.
Step 2 — Install Dependencies and Configure the Client
Install the one library you need:
pip install requests
Then create a config.py file to hold your API key and default parameters. Never hardcode the key — use an environment variable:
import os
PERPLEXITY_API_KEY = os.environ.get("PERPLEXITY_API_KEY")
API_URL = "https://api.perplexity.ai/chat/completions"
DEFAULT_MODEL = "sonar-pro"
MAX_TOKENS = 600
TEMPERATURE = 0.7
Temperature at 0.7 gives you creative variation without going off-brand. If you’re generating captions for regulated industries (finance, pharma), drop it to 0.3 for tighter adherence to your approved language list.
Step 3 — Build the Context Loader
This function reads your brand files and assembles the system prompt. The system prompt is where all your brand context lives — Perplexity’s API respects the system/user message distinction cleanly:
def load_context(brand_voice_path="brand_voice.txt", catalog_path="product_catalog.txt"):
with open(brand_voice_path, "r") as f:
brand_voice = f.read()
with open(catalog_path, "r") as f:
product_catalog = f.read()
system_prompt = f"""You are a social media copywriter for this brand.
BRAND VOICE GUIDELINES:
{brand_voice}
PRODUCT CATALOG:
{product_catalog}
Your job: write captions that match the brand voice exactly.
Never invent product claims not listed in the catalog.
Always produce output as valid JSON."""n
return system_prompt
The final instruction — “Always produce output as valid JSON” — is doing a lot of work here. It makes batch processing reliable and means you can pipe the output directly into a scheduling tool or CMS without manual cleanup.
Step 4 — Build the Caption Request Function
Here’s the core function that calls the API. It takes a topic or product name plus the platforms you want captions for, and returns structured JSON:
import requests
import json
from config import PERPLEXITY_API_KEY, API_URL, DEFAULT_MODEL, MAX_TOKENS, TEMPERATURE
def generate_captions(topic, platforms, system_prompt):
headers = {
"Authorization": f"Bearer {PERPLEXITY_API_KEY}",
"Content-Type": "application/json"
}
user_message = f"""Generate social media captions for: {topic}
Platforms needed: {', '.join(platforms)}
Return a JSON object with platform names as keys.
Each value should have:
- "caption": the post text
- "hashtags": list of 3-5 relevant hashtags
- "character_count": integer
Example format:
{{
"instagram": {{"caption": "...", "hashtags": [...], "character_count": 0}},
"linkedin": {{"caption": "...", "hashtags": [...], "character_count": 0}},
"x": {{"caption": "...", "hashtags": [...], "character_count": 0}}
}}"""n
payload = {
"model": DEFAULT_MODEL,
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_message}
],
"max_tokens": MAX_TOKENS,
"temperature": TEMPERATURE
}
response = requests.post(API_URL, headers=headers, json=payload)
response.raise_for_status()
raw_content = response.json()["choices"][0]["message"]["content"]
# Strip markdown code fences if the model adds them
if raw_content.startswith(""):
raw_content = raw_content.split("")[1]
if raw_content.startswith("json"):
raw_content = raw_content[4:]
return json.loads(raw_content.strip())
The markdown stripping at the end handles a common quirk: even when you ask for pure JSON, language models occasionally wrap it in a code fence out of habit. Two lines of cleanup is easier than fighting the model into perfect compliance every time.
<
Step 5 — Build the Batch Processor
Now chain everything together. The batch processor reads a list of topics from a CSV or plain list, calls the caption generator for each, and writes results to a JSON output file:
import json
import time
def batch_generate(topics, platforms, output_path="captions_output.json"):
system_prompt = load_context()
results = {}
for i, topic in enumerate(topics):
print(f"Generating captions for: {topic} ({i+1}/{len(topics)})")
try:
captions = generate_captions(topic, platforms, system_prompt)
results[topic] = captions
except Exception as e:
print(f"Failed on '{topic}': {e}")
results[topic] = {"error": str(e)}
# Respect rate limits — Perplexity API has per-minute request caps
time.sleep(1.5)
with open(output_path, "w") as f:
json.dump(results, f, indent=2)
print(f"Done. Results saved to {output_path}")
return results
# Example usage
topics = [
"Summer product launch — waterproof backpack",
"New colorway drop — running shoes",
"Limited edition collaboration with Studio Ghibli merch"
]
platforms = ["instagram", "linkedin", "x"]
batch_generate(topics, platforms)
The 1.5-second sleep between requests isn’t just politeness — Perplexity’s API enforces rate limits, and batch jobs that ignore them end up with a pile of 429 errors and a half-finished output file. Build the delay in from the start.
Pro tip ✅
Add exponential backoff to your retry logic. If a request fails with a 429 or 503, wait 2 seconds, then 4, then 8 before giving up. The
tenacitylibrary handles this in about four lines of code and saves you from babysitting batch jobs.
Step 6 — Prompt Variants That Actually Change Output
The system prompt structure matters enormously. Here are four variants to test against your brand — swap them into the system_prompt assembly in Step 3 and compare outputs:
For a direct-response brand that leads with benefits:
You write punchy, benefit-first captions. Lead with what the customer gains.
No passive voice. No filler words like "amazing" or "incredible".
Sentences under 15 words. Verbs over adjectives.
For a premium lifestyle brand that sells aspiration:
You write captions that evoke a feeling before describing a product.
Set the scene in one sentence. Then name the product.
Tone: confident, unhurried, slightly poetic. Never salesy.
For a B2B SaaS company targeting managers:
You write LinkedIn-native captions for a B2B audience.
Lead with a data point or provocative question.
Avoid jargon. Explain value in terms of time saved or risk reduced.
No hashtags on LinkedIn — they perform poorly for this audience.
For a community-driven brand that leans on user identity:
You write captions that speak to a community, not customers.
Use "we" and "you". Reference shared values, not product specs.
Tone: warm, direct, occasionally self-aware. Emoji used sparingly and intentionally.
Warning ⚠️
Don’t stack contradictory tone instructions in one system prompt. “Be formal but casual” and “be concise but detailed” force the model to average your instructions into mush. Pick a direction and commit to it. If you need multiple tones for different sub-brands, maintain separate brand_voice.txt files and swap them per batch run.
Step 7 — Using Perplexity Spaces for Research Context
If your caption workflow needs to reference current trends, recent news about your industry, or competitor activity, Spaces is where Perplexity genuinely earns its place. Create a Space via the Perplexity web app (it’s in the left sidebar), add your product URLs, brand guidelines PDFs, and any reference articles, then use Pro Search within that Space to pull trend-aware insights before your batch run.
The practical workflow: run a Spaces search like this before writing captions for a product launch:
What are the top 3 trending conversations about [your product category] this week?
What language are brands in this space using that resonates with audiences?
What topics should we avoid referencing right now given current news?
Copy the output into a third context file — call it trend_context.txt — and inject it into your system prompt alongside brand voice and product catalog. Your captions stay current without you manually reading 40 industry posts every Monday morning.
Pro tip ✅
Perplexity Spaces cites its sources. When you use trend context in your captions, you can actually trace where each insight came from — which is useful when your CMO asks why you’re using a specific phrase or referencing a particular conversation. Screenshot the Space search before your batch run for a paper trail.
Pro tip ✅
Version your output files by date:
captions_2026-02-28.jsoninstead of overwriting a single file. Three months from now, when someone asks why the March campaign used a specific tone, you’ll have the exact prompt context and outputs archived together.
The Full Prompt Stack — Copy-Paste Reference
Here’s a single consolidated prompt you can use directly in Perplexity’s web interface or Spaces to test your brand voice before committing to the API workflow. Replace the bracketed sections with your actual content:
You are a social media copywriter for [BRAND NAME].
Brand voice: [3-5 adjectives]. We avoid [list of banned words/phrases].
We always [specific stylistic rule, e.g., "use sentence case, never ALL CAPS"].
Our audience is [describe your audience in one sentence].
Product: [PRODUCT NAME]
Key features: [list 3-4 bullet points]
Price/positioning: [one sentence]
Generate captions for Instagram (max 150 words, 3-5 hashtags),
LinkedIn (max 100 words, professional tone, no hashtags),
and X (max 280 characters, punchy, 1-2 hashtags).
Return as JSON with platform keys.
Run this in Perplexity Pro Search and you’ll immediately see whether your brand context is specific enough to produce distinct output — or whether it’s vague enough that the model defaults to generic marketing copy. Fix the vague parts before you build the batch pipeline.
What This Gets You
A working batch caption system built on Perplexity’s real API, not a fantasy product. The workflow is genuinely useful: 50 captions across three platforms from a single batch run takes about three minutes and produces output that’s at least as good as a first draft from a mid-tier copywriter — consistently, at 2am, without complaining about the brief.
The honest ceiling: AI-generated captions are first drafts, not final copy. The workflow cuts the blank-page problem and ensures every draft starts from your actual brand voice and product facts rather than a hallucinated version of them. A human still needs to review for cultural context, timing sensitivity, and anything that requires genuine creative judgment. Use it to move faster, not to eliminate the human in the loop entirely. The brands that win on social in 2026 still have a voice — they just have better tools for scaling it.