Websuche-API für LLM-Agenten#

Private Beta. Lookup ist heute mit deinem normalen API-Schlüssel aufrufbar, in jedem Tarif einschließlich Founding, und zieht wie jeder andere Aufruf von deinem monatlichen Ops-Kontingent ab. Angekündigt oder allgemein verfügbar ist Lookup nicht: Request- und Response-Formen können sich jederzeit ohne Vorankündigung ändern, und es gibt keine Stabilitäts- oder Supportzusage, baue also noch nichts Tragendes darauf. Die Roadmap steht unter Demnächst, und jedes Release wird im Changelog angekündigt.

POST /v2/lookup ist eine Websuche-API für LLM-Agenten: Sie führt eine Suche in einer von sechs Kategorien aus und liefert eine flache, anbieterneutrale Ergebnisliste zurück. Setzt du perceive_top, rendert sie zusätzlich die Top-N-Ergebnis-URLs in einem echten Browser, sodass ein Agent die Suchmaschinen-Ergebnisseite (SERP) und den Seiteninhalt hinter jedem Treffer in einem einzigen Roundtrip erhält. Als SERP-API-Alternative fasst sie den üblichen Stack (eine Such-API ansprechen, deren Ergebnisse parsen, dann einen Scraper hinterherschicken) zu einem einzigen Aufruf zusammen. Sie wird EnConverts Antwort auf Firecrawl /search sein.

Serper ist der Suchanbieter dahinter. Request und Response sprechen ein neutrales Suchvokabular (category, country, locale, time_filter), sodass ein künftiger Anbieterwechsel den Vertrag, gegen den du programmierst, nicht ändert.

Hier ist der kleinste sinnvolle Aufruf. Sende eine Query, erhalte die obersten Webergebnisse zurück:

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"
  }'

Die Response ist eine flache Ergebnisliste plus Provenienz für die Support-Korrelation:

{
    "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": []
}

Endpunkte#

Methode Pfad Zweck
POST /v2/lookup Eine Suche ausführen und optional die Top-N-Ergebnis-URLs automatisch perceiven.

/v2/lookup ist ein Single-Call-Endpunkt ohne separaten Status- oder Abrufpfad. Beim Auto-Perceive wird jede gerenderte Seite zu einer vollwertigen Perceive-Operation mit eigener operation_id, die du später über GET /v2/perceive/{operation_id} erneut abrufen kannst.

Content-Type: application/json.


Authentifizierung#

Authentifiziere dich mit einem privaten Schlüssel im X-API-Key-Header für Server-zu-Server-Aufrufe. Diesen Weg nutzen die Beispiele unten.

X-API-Key: sk_your_private_key

Öffentliche Schlüssel mit einem JWT-Bearer-Token funktionieren ebenfalls und nutzen denselben Ablauf wie jeder andere Endpunkt: Erzeuge ein Token mit deinem pk_-Schlüssel und sende es dann als Authorization: Bearer <token>. Der vollständige Ablauf, inklusive Domain-Locking und Token-Refresh, steht im Authentifizierungsleitfaden.

Jeder API-Schlüssel trägt eine Allowlist erlaubter Endpunkte. Wenn /v2/lookup nicht auf der Liste des Schlüssels steht, wird der Request mit 403 abgewiesen.


Wie lookup funktioniert#

Ein Request führt eine Anbietersuche aus und rendert, nur wenn du es anforderst, anschließend die obersten Ergebnisse.

  1. Quota-Gate. Bevor irgendetwas abgerechnet wird, prüft der Handler das einheitliche monatliche Ops-Kontingent deines Plans. Ein deaktivierter Plan oder ein ausgeschöpftes Kontingent wird mit 402 abgewiesen, sodass bei einer Ablehnung nichts berechnet wird.
  2. Suche. Die Query geht an den Suchanbieter (Serper) auf dem Endpunkt für deine category. Aktualität, Land, Locale, Standort, Seitengröße und Autokorrektur werden auf die Parameter des Anbieters abgebildet.
  3. Normalisieren. Jeder Anbietertreffer wird in ein neutrales LookupResult mit title, url, snippet und position abgeflacht. Die kategoriespezifischen Extras landen in extra, sodass der Vertrag nie eine Spalte pro Anbieter-Eigenheit dazubekommt.
  4. Abrechnen und auditieren. Die Suche war erfolgreich, also wird eine Op berechnet und eine ch_lookup_queries-Audit- Zeile geschrieben. Die Zeilen-ID kommt als lookup_id für die Support-Korrelation zurück.
  5. Auto-Perceive (optional). Wenn perceive_top > 0, werden die Top-N-Ergebnis-URLs eine nach der anderen durch das gemeinsame Headless-Chrome-Singleton gerendert, dieselbe Pipeline wie der Perceive-Endpunkt. Jedes Rendering ist eine vollständige /v2/perceive-Operation: eigene berechnete Op, eigene Operations-Zeile, eigene operation_id. Standardmäßig fordert Auto-Perceive nur Markdown an, ohne Screenshot, ohne PDF und ohne LLM-Extraktion; sende ein enrich-Objekt, um die Ausgaben zu erweitern, sie parallel laufen zu lassen oder Schema-Extraktion und eine synthetisierte Antwort zu ergänzen.

