Skip to main content

Pipelines

The stages a deal moves through, in order, each with the probability a forecast weights an open deal by. Read-only: a pipeline is how one business sells, and its stages are named by the people who sell that way in the console. The API reads them so a deal can be created in the right one and moved to the right stage; it never edits them.

Scopes and the site rule are shared with every CRM resource — see companies.

The pipeline object​

{
"id": "p_7b2e",
"object": "pipeline",
"name": "Sales",
"isDefault": true,
"archived": false,
"archivedAt": null,
"stages": [
{ "id": "prospecting", "name": "Prospecting", "order": 0, "probability": 10, "kind": "open", "forecastCategory": "pipeline" },
{ "id": "qualification", "name": "Qualification", "order": 1, "probability": 10, "kind": "open", "forecastCategory": "pipeline" },
{ "id": "needs-analysis", "name": "Needs Analysis", "order": 2, "probability": 20, "kind": "open", "forecastCategory": "pipeline" },
{ "id": "value-proposition", "name": "Value Proposition", "order": 3, "probability": 50, "kind": "open", "forecastCategory": "pipeline" },
{ "id": "id-decision-makers", "name": "Id. Decision Makers", "order": 4, "probability": 60, "kind": "open", "forecastCategory": "pipeline" },
{ "id": "perception-analysis", "name": "Perception Analysis", "order": 5, "probability": 70, "kind": "open", "forecastCategory": "pipeline" },
{ "id": "proposal-price-quote", "name": "Proposal/Price Quote", "order": 6, "probability": 75, "kind": "open", "forecastCategory": "bestCase" },
{ "id": "negotiation-review", "name": "Negotiation/Review", "order": 7, "probability": 90, "kind": "open", "forecastCategory": "commit" },
{ "id": "won", "name": "Closed Won", "order": 8, "probability": 100, "kind": "won", "forecastCategory": "closed" },
{ "id": "lost", "name": "Closed Lost", "order": 9, "probability": 0, "kind": "lost", "forecastCategory": "omitted" }
],
"siteId": "site_a1b2c3",
"created": "2026-09-05T18:23:23.941Z",
"updated": "2026-09-05T18:23:23.941Z"
}
FieldTypeNotes
idstringOpaque pipeline id. Pass it as a deal's pipelineId.
objectstringAlways "pipeline".
namestringAs named in the console.
isDefaultbooleanThe pipeline a new deal lands in when its create names none. Only an active pipeline is ever the default.
archivedbooleanWhether the pipeline has been retired in the console — see below.
archivedAtstring | nullISO 8601, when it was; null while active.
stagesarrayIn pipeline order. Each has id (pass it as a deal's stageId), name, order, probability (0–100, the odds of an open deal closing from here), kind — open, won or lost — and forecastCategory, the forecast category a deal moved into the stage takes: omitted, pipeline, bestCase, commit or closed. A stage saved without one reads as its kind's — closed for won, omitted for lost, pipeline for open. A pipeline has one won and one lost stage; open is everything between.
siteIdstringThe site the pipeline was created from.
created / updatedstring | nullISO 8601.

A pipeline is seeded by the first deal​

An organization that has never opened the CRM has no pipeline, and a deal cannot exist without a stage. So the first POST /v1/deals that names no pipelineId creates one — named Sales, with Salesforce's standard Opportunity stages above, marked as the default, and stored for the site the deal names. A pipeline seeded before these stages became the default keeps its own; nothing migrates a stored pipeline. Every later deal from a site that can see it lands in it. You never have to create a pipeline before creating a deal, and GET /v1/pipelines on a fresh organization legitimately returns an empty list.

An archived pipeline takes no new deal​

A pipeline the console has archived is still listed and still retrievable: the deals it closed name it, and a client resolving their stageId needs its stages. But a POST /v1/deals that names it is a 400 naming pipelineId, and a create that names no pipeline lands in the default among the active ones. A deal already in an archived pipeline can still be moved — reopened, won, lost — because its stages resolve.

Endpoints​

List pipelines​

GET /v1/pipelines — scope crm:read. Paginated, ordered by id; ?updatedAfter= works as on every CRM list.

curl "https://app.aglyn.com/api/v1/pipelines" \
-H "Authorization: Bearer aglyn_sk_…"

Read this once and cache it: stage ids are stable, and a deal's stageId is only meaningful against its pipeline's stages.

Retrieve a pipeline​

GET /v1/pipelines/{pipelineId} — scope crm:read. Returns a pipeline, or 404 not_found ("No such pipeline").

Errors​

StatustypeWhen
403insufficient_scopeKey lacks crm:read. Checked before the method, so a POST with a read-less key is a 403, not a 405.
404not_found"No such pipeline".
405method_not_allowedAnything other than GET. The Allow header says GET — there is deliberately no write scope for a pipeline's stages, which are edited in the console where the people who sell can see what a rename does to their reports.

See Conventions → Errors for the shared envelope.

  • Deals — created in a pipeline and moved through its stages.