> ## Documentation Index
> Fetch the complete documentation index at: https://docs.leavo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Pipelines and Groups

> Create, configure, reorder and delete sales pipelines

## List pipelines and groups

<Card>
  <strong>GET</strong> `/backend/pipelines`
</Card>

Returns the account's groups and pipelines, ready to build the selector.

### Response

<ResponseField name="groups" type="Group[]">
  Groups ordered by `position`
</ResponseField>

<ResponseField name="pipelines" type="Pipeline[]">
  Pipelines ordered by `position`, each with its `group_id`
</ResponseField>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "groups": [
      { "id": "aa0e8400-e29b-41d4-a716-446655440000", "name": "Sales", "position": 0 }
    ],
    "pipelines": [
      {
        "id": "bb0e8400-e29b-41d4-a716-446655440000",
        "group_id": "aa0e8400-e29b-41d4-a716-446655440000",
        "name": "Inbound Sales",
        "description": "Leads coming from the website",
        "position": 0,
        "created_at": "2026-07-16T09:00:00Z"
      }
    ]
  }
  ```
</ResponseExample>

***

## Get a pipeline

<Card>
  <strong>GET</strong> `/backend/pipelines/{id}`
</Card>

Returns the pipeline **with its stages and loss reasons**.

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "id": "bb0e8400-e29b-41d4-a716-446655440000",
    "group_id": "aa0e8400-e29b-41d4-a716-446655440000",
    "name": "Inbound Sales",
    "description": "Leads coming from the website",
    "position": 0,
    "stages": [
      { "id": "cc0e8400-e29b-41d4-a716-446655440000", "name": "Entrada", "color": "217 91% 60%", "position": 0 },
      { "id": "cc1e8400-e29b-41d4-a716-446655440000", "name": "Em andamento", "color": "38 92% 50%", "position": 1 },
      { "id": "cc2e8400-e29b-41d4-a716-446655440000", "name": "Ganho", "color": "152 60% 40%", "kind": "won", "position": 2 },
      { "id": "cc3e8400-e29b-41d4-a716-446655440000", "name": "Perdido", "color": "0 72% 56%", "kind": "lost", "position": 3 }
    ],
    "loss_reasons": [
      "Sem orçamento",
      "Sem resposta / sumiu",
      "Fechou com concorrente",
      "Sem fit com o produto",
      "Momento errado"
    ],
    "created_at": "2026-07-16T09:00:00Z"
  }
  ```
</ResponseExample>

