> ## 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.

# Pipeline Overview

> Kanban CRM: sales pipelines, stages, deals and product catalog

The **Pipeline** module is Leavo's kanban CRM. While the **Leads** module records the
*contact*, the Pipeline records the *negotiation*: value, products, pipeline stage and loss reason.

<Note>
  Every deal is always linked to a **real Lead**. Contact data (name, company, email, phone)
  is never duplicated on the deal — it is read from the Lead at read time.
</Note>

## Hierarchy

```
Group (e.g. Sales)
└── Pipeline (e.g. Inbound Sales)
    ├── Stages (ordered: Entrada → Em andamento → Ganho → Perdido)
    │   └── Deals
    │       ├── Products (from the catalog or one-off)
    │       ├── Tags (shared with Leads)
    │       ├── Activities (todos)
    │       ├── Files
    │       └── History (events)
    └── Loss reasons
```

The **product catalog** is global per account — it is shared by every pipeline, never
scoped to just one of them.

## Resources

<CardGroup cols={2}>
  <Card title="Pipelines and Groups" icon="folder-tree" href="/en/api-reference/pipeline/pipelines">
    Create, configure, reorder and delete pipelines and their groups
  </Card>

  <Card title="Stages" icon="columns-3" href="/en/api-reference/pipeline/stages">
    Kanban columns, including the Won and Lost stages
  </Card>

  <Card title="Deals" icon="handshake" href="/en/api-reference/pipeline/deals">
    Board, paginated listing, creation, editing and moving
  </Card>

  <Card title="Products" icon="box" href="/en/api-reference/pipeline/products">
    The account's global product catalog
  </Card>

  <Card title="Activities, Files and History" icon="list-check" href="/en/api-reference/pipeline/activities">
    Tasks, attachments and the event log of each deal
  </Card>
</CardGroup>

## Special stages (`kind`)

A stage can have a `kind` that changes how a deal behaves when it enters that stage:

| `kind`     | Meaning       | Effect                                        |
| ---------- | ------------- | --------------------------------------------- |
| *(absent)* | Regular stage | None                                          |
| `won`      | Won           | Sets `won_at` on the deal                     |
| `lost`     | Lost          | Sets `lost_at` and **requires** `loss_reason` |

Each pipeline has at most **one** `won` stage and **one** `lost` stage. They **cannot be
deleted**, because there is no route that recreates them.

Every new pipeline is born with four default stages:

| Name           | Meaning     | `kind` |
| -------------- | ----------- | ------ |
| `Entrada`      | Incoming    | —      |
| `Em andamento` | In progress | —      |
| `Ganho`        | Won         | `won`  |
| `Perdido`      | Lost        | `lost` |

And with the default loss reasons: *Sem orçamento* (no budget), *Sem resposta / sumiu*
(no reply / went dark), *Fechou com concorrente* (closed with a competitor),
*Sem fit com o produto* (no product fit), *Momento errado* (wrong timing).

<Note>
  Default stage names and loss reasons are created by the API in Portuguese. They are stored
  values, not labels translated at read time — you receive them exactly as shown above. Rename
  them through [Configure a pipeline](/en/api-reference/pipeline/pipelines#configure-a-pipeline)
  if you want English names.
</Note>

## Rules enforced by the API

These rules are validated on the server — they are not merely interface guards:

<AccordionGroup>
  <Accordion title="Losing a deal always requires a reason">
    Moving a deal to the `lost` stage (or creating it there) without `loss_reason` returns
    **400**. There is no path that loses a deal silently.
  </Accordion>

  <Accordion title="Deleting a stage that has deals requires a destination">
    Deleting a stage that still contains deals without providing `target_stage_id` returns
    **409**. Deals are never removed along with the stage.
  </Accordion>

  <Accordion title="Deleting a group that has pipelines is blocked">
    Returns **409** with the pipeline count. Move them to another group first.
  </Accordion>

  <Accordion title="Deleting a product from the catalog does not break deals">
    Existing product lines become **one-off** lines (`custom: true`), preserving name and price.
    The deals remain editable.
  </Accordion>

  <Accordion title="The stage must belong to the pipeline">
    Creating or moving a deal into a stage of another pipeline returns **400**.
  </Accordion>
</AccordionGroup>

## Permissions

Every Pipeline route — **including the read ones** — is protected by a granular permission.
A custom role without `pipeline.view` gets **403** from the API, not just a hidden menu.

| Code                       | Allows                                                  |
| -------------------------- | ------------------------------------------------------- |
| `pipeline.view`            | View pipelines and deals                                |
| `pipeline.manage`          | Create and configure pipelines, stages and loss reasons |
| `pipeline.deals.create`    | Create deals                                            |
| `pipeline.deals.edit`      | Edit and move deals between stages                      |
| `pipeline.deals.delete`    | Delete deals                                            |
| `pipeline.products.manage` | Manage the product catalog                              |

The **OPERATOR** system role gets `pipeline.view`, `pipeline.deals.create` and
`pipeline.deals.edit`.

To discover the effective permissions of the authenticated user:

<Card>
  <strong>GET</strong> `/backend/roles/my-permissions`
</Card>

## Deal value

A deal's total (`total`) is calculated like this:

* If the deal **has products**: the sum of `price × qty` for each line.
* If it **has no products**: the legacy `value` field is used.

The `total` field always comes calculated in the response — there is no need to sum on the client.

## Authentication

All Pipeline endpoints require authentication:

```bash theme={null}
Authorization: Bearer your_api_key_here
```

See [Authentication](/en/authentication) for details.
