---
title: "Deals Management"
description: "Manage sales deals and pipeline opportunities in Brevo CRM for Tajo e-commerce revenue tracking"
url: https://tajo.io/docs/sales-crm/deals/
markdown: https://tajo.io/docs/sales-crm/deals.md
lang: en-US
---

# Deals Management

The Brevo CRM Deals API enables you to manage your sales pipeline, track deal progress, and automate revenue-related workflows within the Tajo platform.

## Overview

Deal management is essential for:

- **Sales pipeline tracking** with stage-based progression and forecasting
- **Revenue attribution** linking deals to e-commerce customer activity
- **Automated follow-ups** triggered by deal stage changes
- **Team performance analytics** with win/loss tracking and conversion rates
- **Loyalty program integration** awarding points on deal closure

## Quick Start

### Create Deal

```http
POST https://api.brevo.com/v3/crm/deals
Content-Type: application/json
api-key: YOUR_API_KEY

{
  "name": "Acme Corp - Enterprise Loyalty Package",
  "attributes": {
    "deal_stage": "Qualified",
    "amount": 75000,
    "close_date": "2026-06-30",
    "pipeline": "Enterprise Sales",
    "deal_owner": "sarah.johnson@tajo.io",
    "deal_type": "new_business",
    "probability": 60,
    "company_id": "comp_123456789",
    "contact_id": "contact_987654321",
    "source": "inbound_lead",
    "loyalty_points_bonus": 5000,
    "contract_length_months": 12
  }
}
```

### Response

```json
{
  "id": "deal_abc123def456",
  "name": "Acme Corp - Enterprise Loyalty Package",
  "created_at": "2026-01-25T14:30:00Z",
  "updated_at": "2026-01-25T14:30:00Z"
}
```

## Get Deals

### List All Deals

Retrieve deals with filtering and pagination:

```http
GET https://api.brevo.com/v3/crm/deals?limit=50&offset=0&sort=desc
Content-Type: application/json
api-key: YOUR_API_KEY
```

### Response

```json
{
  "items": [
    {
      "id": "deal_abc123def456",
      "name": "Acme Corp - Enterprise Loyalty Package",
      "attributes": {
        "deal_stage": "Qualified",
        "amount": 75000,
        "close_date": "2026-06-30",
        "pipeline": "Enterprise Sales",
        "deal_owner": "sarah.johnson@tajo.io"
      },
      "created_at": "2026-01-25T14:30:00Z",
      "updated_at": "2026-01-25T14:30:00Z"
    }
  ],
  "total": 1
}
```

### Filter Deals by Stage

```http
GET https://api.brevo.com/v3/crm/deals?filters[attributes.deal_stage]=Negotiation&sort=attributes.amount:desc
```

### Get Single Deal

```http
GET https://api.brevo.com/v3/crm/deals/{deal_id}
Content-Type: application/json
api-key: YOUR_API_KEY
```

## Update Deal

### Update Deal Attributes

```http
PATCH https://api.brevo.com/v3/crm/deals/{deal_id}
Content-Type: application/json
api-key: YOUR_API_KEY

{
  "attributes": {
    "deal_stage": "Negotiation",
    "amount": 82000,
    "probability": 75,
    "next_activity_date": "2026-02-15"
  }
}
```

### Response

```json
{
  "id": "deal_abc123def456",
  "updated_at": "2026-02-01T10:15:00Z"
}
```

## Deal Pipeline Management

### Pipeline Stage Configuration

Implement structured deal progression for e-commerce sales:

