Websuche-API für LLM-Agenten#
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.
- 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
402abgewiesen, sodass bei einer Ablehnung nichts berechnet wird. - 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. - Normalisieren. Jeder Anbietertreffer wird in ein neutrales
LookupResultmittitle,url,snippetundpositionabgeflacht. Die kategoriespezifischen Extras landen inextra, sodass der Vertrag nie eine Spalte pro Anbieter-Eigenheit dazubekommt. - Abrechnen und auditieren. Die Suche war erfolgreich, also wird
eine Op berechnet und eine
ch_lookup_queries-Audit- Zeile geschrieben. Die Zeilen-ID kommt alslookup_idfür die Support-Korrelation zurück. - 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, eigeneoperation_id. Standardmäßig fordert Auto-Perceive nur Markdown an, ohne Screenshot, ohne PDF und ohne LLM-Extraktion; sende einenrich-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.