<!-- Source: https://useworkloom.com/dev/workspace/ · Workloom API v1 -->

# Pipelines, team and fields

The things records point at: your pipelines and their stages, the reasons a deal closes, your teammates and the fields you added. Read these to know which stage keys, reason keys, owner ids and field keys are valid.

Scopes: `deals:read`, `team:read`, `contacts:read`, `companies:read`.

## The pipeline object

- `id` (string, required): The pipeline key. Deals carry it as `pipeline_id`.
- `name` (string, required): Its name.
- `is_default` (boolean, required): Whether deals land here unless told otherwise.
- `stages` (array of Stage, required): Every stage, in order. `key` is what deals carry as `stage` and what the move endpoint takes.

```json
{
  "id": "default",
  "name": "New business",
  "is_default": true,
  "stages": [
    {
      "key": "engaged",
      "label": "Engaged",
      "status": "open",
      "phase": "prospecting",
      "probability": 5,
      "required_fields": []
    },
    {
      "key": "qualified",
      "label": "Qualified",
      "status": "open",
      "phase": "prospecting",
      "probability": 10,
      "required_fields": []
    },
    {
      "key": "discovery",
      "label": "Discovery",
      "status": "open",
      "phase": "opportunity",
      "probability": 20,
      "required_fields": [
        "amount",
        "expected_close_date"
      ]
    },
    {
      "key": "proposal",
      "label": "Proposal",
      "status": "open",
      "phase": "opportunity",
      "probability": 50,
      "required_fields": [
        "amount",
        "expected_close_date"
      ]
    },
    {
      "key": "commit",
      "label": "Commit",
      "status": "open",
      "phase": "opportunity",
      "probability": 80,
      "required_fields": [
        "amount",
        "expected_close_date"
      ]
    },
    {
      "key": "won",
      "label": "Won",
      "status": "won",
      "phase": "closed",
      "probability": 100,
      "required_fields": [
        "amount"
      ]
    },
    {
      "key": "lost",
      "label": "Lost",
      "status": "lost",
      "phase": "closed",
      "probability": 0,
      "required_fields": []
    }
  ]
}
```

## The seat object

- `id` (string, required): The seat id. Records carry it as `owner_seat_id`.
- `name` (string, nullable, required): Their name.
- `email` (string, nullable, required): Their sign-in email. Null for a service account, and for a key acting for someone other than an admin.
- `kind` (string, required): member is a teammate; service a service account; external someone from outside the company.
- `role` (string, nullable, required): Their role in words, for example Admin, Manager or Rep.
- `status` (string, required): Only an active seat can own records.
- `team_id` (string, nullable, required): Their team, if any.

```json
{
  "id": "66e0f1a2e4b0a1b2c3d40a0b",
  "name": "Asha Rao",
  "email": "asha@brightpath.example",
  "kind": "member",
  "role": "Rep",
  "status": "active",
  "team_id": null
}
```

## The custom field object

- `key` (string, required): The key. Values sit under `custom_fields.<key>`.
- `label` (string, required): Its name in Workloom.
- `object` (string, required): Which kind of record it belongs to.
- `type` (string, required): text, textarea, number, currency, date, boolean, select, multiselect, url, email, user, relation or formula.
- `options` (array of string, required): The choices, for select and multiselect.
- `read_only` (boolean, required): True for formula fields and archived fields: they cannot be written.

```json
{
  "key": "region",
  "label": "Region",
  "object": "contact",
  "type": "select",
  "options": [
    "North",
    "South",
    "West"
  ],
  "read_only": false
}
```

## Endpoints

### List pipelines and stages

`GET /pipelines`

Every pipeline with its stages in board order, and the reasons a deal can be lost, won or parked. Use the stage keys for `stage` and the reason keys for `reason_code`.

Scope: `deals:read`

**Request**

```bash
curl "https://api.useworkloom.com/api/public/v1/pipelines" \
  -H "Authorization: Bearer $WORKLOOM_KEY"
```

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/pipelines", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.WORKLOOM_KEY}`
  }
});
const data = await res.json();
```

```python
import os, requests

