Pipelines

A pipeline is an ordered list of stages that deals move through, such as Lead, Qualified, Proposal, Won, and Lost. Each stage has an outcome: open, won, or lost. Every open stage has a likelihood between 0 and 1, which Carom multiplies by a deal’s amount to get its expected value. Use this resource to set up pipelines and their stages and to pull pipeline reports.

Pipelines decide who sees deals. A pipeline is visible to your key when your key’s user created it, was added to it directly or through a group, or when it is public, and its deals are visible to exactly the same people. Only the creator and members flagged as admins can change or delete a pipeline.

#The pipeline object

Returned by every pipeline endpoint except the report. stages holds only active stages; stages removed with Update a pipeline are left out.

Attributes

  • idstring · uuid

    Unique identifier for the pipeline.

  • namestring
  • descriptionstring · nullable
  • positioninteger · nullable

    Order among pipelines, lowest first. Pipelines without a position come after the rest, oldest first.

  • publicboolean

    When true, everyone in the account can see the pipeline and its deals.

  • tracks_amountboolean

    Whether amounts in this pipeline count toward totals. When false, deals can still store an amount, but it is left out of deal summary values and deal report expected values.

  • dealmaker_enabledboolean

    Whether the deal agent (auto_deal) works this pipeline, proposing new deals and stage moves from incoming email.

  • created_by_user_idstring · uuid · nullable
  • admin_user_idsarray of strings · uuid

    The users who can change or delete the pipeline: its creator and every member flagged as an admin. Membership through a group never makes someone an admin.

  • open_deal_countinteger

    Number of open deals in the pipeline.

  • open_deal_valuenumber

    Total amount of the open deals.

  • pinnedboolean · nullable

    Whether your key’s user has pinned this pipeline.

  • stagesarray of objects

    The active stages, in order.

    Show 9 child attributesHide child attributes
    • idstring · uuid
    • namestring
    • positioninteger

      Zero-based order within the pipeline.

    • outcomestring

      What a deal in this stage is. Fixed when the stage is created.

      openwonlost
    • likelihoodnumber · nullable

      Between 0 and 1. A deal’s expected value is its amount times this. Set on every open stage; null on won and lost stages.

    • entry_criteriastring · nullable

      What a deal must show to belong in this stage, written by your team. The deal agent reads it when proposing stage moves.

    • deal_countinteger

      Deals currently in the stage, whatever their status.

    • open_deal_countinteger

      Open deals currently in the stage.

    • open_deal_valuenumber

      Total amount of those open deals. 0 when there are none.

  • usersarray of users · nullable

    Users added to the pipeline directly.

  • groupsarray of groups · nullable

    Groups whose members can see the pipeline.

The pipeline object
{
  "id": "5e8a1c3f-7b2d-4f6e-a9c0-3d1b7e4f2a86",
  "name": "New business",
  "description": "First contracts with property managers and logistics firms.",
  "position": 0,
  "public": false,
  "tracks_amount": true,
  "dealmaker_enabled": true,
  "created_by_user_id": "9c41d2e8-3f6a-4b7c-8d1e-5a2f7b9c0d3e",
  "admin_user_ids": ["9c41d2e8-3f6a-4b7c-8d1e-5a2f7b9c0d3e"],
  "open_deal_count": 12,
  "open_deal_value": 214500.0,
  "pinned": true,
  "stages": [
    {
      "id": "a1c4e7f2-3b6d-4a8e-9c1f-5d2b8e0a4c71",
      "name": "Lead",
      "position": 0,
      "outcome": "open",
      "likelihood": 0.2,
      "entry_criteria": "A named contact has replied about pricing or scope.",
      "deal_count": 5,
      "open_deal_count": 5,
      "open_deal_value": 62000.0
    },
    {
      "id": "b2d5f8a3-4c7e-4b9f-8d2a-6e3c9f1b5d82",
      "name": "Qualified",
      "position": 1,
      "outcome": "open",
      "likelihood": 0.5,
      …
    },
    {
      "id": "c3e6a9b4-5d8f-4cab-9e3b-7f4dab2c6e93",
      "name": "Proposal",
      "position": 2,
      "outcome": "open",
      "likelihood": 0.7,
      …
    },
    {
      "id": "d4f7bac5-6e9a-4dbc-8f4c-8a5ebc3d7fa4",
      "name": "Won",
      "position": 3,
      "outcome": "won",
      "likelihood": null,
      "entry_criteria": null,
      "deal_count": 9,
      "open_deal_count": 0,
      "open_deal_value": 0.0
    },
    {
      "id": "e5a8cbd6-7fab-4ecd-9a5d-9b6fcd4e8ab5",
      "name": "Lost",
      "position": 4,
      "outcome": "lost",
      "likelihood": null,
      …
    }
  ],
  "users": [
    {
      "id": "7a3d5f1b-2e8c-4d6a-9f0b-4c1e7a3d9b28",
      "first_name": "Owen",
      "last_name": "Price",
      …
    }
  ],
  "groups": []
}
get/pipelines Read key