<Note>
  The default stage names (`Entrada`, `Em andamento`, `Ganho`, `Perdido`) and the default loss
  reasons are created by the API in Portuguese and returned verbatim. They are editable data —
  rename them with [Configure a pipeline](#configure-a-pipeline).
</Note>

<Info>
  `color` uses the design system token format — an HSL triple without the `hsl()` wrapper,
  like `"217 91% 60%"`.
</Info>

***

## Create a pipeline

<Card>
  <strong>POST</strong> `/backend/pipelines`
</Card>

Requires the `pipeline.manage` permission. The created pipeline already comes with the
**four default stages** and the **default loss reasons**.

### Request Body

<ParamField body="name" type="string" required>
  Pipeline name
</ParamField>

<ParamField body="description" type="string">
  Pipeline description
</ParamField>

<ParamField body="group_id" type="string">
  UUID of an existing group
</ParamField>

<ParamField body="new_group_name" type="string">
  Name of a group to create along with the pipeline
</ParamField>

<Warning>
  Provide **`group_id` or `new_group_name`** — a pipeline must belong to a group.
</Warning>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.leavo.ai/backend/pipelines" \
    -H "Authorization: Bearer your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Inbound Sales",
      "description": "Leads coming from the website",
      "new_group_name": "Sales"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.leavo.ai/backend/pipelines', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer your_api_key_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: 'Inbound Sales',
      description: 'Leads coming from the website',
      new_group_name: 'Sales'
    })
  });
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.leavo.ai/backend/pipelines',
      headers={'Authorization': 'Bearer your_api_key_here'},
      json={
          'name': 'Inbound Sales',
          'description': 'Leads coming from the website',
          'new_group_name': 'Sales'
      }
  )
  ```
</RequestExample>

Returns **201 Created** with the pipeline.

***

## Configure a pipeline

<Card>
  <strong>PUT</strong> `/backend/pipelines/{id}`
</Card>

**Transactional** save of the "Configure pipeline" screen: name, description, the complete
and ordered list of stages, and the loss reasons.

### Request Body

<ParamField body="name" type="string" required>
  Pipeline name
</ParamField>

<ParamField body="description" type="string">
  Pipeline description
</ParamField>

<ParamField body="stages" type="ConfigStage[]" required>
  The **complete and ordered** list of stages. The position in the array defines the order on the board.
</ParamField>

<Expandable title="ConfigStage properties">
  <ParamField body="id" type="string">
    UUID of the existing stage. **Omit to create a new stage.**
  </ParamField>

  <ParamField body="name" type="string" required>
    Stage name
  </ParamField>

  <ParamField body="color" type="string">
    Color in the `"H S% L%"` format
  </ParamField>
</Expandable>

<ParamField body="loss_reasons" type="string[]">
  The complete list of the pipeline's loss reasons
</ParamField>

<ParamField body="reallocation_targets" type="object">
  Map `{ "removed_stage_id": "destination_stage_id" }` for the stages that left the list
</ParamField>

<Warning>
  **Stages omitted from the `stages` list are deleted.** If a removed stage still has deals,
  you must provide its destination in `reallocation_targets` — otherwise the request returns
  **409**. The destination must be a stage that stayed in the list.
</Warning>

<RequestExample>
  ```bash cURL theme={null}
  curl -X PUT "https://api.leavo.ai/backend/pipelines/bb0e8400-e29b-41d4-a716-446655440000" \
    -H "Authorization: Bearer your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Inbound Sales",
      "description": "Leads coming from the website",
      "stages": [
        { "id": "cc0e8400-e29b-41d4-a716-446655440000", "name": "Entrada", "color": "217 91% 60%" },
        { "name": "Qualification", "color": "271 81% 56%" },
        { "id": "cc2e8400-e29b-41d4-a716-446655440000", "name": "Ganho", "color": "152 60% 40%" },
        { "id": "cc3e8400-e29b-41d4-a716-446655440000", "name": "Perdido", "color": "0 72% 56%" }
      ],
      "loss_reasons": ["Sem orçamento", "Price above expectations"],
      "reallocation_targets": {
        "cc1e8400-e29b-41d4-a716-446655440000": "cc0e8400-e29b-41d4-a716-446655440000"
      }
    }'
  ```
</RequestExample>

In the example above, the *Em andamento* stage left the list and its deals were moved to
*Entrada*. The *Qualification* stage was created (it has no `id`).

***

## Reorder a pipeline

<Card>
  <strong>PUT</strong> `/backend/pipelines/reorder`
</Card>

Moves a pipeline before another one and/or into another group.

### Request Body

<ParamField body="pipeline_id" type="string" required>
  UUID of the moved pipeline
</ParamField>

<ParamField body="group_id" type="string" required>
  UUID of the destination group
</ParamField>

<ParamField body="before_id" type="string">
  UUID of the pipeline that should end up **after** the moved one. Omit to place it at the end of the group.
</ParamField>

<ResponseExample>
  ```json 200 OK theme={null}
  { "success": true }
  ```
</ResponseExample>

***

## Delete a pipeline

<Card>
  <strong>DELETE</strong> `/backend/pipelines/{id}`
</Card>

<Warning>
  Deletes the pipeline and **all of its content**: stages, loss reasons, deals, deal products,
  tags, activities, files and history. The operation is irreversible.
</Warning>

<ResponseExample>
  ```json 200 OK theme={null}
  { "success": true }
  ```
</ResponseExample>

***

## Groups

Groups organize pipelines in the selector (e.g. *Marketing*, *Sales*, *CS*).

### List groups

<Card>
  <strong>GET</strong> `/backend/pipeline/groups`
</Card>

### Create a group

<Card>
  <strong>POST</strong> `/backend/pipeline/groups`
</Card>

<ParamField body="name" type="string" required>
  Group name
</ParamField>

Returns **201 Created**.

### Rename a group

<Card>
  <strong>PUT</strong> `/backend/pipeline/groups/{id}`
</Card>

<ParamField body="name" type="string" required>
  New group name
</ParamField>

### Delete a group

<Card>
  <strong>DELETE</strong> `/backend/pipeline/groups/{id}`
</Card>

<Warning>
  A group that still contains pipelines **cannot be deleted** — the response is **409** with
  the count. Move the pipelines to another group first.
</Warning>

```json 409 Conflict theme={null}
{
  "code": "ERR_CONFLICT",
  "message": "O grupo tem 2 pipeline(s). Mova-as para outro grupo antes de excluir."
}
```

<Note>
  Error `message` strings are returned by the API in Portuguese. Match on `code`
  (`ERR_CONFLICT`), never on the message text.
</Note>
