Skip to main content

Deals & Pipelines

Model your sales process as pipelines and stages, then move deals through them — with automatic won/lost status and close stamping.

Overview

A pipeline is one sales process. Its stages are the ordered steps, each with a position, an optional win probability, and flags marking it as the won or lost terminus. A deal sits in exactly one stage of one pipeline.

Moving a deal onto a stage flagged is_won or is_lost sets the deal's status and stamps closed_at for you — you do not manage those by hand.

Authentication

Authorization: Bearer cm_your_api_key

Pipelines and deals share one scope pair.

OperationScope
Read pipelines, stages, dealscrm_deals:read
Create, update, move, deletecrm_deals:write

Pipelines

{
  "id": "11aa…",
  "tenant_id": "a0b1…",
  "name": "Inbound",
  "is_default": true,
  "created_at": "2026-08-01T09:00:00Z",
  "updated_at": "2026-08-01T09:00:00Z"
}

Exactly one pipeline may be the default. Setting is_default: true clears the flag on the others in the same transaction.

MethodPathNotes
GET/api/v1/crm/pipelinesDefault first, then oldest first. limit 1..200 (default 50), offset 0..100000
POST/api/v1/crm/pipelines201. name 1–255 characters, unique per tenant (409 A pipeline with this name already exists); is_default default false
GET/api/v1/crm/pipelines/{pipeline_id}
PATCH/api/v1/crm/pipelines/{pipeline_id}name, is_default
DELETE/api/v1/crm/pipelines/{pipeline_id}204, and its stages are deleted with it. 409 Move or delete the deals here first if it still holds deals

Stages

{
  "id": "22bb…",
  "tenant_id": "a0b1…",
  "pipeline_id": "11aa…",
  "name": "Negotiation",
  "position": 3,
  "probability": 60,
  "is_won": false,
  "is_lost": false,
  "created_at": "2026-08-01T09:01:00Z",
  "updated_at": "2026-08-01T09:01:00Z"
}

GET /api/v1/crm/pipelines/{pipeline_id}/stages

Ordered by position. No pagination — a pipeline's stage list is always returned whole.

POST /api/v1/crm/pipelines/{pipeline_id}/stages

FieldTypeRequiredConstraints
namestringYes1–255 characters, not blank
positionintegerNo0 <= position <= 10000. Omit to append after the current last stage
probabilitynumberNo0 <= probability <= 100, as a percentage
is_wonbooleanNoDefault false
is_lostbooleanNoDefault false

A stage cannot be both — 422 A stage cannot be both won and lost. Returns 201.

curl -X POST https://api.callmissed.com/api/v1/crm/pipelines/11aa…/stages \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Won", "probability": 100, "is_won": true }'

PATCH /api/v1/crm/pipelines/stages/{stage_id} · DELETE /api/v1/crm/pipelines/stages/{stage_id}

PATCH accepts name, position, probability, is_won and is_lost, all optional, with the same bounds. The won/lost rule is checked against the merged result. Changing a stage's flags does not re-close or re-open deals already on it.

DELETE returns 204, or 409 Move or delete the deals here first when deals still sit on it.

PATCH /api/v1/crm/pipelines/{pipeline_id}/stages/reorder

FieldTypeRequiredConstraints
stage_idsUUID[]Yes1–100 entries. Must be every stage of this pipeline, exactly once

New position is the array index. Returns the stages in their new order.

A list with repeats returns 422 stage_ids contains duplicates; a list that misses a stage or includes one from another pipeline returns 422 stage_ids must list every stage in this pipeline, exactly once. Either way nothing changes.


Deals

The deal object

{
  "id": "33cc…",
  "tenant_id": "a0b1…",
  "title": "Acme — 3 voice agents",
  "value": 240000.0,
  "currency": "INR",
  "pipeline_id": "11aa…",
  "stage_id": "22bb…",
  "contact_id": "4411…",
  "company_id": "5c6d…",
  "owner_user_id": "b1f2…",
  "status": "open",
  "expected_close_date": "2026-09-15",
  "closed_at": null,
  "lost_reason": null,
  "last_activity_at": "2026-08-16T12:05:00Z",
  "created_at": "2026-08-05T09:00:00Z",
  "updated_at": "2026-08-16T12:05:00Z"
}
FieldTypeNotes
statusstringopen, won or lost. Driven by the stage — see below
currencystringISO 4217, three letters, upper-cased. Default INR
closed_atdatetime | nullStamped when the deal lands on a won or lost stage. Moving between won and lost keeps the original time; re-opening clears it
lost_reasonstring | nullWhy the deal was lost, up to 255 characters. Kept only while status is lost; cleared when the deal is re-opened or won
last_activity_atdatetime | nullSet on create and bumped on every update or move

