> ## 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 de recherche

> Recherchez sur le web en langage naturel et obtenez des liens structurés — l’API de recherche IA d’Olostep.

Le point de terminaison Olostep `/v1/searches` vous permet de rechercher sur le web avec une requête en langage naturel et de recevoir une liste dédupliquée de liens pertinents avec des titres et des descriptions.

* Envoyez une requête en anglais courant
* Obtenez des liens structurés de tout le web
* Optionnellement, récupérez chaque URL retournée en un seul aller-retour et intégrez `markdown_content` / `html_content` directement dans la réponse
* Filtrez par domaine, contrôlez le nombre de résultats et limitez le temps d'exécution du scraping

Il recherchera la requête de manière sémantique sur le web et renverra les résultats.

Pour les détails de l'API, consultez la [Référence de l'API du point de terminaison de recherche](/api-reference/searches/create).

## Installation

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

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

  ```bash cURL theme={null}
  # curl est disponible par défaut sur macOS, Linux et Windows
  ```

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

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

## Utilisation de base

Envoyez une requête en langage naturel et recevez une liste de liens pertinents.

<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>

## Paramètres de la requête

| Champ             | Type      | Requis | Par défaut | Description                                                                                                                                                   |
| ----------------- | --------- | ------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`           | string    | oui    | —          | La requête de recherche en langage naturel.                                                                                                                   |
| `limit`           | integer   | non    | `12`       | Nombre maximum de liens à retourner après déduplication. Doit être compris entre `1` et `25`.                                                                 |
| `include_domains` | string\[] | non    | `[]`       | Restreindre les résultats à ces domaines. Hôtes nus uniquement — les préfixes `http(s)://` et les barres obliques finales sont automatiquement supprimés.     |
| `exclude_domains` | string\[] | non    | `[]`       | Exclure les résultats de ces domaines. Hôtes nus uniquement — les préfixes `http(s)://` et les barres obliques finales sont automatiquement supprimés.        |
| `scrape_options`  | object    | non    | —          | Lorsqu'il est fourni, chaque lien retourné est également récupéré et son contenu intégré dans la réponse. Voir [scrape\_options](#scrape-options) ci-dessous. |

### Limiter le nombre de résultats

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

### Filtrer par domaine

`include_domains` limite les résultats à une liste blanche ; `exclude_domains` filtre les sources indésirables. Ils peuvent être combinés.

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

## scrape\_options

Passez `scrape_options` pour récupérer chaque URL retournée en parallèle et intégrer le contenu rendu directement sur chaque lien. Cela économise un aller-retour par résultat par rapport à l'appel de `/v1/searches` et `/v1/scrapes` séparément.

```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
  }
}
```

| Champ                  | Type      | Par défaut     | Description                                                                                                                                                                                                                                           |
| ---------------------- | --------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `formats`              | string\[] | `["markdown"]` | Formats de sortie à attacher à chaque lien. Pour `/v1/searches`, seuls `"html"` et `"markdown"` sont pris en charge. Passez `["html", "markdown"]` pour recevoir les deux.                                                                            |
| `remove_css_selectors` | string    | `"default"`    | Transmis à `/v1/scrapes`. `"default"` supprime le bruit nav/footer/script/style/svg/dialog. Utilisez `"none"` pour désactiver, ou passez un tableau de sélecteurs JSON pour supprimer.                                                                |
| `timeout`              | integer   | `25`           | Budget d'exécution en **secondes** pour toute la phase de récupération. Doit être compris entre `1` et `60`. Après ce délai, la recherche revient immédiatement — les champs de contenu seront `null` pour tous les liens qui n'ont pas été terminés. |

### Comportement

* Tous les liens sont récupérés **en parallèle**. Le `timeout` limite l'ensemble du lot, pas chaque lien individuel.
* Les échecs de récupération par lien (erreurs réseau, délais d'attente individuels) laissent le `markdown_content` / `html_content` de ce lien à `null` tandis que les autres liens retournent normalement.
* Si le `timeout` global expire avant que toutes les récupérations soient terminées, la recherche répond immédiatement avec les liens qu'elle a — les récupérations déjà terminées conservent leur contenu ; celles en cours reviennent avec un contenu `null`.
* Pour les URLs `reddit.com/.../comments/...`, la requête est automatiquement acheminée via le parseur `@olostep/reddit-post` et le JSON structuré est rendu en markdown propre + HTML basique.
* Si le contenu intégré combiné dépasse 9 Mo, les champs de contenu sont annulés, `result.size_exceeded` est défini à `true`, et vous pouvez récupérer la charge utile complète depuis `result.json_hosted_url`.

### Exemple avec récupération

<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>

## Réponse

Vous recevrez un objet `search` en réponse. L'objet `search` contient un `id`, votre `query` originale, `credits_consumed`, et un `result` avec une liste de `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..."
      }
    ]
  }
}
```

Chaque lien dans `result.links` contient :

| Champ              | Type   | Description                                                                                                                                                                                      |
| ------------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `url`              | string | L'URL du résultat de la recherche.                                                                                                                                                               |
| `title`            | string | Le titre de la page de résultat.                                                                                                                                                                 |
| `description`      | string | Un court extrait décrivant le résultat.                                                                                                                                                          |
| `markdown_content` | string | Contenu en markdown de la page. Présent uniquement lorsque `scrape_options.formats` inclut `"markdown"`. `null` si la récupération a échoué, était vide, ou a atteint le délai d'attente global. |
| `html_content`     | string | Contenu HTML de la page. Présent uniquement lorsque `scrape_options.formats` inclut `"html"`. `null` en cas d'échec/délai d'attente.                                                             |

Le résultat complet est également disponible sous forme de fichier JSON hébergé à `result.json_hosted_url` — utile lorsque `result.size_exceeded` est `true`.

## Récupérer une recherche passée

`GET /v1/searches/{search_id}` retourne ce qui a été enregistré au moment de la recherche, y compris tout contenu récupéré. C'est une lecture idempotente pure — pas de nouvelle récupération, pas de nouvelle facturation. Les recherches plus anciennes sans `scrape_options` n'ont simplement pas de champs de contenu par lien.

<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>

Voir [Get Search](/api-reference/searches/get) pour plus de détails.

## Tarification

Chaque recherche coûte **5 crédits** pour la recherche elle-même.

Lorsque `scrape_options` est fourni, chaque page récupérée est facturée au tarif standard `/v1/scrapes` (généralement 1 crédit par page ; certains parseurs coûtent plus cher). Le total est retourné dans `credits_consumed`.

Exemples :

| Requête                                           | `credits_consumed` |
| ------------------------------------------------- | ------------------ |
| Recherche uniquement                              | `5`                |
| Recherche + 5 pages récupérées (1 crédit chacune) | `10`               |
