WorkloomDevelopers
v1Get an API key
Reference/Deals

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 to read, deals:write to change.

The deal object

idstring

The deal’s id.

namestring

Deal name.

pipeline_idstring

Which pipeline it is on. "default" unless you have several.

stagestring

The stage key, as your pipeline names it.

statusstring

Open, won, lost, or parked (off the board until a date). One of open, won, lost, parked.

amountnumber, nullable

Value of the deal.

currencystring

Three-letter currency code.

probabilityinteger, nullable

Chance of winning, 0 to 100, from the stage.

forecast_categorystring

Forecast category, from the stage. One of pipeline, best_case, commit, omitted.

expected_close_datetimestamp, nullable

When you expect it to close.

next_stepobject, nullable

What happens next, and when.

company_namestring, nullable

The account’s name.

company_domainstring, nullable

The account’s website domain.

company_idstring, nullable

The company record, if any.

primary_contact_idstring, nullable

The main contact on the deal.

contactsarray of object

Everyone on the deal, with their role.

closed_attimestamp, nullable

When it was won or lost.

close_reason_codestring, nullable

Why it was won or lost: one of your reason keys.

owner_seat_idstring, nullable

The teammate who owns the deal. Null when nobody does.

sourcestring, nullable

How it was created, for example "manual" or "api:Warehouse sync".

custom_fieldsobject

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_attimestamp

When the deal was created.

updated_attimestamp

When the deal last changed.

The deal object
{
  "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

GET/deals

List 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
statusstring

open, won, lost or parked.

stagestring

A stage key.

pipeline_idstring

A pipeline. Omit for every pipeline.

sortstring

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.

limitinteger

How many to return, 1 to 100. Default 25.

cursorstring

The next_cursor from the previous page.

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 deals
curl "https://api.useworkloom.com/api/public/v1/deals?limit=25" \
  -H "Authorization: Bearer $WORKLOOM_KEY"
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();
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
{
  "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"
}
200 OKsample
POST/deals

Create a deal

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:writeTakes Idempotency-Key
Header parameters
Idempotency-Keystring

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
namestring

Deal name. Defaults to the main contact’s company, then their name.

pipeline_idstring

Which pipeline. Defaults to "default".

stagestring

Stage key. Defaults to the pipeline’s first open stage.

amountnumber, nullable

Value of the deal.

currencystring

Three-letter currency code. Defaults to USD.

expected_close_datetimestamp, nullable

When you expect it to close.

next_stepobject or string, nullable

What happens next: { "text": "Send the proposal", "due_at": "2026-11-02T10:00:00Z" }, or just the text.

company_namestring, nullable

The account’s name.

company_domainstring, nullable

The account’s website domain.

company_idstring, nullable

A company record to open it against.

primary_contact_idstring, nullable

The main contact. One open deal per contact per pipeline.

contactsarray of object

Everyone on the deal. Replaces the list.

owner_seat_idstring, nullable

Who owns it. Only a key that acts for the whole workspace may set this.

reason_codestring, nullable

Needed when the stage is a lost stage: one of your lost reasons.

reason_notestring, nullable

A note on why it closed.

fieldsobject

Your own fields, by key (Settings › Data model). Values are checked against each field’s type.

custom_fieldsobject

The same as fields, by the name the deal object uses.

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.

Create a deal
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"
}'
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();
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
{
  "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
}
201 Createdsample
GET/deals/{id}

Get a deal

Returns one deal.

Scope: deals:read
Path parameters
idstringRequired

The deal’s id.

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.

Get a deal
curl "https://api.useworkloom.com/api/public/v1/deals/66f5c3d1e4b0a1b2c3d4c3d4" \
  -H "Authorization: Bearer $WORKLOOM_KEY"
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();
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
{
  "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"
  }
}
200 OKsample
PATCH/deals/{id}

Update a deal

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
idstringRequired

The deal’s id.

Body parameters
namestring

Deal name.

amountnumber, nullable

Value of the deal. Null clears it.

currencystring

Three-letter currency code.

expected_close_datetimestamp, nullable

When you expect it to close. Null clears it.

next_stepobject or string, nullable

What happens next: { "text": "Send the proposal", "due_at": "2026-11-02T10:00:00Z" }, or just the text.

company_namestring, nullable

The account’s name.

company_domainstring, nullable

The account’s website domain.

primary_contact_idstring, nullable

The main contact.

contactsarray of object

Everyone on the deal. Replaces the list.

owner_seat_idstring, nullable

Hand the deal to a teammate. Null leaves it unowned.

reasonstring, nullable

Why it changed owner. Needed when the key’s role does not reach every record.

fieldsobject

Your own fields, by key (Settings › Data model). Values are checked against each field’s type.

custom_fieldsobject

The same as fields, by the name the deal object uses.

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.

Update a deal
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"
  }
}'
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();
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
{
  "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
}
200 OKsample
DELETE/deals/{id}

Delete a deal

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:writeDeletes
Path parameters
idstringRequired

The deal’s id.

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
curl -X DELETE "https://api.useworkloom.com/api/public/v1/deals/66f5c3d1e4b0a1b2c3d4c3d4" \
  -H "Authorization: Bearer $WORKLOOM_KEY"
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();
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
{
  "data": {
    "id": "66f5c3d1e4b0a1b2c3d4c3d4",
    "deleted": true
  },
  "livemode": true
}
200 OKsample
POST/deals/{id}/move

Move a deal

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:writeTakes Idempotency-Key
Path parameters
idstringRequired

The deal’s id.

Header parameters
Idempotency-Keystring

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
stagestringRequired

The stage key to move to.

reason_codestring, nullable

Needed for a lost stage: one of your lost reasons. Optional for won.

reason_notestring, nullable

A note on why.

competitorstring, nullable

Who it was lost to, if anyone.

fieldsobject

Values the new stage asks for (its required fields), by key.

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.

Move a deal
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"
}'
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();
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
{
  "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
}
200 OKsample
Was this page useful?