Home Pricing Docs Blog Changelog About Log in Go to your tickets
Browse docs

Companies

Overview

A company groups the contacts that belong to the same customer. Each company belongs to a workspace and has a name, an optional domain, a phone number, and free-text notes.

When a contact is created and the host of its email address matches a company's domain, the contact is attached to that company automatically. That rule runs once, at the moment the contact is created, and never runs again. Changing a company's domain later does not move contacts that already exist, and a contact you move by hand stays where you put it.

Every company is scoped to the channels you can reach. A token that is limited to a subset of channels only sees companies with at least one ticket in those channels, and the contact_count and ticket_count on every response are narrowed the same way.

List Companies

Retrieve a paginated list of companies in the current workspace.

GET /api/companies

Query Parameters

Parameter Type Description
per_page integer Results per page (default: 25, max: 100)
sort string Sort field: name, created_at, contact_count, ticket_count. Prefix with - for descending (default: name)
filter[name] string Partial match on company name
filter[domain] string Partial match on company domain
filter[search] string Search across both name and domain

Example Request

curl "https://there-there.app/api/companies?filter[search]=acme&sort=-ticket_count&per_page=10" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Example Response

{
    "data": [
        {
            "id": 1,
            "ulid": "01kzx9m6kce637yvd1m95077kr",
            "name": "Acme",
            "domain": "acme.com",
            "phone": "+32 3 555 55 55",
            "notes": "Pays yearly.",
            "contact_count": 4,
            "ticket_count": 12
        }
    ],
    "links": { "first": "...", "last": "...", "prev": null, "next": "..." },
    "meta": { "current_page": 1, "last_page": 2, "per_page": 10, "total": 14 }
}

Get Company

GET /api/companies/{company}

The {company} segment is the company ULID.

Example Request

curl https://there-there.app/api/companies/01kzx9m6kce637yvd1m95077ks \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Example Response

{
    "data": {
        "id": 2,
        "ulid": "01kzx9m6kce637yvd1m95077ks",
        "name": "Globex",
        "domain": null,
        "phone": null,
        "notes": null,
        "contact_count": 0,
        "ticket_count": 0
    }
}

A company in another workspace returns 404. A company in your own workspace returns 403 when none of its tickets sit in a channel your token can reach.

Create Company

POST /api/companies

Request Body

Field Type Required Description
name string Yes Company name
domain string No Bare hostname, unique per workspace
phone string No
notes string No Free-text notes
contact_ulids array No Contact ULIDs to attach to the new company

The domain is trimmed and lowercased, and it has to be a bare hostname. An address such as jane@acme.com, a scheme such as https://acme.com, or anything with a path is rejected with 422. Two companies in the same workspace cannot claim the same domain, though two workspaces can each have their own company for acme.com.

Matching uses the full host of a contact's email address, not a shortened version of it, so a company that owns acme.com does not pick up contacts at mail.acme.com.

A ULID in contact_ulids that belongs to another workspace is ignored rather than rejected, so the request still returns 201 and simply attaches fewer contacts.

Example Request

curl -X POST https://there-there.app/api/companies \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme",
    "domain": "acme.com",
    "phone": "+32 3 555 55 55",
    "notes": "Pays yearly.",
    "contact_ulids": ["01hx9f3k2n7q4v8w0y2a4c6e8g"]
  }'

Example Response

{
    "data": {
        "id": 3,
        "ulid": "01kzx9m6kce637yvd1m95077kt",
        "name": "Acme",
        "domain": "acme.com",
        "phone": "+32 3 555 55 55",
        "notes": "Pays yearly.",
        "contact_count": 1,
        "ticket_count": 0
    }
}

Returns 201 on success.

Update Company

PUT /api/companies/{company}
PATCH /api/companies/{company}

Request Body

Field Type Required Description
name string No Cannot be empty when it is sent
domain string No Bare hostname, unique per workspace
phone string No
notes string No Free-text notes

All fields are optional. Omit a field to leave it unchanged. Send null for domain, phone, or notes to clear it. A name that is sent has to hold a value.

Changing the domain does not move any contact that already exists. It only decides which contacts created from now on are attached.

This endpoint does not accept contact_ulids. To move one contact into or out of a company, send company_ulid to Update Contact.

Example Request

curl -X PATCH https://there-there.app/api/companies/01kzx9m6kce637yvd1m95077kt \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme Corporation", "notes": "Renewal in March."}'

Example Response

{
    "data": {
        "id": 3,
        "ulid": "01kzx9m6kce637yvd1m95077kt",
        "name": "Acme Corporation",
        "domain": "acme.com",
        "phone": "+32 3 555 55 55",
        "notes": "Renewal in March.",
        "contact_count": 1,
        "ticket_count": 0
    }
}

Delete Company

DELETE /api/companies/{company}

Deleting a company keeps its contacts and every ticket they ever opened. Only the grouping goes: the contacts are detached and stay in the workspace.

Example Request

curl -X DELETE https://there-there.app/api/companies/01kzx9m6kce637yvd1m95077kt \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Accept: application/json"

Returns 204 with an empty body on success.