res = requests.get(
    "https://api.useworkloom.com/api/public/v1/pipelines",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}"},
)
data = res.json()
```

**Response (sample, 200)**

```json
{
  "data": [
    {
      "id": "default",
      "name": "New business",
      "is_default": true,
      "stages": [
        {
          "key": "engaged",
          "label": "Engaged",
          "status": "open",
          "phase": "prospecting",
          "probability": 5,
          "required_fields": []
        },
        {
          "key": "qualified",
          "label": "Qualified",
          "status": "open",
          "phase": "prospecting",
          "probability": 10,
          "required_fields": []
        },
        {
          "key": "discovery",
          "label": "Discovery",
          "status": "open",
          "phase": "opportunity",
          "probability": 20,
          "required_fields": [
            "amount",
            "expected_close_date"
          ]
        },
        {
          "key": "proposal",
          "label": "Proposal",
          "status": "open",
          "phase": "opportunity",
          "probability": 50,
          "required_fields": [
            "amount",
            "expected_close_date"
          ]
        },
        {
          "key": "commit",
          "label": "Commit",
          "status": "open",
          "phase": "opportunity",
          "probability": 80,
          "required_fields": [
            "amount",
            "expected_close_date"
          ]
        },
        {
          "key": "won",
          "label": "Won",
          "status": "won",
          "phase": "closed",
          "probability": 100,
          "required_fields": [
            "amount"
          ]
        },
        {
          "key": "lost",
          "label": "Lost",
          "status": "lost",
          "phase": "closed",
          "probability": 0,
          "required_fields": []
        }
      ]
    }
  ],
  "reasons": {
    "lost": [
      {
        "key": "no_budget",
        "label": "No budget"
      },
      {
        "key": "competitor",
        "label": "Chose a competitor"
      }
    ],
    "won": [
      {
        "key": "price",
        "label": "Best price"
      }
    ],
    "parked": [
      {
        "key": "bad_timing",
        "label": "Bad timing"
      }
    ]
  }
}
```

**Errors**

- 400: `invalid_request`, `unknown_fields`, `reason_required` or `unsupported_version`.
- 401: `authentication_required` or `invalid_key`.
- 403: `missing_scope`, `forbidden`, `seat_inactive` or `organisation_inactive`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.

### List teammates

`GET /seats`

Everyone with a seat: teammates, service accounts and people from outside the company. `owner_seat_id` on a record is one of these ids. Emails are shown to a key acting for the workspace or for an admin.

Scope: `team:read`

**Query parameters**

- `status` (string): Only seats in this state: active, invited, suspended or ended.
- `limit` (integer): How many to return, 1 to 100. Default 25.
- `cursor` (string): The `next_cursor` from the previous page.

**Request**

```bash
curl "https://api.useworkloom.com/api/public/v1/seats?status=active&limit=25" \
  -H "Authorization: Bearer $WORKLOOM_KEY"
```

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/seats?status=active&limit=25", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.WORKLOOM_KEY}`
  }
});
const data = await res.json();
```

```python
import os, requests

res = requests.get(
    "https://api.useworkloom.com/api/public/v1/seats?status=active&limit=25",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}"},
)
data = res.json()
```

**Response (sample, 200)**

```json
{
  "data": [
    {
      "id": "66e0f1a2e4b0a1b2c3d40a0b",
      "name": "Asha Rao",
      "email": "asha@brightpath.example",
      "kind": "member",
      "role": "Rep",
      "status": "active",
      "team_id": null
    }
  ],
  "has_more": true,
  "next_cursor": "66e0f1a2e4b0a1b2c3d40a0b"
}
```

**Errors**

- 400: `invalid_request`, `unknown_fields`, `reason_required` or `unsupported_version`.
- 401: `authentication_required` or `invalid_key`.
- 403: `missing_scope`, `forbidden`, `seat_inactive` or `organisation_inactive`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.

### List your own fields

`GET /custom-fields`

The fields your workspace added in Settings › Data model, with their keys, labels and types. Records carry their values under `custom_fields`. Needs any one of the read scopes.

Needs one of the `contacts:read`, `companies:read`, `deals:read` scopes.

Scope: `contacts:read or companies:read or deals:read`

**Query parameters**

- `object` (string): contact, company or deal. Omit for all three.

**Request**

```bash
curl "https://api.useworkloom.com/api/public/v1/custom-fields?object=contact" \
  -H "Authorization: Bearer $WORKLOOM_KEY"
```

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/custom-fields?object=contact", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.WORKLOOM_KEY}`
  }
});
const data = await res.json();
```

```python
import os, requests

res = requests.get(
    "https://api.useworkloom.com/api/public/v1/custom-fields?object=contact",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}"},
)
data = res.json()
```

**Response (sample, 200)**

```json
{
  "data": [
    {
      "key": "region",
      "label": "Region",
      "object": "contact",
      "type": "select",
      "options": [
        "North",
        "South",
        "West"
      ],
      "read_only": false
    }
  ]
}
```

**Errors**

- 400: `invalid_request`, `unknown_fields`, `reason_required` or `unsupported_version`.
- 401: `authentication_required` or `invalid_key`.
- 403: `missing_scope`, `forbidden`, `seat_inactive` or `organisation_inactive`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.
