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

# Deals

A deal is an opportunity on one of your pipelines. Moving a deal between stages is its own call, so stage rules and required fields are checked the way the board checks them.

Scopes: `deals:read`, `deals:write`.

## The deal object

- `id` (string): The deal’s id.
- `name` (string): Deal name.
- `pipeline_id` (string): Which pipeline it is on. "default" unless you have several.
- `stage` (string): The stage key, as your pipeline names it.
- `status` (string): Open, won, lost, or parked (off the board until a date).
- `amount` (number, nullable): Value of the deal.
- `currency` (string): Three-letter currency code.
- `probability` (integer, nullable): Chance of winning, 0 to 100, from the stage.
- `forecast_category` (string): Forecast category, from the stage.
- `expected_close_date` (timestamp, nullable): When you expect it to close.
- `next_step` (object, nullable): What happens next, and when.
- `company_name` (string, nullable): The account’s name.
- `company_domain` (string, nullable): The account’s website domain.
- `company_id` (string, nullable): The company record, if any.
- `primary_contact_id` (string, nullable): The main contact on the deal.
- `contacts` (array of object): Everyone on the deal, with their role.
- `closed_at` (timestamp, nullable): When it was won or lost.
- `close_reason_code` (string, nullable): Why it was won or lost: one of your reason keys.
- `owner_seat_id` (string, nullable): The teammate who owns the deal. Null when nobody does.
- `source` (string, nullable): How it was created, for example "manual" or "api:Warehouse sync".
- `custom_fields` (object): Your own fields (Settings › Data model), by key. `GET /custom-fields` lists their keys, labels and types. A field with no value is left out.
- `created_at` (timestamp): When the deal was created.
- `updated_at` (timestamp): When the deal last changed.

```json
{
  "id": "66f5c3d1e4b0a1b2c3d4c3d4",
  "name": "Brightline, 10 seats",
  "pipeline_id": "default",
  "stage": "proposal",
  "status": "open",
  "amount": 29900,
  "currency": "USD",
  "probability": 50,
  "forecast_category": "best_case",
  "expected_close_date": "2026-11-14T00:00:00.000Z",
  "next_step": {
    "text": "Call with VP Finance",
    "due_at": "2026-10-09T10:00:00.000Z"
  },
  "company_name": "Brightline",
  "company_domain": "brightline.example",
  "company_id": "66f19b77e4b0a1b2c3d4a1b2",
  "primary_contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
  "contacts": [
    {
      "contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
      "role": "champion"
    }
  ],
  "closed_at": null,
  "close_reason_code": null,
  "owner_seat_id": "66e0f1a2e4b0a1b2c3d40a0b",
  "source": "api:Warehouse sync",
  "custom_fields": {
    "competitor": "Pipedrive"
  },
  "created_at": "2026-09-25T12:00:00.000Z",
  "updated_at": "2026-10-03T08:42:10.000Z"
}
```

## Endpoints

### List deals

`GET /deals`

Deals on every pipeline, oldest first unless you `sort`. Deleted deals are left out. A key acting for one person sees only the deals that person can see.

Scope: `deals:read`

**Query parameters**