Auto-Perceive ist Best-Effort. Eine einzelne URL, die fehlschlägt, oder ein mitten im Durchlauf erschöpftes Ops-Kontingent stuft auf eine Warnung herab und liefert trotzdem die Suchergebnisse. Die SERP ist hier das primäre Produkt, ein Wahrnehmungsproblem versenkt also nie den gesamten Aufruf.


Request-Parameter#

Query und Kategorie#

Parameter Typ Standard Beschreibung
query string -- Die Suchanfrage. 1 bis 512 Zeichen, von führendem/nachgestelltem Whitespace bereinigt. Eine nach dem Trimmen leere Query wird mit 422 abgewiesen. Erforderlich.
category string "web" Eines von web, news, images, scholar, patents, maps.

Targeting und Aktualität#

Parameter Typ Standard Beschreibung
country string null Google-gl-Ländercode, z. B. us, in. Max. 8 Zeichen.
locale string null Google-hl-Oberflächensprache, z. B. en. Max. 16 Zeichen.
time_filter string null Auf Ergebnisse aus dem vergangenen Zeitraum beschränken: hour, day, week, month oder year.
location string null Freitext-Standortangabe, z. B. "Austin, Texas". Max. 128 Zeichen.
autocorrect boolean true Ob der Anbieter die Rechtschreibung der Query automatisch korrigieren darf.

Pagination#

Parameter Typ Standard Beschreibung
num_results integer 10 Ergebnisse pro Seite. 1 bis 100.
page integer 1 Seitenzahl. 1 bis 10.

Auto-Perceive#

Parameter Typ Standard Beschreibung
perceive_top integer 0 Perceive die ersten N Ergebnis-URLs automatisch, die einen navigierbaren Link haben. 0 bis 10. Jede ist ein vollständiges Browser-Rendering, das eine Op aus deinem monatlichen Kontingent verbraucht, weshalb es bei 10 gedeckelt ist. Für größere Mengen nimm die url-Felder und rufe den Perceive-Batch-Endpunkt auf. 0 deaktiviert Auto-Perceive.

Anreicherung (enrich)#

Ein optionales enrich-Objekt steuert, wie die Top-N-Ergebnisse (perceive_top) gelesen werden, und kann eine fundierte Antwort über sie hinweg synthetisieren. Wenn enrich weggelassen wird, behält perceive_top sein Standardverhalten (nur Markdown, ein Ergebnis nach dem anderen).

Parameter Typ Standard Beschreibung
enrich.outputs string[] ["markdown"] Welche Perceive-Ausgaben pro angereichertem Ergebnis erzeugt werden, z. B. markdown, html_cleaned, links, screenshot, structured. Siehe Perceive-Ausgaben.
enrich.concurrency integer 3 Wie viele Ergebnis-URLs parallel angereichert werden. 1 bis 5. Markdown-/HTML-Renderings parallelisieren; Screenshot-/PDF-Renderings serialisieren auf dem gemeinsamen Browser.
enrich.schema object null Führt eine schema-gesteuerte strukturierte Extraktion gegen jedes angereicherte Ergebnis aus. Die extrahierten Daten erscheinen unter perceive.structured des jeweiligen Ergebnisses. JSON-Schema-Objekt oder eine flache {field: description}-Map.
enrich.synthesize_answer boolean false Synthetisiert eine zitierte, fundierte Antwort auf die Query über die angereicherten Ergebnisse hinweg, zurückgegeben als answer (mit answer_sources). Verwendet den perceiveten Seiteninhalt, wenn verfügbar, andernfalls die Ergebnis-Snippets.
enrich.answer_prompt string null Eine Frage, die anstelle der rohen Query beantwortet wird. Wird nur verwendet, wenn synthesize_answer gleich true ist. Max. 1,000 Zeichen.

enrich.schema und enrich.synthesize_answer verwenden die LLM-Extraktionsstufe. Wenn dieser Extraktionsschritt nicht ausgeführt werden kann, stufen sie auf eine Warnung herab, und der Rest der Response bleibt unberührt.

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

Kategorien#

Jede Kategorie spricht einen anderen Anbieter-Endpunkt an und liefert eine leicht abweichende Ergebnisform. Die universellen Felder (title, url, snippet, position) sind stets typisiert; kategoriespezifische Felder landen in extra.

