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

# API di Ricerca

> Cerca sul web con linguaggio naturale e ottieni link strutturati — l’API di ricerca AI di Olostep.

L'endpoint Olostep `/v1/searches` ti permette di cercare sul web con una query in linguaggio naturale e ottenere una lista deduplicata di link rilevanti con titoli e descrizioni.

* Invia una query in inglese semplice
* Ricevi link strutturati da tutto il web
* Facoltativamente, esegui lo scraping di ogni URL restituito in un unico round-trip e incorpora `markdown_content` / `html_content` direttamente nella risposta
* Filtra per dominio, controlla il numero di risultati e limita il tempo di scraping

Cercando la query semanticamente sul web, restituirà i risultati.

Per i dettagli sull'API, consulta la [Riferimento API dell'Endpoint di Ricerca](/api-reference/searches/create).

## Installazione

<CodeGroup>
  ```python Python theme={null}
  pip install olostep
  ```

  ```javascript Node theme={null}
  npm install olostep
  ```

  ```bash cURL theme={null}
  # curl è disponibile di default su macOS, Linux e Windows
  ```

  ```javascript Node (API) theme={null}
  npm install node-fetch
  ```

  ```bash Python (API) theme={null}
  pip install requests
  ```
</CodeGroup>

## Uso di base

Invia una query in linguaggio naturale e ricevi una lista di link rilevanti.

<CodeGroup>
  ```python Python theme={null}
  from olostep import Olostep

  client = Olostep(api_key="YOUR_REAL_KEY")

  search = client.searches.create("Best Answer Engine Optimization startups")

  print(search.id, len(search.links))
  ```

  ```js Node theme={null}
  import Olostep from 'olostep'

  const client = new Olostep({ apiKey: 'YOUR_REAL_KEY' })

  const search = await client.searches.create('Best Answer Engine Optimization startups')

  console.log(search.id, search.links.length)
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.olostep.com/v1/searches" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "Best Answer Engine Optimization startups"
    }'
  ```

  ```js Node (API) theme={null}
  const res = await fetch('https://api.olostep.com/v1/searches', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      query: 'Best Answer Engine Optimization startups'
    })
  })
  console.log(await res.json())
  ```

  ```python Python (API) theme={null}
  import requests, json

  endpoint = "https://api.olostep.com/v1/searches"
  payload = {
    "query": "Best Answer Engine Optimization startups"
  }
  headers = {"Authorization": "Bearer <YOUR_API_KEY>", "Content-Type": "application/json"}

  response = requests.post(endpoint, json=payload, headers=headers)
  print(json.dumps(response.json(), indent=2))
  ```
</CodeGroup>

## Parametri della richiesta