- `status` (string): open, won, lost or parked.
- `stage` (string): A stage key.
- `pipeline_id` (string): A pipeline. Omit for every pipeline.
- `sort` (string): Order by one field, oldest or smallest first; put `-` in front for newest or largest first. Empty values come first ascending and last descending. Default: oldest first. Keep the same `sort` while you follow `next_cursor`.
- `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/deals?limit=25" \
  -H "Authorization: Bearer $WORKLOOM_KEY"
```

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/deals?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/deals?limit=25",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}"},
)
data = res.json()
```

**Response (sample, 200)**

```json
{
  "data": [
    {
      "id": "66f5c3d1e4b0a1b2c3d4c3d4",
      "name": "Brightline, 10 seats",
      "pipeline_id": "default",
      "stage": "proposal",
      "status": "open",
      "amount": 29900,
      "currency": "USD",
      "probability": 50,
      "forecast_category": "best_case",
      "expected_close_date": "2026-11-14T00:00:00.000Z",
      "next_step": {
        "text": "Call with VP Finance",
        "due_at": "2026-10-09T10:00:00.000Z"
      },
      "company_name": "Brightline",
      "company_domain": "brightline.example",
      "company_id": "66f19b77e4b0a1b2c3d4a1b2",
      "primary_contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
      "contacts": [
        {
          "contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
          "role": "champion"
        }
      ],
      "closed_at": null,
      "close_reason_code": null,
      "owner_seat_id": "66e0f1a2e4b0a1b2c3d40a0b",
      "source": "api:Warehouse sync",
      "custom_fields": {
        "competitor": "Pipedrive"
      },
      "created_at": "2026-09-25T12:00:00.000Z",
      "updated_at": "2026-10-03T08:42:10.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "66f5c3d1e4b0a1b2c3d4c3d4"
}
```

**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`.

### Create a deal

`POST /deals`

Opens a deal with the same rules as the board: the stage must exist, a lost stage needs a reason, a stage’s required fields must be filled, and a contact has at most one open deal per pipeline.

Scope: `deals:write`

**Header parameters**

- `Idempotency-Key` (string): Any unique string, up to 255 characters. Send the same key when you retry and the request runs once; the first answer comes back with `Idempotent-Replayed: true`. Kept 24 hours.

**Body parameters**

- `name` (string): Deal name. Defaults to the main contact’s company, then their name.
- `pipeline_id` (string): Which pipeline. Defaults to "default".
- `stage` (string): Stage key. Defaults to the pipeline’s first open stage.
- `amount` (number, nullable): Value of the deal.
- `currency` (string): Three-letter currency code. Defaults to USD.
- `expected_close_date` (timestamp, nullable): When you expect it to close.
- `next_step` (object or string, nullable): What happens next: `{ "text": "Send the proposal", "due_at": "2026-11-02T10:00:00Z" }`, or just the text.
- `company_name` (string, nullable): The account’s name.
- `company_domain` (string, nullable): The account’s website domain.
- `company_id` (string, nullable): A company record to open it against.
- `primary_contact_id` (string, nullable): The main contact. One open deal per contact per pipeline.
- `contacts` (array of object): Everyone on the deal. Replaces the list.
- `owner_seat_id` (string, nullable): Who owns it. Only a key that acts for the whole workspace may set this.
- `reason_code` (string, nullable): Needed when the stage is a lost stage: one of your lost reasons.
- `reason_note` (string, nullable): A note on why it closed.
- `fields` (object): Your own fields, by key (Settings › Data model). Values are checked against each field’s type.
- `custom_fields` (object): The same as `fields`, by the name the deal object uses.

**Request**

```bash
curl -X POST "https://api.useworkloom.com/api/public/v1/deals" \
  -H "Authorization: Bearer $WORKLOOM_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "name": "Brightline, 10 seats",
  "amount": 29900,
  "primary_contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
  "expected_close_date": "2026-11-14"
}'
```

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/deals", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.WORKLOOM_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID()
  },
  body: JSON.stringify({
    "name": "Brightline, 10 seats",
    "amount": 29900,
    "primary_contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
    "expected_close_date": "2026-11-14"
  })
});
const data = await res.json();
```

```python
import os, uuid, requests

res = requests.post(
    "https://api.useworkloom.com/api/public/v1/deals",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
      "name": "Brightline, 10 seats",
      "amount": 29900,
      "primary_contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
      "expected_close_date": "2026-11-14"
    },
)
data = res.json()
```

**Response (sample, 201)**

```json
{
  "data": {
    "id": "66f5c3d1e4b0a1b2c3d4c3d4",
    "name": "Brightline, 10 seats",
    "pipeline_id": "default",
    "stage": "proposal",
    "status": "open",
    "amount": 29900,
    "currency": "USD",
    "probability": 50,
    "forecast_category": "best_case",
    "expected_close_date": "2026-11-14T00:00:00.000Z",
    "next_step": {
      "text": "Call with VP Finance",
      "due_at": "2026-10-09T10:00:00.000Z"
    },
    "company_name": "Brightline",
    "company_domain": "brightline.example",
    "company_id": "66f19b77e4b0a1b2c3d4a1b2",
    "primary_contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
    "contacts": [
      {
        "contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
        "role": "champion"
      }
    ],
    "closed_at": null,
    "close_reason_code": null,
    "owner_seat_id": "66e0f1a2e4b0a1b2c3d40a0b",
    "source": "api:Warehouse sync",
    "custom_fields": {
      "competitor": "Pipedrive"
    },
    "created_at": "2026-09-25T12:00:00.000Z",
    "updated_at": "2026-10-03T08:42:10.000Z"
  },
  "livemode": true
}
```

**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`.
- 409: `duplicate`, `conflict` or `idempotency_key_in_use`.
- 422: `idempotency_key_reused` or `stage_requirements_missing`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.