category Was sie durchsucht Bemerkenswert befüllte Felder
web Allgemeine Webergebnisse title, url, snippet, date, position
news Nachrichtenartikel ergänzt source, image_url
images Bildergebnisse image_url, thumbnail_url, source (oft kein snippet)
scholar Akademische Ergebnisse gleiche Form wie web; Zitationszahlen in extra
patents Patentergebnisse gleiche Form wie web; Patentfelder in extra
maps Lokale Orte url ist die Website des Ortes; snippet trägt die Adresse; Bewertung, Koordinaten in extra

Erwähnenswert: Bei images und maps kann url für einen bestimmten Treffer null sein, wenn der Anbieter keinen navigierbaren Link zurückgibt. Auto-Perceive überspringt jedes Ergebnis, dessen url null ist, sodass ein perceive_top von 5 auf einer SERP mit zwei URL-losen Treffern höchstens drei Seiten perceived.


Antwort#

Der Endpunkt lässt null-Felder weg, sodass ein minimales web-Ergebnis nur die Felder trägt, die tatsächlich befüllt sind.

Feld Typ Beschreibung
lookup_id integer Die ch_lookup_queries-Audit-Zeilen-ID. Nenne sie dem Support. null, wenn der Audit-Write fehlschlug, wobei die Ergebnisse trotzdem gültig sind.
query string Die (getrimmte) Query, die du gesendet hast.
category string Die durchsuchte Kategorie.
country string Echo des gesendeten country, falls vorhanden.
locale string Echo des gesendeten locale, falls vorhanden.
time_filter string Echo des gesendeten time_filter, falls vorhanden.
total integer Anzahl der zurückgegebenen Ergebnisse.
results LookupResult[] Die Ergebnisliste. Siehe unten.
perceive_top integer Wie viele Ergebnisse tatsächlich perceived wurden: höchstens der von dir angeforderte Wert und niedriger, wenn das Ops-Kontingent erschöpft war oder URLs fehlschlugen.
perceive_operation_ids string[] Die per_...-Operations-IDs der perceiveten Ergebnisse, in Reihenfolge.
answer_box object Die Answer-Box des Anbieters, falls vorhanden.
knowledge_graph object Das Knowledge-Graph-Panel des Anbieters, falls vorhanden.
answer string Die synthetisierte, zitierte Antwort über die angereicherten Ergebnisse hinweg. Nur vorhanden, wenn enrich.synthesize_answer gleich true ist und sie erfolgreich war.
answer_sources string[] Die als Grundlage für answer verwendeten URLs, in Zitationsreihenfolge.
credits integer Von dieser Query verbrauchte Anbieter-Credits.
cost_cents number Geldkosten der Suche in Cent. Heute pauschal 0.06 pro Query.
warnings string[] Nicht-fatale Hinweise: ein übersprungenes URL-loses Ergebnis, ein Auto-Perceive-Fehler, ein mitten im Loop erschöpftes Ops-Kontingent.

LookupResult#

Feld Typ Beschreibung
title string Ergebnistitel.
url string Kanonischer Seiten-Link, also das, was du perceiven würdest. null für Ergebnisse ohne navigierbare URL.
snippet string Ergebnis-Snippet. Bei maps trägt dies die Adresse.
position integer Die Position des Ergebnisses auf der SERP.
source string Quelle/Herausgeber, bei news und images.
date string Veröffentlichungsdatum, wenn der Anbieter eines meldet.
image_url string Bild-URL, bei images und news.
thumbnail_url string Thumbnail-URL, bei images.
extra object Kategoriespezifische Felder außerhalb des neutralen Sets: Bewertungen, Koordinaten, Zitationszahlen und so weiter.
perceive PerceiveResponse Das vollständige Inline-Perceive-Ergebnis für diese URL, nur vorhanden für die Top-N, wenn perceive_top > 0 und das Rendering erfolgreich war. Dieselbe Objektform wie der Perceive-Endpunkt.

Auto-Perceive-Ergebnisse lesen#

Wenn du perceive_top sendest, gehe die Ergebnisse durch und prüfe auf das perceive-Feld. Es ist nur auf den Ergebnissen vorhanden, die perceived wurden, und nur, wenn ihr Rendering erfolgreich war. Das Markdown für jedes liegt hinter einer vorsignierten Download-URL (ein kurzlebiger, signierter Link zum Objektspeicher) unter perceive.outputs.markdown.url, genauso wie bei einem direkten Perceive-Aufruf.

{
    "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": []
}

