Documentation

Tasks and opportunities

Sales pipelines, deal stages, follow-up tasks, and lead conversion.

In AppEngine CRM, opportunities are deals progressing through a sales pipeline, and tasks are the follow-up actions a salesperson schedules against a contact, lead, or deal. Both live under the leads controller because the pipeline machinery is shared — a lead becomes an opportunity by being moved into a "deal" pipeline.

Pipelines

A pipeline is a named ordered list of stages. Most orgs run two: a lead pipeline (new → qualified → demo → proposal → won/lost) and a deal/opportunity pipeline (discovery → negotiation → closing → closed-won/closed-lost).

POST/crm/leads/pipelinesJWT
GET/crm/leads/pipelinesJWT
GET/crm/leads/pipelines/:idJWT
PUT/crm/leads/pipelines/:idJWT
DELETE/crm/leads/pipelines/:idJWT
{
  "name": "Enterprise Deals",
  "type": "opportunity",
  "stages": [
    { "name": "Discovery", "probability": 10 },
    { "name": "Demo", "probability": 30 },
    { "name": "Proposal", "probability": 60 },
    { "name": "Negotiation", "probability": 80 },
    { "name": "Closed Won", "probability": 100, "terminal": true },
    { "name": "Closed Lost", "probability": 0, "terminal": true }
  ],
  "routingRules": [
    { "stage": "Demo", "assignTo": "user-rep-east" }
  ]
}

Stage management

POST/crm/leads/pipelines/stages/:idJWT
PUT/crm/leads/pipelines/stages/:id/:stageIdJWT
DELETE/crm/leads/pipelines/stages/:id/:stageIdJWT
PUT/crm/leads/pipelines/stages/reorder/:idJWT

Reorder accepts an array of stage IDs in the new order — the stages drag-reorder UI calls this once on drop.

Routing unassigned

POST/crm/leads/pipelines/:id/route-unassignedJWT

Runs the pipeline's routingRules against every lead/opportunity that doesn't yet have an owner. Useful after adding a new rep or rebalancing territories.

Lead and opportunity CRUD

The same endpoints handle both — pipeline membership is what distinguishes them.

POST/crm/leads/detailJWT
GET/crm/leads/detailJWT
GET/crm/leads/detail/:idJWT
PUT/crm/leads/detail/:idJWT
DELETE/crm/leads/detail/:idJWT

A lead body:

{
  "contactId": "contact-abc",
  "pipelineId": "pipe-enterprise",
  "stageId": "stage-discovery",
  "value": 25000,
  "currency": "USD",
  "expectedCloseDate": "2026-07-15",
  "owner": "user-rep-east"
}

Lifecycle actions

POST/crm/leads/qualify/:idJWT
POST/crm/leads/disqualify/:idJWT
POST/crm/leads/convert/:idJWT
POST/crm/leads/assign/:idJWT
POST/crm/leads/follow-up/:idJWT

qualify moves a lead to the next pipeline stage and stamps qualifiedAt. convert takes a qualified lead and creates an opportunity in the deals pipeline (and optionally a customer record). follow-up schedules a task — the next-action workflow most reps live in.

Tasks (follow-up)

A follow-up task is the simplest task in the system. The endpoint accepts due date, assignee, and notes:

await fetch(`/api/crm/leads/follow-up/${leadId}`, {
  method: 'POST',
  headers: { orgid: ORG_ID, Authorization: `Bearer ${jwt}` },
  body: JSON.stringify({
    dueAt: '2026-04-30T10:00:00Z',
    assignTo: 'user-rep-east',
    notes: 'Follow up on demo recap email',
  }),
});

For richer task management — recurring tasks, subtasks, dependencies — use the Automation module which can create tasks as a workflow action against any record.

Activities

POST/crm/leads/activities/:idJWT
GET/crm/leads/activities/:idJWT

Lead-scoped activities (calls, emails, meetings, notes). The org-wide activity log lives separately under /crm/activity — see Activities and audit.

Lead scoring

POST/crm/leads/score/:idJWT
POST/crm/leads/score/batchJWT
GET/crm/leads/analyticsJWT

Scores feed routing, prioritisation, and analytics. Configure scoring rules in the Rule Engine. The batch endpoint re-scores a list of lead IDs — use it nightly or after rule changes.

Enrichment

POST/crm/leads/enrich/:idJWT
POST/crm/leads/enrich/batchJWT
POST/crm/leads/enrich/autoJWT
GET/crm/leads/enrichment/status/:idJWT

Pulls firmographic and contact data from the Data Enrichment provider configured for the org. auto runs enrichment on every new lead matching a filter.

Stage transitions emit lead.stage_changed events. Wire these to automations to send nurture emails, notify reps, or update revenue forecasts.