### Get a deal

`GET /deals/{id}`

Returns one deal.

Scope: `deals:read`

**Path parameters**

- `id` (string, required): The deal’s id.

**Request**

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

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/deals/66f5c3d1e4b0a1b2c3d4c3d4", {
  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/deals/66f5c3d1e4b0a1b2c3d4c3d4",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}"},
)
data = res.json()
```

**Response (sample, 200)**

```json
{
  "data": {
    "id": "66f5c3d1e4b0a1b2c3d4c3d4",
    "name": "Brightline, 10 seats",
    "pipeline_id": "default",
    "stage": "proposal",
    "status": "open",
    "amount": 29900,
    "currency": "USD",
    "probability": 50,
    "forecast_category": "best_case",
    "expected_close_date": "2026-11-14T00:00:00.000Z",
    "next_step": {
      "text": "Call with VP Finance",
      "due_at": "2026-10-09T10:00:00.000Z"
    },
    "company_name": "Brightline",
    "company_domain": "brightline.example",
    "company_id": "66f19b77e4b0a1b2c3d4a1b2",
    "primary_contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
    "contacts": [
      {
        "contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
        "role": "champion"
      }
    ],
    "closed_at": null,
    "close_reason_code": null,
    "owner_seat_id": "66e0f1a2e4b0a1b2c3d40a0b",
    "source": "api:Warehouse sync",
    "custom_fields": {
      "competitor": "Pipedrive"
    },
    "created_at": "2026-09-25T12:00:00.000Z",
    "updated_at": "2026-10-03T08:42:10.000Z"
  }
}
```

**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`.
- 404: `not_found`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.

### Update a deal

`PATCH /deals/{id}`

Changes only the fields you send. The stage changes through the move endpoint, and `probability` and `forecast_category` come from the stage.

Scope: `deals:write`

**Path parameters**

- `id` (string, required): The deal’s id.

**Body parameters**

- `name` (string): Deal name.
- `amount` (number, nullable): Value of the deal. Null clears it.
- `currency` (string): Three-letter currency code.
- `expected_close_date` (timestamp, nullable): When you expect it to close. Null clears it.
- `next_step` (object or string, nullable): What happens next: `{ "text": "Send the proposal", "due_at": "2026-11-02T10:00:00Z" }`, or just the text.
- `company_name` (string, nullable): The account’s name.
- `company_domain` (string, nullable): The account’s website domain.
- `primary_contact_id` (string, nullable): The main contact.
- `contacts` (array of object): Everyone on the deal. Replaces the list.
- `owner_seat_id` (string, nullable): Hand the deal to a teammate. Null leaves it unowned.
- `reason` (string, nullable): Why it changed owner. Needed when the key’s role does not reach every record.
- `fields` (object): Your own fields, by key (Settings › Data model). Values are checked against each field’s type.
- `custom_fields` (object): The same as `fields`, by the name the deal object uses.

**Request**

```bash
curl -X PATCH "https://api.useworkloom.com/api/public/v1/deals/66f5c3d1e4b0a1b2c3d4c3d4" \
  -H "Authorization: Bearer $WORKLOOM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "expected_close_date": "2026-11-21",
  "next_step": {
    "text": "Send the security review",
    "due_at": "2026-10-10T09:00:00Z"
  }
}'
```

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/deals/66f5c3d1e4b0a1b2c3d4c3d4", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.WORKLOOM_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "expected_close_date": "2026-11-21",
    "next_step": {
      "text": "Send the security review",
      "due_at": "2026-10-10T09:00:00Z"
    }
  })
});
const data = await res.json();
```

```python
import os, requests