```javascript
class TajoDealPipeline {
  constructor() {
    this.dealsApi = new DealsApi();
    this.stages = [
      { name: 'Lead', probability: 10, actions: ['qualify_lead'] },
      { name: 'Qualified', probability: 25, actions: ['schedule_demo'] },
      { name: 'Demo', probability: 40, actions: ['send_proposal'] },
      { name: 'Proposal', probability: 60, actions: ['negotiate_terms'] },
      { name: 'Negotiation', probability: 80, actions: ['finalize_contract'] },
      { name: 'Closed Won', probability: 100, actions: ['onboard_customer', 'award_loyalty_points'] },
      { name: 'Closed Lost', probability: 0, actions: ['analyze_loss', 'schedule_followup'] }
    ];
  }

  async advanceDealStage(dealId, newStage) {
    const deal = await this.dealsApi.getDeal(dealId);
    const stageConfig = this.stages.find(s => s.name === newStage);

    if (!stageConfig) {
      throw new Error(`Invalid stage: ${newStage}`);
    }

    // Update deal with new stage
    await this.dealsApi.updateDeal(dealId, {
      attributes: {
        deal_stage: newStage,
        probability: stageConfig.probability,
        stage_changed_at: new Date().toISOString(),
        previous_stage: deal.attributes.deal_stage
      }
    });

    // Execute stage-specific actions
    for (const action of stageConfig.actions) {
      await this.executeStageAction(dealId, action, deal);
    }

    return { dealId, newStage, probability: stageConfig.probability };
  }

  async executeStageAction(dealId, action, deal) {
    switch (action) {
      case 'award_loyalty_points':
        if (deal.attributes.loyalty_points_bonus > 0) {
          await loyaltyService.awardCorporatePoints(
            deal.attributes.company_id,
            deal.attributes.loyalty_points_bonus,
            { reason: 'Deal closure bonus', dealId }
          );
        }
        break;

      case 'onboard_customer':
        await this.triggerOnboardingWorkflow(deal);
        break;

      case 'analyze_loss':
        await this.logDealLoss(dealId, deal);
        break;

      case 'schedule_followup':
        await this.createFollowUpTask(dealId, deal);
        break;
    }
  }
}
```

### Deal Forecasting

Generate revenue forecasts based on pipeline data:

```javascript
class DealForecasting {
  async generateForecast(pipeline, timeframe) {
    const deals = await this.dealsApi.getDeals({
      filters: {
        'attributes.pipeline': pipeline,
        'attributes.close_date': `<${timeframe.end}`,
        'attributes.deal_stage': '!Closed Lost'
      }
    });

    const forecast = {
      pipeline,
      timeframe,
      totalPipeline: 0,
      weightedPipeline: 0,
      byStage: {},
      byOwner: {},
      byMonth: {}
    };

    for (const deal of deals.items) {
      const amount = deal.attributes.amount || 0;
      const probability = deal.attributes.probability || 0;
      const weighted = amount * (probability / 100);
      const stage = deal.attributes.deal_stage;
      const owner = deal.attributes.deal_owner;
      const month = new Date(deal.attributes.close_date).toISOString().slice(0, 7);

      forecast.totalPipeline += amount;
      forecast.weightedPipeline += weighted;

      // Aggregate by stage
      if (!forecast.byStage[stage]) {
        forecast.byStage[stage] = { count: 0, total: 0, weighted: 0 };
      }
      forecast.byStage[stage].count++;
      forecast.byStage[stage].total += amount;
      forecast.byStage[stage].weighted += weighted;

      // Aggregate by owner
      if (!forecast.byOwner[owner]) {
        forecast.byOwner[owner] = { count: 0, total: 0, weighted: 0 };
      }
      forecast.byOwner[owner].count++;
      forecast.byOwner[owner].total += amount;
      forecast.byOwner[owner].weighted += weighted;

      // Aggregate by month
      if (!forecast.byMonth[month]) {
        forecast.byMonth[month] = { count: 0, total: 0, weighted: 0 };
      }
      forecast.byMonth[month].count++;
      forecast.byMonth[month].total += amount;
      forecast.byMonth[month].weighted += weighted;
    }

    return forecast;
  }
}
```

## E-Commerce Deal Automation

### Automated Deal Creation from Orders

Create deals automatically from high-value e-commerce activity:

