API reference
Companies
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/queryQuery Spec search - POST
/entity/v1/companies/detail-by-idFetch company records
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.
# 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
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
- where
- Type
- object
- Notes
- Query Spec tree. Required by /v1/companies/query
- Parameter
- size
- Type
- integer (1-10000)
- Notes
- Company IDs in one page. Omitting it returns 100
- Parameter
- after
- Type
- string
- Notes
- Cursor. Pass the next value from the previous response
- Parameter
- company_ids
- Type
- string[] (1-100)
- Notes
- IDs from a search, sent to the detail route
- Parameter
- _source / source
- Type
- array, object, or boolean
- Notes
- 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
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 page. What a response may contain is a separate, wider list: a field can be returnable without being queryable.
nameindustrycategories_and_keywordswebsitelinkedin_urlWhat the company is called and what it says it does.
nameindustrycategories_and_keywordswebsitelinkedin_urlOperators: match, eq, in, exists
{
"where": {
"all": [
{
"field": "industry",
"match": "software"
}
]
}
}hq_cityhq_statehq_countryhq_country_iso2hq_regionshq_full_addressHeadquarters location.
hq_cityhq_statehq_countryhq_country_iso2hq_regionshq_full_addressOperators: match, eq, in, exists
{
"where": {
"all": [
{
"field": "hq_country",
"match": "United States"
},
{
"field": "hq_city",
"match": "Austin"
}
]
}
}stock_tickerstock_exchangeListing details for public companies.
stock_tickerstock_exchangeOperators: match, eq, in, exists
{
"where": {
"all": [
{
"field": "stock_exchange",
"exists": true
}
]
}
}typesize_rangeis_b2bExact categories. size_range values carry their unit, for example 51-200 employees.
typesize_rangeis_b2bOperators: eq, in, exists
{
"where": {
"all": [
{
"field": "size_range",
"eq": "51-200 employees"
},
{
"field": "is_b2b",
"eq": true
}
]
}
}employees_countfollowers_countfounded_yearemployees_count_change_yearly_percentageSize, reach, age, and year-over-year headcount change.
founded_year reads on a record; filtering on it is being improved.
employees_countfollowers_countfounded_yearemployees_count_change_yearly_percentageOperators: gte, lte, exists
Ask 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.
{
"where": {
"all": [
{
"field": "employees_count",
"gte": 500
},
{
"field": "employees_count",
"lte": 5000
}
]
}
}last_funding_round_amount_raisedAmount raised in the most recent round.
last_funding_round_amount_raisedOperators: gte, lte, exists
{
"where": {
"all": [
{
"field": "last_funding_round_amount_raised",
"gte": 1000000
}
]
}
}last_funding_round_datelast_updated_atTake YYYY-MM-DD or a relative offset such as now-18m.
last_funding_round_datelast_updated_atOperators: gte, lte, exists
{
"where": {
"all": [
{
"field": "last_funding_round_date",
"gte": "now-3y"
}
]
}
}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
- size_range
- Values
Myself Only1-10 employees11-50 employees51-200 employees201-500 employees501-1000 employees1001-5000 employees5001-10,000 employees10,001+ employees
- Field
- type
- Values
Privately HeldPublic CompanyPartnershipNonprofitEducationalGovernment AgencySelf-EmployedSelf-Owned
Not every category field is a fixed set
Response shape
Successful responses use the public envelope with code, msg, and data.
Search returns IDs, and a next cursor while more pages remain:
{
"code": 200,
"msg": "ok",
"data": {
"company_ids": ["Cm4vTnR2sD", "CmZp8Lk1uH"],
"next": "WzE3MjQwMDAwMDAsIkNtNHZUblIyc0QiXQ"
}
}Detail returns the records, and names the IDs it could not resolve:
{
"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, what each one holds, and a whole one to read.
Access surfaces
- Surface
- REST
- How to use this capability
- POST /v1/companies/query; POST /entity/v1/companies/detail-by-id
- Surface
- Metix AI skill
- How to use this capability
- metix-company-search
- Surface
- MCP
- How to use this capability
- Use the MCP setup page to expose the same REST capability. Capability-specific tool names remain pending schema verification.
- Surface
- Natural-language prompt
- How to use this capability
- 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.