res = requests.patch(
    "https://api.useworkloom.com/api/public/v1/deals/66f5c3d1e4b0a1b2c3d4c3d4",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}"},
    json={
      "expected_close_date": "2026-11-21",
      "next_step": {
        "text": "Send the security review",
        "due_at": "2026-10-10T09:00:00Z"
      }
    },
)
data = res.json()
```

**Response (sample, 200)**

```json
{
  "data": {
    "id": "66f5c3d1e4b0a1b2c3d4c3d4",
    "name": "Brightline, 10 seats",
    "pipeline_id": "default",
    "stage": "proposal",
    "status": "open",
    "amount": 29900,
    "currency": "USD",
    "probability": 50,
    "forecast_category": "best_case",
    "expected_close_date": "2026-11-14T00:00:00.000Z",
    "next_step": {
      "text": "Call with VP Finance",
      "due_at": "2026-10-09T10:00:00.000Z"
    },
    "company_name": "Brightline",
    "company_domain": "brightline.example",
    "company_id": "66f19b77e4b0a1b2c3d4a1b2",
    "primary_contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
    "contacts": [
      {
        "contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
        "role": "champion"
      }
    ],
    "closed_at": null,
    "close_reason_code": null,
    "owner_seat_id": "66e0f1a2e4b0a1b2c3d40a0b",
    "source": "api:Warehouse sync",
    "custom_fields": {
      "competitor": "Pipedrive"
    },
    "created_at": "2026-09-25T12:00:00.000Z",
    "updated_at": "2026-10-03T08:42:10.000Z"
  },
  "livemode": true
}
```

**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`.
- 404: `not_found`.
- 409: `duplicate`, `conflict` or `idempotency_key_in_use`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.

### Delete a deal

`DELETE /deals/{id}`

Deletes the deal. Its contact can be given a new deal in the same pipeline straight away. A key acting for one person needs that person’s permission to delete records.

Scope: `deals:write`

**Path parameters**

- `id` (string, required): The deal’s id.

**Request**

```bash
curl -X DELETE "https://api.useworkloom.com/api/public/v1/deals/66f5c3d1e4b0a1b2c3d4c3d4" \
  -H "Authorization: Bearer $WORKLOOM_KEY"
```

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

```python
import os, requests

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

**Response (sample, 200)**

```json
{
  "data": {
    "id": "66f5c3d1e4b0a1b2c3d4c3d4",
    "deleted": true
  },
  "livemode": true
}
```

**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`.
- 404: `not_found`.
- 409: `duplicate`, `conflict` or `idempotency_key_in_use`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.

### Move a deal

`POST /deals/{id}/move`

Moves a deal to another stage of its pipeline, won and lost included. A lost stage needs `reason_code`, one of your lost reasons. A stage’s required fields must be filled, on the deal or in `fields`, or the move is refused naming them.

Scope: `deals:write`

**Path parameters**

- `id` (string, required): The deal’s id.

**Header parameters**

- `Idempotency-Key` (string): Any unique string, up to 255 characters. Send the same key when you retry and the request runs once; the first answer comes back with `Idempotent-Replayed: true`. Kept 24 hours.

**Body parameters**

- `stage` (string, required): The stage key to move to.
- `reason_code` (string, nullable): Needed for a lost stage: one of your lost reasons. Optional for won.
- `reason_note` (string, nullable): A note on why.
- `competitor` (string, nullable): Who it was lost to, if anyone.
- `fields` (object): Values the new stage asks for (its required fields), by key.

**Request**

```bash
curl -X POST "https://api.useworkloom.com/api/public/v1/deals/66f5c3d1e4b0a1b2c3d4c3d4/move" \
  -H "Authorization: Bearer $WORKLOOM_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "stage": "won"
}'
```

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/deals/66f5c3d1e4b0a1b2c3d4c3d4/move", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.WORKLOOM_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID()
  },
  body: JSON.stringify({
    "stage": "won"
  })
});
const data = await res.json();
```

```python
import os, uuid, requests

res = requests.post(
    "https://api.useworkloom.com/api/public/v1/deals/66f5c3d1e4b0a1b2c3d4c3d4/move",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}", "Idempotency-Key": str(uuid.uuid4())},
    json={
      "stage": "won"
    },
)
data = res.json()
```

**Response (sample, 200)**

```json
{
  "data": {
    "id": "66f5c3d1e4b0a1b2c3d4c3d4",
    "name": "Brightline, 10 seats",
    "pipeline_id": "default",
    "stage": "proposal",
    "status": "open",
    "amount": 29900,
    "currency": "USD",
    "probability": 50,
    "forecast_category": "best_case",
    "expected_close_date": "2026-11-14T00:00:00.000Z",
    "next_step": {
      "text": "Call with VP Finance",
      "due_at": "2026-10-09T10:00:00.000Z"
    },
    "company_name": "Brightline",
    "company_domain": "brightline.example",
    "company_id": "66f19b77e4b0a1b2c3d4a1b2",
    "primary_contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
    "contacts": [
      {
        "contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
        "role": "champion"
      }
    ],
    "closed_at": null,
    "close_reason_code": null,
    "owner_seat_id": "66e0f1a2e4b0a1b2c3d40a0b",
    "source": "api:Warehouse sync",
    "custom_fields": {
      "competitor": "Pipedrive"
    },
    "created_at": "2026-09-25T12:00:00.000Z",
    "updated_at": "2026-10-03T08:42:10.000Z"
  },
  "livemode": true
}
```

**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`.
- 404: `not_found`.
- 409: `duplicate`, `conflict` or `idempotency_key_in_use`.
- 422: `idempotency_key_reused` or `stage_requirements_missing`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.