#List pipelines

Returns every pipeline visible to your key in one response, ordered by position and then by creation; the list isn’t paginated. It takes no parameters.

Returns

get/pipelines
curl https://api.carom.io/pipelines \
  -H "Authorization: Bearer $CAROM_API_KEY"
Response200
{
  "pipelines": [
    {
      "id": "5e8a1c3f-7b2d-4f6e-a9c0-3d1b7e4f2a86",
      "name": "New business",
      "position": 0,
      "open_deal_count": 12,
      "open_deal_value": 214500.0,
      …
    },
    {
      "id": "9d0e1f2a-3b4c-4d5e-8f6a-7b8c9d0e1f2a",
      "name": "Renewals",
      "position": 1,
      "open_deal_count": 4,
      "open_deal_value": 88000.0,
      …
    }
  ]
}
post/pipelines Write key

#Create a pipeline

Creates a pipeline with your key’s user as its creator and first admin. List the stages in the order deals move through them. Without stages, the pipeline gets Lead (0.2), Qualified (0.5), Proposal (0.7), Won, and Lost.

Headers

  • Idempotency-Keystring

    A key you choose, 1 to 255 printable ASCII characters, that makes the request safe to retry. When your key’s user repeats a request to this endpoint with the same key within 24 hours of a successful one, Carom returns the first response again instead of creating a second pipeline. The request body isn’t compared, so use a new key for each new pipeline. A failed request doesn’t use up its key.

Request body application/json

  • pipelineobjectrequired
    Show 10 child attributesHide child attributes
    • namestringrequired
    • descriptionstring
    • positioninteger
    • publicbooleandefault false
    • tracks_amountbooleandefault true
    • dealmaker_enabledbooleandefault false
    • user_idsarray of strings · uuid

      Users to add as members. Ids of users outside your account are ignored; users in the response shows who was added.

    • admin_user_idsarray of strings · uuid

      Which of user_ids are admins. Ids not in user_ids are ignored.

    • group_idsarray of strings · uuid

      Groups whose members can see the pipeline. Ids outside your account are ignored; groups in the response shows which were added.

    • stagesarray of objects

      The stages, in order.

      Show 4 child attributesHide child attributes
      • namestringrequired
      • outcomestringdefault open
        openwonlost
      • likelihoodnumber

        Between 0 and 1. Required for open stages; must be omitted or null for won and lost stages.

      • entry_criteriastring

        Up to 2,000 characters.

Returns

The new pipeline object, wrapped in pipeline, with status 201.

Errors

  • 400invalid_requestA field failed validation, for example an open stage without a likelihood or a won stage with one, or the Idempotency-Key header is malformed. error.fields says which.
  • 409idempotency_key_in_useA request with the same Idempotency-Key is still in progress. Retry shortly.
post/pipelines
curl https://api.carom.io/pipelines \
  -H "Authorization: Bearer $CAROM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8c3a6f0d-2e9b-4d17-a5c8-4b0e9f6d2a13" \
  -d '{
    "pipeline": {
      "name": "Renewals",
      "user_ids": ["7a3d5f1b-2e8c-4d6a-9f0b-4c1e7a3d9b28"],
      "stages": [
        { "name": "Up for renewal", "likelihood": 0.6 },
        { "name": "Terms sent", "likelihood": 0.85 },
        { "name": "Renewed", "outcome": "won" },
        { "name": "Churned", "outcome": "lost" }
      ]
    }
  }'