Diese signierten URLs laufen nach 15 Minuten ab. Um eine perceivete Seite später herunterzuladen, rufe ihre Operation erneut mit GET /v2/perceive/{operation_id} ab, unter Verwendung der ID aus perceive_operation_ids. Das signiert die URLs neu und rendert nicht erneut, kostet also keine Ops. Siehe den Perceive-Abruf-Abschnitt für die Details.


Codebeispiele#

curl: Websuche#

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: aktuelle Nachrichten, lokalisiert#

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: Suche plus Auto-Perceive der Top 3#

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);
}

Wenn du EnConvert aus Claude, Cursor oder einem anderen Model-Context- Protocol-(MCP-)Client aufrufst, wird die Suchfähigkeit auch dort als Tool bereitgestellt. Siehe die MCP-Serverseite.


Fehlerantworten#

Der Handler gibt nie rohen Anbietertext an den Client zurück. Anbieter- und SSRF-Details bleiben in den Server-Logs, und der Client erhält eine saubere, generische Meldung.

Status Bedingung
401 Unauthorized Fehlender oder ungültiger API-Schlüssel / JWT-Token.
402 Payment Required Lookup ist nicht in deinem aktuellen Plan, oder dein monatliches Ops-Kontingent ist erschöpft.
403 Forbidden /v2/lookup ist nicht in den erlaubten Endpunkten des API-Schlüssels.
422 Unprocessable Entity Request-Validierung fehlgeschlagen: leere/zu lange query, eine unbekannte category oder time_filter, num_results oder page außerhalb des Bereichs, perceive_top über 10.
502 Bad Gateway Der Suchanbieter hat eine Fehler-Response oder einen nicht wiederholbaren Transportfehler zurückgegeben (SearchUpstreamError). Ein erneuter Versuch kann helfen.
503 Service Unavailable Der Suchanbieter ist serverseitig fehlkonfiguriert (ein fehlender Schlüssel auf unserer Seite, SearchConfigError), oder er ist vorübergehend nicht verfügbar: der Circuit-Breaker ist offen, oder der Anbieter hat uns rate-limitiert (SearchUnavailableError). Versuche es später erneut.
500 Internal Server Error Ein unerwarteter Fehler. Die Meldung ist generisch; nenne dem Support die Uhrzeit des Aufrufs.

Ein fehlschlagendes Auto-Perceive löst nie einen eigenen Fehler aus. Es landet in warnings, und der Aufruf antwortet trotzdem mit 200. Die vollständige Statuscode-Referenz steht im Fehlercode-Leitfaden.


Limits#

Limit Wert
query-Länge 1 bis 512 Zeichen (getrimmt)
country-Länge 8 Zeichen
locale-Länge 16 Zeichen
location-Länge 128 Zeichen
num_results 1 bis 100
page 1 bis 10
perceive_top 0 bis 10
Ops pro Aufruf 1 für die Query, plus 1 pro auto-perceivetem Ergebnis
Auto-Perceive-Outputs Standardmäßig Markdown; erweiterbar mit enrich.outputs
Auto-Perceive-Nebenläufigkeit Standardmäßig sequenziell; 1 bis 5 mit enrich.concurrency
Kosten pro Suche 0.06 Cent pauschal
Ablauf der signierten URL einer perceiveten Seite 15 Minuten

Häufig gestellte Fragen#

Wie führe ich mit einem einzigen REST-API-Aufruf eine Websuche durch und erhalte gleichzeitig den Seiteninhalt zurück?#

Sende POST /v2/lookup mit einer query und setze perceive_top (0 bis 10). Die Top-N-Ergebnis-URLs werden in einem echten Browser gerendert, und jedes perceivete Ergebnis trägt ein inline perceive-Objekt, dessen Markdown hinter einer vorsignierten URL unter perceive.outputs.markdown.url liegt.

Ist /v2/lookup eine SERP-API-Alternative, die ich ohne Provider-Lock-in einsetzen kann?#

Ja. Serper ist der Suchanbieter dahinter, aber Request und Response sprechen ein neutrales Suchvokabular (category, country, locale, time_filter), sodass ein künftiger Anbieterwechsel den Vertrag, gegen den du programmierst, nicht ändert.

Welche Suchkategorien unterstützt die Lookup-API?#

Sechs: web (die Standardeinstellung), news, images, scholar, patents und maps. Die universellen Felder (title, url, snippet, position) sind stets typisiert, und kategoriespezifische Extras landen in extra.

Warum hat lookup weniger Seiten perceived als mein perceive_top-Wert?#

Auto-Perceive überspringt Ergebnisse, deren url null ist, stoppt, wenn das monatliche Ops-Kontingent mitten im Loop erschöpft ist, und stuft ein fehlgeschlagenes Rendering auf eine Warnung herab. Das perceive_top der Antwort meldet, wie viele Seiten tatsächlich perceived wurden, und warnings erklärt die Lücken.