```javascript
class EcommerceDealAutomation {
  async createDealFromOrder(order) {
    // Only create deals for high-value or B2B orders
    if (order.total < 5000 && !order.isB2B) return null;

    const deal = {
      name: `${order.customerName} - Order #${order.id}`,
      attributes: {
        deal_stage: order.isB2B ? 'Qualified' : 'Proposal',
        amount: order.total,
        close_date: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
        pipeline: order.isB2B ? 'Enterprise Sales' : 'E-Commerce Upsell',
        deal_type: 'new_business',
        source: 'ecommerce_order',
        order_id: order.id,
        product_categories: order.categories.join(', '),
        contact_id: order.contactId,
        company_id: order.companyId || null,
        loyalty_points_bonus: Math.floor(order.total * 0.1)
      }
    };

    return await this.dealsApi.createDeal(deal);
  }

  async createRenewalDeal(subscription) {
    const renewalDate = new Date(subscription.expiresAt);
    const createDate = new Date(renewalDate.getTime() - 90 * 24 * 60 * 60 * 1000);

    if (new Date() < createDate) return null;

    const deal = {
      name: `${subscription.customerName} - Renewal`,
      attributes: {
        deal_stage: 'Qualified',
        amount: subscription.annualValue,
        close_date: subscription.expiresAt,
        pipeline: 'Renewals',
        deal_type: 'renewal',
        probability: 70,
        source: 'auto_renewal',
        subscription_id: subscription.id,
        contact_id: subscription.contactId,
        company_id: subscription.companyId,
        contract_length_months: 12,
        loyalty_points_bonus: Math.floor(subscription.annualValue * 0.05)
      }
    };

    return await this.dealsApi.createDeal(deal);
  }
}
```

### Deal-Triggered Loyalty Workflows

```javascript
class DealLoyaltyIntegration {
  async onDealStageChange(dealId, oldStage, newStage) {
    const deal = await this.dealsApi.getDeal(dealId);

    // Award milestone points at key stages
    const milestoneStages = {
      'Demo': 100,
      'Proposal': 250,
      'Closed Won': deal.attributes.loyalty_points_bonus || 1000
    };

    if (milestoneStages[newStage] && deal.attributes.contact_id) {
      await loyaltyService.awardPoints(
        deal.attributes.contact_id,
        milestoneStages[newStage],
        { reason: `Deal milestone: ${newStage}`, dealId }
      );
    }

    // Trigger tier evaluation on deal closure
    if (newStage === 'Closed Won' && deal.attributes.company_id) {
      const company = await this.companiesApi.getCompany(deal.attributes.company_id);
      const newTotal = (company.attributes.annual_spend || 0) + deal.attributes.amount;

      await this.companiesApi.updateCompany(deal.attributes.company_id, {
        attributes: {
          annual_spend: newTotal,
          last_deal_closed: new Date().toISOString()
        }
      });

      await this.tierManager.evaluateTierUpgrade(deal.attributes.company_id, newTotal);
    }
  }
}
```

## Deal Analytics

### Pipeline Performance Metrics

```javascript
class DealAnalytics {
  async getPipelineMetrics(pipeline, timeframe) {
    const allDeals = await this.dealsApi.getDeals({
      filters: { 'attributes.pipeline': pipeline }
    });

    const closedDeals = allDeals.items.filter(
      d => d.attributes.deal_stage === 'Closed Won' || d.attributes.deal_stage === 'Closed Lost'
    );

    const wonDeals = closedDeals.filter(d => d.attributes.deal_stage === 'Closed Won');
    const lostDeals = closedDeals.filter(d => d.attributes.deal_stage === 'Closed Lost');

    return {
      totalDeals: allDeals.total,
      openDeals: allDeals.total - closedDeals.length,
      wonDeals: wonDeals.length,
      lostDeals: lostDeals.length,
      winRate: closedDeals.length > 0
        ? (wonDeals.length / closedDeals.length * 100).toFixed(1)
        : 0,
      totalRevenue: wonDeals.reduce((sum, d) => sum + (d.attributes.amount || 0), 0),
      averageDealSize: wonDeals.length > 0
        ? wonDeals.reduce((sum, d) => sum + (d.attributes.amount || 0), 0) / wonDeals.length
        : 0,
      averageSalesCycle: this.calculateAverageSalesCycle(wonDeals),
      loyaltyPointsAwarded: wonDeals.reduce(
        (sum, d) => sum + (d.attributes.loyalty_points_bonus || 0), 0
      )
    };
  }