GET /api/v1/crm/deals

Newest first.

ParameterTypeConstraints
pipeline_idUUID
stage_idUUID
statusstringopen, won or lost. Anything else is 422
owner_user_idUUID
contact_idUUID
company_idUUID
limitinteger1 <= limit <= 200, default 50
offsetinteger0 <= offset <= 100000, default 0

GET /api/v1/crm/deals/summary

Board totals for one pipeline, over every deal rather than one page: the count, value and weighted value of each stage (in board order, empty stages included) and of the whole pipeline.

ParameterTypeConstraints
pipeline_idUUIDRequired. Must be your pipeline, otherwise 404
statusstringopen, won or lost. Anything else is 422
owner_user_idUUID
contact_idUUID
company_idUUID

weighted_value is value × probability / 100 using the deal's stage probability. A stage with no probability counts at 100 when it is a won stage and 0 otherwise. Amounts in different currencies are never added together — totals has one entry per currency, sorted by currency.

{
  "pipeline_id": "11aa…",
  "count": 14,
  "totals": [{ "currency": "INR", "value": 2400000.0, "weighted_value": 610000.0 }],
  "stages": [
    {
      "stage_id": "22bb…",
      "count": 6,
      "totals": [{ "currency": "INR", "value": 900000.0, "weighted_value": 180000.0 }]
    }
  ]
}

POST /api/v1/crm/deals

FieldTypeRequiredConstraints
titlestringYes1–255 characters, not blank
pipeline_idUUIDYesMust be your pipeline
stage_idUUIDNoMust belong to that pipeline. Omit to start at the lowest-position stage
valuenumberNo0 <= value <= 999999999999.99
currencystringNoExactly 3 letters, default INR
contact_idUUIDNo
company_idUUIDNo
owner_user_idUUIDNoMust be a user in your tenant
expected_close_datedateNo
lost_reasonstringNoUp to 255 characters. Kept only if the deal starts on a lost stage
curl -X POST https://api.callmissed.com/api/v1/crm/deals \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Acme — 3 voice agents",
    "pipeline_id": "11aa…",
    "value": 240000,
    "company_id": "5c6d…",
    "expected_close_date": "2026-09-15"
  }'

Returns 201. Creating straight onto a won or lost stage closes the deal immediately.

Creating in a pipeline that has no stages yet returns 422 This pipeline has no stages yet — add stages first.

POST /api/v1/crm/deals/{deal_id}/move

FieldTypeRequired
stage_idUUIDYes
lost_reasonstringNo. Up to 255 characters; recorded only when the stage is flagged is_lost

The one call you want for a kanban drag. The stage must belong to the deal's pipeline — 422 Stage does not belong to this pipeline otherwise.

curl -X POST https://api.callmissed.com/api/v1/crm/deals/33cc…/move \
  -H "Authorization: Bearer cm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "stage_id": "22bb…" }'

Returns the updated deal.

What a move does to status

Destination stageEffect
is_wonstatus becomes won, closed_at stamped if unset
is_loststatus becomes lost, closed_at stamped if unset
Neitherstatus returns to open, closed_at and lost_reason are cleared

So re-opening a deal is just moving it back to a working stage.

GET / PATCH / DELETE /api/v1/crm/deals/{deal_id}

PATCH accepts title, value, currency, contact_id, company_id, owner_user_id, expected_close_date, stage_id, status and lost_reason, all optional, with the same bounds as create. pipeline_id cannot be changed.

  • stage_id follows the same rules as a move: it must belong to the deal's pipeline, and it sets status and closed_at as in the table above.
  • status (open, won or lost) marks the deal closed or open without moving it. Sent together with stage_id, the explicit status wins. won/lost stamps closed_at if unset; open clears it.

DELETE returns 204.


Errors

StatusWhen
403Key is missing crm_deals:read / crm_deals:write
404Deal, pipeline, stage, contact, company or owner not in your tenant
409Duplicate pipeline name, or a pipeline/stage that still holds deals
422Blank name/title, a stage outside the deal's pipeline, a stage flagged both won and lost, an incomplete reorder list, or an empty pipeline

Nothing on this page consumes credits.