API de recherche web pour agents LLM#

Bêta privée. Lookup est appelable dès aujourd'hui avec votre clé d'API habituelle, sur tous les forfaits y compris Founding, et décompte votre quota mensuel d'ops comme n'importe quel autre appel. Ce n'est ni annoncé ni disponible de façon générale : les formes de requête et de réponse peuvent changer sans préavis, et il n'y a aucun engagement de stabilité ni de support, donc ne construisez rien de critique dessus pour l'instant. La feuille de route est sur Bientôt disponible, et chaque publication est annoncée dans le changelog.

POST /v2/lookup est une API de recherche web conçue pour les agents LLM : elle exécute une recherche dans l'une des six catégories et renvoie une liste de résultats plate, neutre vis-à-vis du fournisseur. Définissez perceive_top et elle effectue en plus le rendu des N premières URL de résultat dans un vrai navigateur, de sorte qu'un agent obtient la page de résultats du moteur de recherche (SERP) et le contenu de la page derrière chaque résultat en un seul aller-retour. En tant qu'alternative à une API SERP, elle condense la pile habituelle (interroger une API de recherche, analyser ses résultats, puis déployer un scraper en éventail) en un seul appel. Ce sera la réponse d'EnConvert à /search de Firecrawl.

Serper est le fournisseur de recherche qui l'alimente. La requête et la réponse parlent un vocabulaire de recherche neutre (category, country, locale, time_filter), de sorte qu'un futur changement de fournisseur ne modifie pas le contrat sur lequel vous codez.

Voici le plus petit appel utile. Envoyez une requête, récupérez les meilleurs résultats web :

curl -X POST https://api.enconvert.com/v2/lookup \
  -H "X-API-Key: sk_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "headless chrome pdf rendering"
  }'

La réponse est une liste de résultats plate plus la provenance pour la corrélation côté support :

{
    "lookup_id": 81423,
    "query": "headless chrome pdf rendering",
    "category": "web",
    "total": 10,
    "results": [
        {
            "title": "Generate PDFs with headless Chrome",
            "url": "https://example.com/guide/chrome-pdf",
            "snippet": "Render a page and print it to PDF...",
            "position": 1
        },
        {
            "title": "Print to PDF with the Chrome DevTools Protocol",
            "url": "https://example.dev/cdp/print-to-pdf",
            "snippet": "Page.printToPDF returns base64 PDF data...",
            "position": 2
        }
    ],
    "perceive_top": 0,
    "perceive_operation_ids": [],
    "credits": 1,
    "cost_cents": 0.06,
    "warnings": []
}

Points de terminaison#

Méthode Chemin Objectif
POST /v2/lookup Exécuter une recherche et, en option, auto-percevoir les N premières URL de résultat.

/v2/lookup est un point de terminaison à appel unique, sans chemin distinct de statut ou de récupération. Lorsque vous auto-percevez, chaque page rendue devient une opération perceive de premier ordre dotée de son propre operation_id, que vous pouvez récupérer ultérieurement via GET /v2/perceive/{operation_id}.

Content-Type : application/json.


Authentification#

Authentifiez-vous avec une clé privée dans l'en-tête X-API-Key pour les appels serveur à serveur. C'est la voie qu'utilisent les exemples ci-dessous.

X-API-Key: sk_your_private_key

Les clés publiques avec un jeton bearer JWT fonctionnent aussi, selon le même flux que tout autre point de terminaison : générez un jeton avec votre clé pk_, puis envoyez-le sous la forme Authorization: Bearer <token>. Le flux complet, y compris le verrouillage de domaine et le rafraîchissement du jeton, figure dans le guide d'authentification.

Chaque clé API porte une liste blanche de points de terminaison autorisés. Si /v2/lookup n'est pas sur la liste de la clé, la requête est rejetée avec 403.


Comment fonctionne lookup#

