Skip to main content

Overview

This guide walks through the complete process of generating commentary from your licensed personas.

The Workflow

Step 1: Get Your Licensed Personas

First, retrieve the personas you have access to:
async function getPersonas() {
  const response = await fetch('https://api.unleeshed.ai/partner/v1/personas', {
    headers: { 'X-Api-Key': process.env.UNLEESHED_API_KEY }
  });
  
  const { data } = await response.json();
  return data;
}

const personas = await getPersonas();
// Store persona IDs for later use
const personaIds = personas.map(p => p.id);
Cache persona data for 1 hour to reduce API calls.

Step 2: Create a Topic

Submit your topic with selected personas:
async function createTopic(content, personaIds, options = {}) {
  const response = await fetch('https://api.unleeshed.ai/partner/v1/topics', {
    method: 'POST',
    headers: {
      'X-Api-Key': process.env.UNLEESHED_API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      content,
      persona_ids: personaIds,
      output_types: options.outputTypes || ['text'],
      metadata: options.metadata || {}
    })
  });
  
  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.error.message);
  }
  
  const { data } = await response.json();
  return data;
}

const topic = await createTopic(
  "Should the Lakers trade Anthony Davis before the deadline?",
  personaIds,
  { 
    outputTypes: ['text'],
    metadata: { source: 'daily_poll' }
  }
);

console.log(`Topic created: ${topic.topic_id}`);
console.log(`Personas: ${topic.personas_sent} will generate commentary`);

Handling Per-Persona Results

The response includes status for each persona:
{
  "topic_id": "abc123...",
  "personas_sent": 2,
  "results": [
    { "persona_id": "...", "status": "sent" },
    { "persona_id": "...", "status": "sent" }
  ]
}
StatusMeaningAction
sentSuccessfully queuedWait for generation
not_licensedNo active licenseContact support
duplicateSame topic sent within 24hUse existing topic

Step 3: Poll for Completion

Commentary generation takes 30-120 seconds. Poll until ready:
async function waitForCommentaries(topicId, options = {}) {
  const { 
    maxWaitMs = 180000,  // 3 minutes max
    pollIntervalMs = 10000  // Poll every 10 seconds
  } = options;
  
  const startTime = Date.now();
  
  while (Date.now() - startTime < maxWaitMs) {
    const response = await fetch(
      `https://api.unleeshed.ai/partner/v1/topics/${topicId}`,
      { headers: { 'X-Api-Key': process.env.UNLEESHED_API_KEY } }
    );
    
    const { data } = await response.json();
    
    // All done
    if (data.status === 'completed') {
      return data;
    }
    
    // Some ready - can return partial results
    if (data.status === 'partial' && options.allowPartial) {
      return data;
    }
    
    console.log(`Status: ${data.status} (${data.summary.completed}/${data.summary.total_personas})`);
    
    // Wait before next poll
    await new Promise(r => setTimeout(r, pollIntervalMs));
  }
  
  throw new Error('Timeout waiting for commentaries');
}

const result = await waitForCommentaries(topic.topic_id);

Status Values

StatusDescription
pendingWaiting to start
in_progressGeneration in progress
partialSome personas done, others still processing
completedAll personas finished

Step 4: Fetch Commentaries

Once ready, get the commentary content:
async function getCommentaries(topicId) {
  const response = await fetch(
    `https://api.unleeshed.ai/partner/v1/topics/${topicId}/commentaries`,
    { headers: { 'X-Api-Key': process.env.UNLEESHED_API_KEY } }
  );
  
  const { data } = await response.json();
  return data.commentaries;
}

const commentaries = await getCommentaries(topic.topic_id);

commentaries.forEach(c => {
  console.log(`${c.persona.name}: ${c.content.substring(0, 100)}...`);
});

Complete Example

Here’s a complete integration:
class UnleeshedClient {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.baseUrl = 'https://api.unleeshed.ai/partner/v1';
  }
  
  async request(path, options = {}) {
    const response = await fetch(`${this.baseUrl}${path}`, {
      ...options,
      headers: {
        'X-Api-Key': this.apiKey,
        'Content-Type': 'application/json',
        ...options.headers
      }
    });
    
    const data = await response.json();
    
    if (!response.ok) {
      throw new Error(data.error?.message || 'Request failed');
    }
    
    return data;
  }
  
  async getPersonas() {
    const { data } = await this.request('/personas');
    return data;
  }
  
  async createTopic(content, personaIds, outputTypes = ['text']) {
    const { data } = await this.request('/topics', {
      method: 'POST',
      body: JSON.stringify({ content, persona_ids: personaIds, output_types: outputTypes })
    });
    return data;
  }
  
  async getTopicWithCommentaries(topicId) {
    const { data } = await this.request(`/topics/${topicId}`);
    return data;
  }
  
  async generateCommentary(content, personaIds, options = {}) {
    // Create topic
    const topic = await this.createTopic(content, personaIds, options.outputTypes);
    
    // Wait for completion
    const maxWait = options.maxWaitMs || 180000;
    const pollInterval = options.pollIntervalMs || 10000;
    const start = Date.now();
    
    while (Date.now() - start < maxWait) {
      const result = await this.getTopicWithCommentaries(topic.topic_id);
      
      if (result.status === 'completed') {
        return result;
      }
      
      await new Promise(r => setTimeout(r, pollInterval));
    }
    
    throw new Error('Timeout');
  }
}

// Usage
const client = new UnleeshedClient(process.env.UNLEESHED_API_KEY);

const personas = await client.getPersonas();
const result = await client.generateCommentary(
  "Should the Lakers trade AD?",
  personas.map(p => p.id)
);

console.log(result.commentaries);

Next Steps