crm.stages & crm.pipelines #

Retrieve pipeline configurations and stage hierarchies to dynamically evaluate stage progression in your custom functions.


TypeScript Signatures #

typescript
crm.stages.list(): Promise<Stage[]>;
crm.pipelines.list(): Promise<Pipeline[]>;

Method Details #

crm.stages.list() #

Retrieves all configured stages for the scoped module, sorted in execution sequence order.

Return Value

Returns a Promise<Stage[]> containing all active stages.

FieldTypeDescription
idnumberUnique numeric identifier for the stage.
namestringDisplay name of the stage (e.g. "Initial Outreach").
slugstringURL-safe machine identifier (e.g. "initial_outreach").
typestringStage classification ("open", "won", "lost").
ordernumberDisplay sequence number within the pipeline.
pipelineIdnumberID of the parent pipeline.

crm.pipelines.list() #

Retrieves all pipelines associated with the scoped module, including nested stage trees.

Return Value

Returns a Promise<Pipeline[]> where each pipeline contains its child stages.

FieldTypeDescription
idnumberPipeline unique identifier.
namestringDisplay name of the pipeline (e.g. "Enterprise Sales").
slugstringUnique pipeline slug identifier.
moduleIdnumberParent CRM module ID.
stagesStage[]Array of child stage objects belonging to this pipeline.

Models & Interfaces #

typescript
interface Stage {
  id: number;
  name: string;
  slug: string;
  type: string;
  order: number;
  pipelineId: number;
}

interface Pipeline {
  id: number;
  name: string;
  slug: string;
  moduleId: number;
  stages: Stage[];
}

Minimal Example #

typescript
async function run(context: Context, dolfin: DolfinApi): Promise<void> {
  const { lead } = context;
  const crm = await dolfin.crm.module(lead.moduleId);

  const stages = await crm.stages.list();
  console.log(`Configured stages for module ${lead.moduleId}:`);
  stages.forEach((s) => console.log(`- #${s.order}: ${s.name} (${s.slug})`));
}

Production Recipe: Dynamic Pipeline Branching #

Routes high-value enterprise leads to an expedited VIP pipeline stage while leaving standard leads in the default flow:

typescript
async function run(context: Context, dolfin: DolfinApi): Promise<void> {
  const { lead } = context;
  const crm = await dolfin.crm.module(lead.moduleId);

  const estimatedValue = Number(lead.meta?.deal_value || 0);

  // Fetch all available pipelines
  const pipelines = await crm.pipelines.list();

  if (estimatedValue >= 50000) {
    console.log(`High-value lead ($${estimatedValue}) — routing to Enterprise Fast-Track`);
    await crm.leads.changeStage(lead.id, "enterprise_pipeline", "executive_review");
    
    await crm.leads.notes.add(
      lead.id,
      "⚡ Lead routed to Enterprise Fast-Track pipeline due to deal value >= $50k."
    );
  } else {
    console.log(`Standard lead ($${estimatedValue}) — routing to standard pipeline`);
    await crm.leads.changeStage(lead.id, "default_pipeline", "sales_discovery");
  }
}

Error Handling & Best Practices #

ScenarioThrown ErrorResolution
Module not found / inactiveModule with ID {id} not foundVerify that the module is active in settings before querying.
Cross-tenant isolation violationAccess DeniedThe SDK automatically constrains lookups to your tenant organization.
ℹ️ Note

Stages and pipelines are cached in memory during a single function execution. Multiple calls to crm.stages.list() within the same execution will not incur redundant database overhead.