Companies
The company record screen, and the REST API endpoints for managing companies within your organization.
The company list
Companies in the sidebar opens the list of every company in your
organization, at /app/<your-org>/companies. Each row shows:
| Column | What it holds |
|---|---|
| Name | The company's name. Clicking it opens the company's record page. |
| Stage | Its lifecycle stage — Lead, Disqualified, Customer or Former customer. |
| People | How many people are linked to the company. |
| Open deals | How many open deals the company has. Closed ones are history and are not counted. |
| Updated | How long ago the company last changed. |
Search the list with the box above it — it matches the company's name and its notes. Narrow it with the Stage filter, and sort by clicking the Name, Stage or Updated header. The two count columns cannot be sorted.
Your search, filter, sort and page number all live in the address bar, so a filtered list is a link you can send to a colleague or bookmark.
Each row's ⋯ menu repeats View — the same destination as the name — and
adds Edit and Delete.
Creating and editing a company
New company, above the list, opens a panel from the right of the screen.
While the list is empty, the same button also sits under the empty message.
Edit, in a row's ⋯ menu or in the ⋯ menu on a company's record page,
opens the same panel filled in with what the company already holds.
| Field | What to put in it |
|---|---|
| Name | Required, up to 200 characters. |
| Lifecycle stage | Lead, Disqualified, Customer or Former customer. A new company starts as Lead. |
| Source | How the company reached you — Website, Referral, Social media, Advertising, Cold call, Email, Event or Other. A new company starts as Other. |
| Notes | Optional free text, up to 5000 characters. Clearing it empties the notes. |
Saving closes the panel and updates the screen you opened it from — the list refreshes in place, and a record page reloads with the new values. Cancel, the close button and clicking outside the panel all discard what you typed.
The company record screen
Opening a company from anywhere in the app takes you to its record page at
/app/<your-org>/companies/<company-id>. The page is in two parts.
The company's name is the page title, with a ⋯ menu beside it holding every
action the page offers — Edit and Delete. On the left, the company's own
attributes, which stay on screen the whole time:
| Attribute | What it holds |
|---|---|
| Lifecycle stage | Lead, Disqualified, Customer or Former customer. |
| Source | How the company reached you — Website, Referral, Social media, Advertising, Cold call, Email, Event or Other. |
| Notes | Free text. Empty until someone writes something. |
On the right, the company's related records in tabs:
- Deals, the tab the page opens on — every deal of this account, open and closed, across every pipeline, soonest expected close date first. Add deal creates one with the company already filled in. See Working with Deals.
- People, listing everyone linked to the company with their job title, email and phone, and showing how many there are next to the tab name.
The active tab is part of the URL — ?tab=people — so a link you copy from the
address bar reopens the company on the tab you were reading, and a refresh keeps
you there. On a narrow screen the attributes become a Details section at the
top of the page that you can collapse, with the tabs underneath.
Deleting a company is refused while people are still linked to it. The confirmation names how many people are in the way and offers no delete button — move or delete those people first, then delete the company.
Deals refuse it too, whatever their status: a company that still has any is kept, and the delete reports a failure rather than taking its history with it. Reassign those deals to another company, or delete them, first — see Deals. When people and deals both stand in the way, the refusal names both counts.
Endpoints
All endpoints require a valid API key in the Authorization header. See Authentication for details.
Base URL: /api/v1List Companies
GET /api/v1/companiesQuery parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 25 | Number of results (1-100) |
offset | number | 0 | Pagination offset |
query | string | — | Search by name or notes |
sortBy | string | "createdAt" | Sort field: name, lifecycleStage, createdAt, updatedAt |
sortOrder | string | "asc" | Sort direction: asc or desc |
lifecycleStage | string | — | Comma-separated stage filter (e.g., lead,customer) |
source | string | — | Comma-separated source filter (e.g., website,referral) |
Lifecycle stage values: lead, disqualified, customer, formerCustomer
Source values: website, referral, socialMedia, advertising, coldCall, email, event, other
query is split into words, and a company matches when every word
appears in its name or its notes — in any order, case-insensitive — so a word
found only in the notes still matches it. A word that matches neither excludes
the company. query takes up to 200 characters, and a longer one is a 422.
Words past the eighth are ignored, and a query of only spaces is the same as
none.
Returns { "data": [...], "total": number }.
Get Company
GET /api/v1/companies/:idCreate Company
POST /api/v1/companies
Content-Type: application/json| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Company name (1-200 characters) |
lifecycleStage | string | No | Lifecycle stage (default: lead) |
source | string | No | How the company was acquired (default: other) |
notes | string | No | Free-text notes (up to 5000 characters) |
Update Company
PATCH /api/v1/companies/:id
Content-Type: application/jsonBody: same fields as Create (all optional). notes accepts null to clear it.
Delete Company
DELETE /api/v1/companies/:idReturns { "success": true } on success.
A company that still has people linked to it cannot be deleted. The request responds 409 with the number of people that are in the way, so you can report it without a second request:
{
"error": "Company still has people linked to it",
"peopleCount": 3
}Move or delete those people first — see People.
Deals block the deletion the same way, whatever their status: the 409 carries a
dealCount instead. Reassign them to another company with
PATCH /api/v1/deals/:id and a new companyId, or delete them, before the
company can go.
{
"error": "Company still has deals linked to it",
"dealCount": 4
}Both guards are evaluated before the refusal, so a company held by people and
deals reports both counts at once — the error prose and the count keys name
every blocker, not just the first one found.
{
"error": "Company still has people and deals linked to it",
"peopleCount": 3,
"dealCount": 4
}See Deals.
Response shape
{
"id": "0c1f5b8e-...",
"organizationId": "9a2d...",
"name": "Acme Inc.",
"lifecycleStage": "lead",
"source": "website",
"notes": null,
"createdAt": "2026-09-01T14:54:01.000Z",
"updatedAt": "2026-09-01T14:54:01.000Z",
"counts": { "people": 0, "openDeals": 0 }
}counts carries the number of people and open deals attached to the company.
openDeals counts only the deals still open — a won or lost one is history and
does not appear in it. See Deals.
createdAt and updatedAt are ISO 8601 in UTC, and the counts are raw numbers.
The API is not localized, whatever language the app itself is showing you — see
Data Formats.
Examples
cURL
# List companies
curl https://your-app.com/api/v1/companies \
-H "Authorization: Bearer ba_a1b2c3d4e5f6..."
# List with filters
curl "https://your-app.com/api/v1/companies?lifecycleStage=lead,customer&source=website&sortBy=name&sortOrder=asc&limit=10" \
-H "Authorization: Bearer ba_a1b2c3d4e5f6..."
# Get a single company
curl https://your-app.com/api/v1/companies/UUID_HERE \
-H "Authorization: Bearer ba_a1b2c3d4e5f6..."
# Create a company
curl -X POST https://your-app.com/api/v1/companies \
-H "Authorization: Bearer ba_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{"name":"Acme Inc.","source":"website"}'
# Update a company
curl -X PATCH https://your-app.com/api/v1/companies/UUID_HERE \
-H "Authorization: Bearer ba_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{"lifecycleStage":"customer","notes":"Signed the annual contract"}'
# Delete a company
curl -X DELETE https://your-app.com/api/v1/companies/UUID_HERE \
-H "Authorization: Bearer ba_a1b2c3d4e5f6..."JavaScript / TypeScript
const API_KEY = "ba_a1b2c3d4e5f6...";
const BASE_URL = "https://your-app.com/api/v1";
// List companies
const response = await fetch(
`${BASE_URL}/companies?lifecycleStage=customer&limit=10&sortOrder=desc`,
{ headers: { Authorization: `Bearer ${API_KEY}` } },
);
const { data, total } = await response.json();
// Create a company
const createRes = await fetch(`${BASE_URL}/companies`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Acme Inc.",
source: "website",
}),
});
const { data: newCompany } = await createRes.json();Python
import requests
API_KEY = "ba_a1b2c3d4e5f6..."
BASE_URL = "https://your-app.com/api/v1"
# List companies
response = requests.get(
f"{BASE_URL}/companies",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"lifecycleStage": "lead,customer", "limit": 10, "sortOrder": "desc"},
)
data = response.json()
# Create a company
response = requests.post(
f"{BASE_URL}/companies",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"name": "Acme Inc.", "source": "website"},
)
new_company = response.json()