> ## Documentation Index
> Fetch the complete documentation index at: https://docs.messora.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Search

> Busca premium multi-fonte com análise LLM — resultados relevantes já ranqueados.

# Search

O endpoint `POST /search` inicia uma busca premium assíncrona. Ele consulta
múltiplas fontes web e aplica julgamento LLM para selecionar e sumarizar os
resultados mais relevantes.

## Endpoint

```
POST /search
```

## Autenticação

Header `X-API-Key` obrigatório. Veja [Autenticação](/pt-BR/authentication).

## Parâmetros

<ParamField body="query" type="string" required>
  Texto da busca. Deve conter ao menos 1 caractere.
</ParamField>

<ParamField body="num_results" type="integer" default="10">
  Quantidade de resultados finais desejados (10–100).
</ParamField>

<ParamField body="country" type="string">
  Código ISO 3166-1 alpha-2 para restringir resultados por região (ex.: `BR`, `US`, `GB`).
</ParamField>

<ParamField body="include_domains" type="string[]">
  Restringe resultados a estes domínios (até 20). Hostname exato ou subdomínio.
</ParamField>

<ParamField body="exclude_domains" type="string[]">
  Omite resultados destes domínios (até 20). Não pode ter sobreposição com `include_domains`.
</ParamField>

<ParamField body="freshness" type="string">
  Janela temporal dos resultados: `day`, `week`, `month`, `year`. Omita para sem filtro.
</ParamField>

<ParamField body="timeout_seconds" type="integer">
  Limite de duração da busca em segundos (15–120). Omita para usar o timeout padrão do worker.
</ParamField>

<ParamField body="tags" type="string[]">
  Tags de atribuição para o registro de uso (até 10 tags).
</ParamField>

## Custo

**1 crédito por resultado retornado** (cobrado por resultados efetivos, não solicitados).

O pré-check exige saldo ≥ `num_results` solicitado (pior caso). Se o saldo for
insuficiente, a API retorna `402`.

## Fluxo assíncrono

1. Envie `POST /search` → receba `202` com `job_id`
2. Poll via `GET /jobs/{job_id}` a cada 2s
3. Quando `status: "SUCCESS"`, os resultados estão no campo `results`

<Note>
  O campo `stopped_reason` pode indicar `token_cap` se o limite de tokens LLM foi atingido antes de processar todas as fontes.
</Note>

## Exemplo

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.messora.dev/search \
    -H "Content-Type: application/json" \
    -H "X-API-Key: YOUR_API_KEY" \
    -d '{
      "query": "melhores frameworks Python 2025",
      "num_results": 10,
      "country": "BR",
      "freshness": "year"
    }'
  ```

  ```python Python theme={null}
  import requests
  import time

  # 1. Inicia a busca
  response = requests.post(
      "https://api.messora.dev/search",
      headers={
          "Content-Type": "application/json",
          "X-API-Key": "YOUR_API_KEY",
      },
      json={
          "query": "melhores frameworks Python 2025",
          "num_results": 10,
          "country": "BR",
          "freshness": "year",
      },
  )

  job_id = response.json()["job_id"]
  print(f"Job criado: {job_id}")

  # 2. Poll até conclusão
  while True:
      status = requests.get(
          f"https://api.messora.dev/jobs/{job_id}",
          headers={"X-API-Key": "YOUR_API_KEY"},
      ).json()

      if status["status"] in ("SUCCESS", "FAILURE"):
          break
      time.sleep(2)

  # 3. Resultados
  for result in status.get("results", []):
      print(result)
  ```

  ```javascript JavaScript theme={null}
  // 1. Inicia a busca
  const res = await fetch("https://api.messora.dev/search", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-Key": "YOUR_API_KEY",
    },
    body: JSON.stringify({
      query: "melhores frameworks Python 2025",
      num_results: 10,
      country: "BR",
      freshness: "year",
    }),
  });

  const { job_id } = await res.json();
  console.log(`Job criado: ${job_id}`);

  // 2. Poll até conclusão
  let status;
  do {
    await new Promise((r) => setTimeout(r, 2000));
    const poll = await fetch(
      `https://api.messora.dev/jobs/${job_id}`,
      { headers: { "X-API-Key": "YOUR_API_KEY" } }
    );
    status = await poll.json();
  } while (!["SUCCESS", "FAILURE"].includes(status.status));

  // 3. Resultados
  console.log(status.results);
  ```
</CodeGroup>

## Resposta de sucesso (via polling)

```json theme={null}
{
  "status": "SUCCESS",
  "job_id": "550e8400-e29b-41d4-a716-446655440001",
  "results": [
    {
      "title": "Top Python Frameworks",
      "url": "https://example.com/frameworks",
      "snippet": "Uma análise dos frameworks mais usados..."
    }
  ],
  "credits_used": 10,
  "stopped_reason": null
}
```

## Erros

| HTTP Status | Descrição                                       |
| ----------- | ----------------------------------------------- |
| `401`       | `X-API-Key` ausente                             |
| `402`       | Créditos insuficientes (saldo \< `num_results`) |
| `403`       | API key inválida ou revogada                    |
| `422`       | Query vazia ou parâmetros inválidos             |
| `429`       | Rate limit excedido (2 req/min)                 |
