# Find company KObjects (custom Objects)

> GET /v1/companies/{id}/klasses/{name} · Core resources API

Source: https://developer.kustomer.com/api/core-resources/find-company-kobjects-custom-objects

```http
GET https://{orgname}.api.kustomerapp.com/v1/companies/{id}/klasses/{name}
Authorization: Bearer <API key>
```

## Authorization

Requires any one of these roles: `org.permission.company.read`; or legacy `org.user.company.read`. The API key or user must hold at least one of them. Legacy roles predate permission sets and still work.

Retrieves all [KObjects (custom Objects)](https://help.kustomer.com/en_us/define-attributes-Skr924HI) that are linked to a company based on the unique company ID and unique Klass name.

## About Companies

A company is an organization that your customers belong to, such as a business account. It holds the organization's contact details, tags and custom attributes, can own custom objects, and can sit in a parent-child hierarchy with other companies.

Companies group customers who belong to the same organization, which matters most for B2B support: agents can see which account a person works for, and searches, workflows and reports can filter on company data. A customer links to one company through its `company` attribute, which holds the company ID. Companies are usually created by a CRM sync or an import, then kept up to date as the source system changes. There is no `DELETE` endpoint: you delete a company by updating it with `deleted: true`.

#### Key fields

`name` is the only required field. Set `externalId` to the account's ID in your own system so you can find it again: `GET /v1/companies` accepts `externalId`, or `filter` for a name match, but if you send both, both are ignored. The contact lists `emails`, `phones`, `whatsapps`, `socials`, `urls`, `domains` and `locations` each hold up to 10 entries, and `tags` holds up to 20. Your own fields go in `custom`, named with a type suffix such as `tierStr` or `seatsNum`; see [custom attributes](https://developer.kustomer.com/docs/concepts/custom-attributes).

Updates merge into the existing company by default. Add `replace=true` to replace the whole resource. Updates are subject to object rate limiting, which caps how often one user can change the same company; see [rate limits](https://developer.kustomer.com/docs/concepts/rate-limits).

#### Hierarchies

The hierarchy endpoints link existing companies into trees, such as a parent company and its subsidiaries. Each link is an edge of type `kedge` with its own ID: `sourceId` is the parent and `targetId` is the child. Edges belong to a named tree (`name`, default `company_hierarchy`), and a company has at most one parent per tree, so setting a new parent replaces the old edge. A tree can be at most 20 levels deep and hold at most 2,000 companies. Cycles and self-parenting fail with `400`.

Most hierarchy endpoints take a company ID. The exception is `DELETE /v1/kedge/{id}`, which takes an edge ID. Reading a company returns a `kedge-node` with its parent edge, one page of direct children, and `breadcrumbs` from the root down to the company itself.

#### Which endpoint to use

| To | Call |
| --- | --- |
| List companies, or find one by `externalId` or name | [`GET /v1/companies`](https://developer.kustomer.com/api/core-resources/get-companies) |
| Create, read or update a company (including deleting it with `deleted: true`) | [`POST /v1/companies`](https://developer.kustomer.com/api/core-resources/create-company), [`GET`](https://developer.kustomer.com/api/core-resources/get-company-by-id) or [`PUT /v1/companies/{id}`](https://developer.kustomer.com/api/core-resources/update-company-attributes) |
| List a company's custom objects of one Klass | [`GET /v1/companies/{id}/klasses/{name}`](https://developer.kustomer.com/api/core-resources/find-company-kobjects-custom-objects) |
| Create or update up to 100 companies at once | [`POST`](https://developer.kustomer.com/api/core-resources/bulk-create-companies) or [`PUT /v1/companies/bulk`](https://developer.kustomer.com/api/core-resources/bulk-batch-update-companies) |
| Link a child to a parent | [`POST /v1/kedge`](https://developer.kustomer.com/api/core-resources/create-a-company-hierarchy-edge) or [`POST /v1/kedge/{id}/parent`](https://developer.kustomer.com/api/core-resources/set-a-companys-parent) |
| Read a company's place in the tree | [`GET /v1/kedge/{id}`](https://developer.kustomer.com/api/core-resources/get-a-company-hierarchy-node), or [`GET /v1/kedge/{id}/parent`](https://developer.kustomer.com/api/core-resources/get-a-companys-direct-parent-edge) for just the parent edge (`404` for a root) |
| Make a company a root, keeping its children | [`DELETE /v1/kedge/{id}/parent`](https://developer.kustomer.com/api/core-resources/remove-a-companys-parent) |
| Delete one edge by its edge ID | [`DELETE /v1/kedge/{id}`](https://developer.kustomer.com/api/core-resources/delete-a-company-hierarchy-edge) |

Bulk requests run asynchronously and return a bulk operation; poll it with the [bulk operations](https://developer.kustomer.com/api/core-resources#bulk-operations) endpoints. Add `_clientRef` to every item to match per-item results back to your rows. Deleting a company that still has children in any tree fails with `409 Conflict`, naming the first blocking child and its tree; unlink or delete that child first. A `409` on an edge write means another write to the same tree was in progress, so retry it.

Related: [Customers](https://developer.kustomer.com/api/core-resources#customers), [Model company hierarchies](https://developer.kustomer.com/docs/guides/company-hierarchy), [Bulk operations](https://developer.kustomer.com/docs/guides/bulk-operations), [KObjects (custom objects)](https://developer.kustomer.com/api/core-resources#kobjects-custom-objects)

### Recipes

#### 1. Find or create a company by your account ID

Map an account in your CRM to one Kustomer company, so a sync can run again without creating duplicates.

**Step 1.** [`GET /v1/companies`](https://developer.kustomer.com/api/core-resources/get-companies.md). Look the company up by the account's ID, which you store in `externalId`. The response is a list: the company is the first item in `data`, and an empty list means it doesn't exist yet. Don't add `filter` to the same request, because sending both parameters makes the API ignore both.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/companies?externalId=$ACCOUNT_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/companies --query externalId=$ACCOUNT_ID | jq -r '.data[0].id // empty'
```

**Step 2.** [`POST /v1/companies`](https://developer.kustomer.com/api/core-resources/create-company.md). If there's no match, create the company. `name` needs at least 3 characters. Lists such as `domains` (each `{ domain }`), `emails` and `phones` hold up to 10 entries, and custom attributes go under `custom` with a type suffix such as `tierStr`. Keep `data.id`; customers link to the company by that ID.

```bash title="cURL"
curl --request POST "https://api.kustomerapp.com/v1/companies" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{\"name\": \"$ACCOUNT_NAME\", \"externalId\": \"$ACCOUNT_ID\", \"domains\": [{\"domain\": \"acme.example\"}], \"custom\": {\"tierStr\": \"enterprise\"}}"
```

```bash title="kusty"
kusty api POST /v1/companies \
  --field name="$ACCOUNT_NAME" --field externalId=$ACCOUNT_ID \
  --field domains.0.domain=acme.example --field custom.tierStr=enterprise \
  | jq -r .data.id
```

**Step 3.** [`PUT /v1/companies/{id}`](https://developer.kustomer.com/api/core-resources/update-company-attributes.md). When the account changes later, update the company. Fields you leave out are kept unless you add `replace=true`. Skip the call when nothing changed: one company can only be updated so often in a short window (see [Rate limits](https://developer.kustomer.com/docs/concepts/rate-limits#object-limits)).

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v1/companies/$COMPANY_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"custom": {"tierStr": "strategic"}}'
```

```bash title="kusty"
kusty api PUT /v1/companies/$COMPANY_ID --field custom.tierStr=strategic
```

> For a first import of many accounts, use [`POST /v1/companies/bulk`](https://developer.kustomer.com/api/core-resources/bulk-create-companies) with `_clientRef` on each item, and poll the job as described in [Bulk operations](https://developer.kustomer.com/docs/guides/bulk-operations).

#### 2. Link a customer to their company

Attach a person to the account they work for, so agents see the company on the customer's profile and searches can filter by company.

**Step 1.** [`PUT /v1/customers/{id}`](https://developer.kustomer.com/api/core-resources/update-customer.md). Set the customer's `company` to the company ID. A customer belongs to at most one company. Remember that every later `PUT` on the customer must include `company` too, because leaving it out unlinks them.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v1/customers/$CUSTOMER_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{\"company\": \"$COMPANY_ID\"}"
```

```bash title="kusty"
kusty api PUT /v1/customers/$CUSTOMER_ID --field company=$COMPANY_ID
```

**Step 2.** [`GET /v1/customers/{id}`](https://developer.kustomer.com/api/core-resources/get-customer-by-id.md). Read the customer with `include=company` to get the company record alongside it in one call, for example to show the account name and tier next to the person.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/customers/$CUSTOMER_ID?include=company" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/customers/$CUSTOMER_ID --query include=company
```

> To link many customers at once, send `{ "id", "company" }` items to [`PUT /v1/customers/bulk`](https://developer.kustomer.com/api/core-resources/bulk-batch-update-customers), up to 100 per request.

#### 3. Put a subsidiary under its parent company

Mirror a corporate structure, such as a parent account and its regional offices, in Kustomer's company hierarchy.

**Step 1.** [`POST /v1/kedge/{id}/parent`](https://developer.kustomer.com/api/core-resources/set-a-companys-parent.md). Call this on the child company with the parent's ID as `parentId`. A company has one parent per tree, so this replaces any parent it already had. Trees are named; leave out `name` to use the default `company_hierarchy`. Making a company its own parent or creating a cycle fails with `400`, and a `409` means another write to the same tree was in progress, so retry.

```bash title="cURL"
curl --request POST "https://api.kustomerapp.com/v1/kedge/$CHILD_ID/parent" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{\"parentId\": \"$PARENT_ID\"}"
```

```bash title="kusty"
kusty api POST /v1/kedge/$CHILD_ID/parent --field parentId=$PARENT_ID
```

**Step 2.** [`GET /v1/kedge/{id}`](https://developer.kustomer.com/api/core-resources/get-a-company-hierarchy-node.md). Read the child's place in the tree. `parent` is the edge to its parent, `children` is one page of its direct children, and `breadcrumbs` runs from the root down to the company itself, ready to show as a path such as "Acme Corp › Acme EMEA".

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/kedge/$CHILD_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/kedge/$CHILD_ID | jq -r '[.data.attributes.breadcrumbs[].displayName] | join(" › ")'
```

> A tree can be at most 20 levels deep and hold at most 2,000 companies. [Model company hierarchies](https://developer.kustomer.com/docs/guides/company-hierarchy) covers multiple trees and moving whole branches.

#### 4. Delete a company that has subsidiaries

Remove a company you no longer need, first detaching any child companies that would block the delete.

**Step 1.** [`GET /v1/kedge/{id}`](https://developer.kustomer.com/api/core-resources/get-a-company-hierarchy-node.md). List the company's direct children. Each item in `children` is an edge whose `targetId` is a child company ID. Pass `name` if the company is in a tree other than `company_hierarchy`.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/kedge/$COMPANY_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/kedge/$COMPANY_ID | jq -r '.data.attributes.children[].attributes.targetId'
```

**Step 2.** [`DELETE /v1/kedge/{id}/parent`](https://developer.kustomer.com/api/core-resources/remove-a-companys-parent.md). For each child, remove its parent edge. The child becomes a root and keeps its own children. This takes the child's company ID, not the edge ID.

```bash title="cURL"
curl --request DELETE "https://api.kustomerapp.com/v1/kedge/$CHILD_ID/parent" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api DELETE /v1/kedge/$CHILD_ID/parent --confirm --yes
```

**Step 3.** [`PUT /v1/companies/{id}`](https://developer.kustomer.com/api/core-resources/update-company-attributes.md). There's no `DELETE` for companies; you delete one by sending `deleted: true`. If a child is still attached in any tree, the API answers `409 Conflict` and names the first blocking child and its tree; detach it with `name` set to that tree and try again.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v1/companies/$COMPANY_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"deleted": true}'
```

```bash title="kusty"
kusty api PUT /v1/companies/$COMPANY_ID --field deleted:=true
```

### Example object

A real record from [`GET /v1/companies`](https://developer.kustomer.com/api/core-resources/get-companies.md):

```json
{
  "type": "company",
  "id": "58224b3eaa5f92110005d61e",
  "attributes": {
    "name": "foobar Company Name",
    "externalId": "foobar",
    "createdAt": "2016-11-08T22:01:34.620Z",
    "updatedAt": "2016-11-08T22:11:35.776Z",
    "modifiedAt": "2016-11-08T22:11:35.776Z",
    "tags": [
      "58224d97d4e96711004ecc56"
    ]
  },
  "relationships": {
    "org": {
      "links": {
        "self": "/v1/orgs/57f29863a1dbf61100e6aa92"
      },
      "data": {
        "type": "org",
        "id": "57f29863a1dbf61100e6aa92"
      }
    },
    "createdBy": {
      "links": {
        "self": "/v1/users/58190b991f2932100010d683"
      },
      "data": {
        "type": "user",
        "id": "58190b991f2932100010d683"
      }
    },
    "modifiedBy": {
      "links": {
        "self": "/v1/users/58190b991f2932100010d683"
      },
      "data": {
        "type": "user",
        "id": "58190b991f2932100010d683"
      }
    }
  },
  "links": {
    "self": "/v1/companies/58224b3eaa5f92110005d61e"
  }
}
```

Fields:

- `attributes.name` (string): The company's name, 3 to 256 characters. The only field required on create.
- `attributes.externalId` (string): The account's ID in your CRM or other system, up to 256 characters. Find the company again with `GET /v1/companies?externalId=…`.
- `attributes.createdAt` (string): When the company was created in Kustomer. You can set it on create when importing, along with `importedAt`.
- `attributes.modifiedAt` (string): When the company was last changed.
- `attributes.tags` (array): Tag IDs, up to 20. Sending `tags` on an update replaces the whole list.
- `relationships.createdBy` (object): The user or API key that created the company.

### Relationships

- Referenced by **Customers** via `relationships.company`: The company this customer belongs to. A customer has at most one; set it by sending the company ID as `company`, and resend it on every `PUT`, because leaving it out unlinks the customer.
- Referenced by **KObjects (custom objects)** via `relationships.company`: The company whose timeline shows this KObject, set with `company` when you create it. List them with `GET /v1/companies/{id}/klasses/{name}`.

### Permissions

Fewest roles for a read-only integration: `org.permission.company.read`. For every endpoint: `org.permission.company.update`, `org.permission.company.read`, `org.permission.company.create`.

### Events

Workflow triggers:

- `kustomer.company.create` (Company Created): A company is created
- `kustomer.company.update` (Company Updated): A company changes

Workflow actions:

- `kustomer.company.create` (Company: Create): required inputs `name`
- `kustomer.company.update` (Company: Update): required inputs `id`
- `kustomer.company.find` (Company: Lookup (By ID)): required inputs `identifier`
- `kustomer.company.find-by-external-id` (Company: Lookup (By External ID)): required inputs `externalId`

## Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | Company ID. |
| `name` | string | yes | Klass name. |

## Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | integer | no | Page number of results to return. |
| `pageSize` | integer | no | Number of results to return per page. |
| `sort` | string | no | Sort direction for results. |
| `fromDate` | string | no | Return resources after this date or cursor timestamp, using the endpoint's sort direction. |
| `fields` | string | no | Comma-separated response fields to project. The example is representative, not exhaustive; supported values are resource field names and custom field paths accepted by the endpoint handler. |

## Responses

### 200

OK

- `meta` (object, required)
  - `pageSize` (integer, required)
  - `page` (integer, required)
- `data` (array<object>, required)
  - `type` (string, required)
  - `id` (string, required)
  - `attributes` (object, required)
    - `title` (string, required)
    - `icon` (string, required)
    - `images` (array<string>, required)
    - `s3DataUrl` (string)
    - `custom` (object, required)
    - `tags` (array<any>, required)
    - `updatedAt` (string, required)
    - `createdAt` (string, required)
    - `rev` (integer, required)
  - `relationships` (object, required)
    - `org` (object, required)
    - `klass` (object, required)
    - `company` (object, required)
  - `links` (object, required)
    - `self` (string, required)
- `links` (object, required)
  - `self` (string, required)
  - `first` (string, required)
  - `prev` (string, required, nullable)
  - `next` (string, required, nullable)

```json
{
  "meta": {
    "pageSize": 1,
    "page": 1
  },
  "data": [
    {
      "type": "string",
      "id": "65f2c0a1b4e3d2001234abcd",
      "attributes": {
        "title": "Example title",
        "icon": "string",
        "images": [
          "string"
        ],
        "s3DataUrl": "https://example.com",
        "custom": {},
        "tags": [
          null
        ],
        "updatedAt": "string",
        "createdAt": "string",
        "rev": 0
      },
      "relationships": {
        "org": {
          "links": {
            "self": "string"
          },
          "data": {
            "type": "string",
            "id": "65f2c0a1b4e3d2001234abcd"
          }
        },
        "klass": {
          "link": {
            "self": "string"
          },
          "data": {
            "type": "string",
            "id": "65f2c0a1b4e3d2001234abcd"
          }
        },
        "company": {
          "links": {
            "self": "string"
          },
          "data": {
            "type": "string",
            "id": "65f2c0a1b4e3d2001234abcd"
          }
        }
      },
      "links": {
        "self": "string"
      }
    }
  ],
  "links": {
    "self": "string",
    "first": "string",
    "prev": "string",
    "next": "string"
  }
}
```

### 400

Bad Request

### 401

Unauthorized

### 403

Forbidden

### 404

Not Found

## Example request

```bash
curl --request GET \
  --url 'https://api.kustomerapp.com/v1/companies/6195640664b2fbb9eddc1e9b/klasses/orders' \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```