Une requête exécute une recherche fournisseur puis, seulement si vous le demandez, effectue le rendu des meilleurs résultats.

  1. Contrôle de quota. Avant toute facturation, le gestionnaire vérifie le quota mensuel unifié d'ops de votre plan. Un plan désactivé ou un quota épuisé est rejeté avec 402, de sorte que rien n'est facturé en cas de rejet.
  2. Recherche. La requête part vers le fournisseur de recherche (Serper) sur le point de terminaison correspondant à votre category. Récence, pays, locale, localisation, taille de page et autocorrection sont mappés sur les paramètres du fournisseur.
  3. Normalisation. Chaque résultat du fournisseur est aplati en un LookupResult neutre qui porte title, url, snippet et position. Les extras propres à la catégorie atterrissent dans extra, de sorte que le contrat n'ajoute jamais une colonne par particularité de fournisseur.
  4. Facturation et audit. La recherche a réussi, donc une op est facturée et une ligne d'audit ch_lookup_queries est écrite. L'identifiant de la ligne revient sous lookup_id pour la corrélation côté support.
  5. Auto-perception (optionnelle). Si perceive_top > 0, les N premières URL de résultat sont rendues une par une via le singleton headless Chrome partagé, le même pipeline que le point de terminaison perceive. Chaque rendu est une opération /v2/perceive complète : sa propre op facturée sur le quota partagé, sa propre ligne d'opération, son propre operation_id. Par défaut, l'auto-perception ne demande que du Markdown, sans capture d'écran, PDF ni extraction LLM ; envoyez un objet enrich pour élargir les sorties, les exécuter en parallèle, ou ajouter une extraction par schéma et une réponse synthétisée.

L'auto-perception est au mieux. Une URL isolée qui échoue, ou le quota d'ops qui s'épuise en cours de route, se dégrade en avertissement et renvoie tout de même les résultats de recherche. La SERP est ici le produit principal, donc un problème de perception ne fait jamais couler l'appel entier.


Paramètres de requête#

Requête et catégorie#

Paramètre Type Valeur par défaut Description
query string aucune La requête de recherche. 1–512 caractères, dépouillée des espaces de début et de fin. Une requête vide après ce nettoyage est rejetée avec 422. Obligatoire.
category string "web" L'une de web, news, images, scholar, patents, maps.

Ciblage et récence#

Paramètre Type Valeur par défaut Description
country string null Code pays Google gl, par ex. us, in. 8 caractères maximum.
locale string null Langue d'interface Google hl, par ex. en. 16 caractères maximum.
time_filter string null Restreindre aux résultats de la période passée : hour, day, week, month, ou year.
location string null Chaîne de localisation en texte libre, par ex. "Austin, Texas". 128 caractères maximum.
autocorrect boolean true Indique si le fournisseur peut autocorriger l'orthographe de la requête.

Pagination#

Paramètre Type Valeur par défaut Description
num_results integer 10 Résultats par page. 1–100.
page integer 1 Numéro de page. 1–10.

Auto-perception#

Paramètre Type Valeur par défaut Description
perceive_top integer 0 Auto-percevoir les N premières URL de résultat qui ont un lien navigable. 0–10. Chacune est un rendu navigateur complet qui facture une op sur votre quota mensuel, ce qui explique le plafond de 10. Pour des ensembles plus grands, prenez les champs url et appelez le point de terminaison de perception par lot. 0 désactive l'auto-perception.

Enrichissement (enrich)#

Un objet enrich optionnel ajuste la manière dont les N premiers résultats (perceive_top) sont lus, et peut synthétiser une réponse unique et fondée à travers eux. Lorsque enrich est omis, perceive_top conserve son comportement par défaut (Markdown uniquement, un résultat à la fois).

Paramètre Type Valeur par défaut Description
enrich.outputs string[] ["markdown"] Les sorties perceive à produire par résultat enrichi, par exemple markdown, html_cleaned, links, screenshot, structured. Voir les sorties de perceive.
enrich.concurrency integer 3 Combien d'URL de résultat enrichir en parallèle. 1–5. Les rendus Markdown/HTML se parallélisent ; les rendus capture d'écran/PDF se sérialisent sur le navigateur partagé.
enrich.schema object null Exécute une extraction structurée pilotée par schéma sur chaque résultat enrichi. Les données extraites apparaissent sous le perceive.structured de chaque résultat. Objet JSON-Schema ou une correspondance plate {field: description}.
enrich.synthesize_answer boolean false Synthétise une réponse citée et fondée à la requête à travers les résultats enrichis, renvoyée sous answer (avec answer_sources). Utilise le contenu de page perçu lorsqu'il est disponible, sinon les extraits de résultat.
enrich.answer_prompt string null Une question à laquelle répondre au lieu de la requête brute. Utilisée uniquement lorsque synthesize_answer vaut true. 1,000 caractères max.

