# Search wide, then read narrow.

Section: Get started
Source: https://platform.metix.ai/docs/quickstart
Every page in one file: https://platform.metix.ai/llms-full.txt

Every search answers with encrypted ids, and a second call turns the ids you keep into records. Searching is the cheap half, so filter as hard as you like before you read. All three datasets work exactly this way.

## Four ways to ask

Same request, four interfaces. The top two are sentences you type at an agent; the bottom two are calls you build. Switch between them and the bottom half stays the same, because it is the same two endpoints underneath.

No key yet? [Create one in the dashboard](https://platform.metix.ai/api-keys). The free plan starts with 100 Credits and needs no card.

## The shape of every request

Every search route answers with encrypted string ids and no record data at all. To read the records you send up to 100 of those ids to the detail route for the same dataset. There is no single call that does both, and no phrasing of a search that makes records come back early.

The practical consequence is worth stating on its own: **a response full of ids means the search worked**. Code that reads a search response looking for names finds nothing and concludes the dataset is empty. It is not. The names are one call away.

| Dataset | Search with | Then read with | Ids are called |
| --- | --- | --- | --- |
| People | POST /v1/people-search or /v1/people/query | POST /entity/v1/profiles/detail-by-id | profile_ids |
| Jobs | POST /v1/jobs/query | POST /entity/v1/jobs/detail-by-id | job_ids |
| Companies | POST /v1/companies/query | POST /entity/v1/companies/detail-by-id | company_ids |

Ids are permanently stable. Store one today and the same detail call resolves it months from now, so a pipeline can keep ids and re-read records on its own schedule rather than re-running the search.

## Wire it into an agent

We run an MCP server at `https://mira-api.metix.ai/mcp` over streamable HTTP, with legacy SSE on `/sse` for older clients. Both authenticate with the same Bearer key as the REST API and settle against the same Credit balance. One line registers it. Keep `--scope user`: without it the server is registered against the directory you happened to run the command in, and it will be missing from the next project you open.

```shell
claude mcp add --scope user --transport http metix \
  https://mira-api.metix.ai/mcp \
  --header "Authorization: Bearer $METIX_KEY"
```

Codex takes the key from your environment instead of writing it into the config file:

```shell
codex mcp add metix \
  --url https://mira-api.metix.ai/mcp \
  --bearer-token-env-var METIX_KEY
```

Any other MCP client needs the same three facts: the URL above, the transport, and an `Authorization: Bearer` header carrying your key.

Agents that do not speak MCP can install the skills instead, which are plain instructions describing these endpoints, the field vocabulary, and the two-step shape. They read the same `METIX_KEY` as everything else on this page, and they install for Codex as well as for Claude Code:

```shell
npx skills add MetixAI-Official/metix-skills
export METIX_KEY="metix_xxxxxxxxxxxx"
```

If the agent still has the retired OpenJobs skills installed, remove them first, or it will sometimes follow those instead. The [skills page](https://platform.metix.ai/docs/skills#moving) has the commands and a prompt you can hand the agent.

> **Reading this page as an agent**
>
> [/llms.txt](https://platform.metix.ai/llms.txt) carries the same surface in one plain-text file: every route, what it returns, and the field vocabulary, without the HTML around it. Fetch that instead of scraping these pages.

## Run it yourself

Create a key under API Keys and export it once. Keys begin with `metix_`; one issued before that rename begins with `mira_` and keeps working, so there is nothing to rotate. Keep the value out of source control and out of anything the browser can read.

```bash
export METIX_KEY="metix_xxxxxxxxxxxx"

# Free, and worth doing first: scopes, rate limit, remaining quota.
curl -s "https://mira-api.metix.ai/auth/key/status" \
  -H "Authorization: Bearer $METIX_KEY"
```

A 401 means the key is wrong or missing, a 403 means it is disabled or out of scope, and a 402 on a later call means the balance is exhausted.

[Create an account](https://platform.metix.ai/signup) [API Keys](https://platform.metix.ai/api-keys)

Now the first call. Natural-language people search is the shortest route into the data: describe who you want and it returns ids.

`POST /v1/people-search`

Request:

```bash
curl -s -X POST "https://mira-api.metix.ai/v1/people-search" \
  -H "Authorization: Bearer $METIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "machine learning engineers in San Francisco", "size": 25}'
```

Response:

```json
{
  "code": 200,
  "msg": "ok",
  "data": {
    "profile_ids": [
      "UHyKQXeFCLaGeBwgjwisBg",
      "YhlkBSsJWv7zeGUJMaymMw",
      "E-i6XGwZbYe-8QkHWd5Tbw"
    ]
  }
}
```

Ids, exactly as promised, and nothing else. Hand them to the profile detail route, up to 100 per request, and choose the fields you want back with `_source`. Omit `_source` and you get the default set.

`POST /entity/v1/profiles/detail-by-id`

Request:

```bash
curl -s -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": ["UHyKQXeFCLaGeBwgjwisBg"],
    "_source": ["profile_id", "full_name", "active_experience_title", "skills"]
  }'
```

Response:

```json
{
  "code": 200,
  "msg": "ok",
  "data": {
    "total": 1,
    "found": 1,
    "not_found": [],
    "results": [
      {
        "profile_id": "UHyKQXeFCLaGeBwgjwisBg",
        "full_name": "Jordan Reyes",
        "active_experience_title": "Machine Learning Engineer",
        "skills": ["machine learning", "model deployment", "pytorch"]
      }
    ]
  }
}
```

Detail answers with `found` and `not_found` alongside the records, so a partial resolve is visible rather than silent. Ids that resolve to nothing are not charged.

## Exact conditions, and the other two datasets

Natural language is for a brief. When the conditions are exact, a named employer, a country, a numeric range, use the Query Spec routes. All three datasets take the same tree, so the jobs and companies examples below are the people example with different field names.

A tree is composed with `all`, `any` and `not`, and each leaf carries exactly one of `eq`, `in`, `match`, `gte`, `lte` or `exists`.

```bash
# People: currently working machine learning engineers in San Francisco
curl -s -X POST "https://mira-api.metix.ai/v1/people/query" \
  -H "Authorization: Bearer $METIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "where": {"all": [
      {"field": "active_title", "match": "machine learning engineer"},
      {"field": "city", "eq": "San Francisco"},
      {"field": "is_working", "eq": true}
    ]},
    "size": 25
  }'

# Jobs: US data engineering roles posted in the last 30 days
curl -s -X POST "https://mira-api.metix.ai/v1/jobs/query" \
  -H "Authorization: Bearer $METIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "where": {"all": [
      {"field": "title", "match": "data engineer"},
      {"field": "country_iso_2", "eq": "US"},
      {"field": "posted", "gte": "now-30d"}
    ]},
    "size": 25
  }'

# Companies: US biotechnology companies with 50 to 500 employees
curl -s -X POST "https://mira-api.metix.ai/v1/companies/query" \
  -H "Authorization: Bearer $METIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "where": {"all": [
      {"field": "industry", "match": "biotechnology"},
      {"field": "hq_country", "match": "United States"},
      {"field": "employees_count", "gte": 50},
      {"field": "employees_count", "lte": 500}
    ]},
    "size": 25
  }'
```

Each of those answers with the id list for its dataset, a `total`, and a `next` cursor while pages remain. Feed the ids to that dataset's detail route exactly as the people example does.

> **Two leaves, not two operators**
>
> The company example bounds headcount with two separate leaves. A leaf carries exactly one operator, so `{"field": "employees_count", "gte": 50, "lte": 500}` is refused rather than half-applied.

> **People carry same-record scopes**
>
> A profile holds many jobs and many degrees, so `has_experience`, `has_education` and `has_language` exist to say "one job that is both at Google and at director level" rather than "some job at Google, and separately some job at director level". Everything inside one scope must match the same record. See the [Query Spec grammar](https://platform.metix.ai/docs/api/query-spec.md).

## More than one page

A Query Spec response carries a `next` value while more results remain. Send it back as `after` to get the following page, and keep the rest of the request identical. When `next` is absent you have reached the last page.

```bash
# Page one answered with:
#   "next": "WzE3MjQwMDAwMDAsImtSM25Rdjh4VG0iXQ"

curl -s -X POST "https://mira-api.metix.ai/v1/jobs/query" \
  -H "Authorization: Bearer $METIX_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "where": {"all": [
      {"field": "title", "match": "data engineer"},
      {"field": "country_iso_2", "eq": "US"},
      {"field": "posted", "gte": "now-30d"}
    ]},
    "size": 25,
    "after": "WzE3MjQwMDAwMDAsImtSM25Rdjh4VG0iXQ"
  }'
```

> **Pages are not a snapshot**
>
> The index keeps moving while you page through it. Two pages of one walk are not guaranteed to be consistent with each other, so a record can appear twice or not at all across a long pagination. Deduplicate on the id if that matters to you, and do not treat a full walk as a point-in-time export.

## Where to go next

[Query Spec grammar](https://platform.metix.ai/docs/api/query-spec.md) [People fields](https://platform.metix.ai/docs/api/people.md) [Job fields](https://platform.metix.ai/docs/api/jobs.md) [Company fields](https://platform.metix.ai/docs/api/companies.md) [MCP setup](https://platform.metix.ai/docs/mcp.md) [Agent skills](https://platform.metix.ai/docs/skills.md)

> **Credit settlement**
>
> A Query Spec search costs one Credit per 25 ids returned and nothing when it returns nothing. Natural-language people search adds a base of 5 Credits, which is charged even on an empty result. Detail costs one Credit per five records found, so five ids in one request cost 1 while five single-id requests cost 5. Read the [Credits page](https://platform.metix.ai/docs/credits.md) before sizing a batch job.