### Search deals

`POST /deals/search`

Deals matching every filter, oldest first unless you `sort` (created_at, updated_at, amount, expected_close_date or closed_at), paged like the list. Searchable: name, pipeline_id, stage, status, amount, currency, expected_close_date, closed_at, close_reason_code, company_name, company_domain, company_id, primary_contact_id, owner_seat_id, source, created_at, updated_at, and custom_fields.<key>.

Scope: `deals:read`

**Body parameters**

- `filters` (array of SearchFilter): Up to 20 filters. All must match.
- `limit` (integer): How many to return, 1 to 100. Default 25.
- `cursor` (string, nullable): The `next_cursor` from the previous page.
- `sort` (string, nullable): Order by one field, as `sort` on the list: `-` in front for newest or largest first. Keep the same `sort` while you follow `next_cursor`.

**Request**

```bash
curl -X POST "https://api.useworkloom.com/api/public/v1/deals/search" \
  -H "Authorization: Bearer $WORKLOOM_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "filters": [
    {
      "field": "stage",
      "op": "in",
      "value": [
        "proposal",
        "commit"
      ]
    },
    {
      "field": "amount",
      "op": "gte",
      "value": 10000
    }
  ]
}'
```

```javascript
const res = await fetch("https://api.useworkloom.com/api/public/v1/deals/search", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.WORKLOOM_KEY}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "filters": [
      {
        "field": "stage",
        "op": "in",
        "value": [
          "proposal",
          "commit"
        ]
      },
      {
        "field": "amount",
        "op": "gte",
        "value": 10000
      }
    ]
  })
});
const data = await res.json();
```

```python
import os, requests

res = requests.post(
    "https://api.useworkloom.com/api/public/v1/deals/search",
    headers={"Authorization": f"Bearer {os.environ['WORKLOOM_KEY']}"},
    json={
      "filters": [
        {
          "field": "stage",
          "op": "in",
          "value": [
            "proposal",
            "commit"
          ]
        },
        {
          "field": "amount",
          "op": "gte",
          "value": 10000
        }
      ]
    },
)
data = res.json()
```

**Response (sample, 200)**

```json
{
  "data": [
    {
      "id": "66f5c3d1e4b0a1b2c3d4c3d4",
      "name": "Brightline, 10 seats",
      "pipeline_id": "default",
      "stage": "proposal",
      "status": "open",
      "amount": 29900,
      "currency": "USD",
      "probability": 50,
      "forecast_category": "best_case",
      "expected_close_date": "2026-11-14T00:00:00.000Z",
      "next_step": {
        "text": "Call with VP Finance",
        "due_at": "2026-10-09T10:00:00.000Z"
      },
      "company_name": "Brightline",
      "company_domain": "brightline.example",
      "company_id": "66f19b77e4b0a1b2c3d4a1b2",
      "primary_contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
      "contacts": [
        {
          "contact_id": "66f2a1c0e4b0a1b2c3d4e5f6",
          "role": "champion"
        }
      ],
      "closed_at": null,
      "close_reason_code": null,
      "owner_seat_id": "66e0f1a2e4b0a1b2c3d40a0b",
      "source": "api:Warehouse sync",
      "custom_fields": {
        "competitor": "Pipedrive"
      },
      "created_at": "2026-09-25T12:00:00.000Z",
      "updated_at": "2026-10-03T08:42:10.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "66f5c3d1e4b0a1b2c3d4c3d4"
}
```

**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`.
- 409: `duplicate`, `conflict` or `idempotency_key_in_use`.
- 429: `rate_limited`. Wait `Retry-After` seconds.
- 500: `internal_error`.