Response201
{
  "pipeline": {
    "id": "9d0e1f2a-3b4c-4d5e-8f6a-7b8c9d0e1f2a",
    "name": "Renewals",
    "public": false,
    "tracks_amount": true,
    "dealmaker_enabled": false,
    "admin_user_ids": ["9c41d2e8-3f6a-4b7c-8d1e-5a2f7b9c0d3e"],
    "open_deal_count": 0,
    "open_deal_value": 0.0,
    "stages": [
      {
        "id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
        "name": "Up for renewal",
        "position": 0,
        "outcome": "open",
        "likelihood": 0.6,
        …
      },
      …
    ],
    …
  }
}
get/pipelines/{id} Read key

#Retrieve a pipeline

Returns a single pipeline with its active stages and their deal counts. To list the deals themselves, use List deals with pipeline_id.

Path parameters

  • idstring · uuidrequired

    The pipeline’s id.

Returns

The pipeline object, wrapped in pipeline.

Errors

  • 404record_not_foundNo pipeline with that id is visible to your key.
get/pipelines/{id}
curl https://api.carom.io/pipelines/5e8a1c3f-7b2d-4f6e-a9c0-3d1b7e4f2a86 \
  -H "Authorization: Bearer $CAROM_API_KEY"
Response200
{
  "pipeline": {
    "id": "5e8a1c3f-7b2d-4f6e-a9c0-3d1b7e4f2a86",
    "name": "New business",
    "open_deal_count": 12,
    "open_deal_value": 214500.0,
    "stages": [
      {
        "id": "a1c4e7f2-3b6d-4a8e-9c1f-5d2b8e0a4c71",
        "name": "Lead",
        "position": 0,
        "outcome": "open",
        "likelihood": 0.2,
        "deal_count": 5,
        "open_deal_count": 5,
        "open_deal_value": 62000.0,
        …
      },
      …
    ],
    …
  }
}
patch/pipelines/{id} Write key

#Update a pipeline

Changes the fields you send and leaves the rest alone. Only the pipeline’s admins can update it. user_ids and group_ids, when sent, replace the current lists.

stages, when sent, is the complete new list of stages in order. Include every active stage exactly once by id; leaving one out is an error, not a removal. An entry without an id adds a stage. To remove a stage, send {"id": …, "removal": {…}} in its place. If the stage holds deals, name a replacement_stage_id: an existing open stage that stays in the pipeline. Carom moves the deals there and records each move in the deal’s transitions. A won or lost stage that holds deals can’t be removed, and at least one stage must remain.

Path parameters

  • idstring · uuidrequired

Request body application/json

  • pipelineobjectrequired

    Any of the attributes accepted by Create a pipeline. A null for public, tracks_amount, or dealmaker_enabled is ignored. Omit admin_user_ids to keep current admins as they are; send it to set exactly which members are admins.

    Show 1 child attributeHide child attributes
    • stagesarray of objects

      Each entry is either a stage to keep or add, or a removal.

      Show 6 child attributesHide child attributes
      • idstring · uuid

        An existing stage. Omit to add a new one. Required on a removal.

      • namestring

        Required on every entry except a removal.

      • outcomestring

        For a new stage; defaults to open. An existing stage’s outcome can’t change, so you can omit it.

        openwonlost
      • likelihoodnumber

        Required for open stages, including existing ones; must be omitted or null for won and lost stages.

      • entry_criteriastring

        Up to 2,000 characters.

      • removalobject

        Removes the stage named by id. Can’t be combined with name, outcome, likelihood, or entry_criteria.

        Show 1 child attributeHide child attributes
        • replacement_stage_idstring · uuid · nullable

          Where the stage’s deals go. Required when the stage holds deals.

Returns

  • pipelinepipeline

    The updated pipeline.

  • stage_removalsarray of objects

    One entry per stage removed by this request. Empty when none were.

    Show 3 child attributesHide child attributes
    • stage_idstring · uuid
    • replacement_stage_idstring · uuid · nullable
    • moved_deal_countinteger

      Deals moved to the replacement stage.

