---
title: "Assert Company"
method: PUT
path: "/companies/assert"
tags: ["Assert / Upsert"]
---

# Assert Company

`PUT /companies/assert`

## Request

- Base URL: `https://be.graph8.com/api/v1`
- URL: `https://be.graph8.com/api/v1/companies/assert`
- Auth: HTTP bearer

Create or update a company. Matches by domain, then linkedin_url.

## Headers

- `Authorization` string, nullable
- `X-Target-Org-Id` string, nullable

## Request body

- CompanyAssertRequest
  - `list_id` integer, required: Target list ID
  - `domain` string, nullable: Company domain (primary match key)
  - `linkedin_url` string, nullable: LinkedIn URL (fallback match key)
  - `name` string, nullable
  - `industry` string, nullable
  - `employee_count` integer, nullable
  - `annual_revenue` string, nullable
  - `city` string, nullable
  - `state` string, nullable
  - `country` string, nullable
  - `website` string, nullable
  - `description` string, nullable
  - `custom_fields` object, nullable: Custom column values to write on this record, keyed by the column's display title (e.g. 'Followup 1'), its slug (e.g. 'udo_followup_1_ab12cd34'), or a case/space variant of the title. Keys that match no existing column are reported back in `ignored_fields` unless `create_missing_fields` is true.
  - `create_missing_fields` boolean: When true, any key in `custom_fields` that matches no existing column is created as a NEW list-scoped custom column (max 100 per request) and then written. Default false preserves the previous behaviour of not creating columns implicitly.

## Response `200`

Successful Response

- ApiResponseCompanyAssertResponse
  - `data` CompanyAssertResponse, required
    - `action` string, required: 'created' or 'updated'
    - `count` integer
    - `custom_fields` CustomFieldWriteReport: How a write path handled the request's custom (dynamic) column keys. Shared by every Developer API write surface that accepts custom columns (``POST /contacts``, ``PUT /contacts/assert[/batch]``, ``PUT /companies/assert[/batch]``). Every field defaults to empty, so a client that ignores this object sees no behavioural change. It exists because these keys were previously dropped with NO caller-visible signal — the only trace was a server-side ``logger.warning`` in ``append_to_audience``.
      - `written` string[]: Caller keys that resolved to a custom column and were written.
      - `created` string[]: Caller keys for which a NEW custom column was created by this request.
      - `ignored` string[]: Caller keys that matched no custom column and were NOT written. Create the column first (POST /fields) or pass create_missing_fields=true.
    - `warnings` string[]: Advisory notes about values saved as sent that look wrong (e.g. an unrecognised country). Empty when the input is clean.
    - `company_id` integer, nullable: ID of the company that was created or updated (use it with GET/PATCH /companies/{company_id}). Null when the saved record cannot be identified unambiguously, e.g. when the domain already matched several companies in the list.
  - `pagination` PaginationMeta
    - `page` integer, required: Current page number (1-indexed)
    - `limit` integer, required: Items per page
    - `total` integer, required: Total number of items
    - `has_next` boolean, required: Whether there are more pages
    - `next_cursor` string, nullable: Opaque cursor for the next page; null when there are no more items. Pass it back as the `cursor` query param to fetch the following page without computing page numbers.
    - `total_available` integer, nullable: Search endpoints only: how many records really match, when known. Can be larger than `total`, which is capped at the 10,000 results that can be paged. For company search this is a distinct-company estimate. Null when unknown; absent outside search.
    - `total_is_lower_bound` boolean, nullable: Search endpoints only: true when more records match than `total` shows (the result set is larger than the 10,000 results that can be paged). Absent outside search.
    - `notes` string[], nullable: Search endpoints only: plain-language notes about the result, e.g. that more records match than can be paged, or that a reversed `between` range was put in order.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/graph8/apis/graph8-developer-api.md) · [All operations](https://skmtc.dev/graph8/apis/graph8-developer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/graph8/apis/graph8-developer-api/revisions/2e7cfa0ca921?raw)
