# Companies

Section: API reference
Source: https://platform.metix.ai/docs/api/companies
Every page in one file: https://platform.metix.ai/llms-full.txt

Search organizations with a Query Spec tree and read the records you select. Use it to build account lists and to attach company context to people and job results.

Routes: 2. Search: /v1/companies/query. Search returns: encrypted IDs. Detail batch: up to 100 IDs.

- `POST /v1/companies/query`: Query Spec search (MCP tool `metix_query_companies`)
- `POST /entity/v1/companies/detail-by-id`: Fetch company records (MCP tool `metix_get_companies`)

## Search, then fetch

Search never returns company records. It returns encrypted string company IDs, and you pass up to 100 of them to the detail route to read the records. There is no one-shot endpoint, so plan for two calls.

```bash
# 1. Search. Returns encrypted IDs, never records.
curl -X POST "https://mira-api.metix.ai/v1/companies/query" \
  -H "Authorization: Bearer $METIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "where": {"all": [
      {"field": "categories_and_keywords", "match": "artificial intelligence"},
      {"field": "hq_country", "match": "United States"},
      {"field": "employees_count", "gte": 50},
      {"field": "employees_count", "lte": 500},
      {"not": {"field": "type", "eq": "Public Company"}}
    ]},
    "size": 25
  }'

# 2. Read the records, up to 100 IDs per call.
curl -X POST "https://mira-api.metix.ai/entity/v1/companies/detail-by-id" \
  -H "Authorization: Bearer $METIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "company_ids": ["Cm4vTnR2sD", "CmZp8Lk1uH"],
    "_source": ["id", "name", "industry", "size_range", "hq_full_address"]
  }'
```

> **Two calls, always**
>
> A search response carries IDs and nothing else. If your code expects records back from a search, it will read an empty payload and conclude there is no data. Send the IDs to the detail route, in batches of up to 100.

## When to use it

- Build an account list by industry, size, headquarters, or funding.
- Attach organization context to a job or profile result set.
- Separate B2B from B2C, or public from private, before a market count.

## Request parameters and limits

| Parameter | Type | Notes |
| --- | --- | --- |
| where | object | Query Spec tree. Required by /v1/companies/query |
| size | integer (1-10000) | Company IDs in one page. Omitting it returns 100 |
| after | string | Cursor. Pass the next value from the previous response |
| company_ids | string[] (1-100) | IDs from a search, sent to the detail route |
| _source / source | array, object, or boolean | Optional field selection on detail |

- One operator per leaf. A headcount band is an all of two leaves, not gte and lte in one node.
- A field name that is not in this dataset's list is refused, so a typo is visible rather than returning a record without it. The three datasets do not share one vocabulary.
- Search returns at most 10,000 IDs per page and 100 when size is omitted; detail accepts at most 100 IDs per request.
- Companies declare no scope nodes. One document is one company, so there is nothing to group.
- The response carries IDs and a cursor, not a match count. Page until next is absent if you need the size of a set.
- Company data is a periodically refreshed snapshot and can lag real-world changes.

> **Credit cost**
>
> Company search costs ceil(returned IDs / 25) Credits, and 0 when it returns nothing. Company detail costs ceil(found records / 5) Credits, and not_found rows are free.

## Queryable fields

These are the only names a leaf may put in `field`. The grammar around them, including composition, one operator per leaf, and relative dates, is on the [Query Spec](https://platform.metix.ai/docs/api/query-spec.md) page. What a response may contain is a separate, wider list: a field can be returnable without being queryable.

`name``industry``categories_and_keywords``website``linkedin_url`What the company is called and what it says it does.Operators: match, eq, in, exists `hq_city``hq_state``hq_country``hq_country_iso2``hq_regions``hq_full_address`Headquarters location.Operators: match, eq, in, exists `stock_ticker``stock_exchange`Listing details for public companies.Operators: match, eq, in, exists `type``size_range``is_b2b`Exact categories. size_range values carry their unit, for example 51-200 employees.Operators: eq, in, exists `employees_count``followers_count``founded_year``employees_count_change_yearly_percentage`Size, reach, age, and year-over-year headcount change.founded_year reads on a record; filtering on it is being improved.Operators: gte, lte, existsAsk for founded_year in _source and it comes back on the record as normal. Using it as a filter answers with an error for now, rather than a set that looks right and is not, while we make the comparison reliable. Narrow with the other fields in this group and sort what comes back. Everything else here filters normally. `last_funding_round_amount_raised`Amount raised in the most recent round.Operators: gte, lte, exists `last_funding_round_date``last_updated_at`Take YYYY-MM-DD or a relative offset such as now-18m.Operators: gte, lte, exists

## Fields with a fixed set of values

These are matched against the whole stored value, so the spelling and the capitalisation both have to match. Getting either wrong is the one mistake in the grammar that raises no error: the query is valid, it costs nothing, and it returns zero, which reads as an answer about the data rather than about the query.

| Field | Values |
| --- | --- |
| size_range | `Myself Only``1-10 employees``11-50 employees``51-200 employees``201-500 employees``501-1000 employees``1001-5000 employees``5001-10,000 employees``10,001+ employees` |
| type | `Privately Held``Public Company``Partnership``Nonprofit``Educational``Government Agency``Self-Employed``Self-Owned` |

> **Not every category field is a fixed set**
>
> industry is not a fixed set here: a company's industry runs to over three hundred values, unlike the twenty-value set on a person's experience. Ask it with match.

## Response shape

Successful responses use the public envelope with `code`, `msg`, and `data`.

Search returns IDs, and a `next` cursor while more pages remain:

```json
{
  "code": 200,
  "msg": "ok",
  "data": {
    "company_ids": ["Cm4vTnR2sD", "CmZp8Lk1uH"],
    "next": "WzE3MjQwMDAwMDAsIkNtNHZUblIyc0QiXQ"
  }
}
```

Detail returns the records, and names the IDs it could not resolve:

```json
{
  "code": 200,
  "msg": "ok",
  "data": {
    "total": 2,
    "found": 2,
    "not_found": [],
    "results": [{
      "id": "Cm4vTnR2sD",
      "name": "Example Corp",
      "industry": "Software Development",
      "size_range": "201-500 employees",
      "hq_full_address": "San Francisco, CA, United States"
    }]
  }
}
```

The record itself is a page of its own: [every field it can carry](https://platform.metix.ai/docs/api/companies/record.md), what each one holds, and a whole one to read.

## Access surfaces

| Surface | How to use this capability |
| --- | --- |
| REST | POST /v1/companies/query; POST /entity/v1/companies/detail-by-id |
| Metix AI skill | metix-company-search |
| MCP | Use the MCP setup page to expose the same REST capability. Capability-specific tool names remain pending schema verification. |
| Natural-language prompt | Find privately held US AI companies with 50 to 500 employees, fetch their records, and group them by industry. |

Common next step: [find the people inside those companies](https://platform.metix.ai/docs/api/people.md).