Errors

  • 400invalid_requestA field failed validation, or the stages list breaks one of the rules above. error.fields names the entry, such as stages.1.removal.replacement_stage_id.
  • 403permission_deniedThe pipeline is visible to your key, but your key’s user isn’t one of its admins.
  • 404record_not_foundNo pipeline with that id is visible to your key.
patch/pipelines/{id}
curl -X PATCH https://api.carom.io/pipelines/5e8a1c3f-7b2d-4f6e-a9c0-3d1b7e4f2a86 \
  -H "Authorization: Bearer $CAROM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "pipeline": {
      "stages": [
        { "id": "a1c4e7f2-3b6d-4a8e-9c1f-5d2b8e0a4c71", "name": "Lead", "likelihood": 0.2 },
        {
          "id": "b2d5f8a3-4c7e-4b9f-8d2a-6e3c9f1b5d82",
          "removal": { "replacement_stage_id": "c3e6a9b4-5d8f-4cab-9e3b-7f4dab2c6e93" }
        },
        { "id": "c3e6a9b4-5d8f-4cab-9e3b-7f4dab2c6e93", "name": "Proposal", "likelihood": 0.7 },
        { "id": "d4f7bac5-6e9a-4dbc-8f4c-8a5ebc3d7fa4", "name": "Won" },
        { "id": "e5a8cbd6-7fab-4ecd-9a5d-9b6fcd4e8ab5", "name": "Lost" }
      ]
    }
  }'
Response200
{
  "pipeline": {
    "id": "5e8a1c3f-7b2d-4f6e-a9c0-3d1b7e4f2a86",
    "name": "New business",
    "stages": [
      { "id": "a1c4e7f2-3b6d-4a8e-9c1f-5d2b8e0a4c71", "name": "Lead", "position": 0, … },
      { "id": "c3e6a9b4-5d8f-4cab-9e3b-7f4dab2c6e93", "name": "Proposal", "position": 1, … },
      { "id": "d4f7bac5-6e9a-4dbc-8f4c-8a5ebc3d7fa4", "name": "Won", "position": 2, … },
      { "id": "e5a8cbd6-7fab-4ecd-9a5d-9b6fcd4e8ab5", "name": "Lost", "position": 3, … }
    ],
    …
  },
  "stage_removals": [
    {
      "stage_id": "b2d5f8a3-4c7e-4b9f-8d2a-6e3c9f1b5d82",
      "replacement_stage_id": "c3e6a9b4-5d8f-4cab-9e3b-7f4dab2c6e93",
      "moved_deal_count": 3
    }
  ]
}
delete/pipelines/{id} Write key

#Delete a pipeline

Permanently deletes a pipeline that holds no deals, open or closed, along with its stages, members, group grants, and stage history. Only the pipeline’s admins can delete it. Deals can’t be moved to another pipeline, so delete its deals first.

Path parameters

  • idstring · uuidrequired

Returns

An empty response with status 204.

Errors

  • 403permission_deniedThe pipeline is visible to your key, but your key’s user isn’t one of its admins.
  • 404record_not_foundNo pipeline with that id is visible to your key.
  • 422pipeline_not_emptyThe pipeline still holds deals. The message says how many.
delete/pipelines/{id}
curl -X DELETE https://api.carom.io/pipelines/9d0e1f2a-3b4c-4d5e-8f6a-7b8c9d0e1f2a \
  -H "Authorization: Bearer $CAROM_API_KEY"
Response204
No content
get/pipelines/{id}/report Read key

#Retrieve a pipeline report

Returns one pipeline’s stages and one flat row per deal, with each deal’s path through the stages, for building your own reports such as conversion rates and time in stage. The report holds every open deal and every deal won or lost in the last 24 months, newest first, up to 10,000 deals. Filter and aggregate the rows yourself.

If there are more than 10,000 such deals, Carom leaves out the ones created longest ago, open or closed, and says so with truncated and omitted_count.

stages includes removed stages, so you can label every stage a deal passed through.

Path parameters

  • idstring · uuidrequired