  calculateAverageSalesCycle(wonDeals) {
    if (wonDeals.length === 0) return 0;

    const totalDays = wonDeals.reduce((sum, deal) => {
      const created = new Date(deal.created_at);
      const closed = new Date(deal.attributes.stage_changed_at || deal.updated_at);
      return sum + Math.floor((closed - created) / (1000 * 60 * 60 * 24));
    }, 0);

    return Math.round(totalDays / wonDeals.length);
  }
}
```

## API Methods Reference

### Deals CRUD Operations

```javascript
// Create a new deal
const deal = await dealsApi.createDeal({
  name: 'New Enterprise Deal',
  attributes: {
    deal_stage: 'Lead',
    amount: 50000,
    pipeline: 'Enterprise Sales'
  }
});

// Get deal by ID
const deal = await dealsApi.getDeal('deal_abc123def456');

// Update deal attributes
await dealsApi.updateDeal('deal_abc123def456', {
  attributes: {
    deal_stage: 'Negotiation',
    amount: 55000,
    probability: 80
  }
});

// Delete a deal
await dealsApi.deleteDeal('deal_abc123def456');

// List deals with filtering
const deals = await dealsApi.getDeals({
  filters: {
    'attributes.deal_stage': 'Qualified',
    'attributes.amount': '>10000'
  },
  sort: 'attributes.amount:desc',
  limit: 50
});
```

### Advanced Queries

```javascript
// Find deals closing this quarter
const quarterEnd = new Date();
quarterEnd.setMonth(quarterEnd.getMonth() + 3);
const closingDeals = await dealsApi.getDeals({
  filters: {
    'attributes.close_date': `<${quarterEnd.toISOString()}`,
    'attributes.deal_stage': '!Closed Won,!Closed Lost'
  }
});

// Find high-value stale deals (no update in 14 days)
const staleDate = new Date(Date.now() - 14 * 24 * 60 * 60 * 1000);
const staleDeals = await dealsApi.getDeals({
  filters: {
    'attributes.amount': '>25000',
    'updated_at': `<${staleDate.toISOString()}`,
    'attributes.deal_stage': '!Closed Won,!Closed Lost'
  }
});

// Get deals by owner for performance review
const ownerDeals = await dealsApi.getDeals({
  filters: {
    'attributes.deal_owner': 'sarah.johnson@tajo.io',
    'attributes.deal_stage': 'Closed Won'
  }
});
```

## Best Practices

1. **Consistent stages**: Define clear pipeline stages with expected actions at each stage
2. **Probability tracking**: Keep deal probabilities updated to improve forecast accuracy
3. **Timely updates**: Update deal attributes promptly to maintain accurate pipeline visibility
4. **Loyalty integration**: Link deal closures to loyalty point awards for customer retention
5. **Automated workflows**: Use stage-change triggers to automate follow-up tasks
6. **Regular pipeline review**: Schedule weekly pipeline reviews to identify stale or at-risk deals

## Error Handling

```javascript
try {
  const deal = await dealsApi.createDeal(dealData);
  console.log('Deal created:', deal.id);
} catch (error) {
  if (error.status === 400) {
    console.error('Invalid deal data:', error.message);
  } else if (error.status === 404) {
    console.error('Associated company or contact not found');
  } else if (error.status === 409) {
    console.error('Duplicate deal detected');
  } else {
    console.error('Unexpected error:', error);
  }
}
```

## Next Steps

- **[Companies Management](https://tajo.io/docs/sales-crm/companies)** - Manage B2B corporate accounts
- **[Task Management](https://tajo.io/docs/sales-crm/tasks)** - Manage deal activities and follow-ups
- **[Notes and Files](https://tajo.io/docs/sales-crm/notes)** - Document deal interactions
- **CRM Analytics** - Advanced reporting and insights