enrich.schema et enrich.synthesize_answer utilisent le palier d'extraction LLM. Si cette étape d'extraction ne peut pas s'exécuter, ils se dégradent en avertissement et le reste de la réponse n'est pas affecté.

{
  "query": "best open-source vector databases",
  "perceive_top": 3,
  "enrich": {
    "outputs": ["markdown"],
    "concurrency": 3,
    "synthesize_answer": true
  }
}

Catégories#

Chaque catégorie atteint un point de terminaison fournisseur différent et fait apparaître une forme de résultat légèrement différente. Les champs universels (title, url, snippet, position) sont toujours typés ; les champs propres à la catégorie atterrissent dans extra.

category Ce qu'elle recherche Champs notables renseignés
web Résultats web généraux title, url, snippet, date, position
news Articles d'actualité ajoute source, image_url
images Résultats d'images image_url, thumbnail_url, source (souvent pas de snippet)
scholar Résultats académiques même forme que web ; nombre de citations dans extra
patents Résultats de brevets même forme que web ; champs de brevet dans extra
maps Lieux locaux url est le site web du lieu ; snippet porte l'adresse ; note, coordonnées dans extra

À signaler : pour images et maps, url peut être null pour un résultat donné lorsque le fournisseur ne renvoie aucun lien navigable. L'auto-perception ignore tout résultat dont l'url est null, de sorte qu'un perceive_top de 5 sur une SERP comptant deux résultats sans URL perçoit au plus trois pages.


Réponse#

Le point de terminaison omet les champs null, de sorte qu'un résultat web minimal ne porte que les champs réellement renseignés.

Champ Type Description
lookup_id integer L'identifiant de la ligne d'audit ch_lookup_queries. Citez-le au support. null si l'écriture d'audit a échoué, sachant que les résultats restent valides.
query string La requête (nettoyée) que vous avez envoyée.
category string La catégorie recherchée.
country string Écho du country que vous avez envoyé, le cas échéant.
locale string Écho du locale que vous avez envoyé, le cas échéant.
time_filter string Écho du time_filter que vous avez envoyé, le cas échéant.
total integer Nombre de résultats renvoyés.
results LookupResult[] La liste de résultats. Voir ci-dessous.
perceive_top integer Combien de résultats ont réellement été perçus : au plus la valeur que vous avez demandée, et moins si le quota d'ops s'est épuisé ou si des URL ont échoué.
perceive_operation_ids string[] Les identifiants d'opération per_... des résultats perçus, dans l'ordre.
answer_box object La boîte de réponse du fournisseur, lorsqu'elle est présente.
knowledge_graph object Le panneau knowledge graph du fournisseur, lorsqu'il est présent.
answer string La réponse citée synthétisée à travers les résultats enrichis. Présente uniquement lorsque enrich.synthesize_answer vaut true et qu'elle a réussi.
answer_sources string[] Les URL utilisées comme fondement pour answer, dans l'ordre de citation.
credits integer Crédits fournisseur consommés par cette requête.
cost_cents number Coût monétaire de la recherche en cents. Un forfait de 0.06 par requête aujourd'hui.
warnings string[] Notes non fatales : un résultat sans URL ignoré, un échec d'auto-perception, le quota d'ops épuisé en cours de boucle.

LookupResult#