| Campo             | Tipo      | Richiesto | Default | Descrizione                                                                                                                                                          |
| ----------------- | --------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`           | string    | sì        | —       | La query di ricerca in linguaggio naturale.                                                                                                                          |
| `limit`           | integer   | no        | `12`    | Numero massimo di link da restituire dopo la deduplicazione. Deve essere tra `1` e `25`.                                                                             |
| `include_domains` | string\[] | no        | `[]`    | Restringi i risultati a questi domini. Solo host nudi — `http(s)://` iniziale e slash finali vengono rimossi automaticamente.                                        |
| `exclude_domains` | string\[] | no        | `[]`    | Escludi i risultati da questi domini. Solo host nudi — `http(s)://` iniziale e slash finali vengono rimossi automaticamente.                                         |
| `scrape_options`  | object    | no        | —       | Quando fornito, ogni link restituito viene anche sottoposto a scraping e il suo contenuto incorporato nella risposta. Vedi [scrape\_options](#scrape-options) sotto. |

### Limitare il numero di risultati

```json theme={null}
{
  "query": "What's going on with OpenAI's Sora shutting down?",
  "limit": 5
}
```

### Filtrare per dominio

`include_domains` restringe i risultati a una whitelist; `exclude_domains` filtra le fonti indesiderate. Possono essere combinati.

```json theme={null}
{
  "query": "OpenAI Sora shutdown analysis",
  "include_domains": ["nytimes.com", "wsj.com", "bbc.com"],
  "exclude_domains": ["pinterest.com"]
}
```

## scrape\_options

Passa `scrape_options` per eseguire lo scraping di ogni URL restituito in parallelo e incorpora il contenuto reso direttamente su ciascun link. Questo salva un round-trip per risultato rispetto a chiamare `/v1/searches` e `/v1/scrapes` separatamente.

```json theme={null}
{
  "query": "What's going on with OpenAI's Sora shutting down?",
  "limit": 10,
  "scrape_options": {
    "formats": ["markdown"],
    "remove_css_selectors": "default",
    "timeout": 25
  }
}
```

| Campo                  | Tipo      | Default        | Descrizione                                                                                                                                                                                                                            |
| ---------------------- | --------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `formats`              | string\[] | `["markdown"]` | Formati di output da allegare a ciascun link. Per `/v1/searches`, sono supportati solo `"html"` e `"markdown"`. Passa `["html", "markdown"]` per ricevere entrambi.                                                                    |
| `remove_css_selectors` | string    | `"default"`    | Inoltrato a `/v1/scrapes`. `"default"` rimuove rumore di nav/footer/script/style/svg/dialog. Usa `"none"` per disabilitare, o passa un array di selettori JSON-stringificato da rimuovere.                                             |
| `timeout`              | integer   | `25`           | Budget di wallclock in **secondi** per l'intera fase di scraping. Deve essere tra `1` e `60`. Dopo questo tempo, la ricerca restituisce immediatamente — i campi di contenuto saranno `null` per i link che non sono stati completati. |

### Comportamento

* Tutti i link vengono sottoposti a scraping **in parallelo**. Il `timeout` limita l'intero batch, non ogni singolo link.
* I fallimenti di scraping per link (errori di rete, timeout della pagina individuale) lasciano il `markdown_content` / `html_content` di quel link come `null` mentre gli altri link vengono restituiti normalmente.
* Se il `timeout` globale scade prima che tutti gli scraping siano completati, la ricerca risponde immediatamente con i link che ha — gli scraping già completati mantengono il loro contenuto; quelli in corso tornano con contenuto `null`.
* Per gli URL `reddit.com/.../comments/...`, la richiesta viene automaticamente instradata attraverso il parser `@olostep/reddit-post` e il JSON strutturato viene reso in markdown pulito + HTML di base
* Se il contenuto combinato in linea supera i 9MB, i campi di contenuto vengono annullati, `result.size_exceeded` è impostato su `true`, e puoi recuperare il payload completo da `result.json_hosted_url`.

### Esempio con scraping

<CodeGroup>
  ```python Python theme={null}
  from olostep import Olostep

  client = Olostep(api_key="YOUR_REAL_KEY")

  search = client.searches.create(
      query="What's going on with OpenAI's Sora shutting down?",
      limit=5,
      scrape_options={"formats": ["markdown"], "timeout": 25},
  )

  for link in search.links:
      print(link["url"], "—", len(link.get("markdown_content") or ""), "chars")
  ```

  ```js Node theme={null}
  import Olostep, { Format } from 'olostep'

  const client = new Olostep({ apiKey: 'YOUR_REAL_KEY' })

  const search = await client.searches.create({
    query: "What's going on with OpenAI's Sora shutting down?",
    limit: 5,
    scrapeOptions: {
      formats: [Format.MARKDOWN],
      timeout: 25
    }
  })

  for (const link of search.links) {
    console.log(link.url, '—', (link.markdown_content || '').length, 'chars')
  }
  ```

  ```bash cURL theme={null}
  curl -s -X POST "https://api.olostep.com/v1/searches" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "What'"'"'s going on with OpenAI'"'"'s Sora shutting down?",
      "limit": 5,
      "scrape_options": {
        "formats": ["markdown"],
        "timeout": 25
      }
    }'
  ```

  ```js Node (API) theme={null}
  const res = await fetch('https://api.olostep.com/v1/searches', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' },
    body: JSON.stringify({
      query: "What's going on with OpenAI's Sora shutting down?",
      limit: 5,
      scrape_options: {
        formats: ['markdown'],
        timeout: 25
      }
    })
  })
  const data = await res.json()
  for (const link of data.result.links) {
    console.log(link.url, '—', (link.markdown_content || '').length, 'chars')
  }
  ```

  ```python Python (API) theme={null}
  import requests, json

  endpoint = "https://api.olostep.com/v1/searches"
  payload = {
    "query": "What's going on with OpenAI's Sora shutting down?",
    "limit": 5,
    "scrape_options": {
      "formats": ["markdown"],
      "timeout": 25
    }
  }
  headers = {"Authorization": "Bearer <YOUR_API_KEY>", "Content-Type": "application/json"}

  response = requests.post(endpoint, json=payload, headers=headers)
  data = response.json()
  for link in data["result"]["links"]:
    print(link["url"], "—", len(link.get("markdown_content") or ""), "chars")
  ```
</CodeGroup>

## Risposta

Riceverai un oggetto `search` in risposta. L'oggetto `search` contiene un `id`, la tua `query` originale, `credits_consumed`, e un `result` con una lista di `links`.

```json theme={null}
{
  "id": "search_9bi0sbj9xa",
  "object": "search",
  "created": 1760327323,
  "metadata": {},
  "query": "What's going on with OpenAI's Sora shutting down?",
  "credits_consumed": 10,
  "result": {
    "json_content": "...",
    "json_hosted_url": "https://olostep-storage.s3.us-east-1.amazonaws.com/search_9bi0sbj9xa.json",
    "size_exceeded": false,
    "credits_consumed": 10,
    "links": [
      {
        "url": "https://www.bbc.com/news/articles/c3w3e467ewqo",
        "title": "OpenAI to shut down Sora video platform",
        "description": "OpenAI says it will discontinue its Sora app...",
        "markdown_content": "# OpenAI to shut down Sora video platform\n\nOpenAI says it will discontinue..."
      },
      {
        "url": "https://www.reddit.com/r/OutOfTheLoop/comments/1s2u847/whats_going_on_with_openais_sora_shutting_down/",
        "title": "What's going on with OpenAI's Sora shutting down?",
        "description": "Reddit thread discussing the shutdown.",
        "markdown_content": "# What's going on with OpenAI's Sora shutting down?\n\n*r/OutOfTheLoop · u/rm-minus-r · 1mo ago*\n\n..."
      }
    ]
  }
}
```

Ogni link in `result.links` contiene:

| Campo              | Tipo   | Descrizione                                                                                                                                                                         |
| ------------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `url`              | string | L'URL del risultato di ricerca.                                                                                                                                                     |
| `title`            | string | Il titolo della pagina del risultato.                                                                                                                                               |
| `description`      | string | Un breve snippet che descrive il risultato.                                                                                                                                         |
| `markdown_content` | string | Contenuto markdown della pagina. Presente solo quando `scrape_options.formats` include `"markdown"`. `null` se lo scraping è fallito, era vuoto, o ha raggiunto il timeout globale. |
| `html_content`     | string | Contenuto HTML della pagina. Presente solo quando `scrape_options.formats` include `"html"`. `null` in caso di fallimento/timeout.                                                  |

Il risultato completo è anche disponibile come file JSON ospitato su `result.json_hosted_url` — utile quando `result.size_exceeded` è `true`.

## Recuperare una ricerca passata

`GET /v1/searches/{search_id}` restituisce ciò che è stato memorizzato al momento della ricerca, incluso qualsiasi contenuto sottoposto a scraping. È una lettura idempotente pura — nessun nuovo scraping, nessuna nuova fatturazione. Le ricerche più vecchie senza `scrape_options` semplicemente non hanno campi di contenuto per link.

<CodeGroup>
  ```python Python theme={null}
  from olostep import Olostep

  client = Olostep(api_key="YOUR_REAL_KEY")

  search = client.searches.get(search_id="search_9bi0sbj9xa")
  print(search.id, len(search.links))
  ```

  ```js Node theme={null}
  import Olostep from 'olostep'

  const client = new Olostep({ apiKey: 'YOUR_REAL_KEY' })

  const search = await client.searches.get('search_9bi0sbj9xa')
  console.log(search.id, search.links.length)
  ```

  ```bash cURL theme={null}
  curl -s "https://api.olostep.com/v1/searches/search_9bi0sbj9xa" \
    -H "Authorization: Bearer $OLOSTEP_API_KEY"
  ```
</CodeGroup>

Consulta [Get Search](/api-reference/searches/get) per i dettagli completi.

## Prezzi

Ogni ricerca costa **5 crediti** per la ricerca stessa.

Quando `scrape_options` è fornito, ogni pagina sottoposta a scraping viene addebitata al tasso standard `/v1/scrapes` (tipicamente 1 credito per pagina; alcuni parser costano di più). Il totale viene restituito in `credits_consumed`.

Esempi:

| Richiesta                                                     | `credits_consumed` |
| ------------------------------------------------------------- | ------------------ |
| Solo ricerca                                                  | `5`                |
| Ricerca + 5 pagine sottoposte a scraping (1 credito ciascuna) | `10`               |
