# People

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

Search profiles with a Query Spec tree, or ask in plain language. Both return encrypted profile IDs, and the detail route turns those IDs into records.

Routes: 3. Search: /v1/people/query. Search returns: encrypted IDs. Detail batch: up to 100 IDs.

- `POST /v1/people/query`: Query Spec search (MCP tool `metix_query_people`)
- `POST /v1/people-search`: Natural-language search (MCP tool `metix_search_people`)
- `POST /entity/v1/profiles/detail-by-id`: Fetch profile records (MCP tool `metix_get_profiles`)

## Search, then fetch

Search never returns profile records. It returns encrypted string 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/people/query" \
  -H "Authorization: Bearer $METIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "where": {"all": [
      {"field": "city", "eq": "San Francisco"},
      {"has_experience": {"all": [
        {"field": "company_name", "match": "Google"},
        {"field": "level", "eq": "Director"},
        {"field": "is_current", "eq": true}
      ]}}
    ]},
    "size": 25
  }'

# 2. Read the records, up to 100 IDs per call.
curl -X POST "https://mira-api.metix.ai/entity/v1/profiles/detail-by-id" \
  -H "Authorization: Bearer $METIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "profile_ids": ["kR3nQv8xTm", "9tQmLd2wYb"],
    "_source": ["profile_id", "full_name", "active_experience_title", "skills"]
  }'
```

> **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 a profile set by role, skills, employer, education, location, or seniority.
- Express what a flat filter list cannot: alternatives, negation, and numeric or date ranges.
- Ask for a person who held one specific job, rather than a person who separately matched two facts.
- Ask in natural language when the constraints are awkward to write out as a tree.

## Request parameters and limits

| Parameter | Type | Notes |
| --- | --- | --- |
| where | object | Query Spec tree. Required by /v1/people/query |
| size | integer (1-10000) | Profile IDs in one page. Omitting it returns 100 |
| after | string | Cursor. Pass the next value from the previous response |
| text | string (1-5000 chars) | Natural-language question for /v1/people-search. That route accepts text and size only |
| profile_ids | string[] (1-100) | IDs from a search, sent to the detail route |
| _source / source | array, object, or boolean | Field selection on detail. Omit it for the default record; name fields to trade it for a narrower or a wider one |

- One operator per leaf. A bounded range is an all of two leaves, not gte and lte in one node. This is the first mistake almost every caller makes.
- 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.
- Scope nodes exist for people only. Jobs and companies are one document each, so there is nothing to group.
- Every Query Spec search reports total: an exact integer below 100000, and the string "100000+" at or above it. It counts what matched, not what was returned. Read it as a union, not as an integer.
- Profile data is a periodically refreshed snapshot and can lag real-world changes.
- The default record is a subset. Naming fields in _source reaches the full published set: the subject's own links and prose, their employer as a company, and their institution.
- Prose fields carry no email addresses or phone numbers. Contact data is a separate surface with its own pricing.

> **Credit cost**
>
> Query Spec search costs ceil(returned IDs / 25) Credits, and 0 when it returns nothing. Natural-language search costs 5 + ceil(returned IDs / 25) Credits, and keeps the 5 Credit base on any successful response. Profile 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.

`active_title``active_department``title``headline`Role text. active_title and active_department describe the current job; title matches any job held.Operators: match, eq, in, exists `company_name``institution_name`Employer and school names.Operators: match, eq, in, exists `skills``languages``certifications``courses``awards``publications``patents``major`List and free-text attributes attached to the person.Operators: match, eq, in, exists `language_proficiency`How well one language is spoken, as one of five levels. Put it in the same has_language as the language it describes, or it will be satisfied by any language on the profile.Operators: eq, in, exists `full_name``first_name``last_name``linkedin_url`Identity, matched exactly.Operators: eq, in, exists `city``state``country``country_iso2``country_iso3``regions`Where the person is. country takes a name such as United States.Operators: eq, in, exists `workplace_city``workplace_state``workplace_country`Where a job is. Most useful inside has_experience, where it binds to one job.Operators: eq, in, exists `role``level``management_level``industry``company_type`Platform vocabulary, matched exactly rather than fuzzily.Operators: eq, in, exists `is_working``is_decision_maker``is_current``is_studying`Booleans. is_current and is_studying describe a record, so they belong in a scope.Operators: eq, in, exists `experience_months``duration_months`Time spans in months. experience_months is career total; duration_months is one job.Operators: gte, lte, exists `company_employees_count``company_size_range`Employer size. company_size_range is an ordinal band, so it compares as a number.Operators: gte, lte, exists `degree_level``institution_ranking``graduation_year``study_start_year`Education, as ordinals and years.Operators: gte, lte, exists `started_at``ended_at`Job dates. Takes YYYY-MM-DD or a relative offset such as now-6m.Operators: gte, lte, exists

> **Same-record scopes**
>
> People hold many jobs and many degrees, so people are the only entity with same-record scopes: has_experience, has_education, and has_language. Every condition inside one scope must match the same record. That is the difference between a director at Google and someone who worked at Google and was a director somewhere else.

## 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 |
| --- | --- |
| language_proficiency | `Elementary proficiency``Limited working proficiency``Professional working proficiency``Full professional proficiency``Native or bilingual proficiency`The whole scale, lowest to highest. A record carries the same five strings, so a level you read is a level you can filter on. Nothing else is accepted, including numbers and words like fluent or advanced, because those mean different levels to different people. |
| management_level, level | `Specialist``Senior``Manager``Head``Director``Vice President``President/Vice President``C-Level``Partner``Founder``Owner``Intern`level is the same set inside has_experience, where it describes one job rather than the person. |
| active_department | `Administrative``C-Suite``Consulting``Customer Service``Design``Education``Engineering and Technical``Finance & Accounting``General Management``Human Resources``Legal``Marketing``Medical``Operations``Other``Product``Project Management``Real Estate``Research``Sales``Trades` |
| industry | `Accommodation Services``Administrative and Support Services``Construction``Consumer Services``Education``Entertainment Providers``Farming, Ranching, Forestry``Financial Services``Government Administration``Holding Companies``Hospitals and Health Care``Manufacturing``Oil, Gas, and Mining``Professional Services``Real Estate and Equipment Rental Services``Retail``Technology, Information and Media``Transportation, Logistics, Supply Chain and Storage``Utilities``Wholesale`This is the twenty-value set used on a person's experience. A company's own industry field is a different, much longer vocabulary. |

> **Not every category field is a fixed set**
>
> role, company_type and the free-text fields are not fixed sets. Ask them with match and expect a long tail.

## 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": {
    "profile_ids": ["kR3nQv8xTm", "9tQmLd2wYb"],
    "total": 418,
    "next": "WzE3MjQwMDAwMDAsImtSM25Rdjh4VG0iXQ"
  }
}
```

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

```json
{
  "code": 200,
  "msg": "ok",
  "data": {
    "total": 2,
    "found": 1,
    "not_found": ["9tQmLd2wYb"],
    "results": [{
      "profile_id": "kR3nQv8xTm",
      "full_name": "Example Profile",
      "active_experience_title": "Staff Machine Learning Engineer",
      "skills": ["Python", "distributed training"]
    }]
  }
}
```

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

## Access surfaces

| Surface | How to use this capability |
| --- | --- |
| REST | POST /v1/people/query; POST /v1/people-search; POST /entity/v1/profiles/detail-by-id |
| Metix AI skill | metix-people-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 people who are currently directors at Google and based in San Francisco, then fetch their full records and summarize their skills. |

Common next step: [search the jobs dataset](https://platform.metix.ai/docs/api/jobs.md).
