Ζητήστε πρώιμη πρόσβαση

Συμπληρώστε το όνομά σας και ένα email ή έναν αριθμό τηλεφώνου. Θα σας στείλουμε πληροφορίες για την πρόσβαση στο Tajo.

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

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": "[email protected]",
"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

{
"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:

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

Response

{
"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": "[email protected]"
},
"created_at": "2026-01-25T14:30:00Z",
"updated_at": "2026-01-25T14:30:00Z"
}
],
"total": 1
}

Filter Deals by Stage

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

Get Single Deal

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

Update Deal

Update Deal Attributes

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

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

Deal Pipeline Management

Pipeline Stage Configuration

Implement structured deal progression for e-commerce sales:

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:

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:

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

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

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

// 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

// 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': '[email protected]',
'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

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

Ζητήστε πρώιμη πρόσβαση

Συμπληρώστε το όνομά σας και ένα email ή έναν αριθμό τηλεφώνου. Θα σας στείλουμε πληροφορίες για την πρόσβαση στο Tajo.

αυτόματη αναγνώριση
AI Βοηθός

Γεια! Ρωτήστε με οτιδήποτε για την τεκμηρίωση.