Skip to main content

Overview

Tags and statuses help organize prospects in your Inbox. Tags are flexible labels for categorization. Statuses represent pipeline stages.
FeatureTagsStatuses
Per prospectMultipleOne
Use caseFlexible labelsPipeline stages
OrderedNoYes
Example”Hot Lead”, “Enterprise""New → Qualified → Won”

Tags

Data Model

interface Tag {
  id: string;
  name: string;
  color: string;    // Hex color code
  createdAt: string;
}

List Tags

const { data } = await client.get('/tags');

console.log(`Found ${data.tags.length} tags`);
data.tags.forEach(tag => {
  console.log(`${tag.name} (${tag.color})`);
});
Response:
{
  "tags": [
    { "id": "tag_abc123", "name": "Hot Lead", "color": "#EF4444" },
    { "id": "tag_def456", "name": "Enterprise", "color": "#3B82F6" },
    { "id": "tag_ghi789", "name": "Partner", "color": "#10B981" }
  ]
}

Create Tag

const { data } = await client.post('/tags', {
  name: 'VIP',
  color: '#8B5CF6'  // Purple
});

console.log('Created tag:', data.tag.id);

Get Available Colors

const { data } = await client.get('/tags/colors');
console.log('Available colors:', data.colors);
// ["#EF4444", "#F97316", "#F59E0B", "#10B981", "#3B82F6", "#8B5CF6", ...]

Update Tag

await client.patch(`/tags/${tagId}`, {
  name: 'VIP Customer',
  color: '#6366F1'
});

Delete Tag

await client.delete(`/tags/${tagId}`);
// Tag is removed from all prospects
Deleting a tag removes it from all prospects. This cannot be undone.

Apply Tags to Prospect

// Get current prospect
const { data: prospectData } = await client.get(`/prospects/${prospectId}`);
const currentTagIds = prospectData.prospect.tags.map(t => t.id);

// Add new tag
const newTagIds = [...currentTagIds, 'tag_new'];

await client.patch(`/prospects/${prospectId}/context`, {
  tagIds: newTagIds
});

Remove Tag from Prospect

// Get current tags
const { data: prospectData } = await client.get(`/prospects/${prospectId}`);
const currentTagIds = prospectData.prospect.tags.map(t => t.id);

// Remove specific tag
const updatedTagIds = currentTagIds.filter(id => id !== 'tag_to_remove');

await client.patch(`/prospects/${prospectId}/context`, {
  tagIds: updatedTagIds
});

Statuses

Data Model

interface Status {
  id: string;
  name: string;
  color: string;    // Hex color code
  order: number;    // Display order (lower = earlier in pipeline)
  createdAt: string;
}

List Statuses

const { data } = await client.get('/statuses');

// Statuses are returned in order
data.statuses.forEach((status, index) => {
  console.log(`${index + 1}. ${status.name} (order: ${status.order})`);
});
Response:
{
  "statuses": [
    { "id": "status_new", "name": "New", "color": "#6B7280", "order": 0 },
    { "id": "status_contacted", "name": "Contacted", "color": "#3B82F6", "order": 1 },
    { "id": "status_qualified", "name": "Qualified", "color": "#F59E0B", "order": 2 },
    { "id": "status_proposal", "name": "Proposal", "color": "#8B5CF6", "order": 3 },
    { "id": "status_won", "name": "Won", "color": "#10B981", "order": 4 },
    { "id": "status_lost", "name": "Lost", "color": "#EF4444", "order": 5 }
  ]
}

Create Status

const { data } = await client.post('/statuses', {
  name: 'Demo Scheduled',
  color: '#06B6D4',
  order: 3  // Position in pipeline
});

console.log('Created status:', data.status.id);

Update Status

await client.patch(`/statuses/${statusId}`, {
  name: 'Demo Complete',
  order: 4  // Move later in pipeline
});

Delete Status

await client.delete(`/statuses/${statusId}`);
// Status is removed from all prospects

Set Prospect Status

await client.patch(`/prospects/${prospectId}/context`, {
  statusId: 'status_qualified'
});

Clear Prospect Status

await client.patch(`/prospects/${prospectId}/context`, {
  statusId: null
});

Filtering by Tags and Statuses

Threads with Specific Tags

// Prospects with ANY of these tags (OR logic)
const { data } = await client.get('/threads', {
  params: {
    'filter[tagIds][0]': 'tag_hot_lead',
    'filter[tagIds][1]': 'tag_enterprise'
  }
});

Threads with No Tags

const { data } = await client.get('/threads', {
  params: {
    'filter[noTags]': true
  }
});

Threads with Specific Status

const { data } = await client.get('/threads', {
  params: {
    'filter[statusIds][0]': 'status_qualified'
  }
});

Threads with No Status

const { data } = await client.get('/threads', {
  params: {
    'filter[noStatus]': true
  }
});

Combined Filters

// Hot leads in the qualified stage, unassigned
const { data } = await client.get('/threads', {
  params: {
    'filter[tagIds][0]': 'tag_hot_lead',
    'filter[statusIds][0]': 'status_qualified',
    'filter[noAssignee]': true,
    inboxView: 'default'
  }
});

Common Patterns

Tag System Setup