Champ Type Description
title string Titre du résultat.
url string Lien canonique de la page, celui que vous percevriez. null pour les résultats sans URL navigable.
snippet string Extrait du résultat. Pour maps, il porte l'adresse.
position integer La position du résultat sur la SERP.
source string Source/éditeur, pour news et images.
date string Date de publication, lorsque le fournisseur en signale une.
image_url string URL de l'image, pour images et news.
thumbnail_url string URL de la miniature, pour images.
extra object Champs propres à la catégorie absents de l'ensemble neutre : notes, coordonnées, nombre de citations, et ainsi de suite.
perceive PerceiveResponse Le résultat de perception complet en ligne pour cette URL, présent uniquement pour les N premiers lorsque perceive_top > 0 et que le rendu a réussi. Même forme d'objet que le point de terminaison perceive.

Lire les résultats d'auto-perception#

Lorsque vous envoyez perceive_top, parcourez les résultats et vérifiez la présence du champ perceive. Il n'est présent que sur les résultats qui ont été perçus, et seulement lorsque leur rendu a réussi. Le Markdown de chacun se trouve derrière une URL de téléchargement pré-signée (un lien signé à courte durée de vie vers le stockage objet) sous perceive.outputs.markdown.url, comme pour un appel perceive direct.

{
    "lookup_id": 81910,
    "query": "react server components data fetching",
    "category": "web",
    "total": 10,
    "results": [
        {
            "title": "Data fetching with RSC",
            "url": "https://example.com/rsc/data",
            "snippet": "Fetch on the server, stream to the client...",
            "position": 1,
            "perceive": {
                "operation_id": "per_3f9a2c1b8e7d4a6f90b1c2d3e4f5a6b7",
                "status": "completed",
                "url": "https://example.com/rsc/data",
                "outputs": {
                    "markdown": {
                        "url": "https://spaces.example.com/...signed...",
                        "size_bytes": 7421,
                        "content_type": "text/markdown; charset=utf-8",
                        "expires_in": 900
                    }
                },
                "cost_cents": 0.0,
                "duration_ms": 5840
            }
        }
    ],
    "perceive_top": 1,
    "perceive_operation_ids": [
        "per_3f9a2c1b8e7d4a6f90b1c2d3e4f5a6b7"
    ],
    "credits": 1,
    "cost_cents": 0.06,
    "warnings": []
}

Ces URL signées expirent au bout de 15 minutes. Pour télécharger une page perçue plus tard, récupérez à nouveau son opération avec GET /v2/perceive/{operation_id} en utilisant l'identifiant tiré de perceive_operation_ids. Cela re-signe les URL et n'effectue pas de nouveau rendu, donc cela ne coûte aucune op. Consultez la section de récupération de perceive pour les détails.


Exemples de code#

curl : recherche web#

curl -X POST https://api.enconvert.com/v2/lookup \
  -H "X-API-Key: sk_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "open source vector database",
    "num_results": 20
  }'

curl : actualités récentes, localisées#

curl -X POST https://api.enconvert.com/v2/lookup \
  -H "X-API-Key: sk_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "rbi monetary policy",
    "category": "news",
    "country": "in",
    "locale": "en",
    "time_filter": "week"
  }'

curl : recherche plus auto-perception des 3 premiers#

curl -X POST https://api.enconvert.com/v2/lookup \
  -H "X-API-Key: sk_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "langchain retrieval augmented generation",
    "perceive_top": 3
  }'

Python#

import requests

response = requests.post(
    "https://api.enconvert.com/v2/lookup",
    headers={"X-API-Key": "sk_your_private_key"},
    json={
        "query": "langchain retrieval augmented generation",
        "perceive_top": 3,
    },
)
response.raise_for_status()
data = response.json()

# Pull the Markdown of every result that was perceived
for result in data["results"]:
    perceived = result.get("perceive")
    if not perceived:
        continue
    markdown_url = perceived["outputs"]["markdown"]["url"]
    page_text = requests.get(markdown_url).text
    print(result["url"], len(page_text), "chars")

for note in data["warnings"]:
    print("warning:", note)

Node.js#

const res = await fetch("https://api.enconvert.com/v2/lookup", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "X-API-Key": "sk_your_private_key"
    },
    body: JSON.stringify({
        query: "langchain retrieval augmented generation",
        perceive_top: 3
    })
});

const data = await res.json();