Returns

  • reportobject
    Show 9 child attributesHide child attributes
    • pipeline_idstring · uuid
    • generated_atstring · date-time
    • window_monthsinteger

      How far back closed deals go. Currently 24.

    • total_openinteger

      Open deals in the pipeline.

    • total_closed_in_windowinteger

      Deals won or lost within the window.

    • truncatedboolean

      True when some deals were left out to stay within 10,000.

    • omitted_countinteger

      How many deals were left out.

    • stagesarray of objects

      Active stages in order, then removed ones.

      Show 6 child attributesHide child attributes
      • idstring · uuid
      • namestring
      • positioninteger · nullable

        Null for removed stages. Active stages are renumbered from 0 whenever the stages change, so a removed stage’s old position may now belong to another stage.

      • outcomestring
        openwonlost
      • likelihoodnumber · nullable

        Null on won and lost stages.

      • archived_atstring · date-time · nullable

        When the stage was removed. Null for active stages.

    • dealsarray of objects

      Newest first.

      Show 15 child attributesHide child attributes
      • idstring · uuid
      • namestring
      • statusstring
        openwonlost
      • pipeline_stage_idstring · uuid
      • amountnumber · nullable
      • currencystring
      • expected_valuenumber · nullable

        For an open deal, amount times its stage’s likelihood; the full amount for a won deal; 0 for a lost one. Null when the deal has no amount.

      • owner_user_idstring · uuid · nullable
      • created_atstring · date-time
      • expected_close_datestring · date · nullable
      • closed_atstring · date-time · nullable
      • lost_reasonstring · nullable
      • reached_stage_idsarray of strings · uuid

        Every open stage the deal has entered, in the order it first entered them.

      • current_stage_entered_atstring · date-time · nullable

        When an open deal last entered its current stage. Null for closed deals.

      • stage_daysobject · nullable

        For a closed deal, the days it spent in each open stage, keyed by stage id, to one decimal place. Null for open deals.

Errors

  • 404record_not_foundNo pipeline with that id is visible to your key.
get/pipelines/{id}/report
curl https://api.carom.io/pipelines/5e8a1c3f-7b2d-4f6e-a9c0-3d1b7e4f2a86/report \
  -H "Authorization: Bearer $CAROM_API_KEY"
Response200
{
  "report": {
    "pipeline_id": "5e8a1c3f-7b2d-4f6e-a9c0-3d1b7e4f2a86",
    "generated_at": "2026-09-19T14:30:12.418Z",
    "window_months": 24,
    "total_open": 12,
    "total_closed_in_window": 31,
    "truncated": false,
    "omitted_count": 0,
    "stages": [
      {
        "id": "a1c4e7f2-3b6d-4a8e-9c1f-5d2b8e0a4c71",
        "name": "Lead",
        "position": 0,
        "outcome": "open",
        "likelihood": 0.2,
        "archived_at": null
      },
      …
    ],
    "deals": [
      {
        "id": "3c9e1a7f-5b2d-4c8e-a6f0-2d4b8e1c7a53",
        "name": "Halvorsen Freight dispatch pilot",
        "status": "won",
        "pipeline_stage_id": "d4f7bac5-6e9a-4dbc-8f4c-8a5ebc3d7fa4",
        "amount": 12500.0,
        "currency": "USD",
        "expected_value": 12500.0,
        "owner_user_id": "7a3d5f1b-2e8c-4d6a-9f0b-4c1e7a3d9b28",
        "created_at": "2026-09-08T19:12:40.200Z",
        "expected_close_date": "2026-10-09",
        "closed_at": "2026-09-18T16:55:03.260Z",
        "lost_reason": null,
        "reached_stage_ids": [
          "a1c4e7f2-3b6d-4a8e-9c1f-5d2b8e0a4c71",
          "c3e6a9b4-5d8f-4cab-9e3b-7f4dab2c6e93"
        ],
        "current_stage_entered_at": null,
        "stage_days": {
          "a1c4e7f2-3b6d-4a8e-9c1f-5d2b8e0a4c71": 4.2,
          "c3e6a9b4-5d8f-4cab-9e3b-7f4dab2c6e93": 5.7
        }
      },
      …
    ]
  }
}