Initialize a standard tag structure:
const standardTags = [
  { name: 'Hot Lead', color: '#EF4444' },
  { name: 'Warm Lead', color: '#F97316' },
  { name: 'Cold Lead', color: '#6B7280' },
  { name: 'Customer', color: '#10B981' },
  { name: 'Partner', color: '#3B82F6' },
  { name: 'Competitor', color: '#8B5CF6' },
  { name: 'Do Not Contact', color: '#1F2937' }
];

async function setupTags() {
  for (const tag of standardTags) {
    try {
      await client.post('/tags', tag);
      console.log(`Created tag: ${tag.name}`);
    } catch (error) {
      if (error.response?.status === 409) {
        console.log(`Tag exists: ${tag.name}`);
      } else {
        throw error;
      }
    }
  }
}

Pipeline Setup

Create a sales pipeline:
const pipeline = [
  { name: 'New', color: '#6B7280', order: 0 },
  { name: 'Contacted', color: '#3B82F6', order: 1 },
  { name: 'Qualified', color: '#F59E0B', order: 2 },
  { name: 'Demo', color: '#8B5CF6', order: 3 },
  { name: 'Proposal', color: '#EC4899', order: 4 },
  { name: 'Negotiation', color: '#06B6D4', order: 5 },
  { name: 'Won', color: '#10B981', order: 6 },
  { name: 'Lost', color: '#EF4444', order: 7 }
];

async function setupPipeline() {
  for (const status of pipeline) {
    try {
      await client.post('/statuses', status);
      console.log(`Created status: ${status.name}`);
    } catch (error) {
      if (error.response?.status === 409) {
        console.log(`Status exists: ${status.name}`);
      }
    }
  }
}

Pipeline Progress Report

async function getPipelineReport() {
  const { data: statusData } = await client.get('/statuses');
  const report: Record<string, number> = {};

  // Initialize counts
  for (const status of statusData.statuses) {
    report[status.name] = 0;
  }
  report['No Status'] = 0;

  // Count threads per status
  let cursor = undefined;
  do {
    const { data } = await client.get('/threads', {
      params: {
        limit: 100,
        ...(cursor && {
          'cursor[id]': cursor.id,
          'cursor[timestamp]': cursor.timestamp
        })
      }
    });

    for (const thread of data.threads) {
      const statusName = thread.prospect.status?.name || 'No Status';
      report[statusName] = (report[statusName] || 0) + 1;
    }

    cursor = data.nextCursor;
  } while (cursor);

  return report;
}

// Usage
const report = await getPipelineReport();
console.log('Pipeline Report:');
Object.entries(report).forEach(([status, count]) => {
  console.log(`  ${status}: ${count}`);
});

Auto-Tagging

Tag prospects automatically based on criteria:
async function autoTagProspect(prospectId: string) {
  const { data } = await client.get(`/prospects/${prospectId}`);
  const prospect = data.prospect;

  const tagsToApply: string[] = [];

  // Tag based on followers
  if (prospect.followersCount > 100000) {
    tagsToApply.push('tag_influencer');
  } else if (prospect.followersCount > 10000) {
    tagsToApply.push('tag_high_reach');
  }

  // Tag based on bio
  const bio = prospect.description?.toLowerCase() || '';
  if (bio.includes('founder') || bio.includes('ceo')) {
    tagsToApply.push('tag_decision_maker');
  }
  if (bio.includes('developer') || bio.includes('engineer')) {
    tagsToApply.push('tag_technical');
  }

  // Tag verified accounts
  if (prospect.verified) {
    tagsToApply.push('tag_verified');
  }

  if (tagsToApply.length > 0) {
    // Merge with existing tags
    const existingTagIds = prospect.tags.map(t => t.id);
    const uniqueTagIds = [...new Set([...existingTagIds, ...tagsToApply])];

    await client.patch(`/prospects/${prospectId}/context`, {
      tagIds: uniqueTagIds
    });

    console.log(`Applied ${tagsToApply.length} tags to ${prospect.platformUsername}`);
  }
}

Status Progression

Move prospects through pipeline stages:
async function progressStatus(prospectId: string) {
  const { data: statusData } = await client.get('/statuses');
  const { data: prospectData } = await client.get(`/prospects/${prospectId}`);

  const currentStatus = prospectData.prospect.status;
  const statuses = statusData.statuses.sort((a, b) => a.order - b.order);

  if (!currentStatus) {
    // Set to first status
    await client.patch(`/prospects/${prospectId}/context`, {
      statusId: statuses[0].id
    });
    return statuses[0];
  }

  // Find next status
  const currentIndex = statuses.findIndex(s => s.id === currentStatus.id);
  if (currentIndex < statuses.length - 1) {
    const nextStatus = statuses[currentIndex + 1];
    await client.patch(`/prospects/${prospectId}/context`, {
      statusId: nextStatus.id
    });
    return nextStatus;
  }

  return currentStatus;  // Already at end
}

Best Practices

Establish naming conventions for your team:
  • Tags: Capitalize each word (“Hot Lead”, not “hot_lead”)
  • Statuses: Short and clear (“Demo” not “Demo Has Been Scheduled”)
Too many tags become hard to manage. Aim for 10-20 essential tags maximum.
Statuses work best as a linear progression. Use tags for non-linear attributes.
Create a guide for your team explaining when to apply each tag and status.

Next Steps