// Pull the Markdown of every result that was perceived
for (const result of data.results) {
    if (!result.perceive) continue;
    const markdownUrl = result.perceive.outputs.markdown.url;
    const pageText = await fetch(markdownUrl).then(r => r.text());
    console.log(result.url, pageText.length, "chars");
}

for (const note of data.warnings) {
    console.log("warning:", note);
}

Si vous appelez EnConvert depuis Claude, Cursor, ou un autre client Model Context Protocol (MCP), la capacité de recherche y sera également exposée comme un outil. Voir la page du serveur MCP.


Réponses d'erreur#

Le gestionnaire ne renvoie jamais le texte brut du fournisseur au client. Les détails du fournisseur et de la SSRF restent dans les journaux du serveur, et le client reçoit un message propre et générique.

Statut Condition
401 Unauthorized Clé API / jeton JWT manquant ou invalide.
402 Payment Required Lookup ne figure pas dans votre plan actuel, ou votre quota mensuel d'ops est épuisé.
403 Forbidden /v2/lookup ne figure pas dans les points de terminaison autorisés de la clé API.
422 Unprocessable Entity La validation de la requête a échoué : query vide/trop longue, category ou time_filter inconnu, num_results ou page hors plage, perceive_top supérieur à 10.
502 Bad Gateway Le fournisseur de recherche a renvoyé une réponse d'erreur ou une faute de transport non réessayable (SearchUpstreamError). Réessayer peut aider.
503 Service Unavailable Le fournisseur de recherche est mal configuré côté serveur (une clé manquante de notre côté, SearchConfigError), ou il est temporairement indisponible : le disjoncteur est ouvert, ou le fournisseur nous a limités en débit (SearchUnavailableError). Réessayez plus tard.
500 Internal Server Error Un échec inattendu. Le message est générique ; citez l'heure de l'appel au support.

Une auto-perception qui échoue ne lève jamais d'erreur de son propre fait. Elle atterrit dans warnings et l'appel répond tout de même 200. La référence complète des codes de statut figure dans le guide des codes d'erreur.


Limites#

Limite Valeur
Longueur de query 1–512 caractères (nettoyée)
Longueur de country 8 caractères
Longueur de locale 16 caractères
Longueur de location 128 caractères
num_results 1–100
page 1–10
perceive_top 0–10
Ops par appel 1 pour la requête, plus 1 par résultat auto-perçu
Sorties d'auto-perception Markdown par défaut ; élargies avec enrich.outputs
Concurrence d'auto-perception Séquentielle par défaut ; 1–5 avec enrich.concurrency
Coût par recherche 0.06 cent forfaitaire
Expiration de l'URL signée d'une page perçue 15 minutes

Questions fréquentes#

Comment lancer une recherche web et récupérer le contenu de page en un seul appel API REST ?#

Envoyez POST /v2/lookup avec une query et définissez perceive_top (0–10). Les URL des N premiers résultats sont rendues dans un vrai navigateur, et chaque résultat perçu porte un objet perceive en ligne dont le Markdown se trouve derrière une URL pré-signée à perceive.outputs.markdown.url.

/v2/lookup est-elle une alternative à une API SERP sans dépendance à un fournisseur ?#

Oui. Serper est le fournisseur de recherche qui l'alimente, mais la requête et la réponse parlent un vocabulaire de recherche neutre (category, country, locale, time_filter), de sorte qu'un futur changement de fournisseur ne modifie pas le contrat sur lequel vous codez.

Quelles catégories de recherche l'API lookup prend-elle en charge ?#

Six : web (par défaut), news, images, scholar, patents et maps. Les champs universels (title, url, snippet, position) sont toujours typés, et les extras propres à la catégorie atterrissent dans extra.

Pourquoi lookup a-t-il perçu moins de pages que ma valeur perceive_top ?#

L'auto-perception ignore les résultats dont url est null, s'arrête si le quota mensuel d'ops s'épuise en cours de boucle, et dégrade un rendu échoué en simple avertissement. Le perceive_top de la réponse indique combien de pages ont réellement été perçues, et warnings explique les écarts.