Discover

POST /v2/discover énumère les URL d'un site sans afficher la moindre page. Aucun navigateur, aucune capture d'écran, aucun PDF, aucun artefact stocké — uniquement un crawl HTTP plus l'analyse du sitemap, qui renvoie une liste plate d'URL et un décompte de l'origine de chacune. C'est la primitive économique « cartographier le site » : pointez-la vers un domaine, récupérez les pages qui valent la peine d'être traitées, puis transmettez cette liste à l'endpoint perceive ou à une tâche d'ingestion en mode crawl.

Voici l'appel utile le plus simple. Envoyez une URL, récupérez sa carte :

curl -X POST https://api.enconvert.com/v2/discover \
  -H "X-API-Key: sk_live_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com"
  }'

La réponse est une simple liste d'URL accompagnée de compteurs de provenance — pas d'URL signées, pas d'identifiant d'opération, pas de polling :

{
    "url": "https://example.com",
    "mode": "hybrid",
    "total": 47,
    "urls": [
        "https://example.com/",
        "https://example.com/pricing",
        "https://example.com/docs",
        "https://example.com/blog/launch"
    ],
    "pages_crawled": 12,
    "truncated": false,
    "robots_respected": false,
    "sources": {"sitemap": 42, "crawl": 30},
    "warnings": []
}

À signaler d'emblée. /v2/discover est un endpoint V2, conditionné par l'indicateur de plan discover_enabled. Contrairement à la plupart des endpoints V2, il n'a aucun compteur de quota par opération — il est économique (pas de navigateur, pas de stockage), il n'y a donc aucun compteur mensuel à épuiser. Si votre plan n'inclut pas V2 discover, l'appel renvoie 402. Consultez la page tarifs pour savoir quels plans le proposent.


Endpoints

Method Path Purpose
POST /v2/discover Cartographie les URL d'un site uniquement via HTTP et renvoie une liste plate avec le décompte des sources.

/v2/discover expose un seul chemin. Il est sans état — il n'y a aucune ligne d'opération à récupérer de nouveau ni aucune tâche à interroger, donc aucun endpoint GET compagnon comme perceive en possède un.

Content-Type : application/json sur le POST.


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 utilisée par les exemples ci-dessous.

X-API-Key: sk_live_your_private_key

Les clés publiques avec un jeton porteur JWT fonctionnent aussi, selon le même flux que tout autre endpoint — générez un jeton avec votre clé pk_, puis envoyez-le dans 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 d'endpoints autorisés. Si /v2/discover ne figure pas sur la liste de la clé, la requête est rejetée avec 403 et un message nommant le chemin qui a été bloqué.


Fonctionnement de discover

Une requête s'exécute entièrement via HTTP. Le Chrome headless unique qui alimente perceive n'est jamais sollicité — la voie de crawl utilise la stratégie de crawler HTTP de Crawl4AI (un GET httpx plus une analyse de liens lxml par page), et la voie du sitemap réutilise les mêmes assistants purement HTTP de sitemap et de flux que le reste de la plateforme.

  1. Filtrer la graine. L'URL que vous envoyez est vérifiée contre le SSRF avant toute récupération : le schéma, les identifiants embarqués, les noms d'hôte bloqués et l'IP résolue sont tous validés. Une URL qui se résout vers une adresse privée, de bouclage, link-local ou de métadonnées cloud est rejetée avec 400. La graine est toujours incluse comme première entrée de sa propre carte.
  2. Collecter depuis les sitemaps. En mode sitemap ou hybrid, discover lit robots.txt, sonde sitemap.xml (en récursant dans les enfants <sitemapindex>) et récupère les pages de flux RSS/Atom. Un sitemap manquant ou cassé devient un avertissement, pas une erreur.
  3. Crawler via HTTP. En mode crawl ou hybrid, discover exécute un crawl en largeur d'abord depuis la graine jusqu'à max_depth, en récoltant les liens <a href> du HTML brut de chaque page récupérée. Chaque lien suivi est filtré contre le SSRF avant d'être récupéré.
  4. Normaliser et filtrer. La liste brute combinée est canonicalisée (fragments et paramètres de suivi supprimés, ports par défaut retirés, clés de requête triées), puis passée à travers la vérification de même domaine, vos motifs regex d'inclusion et d'exclusion, le filtre robots.txt, la déduplication et, enfin, le plafond max_urls.

Comme il n'y a aucun rendu, une application monopage rendue côté client renvoie uniquement sa coquille HTML en mode crawl — généralement la graine plus zéro ou une URL. C'est le comportement correct d'un endpoint sans navigateur, pas un échec. Pour les SPA, utilisez le mode sitemap (la plupart des SPA soucieuses du SEO publient un sitemap) ou repliez-vous sur des appels perceive par URL.


Paramètres de requête

Cœur

Parameter Type Default Description
url string Le site à cartographier. Doit commencer par http:// ou https://. 2 048 caractères max. Obligatoire.
mode string "hybrid" sitemap, crawl ou hybrid. Voir Modes.
max_urls integer 100 Nombre maximal d'URL renvoyées. 1–1 000. La liste est plafonnée ici et truncated le signale si davantage existaient.
max_depth integer 2 Profondeur de crawl depuis la graine, en mode crawl/hybrid. 1–5.
same_domain_only boolean true Ne conserve que les URL sur l'hôte de la graine. Quand false, les liens hors hôte découverts pendant le crawl sont conservés aussi.

Filtrage

Parameter Type Default Description
include_patterns string[] [] Liste blanche de regex Python (sémantique re.search, pas glob). Une URL doit en faire correspondre au moins un pour être conservée. Vide signifie tout autoriser. 50 motifs max.
exclude_patterns string[] [] Liste noire de regex Python. Une URL correspondant à n'importe quel motif est écartée. Appliquée après include_patterns. 50 motifs max.
respect_robots boolean false Quand true, les URL interdites par le robots.txt du site sont écartées de la liste renvoyée.

Les motifs sont de véritables expressions régulières Python, compilées au moment de la validation. Un motif mal formé est un 422 en bordure, pas un 500 en plein crawl. Comme la sémantique est re.search, une simple sous-chaîne comme "/blog/" correspond n'importe où dans l'URL — ancrez avec ^/$ si vous avez besoin d'une correspondance positionnelle.

À signaler d'emblée. respect_robots est appliqué au moment du filtrage de sortie, pas de la récupération. Crawl4AI 0.8.9 n'a aucune barrière robots native, donc en mode crawl ou hybrid une page interdite peut quand même être récupérée via HTTP, puis écartée avant d'atteindre la réponse. Contrairement à perceive, où respect_robots=true rejette une URL interdite avec 403, discover ne renvoie jamais 403 pour une règle robots — il écarte silencieusement l'URL et ne signale rien.

Modes

mode What it does
sitemap Les entrées de sitemap du robots.txt, le sitemap.xml sondé (avec récursion d'index) et les pages de flux RSS/Atom. Instantané, sans crawl.
crawl Crawl en largeur d'abord, uniquement via HTTP, depuis la graine, en récoltant les liens <a href> du balisage brut.
hybrid (default) L'union dédupliquée de sitemap et crawl.

Pour être clair : le mode crawl borne le nombre de pages qu'il récupère réellement à min(max_urls, 50). Un max_urls de 1 000 n'émet pas mille GET HTTP — discover cesse de récupérer à 50 pages, mais chaque page apporte de nombreux liens <a href>, si bien que la liste renvoyée peut tout de même atteindre max_urls. Ce plafond de 50 pages récupérées maintient la requête synchrone bien en deçà du délai de requête de 300 secondes. pages_crawled dans la réponse vous indique exactement combien de GET ont été exécutés.


Réponse

POST /v2/discover renvoie cet objet directement — il n'y a aucune tâche asynchrone ni second appel.

Field Type Description
url string L'URL graine que vous avez envoyée.
mode string Le mode qui s'est exécuté : sitemap, crawl ou hybrid.
total integer Nombre d'URL dans urls (après déduplication, filtrage et plafond).
urls string[] La liste d'URL dédupliquée, normalisée et plafonnée. La graine est toujours le premier candidat.
pages_crawled integer GET HTTP émis par le crawl. 0 en mode sitemap pur.
truncated boolean true quand davantage d'URL uniques existaient que ce qu'autorisait max_urls.
robots_respected boolean Renvoie la valeur respect_robots que vous avez envoyée.
sources object Décompte brut d'URL par source avant déduplication/filtrage, p. ex. {"sitemap": 42, "crawl": 30}. Les décomptes se chevauchent et leur somme dépasse total.
warnings string[] Notes non fatales : un sitemap manquant, un crawl en échec, un robots.txt inaccessible.

Les décomptes sources sont bruts — c'est le nombre d'URL que chaque voie a produites avant l'exécution de la normalisation, de la vérification de même domaine, de vos filtres et de la déduplication. Ils dépasseront couramment total, car le mode hybrid trouve les mêmes pages à la fois depuis le sitemap et le crawl. Utilisez-les pour voir quelle voie porte la carte, pas comme un décompte post-filtrage.


Exemples de code

curl — carte hybride par défaut

curl -X POST https://api.enconvert.com/v2/discover \
  -H "X-API-Key: sk_live_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com"
  }'

curl — sitemap seulement, pages de blog, plafonné à 500

curl -X POST https://api.enconvert.com/v2/discover \
  -H "X-API-Key: sk_live_your_private_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "mode": "sitemap",
    "max_urls": 500,
    "include_patterns": ["/blog/"],
    "exclude_patterns": ["/tag/", "/author/"],
    "respect_robots": true
  }'

Python

import requests

response = requests.post(
    "https://api.enconvert.com/v2/discover",
    headers={"X-API-Key": "sk_live_your_private_key"},
    json={
        "url": "https://example.com",
        "mode": "hybrid",
        "max_urls": 200,
        "include_patterns": [r"/docs/"],
    },
)
response.raise_for_status()
data = response.json()

print(f"found {data['total']} URLs from {data['sources']}")
for page_url in data["urls"]:
    print(page_url)

Node.js

const res = await fetch("https://api.enconvert.com/v2/discover", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "X-API-Key": "sk_live_your_private_key"
    },
    body: JSON.stringify({
        url: "https://example.com",
        mode: "hybrid",
        max_urls: 200,
        include_patterns: ["/docs/"]
    })
});

const data = await res.json();

console.log(`found ${data.total} URLs from`, data.sources);
data.urls.forEach((pageUrl) => console.log(pageUrl));

Un schéma courant consiste à découvrir d'abord, puis à afficher : prenez data.urls et transmettez-les à l'endpoint perceive — des appels individuels pour une poignée de pages, ou sa voie par lots pour toute la liste.


Conditionnement par plan

/v2/discover est conditionné par l'indicateur de plan discover_enabled et se comporte différemment des endpoints V2 mesurés. Les endpoints mesurés — perceive parmi eux — consomment chacun un compteur mensuel (perceive_operations, lookup_queries, ingest_pages, watch_checks, distill_operations). Discover n'a pas de tel compteur : il est uniquement HTTP, il ne stocke rien, il n'y a donc aucun compteur par opération à épuiser.

Ce que cela signifie en pratique :

  • Si votre plan porte discover_enabled, vous pouvez l'appeler. Il n'y a aucun quota mensuel de discover à épuiser.
  • Si votre plan ne le porte pas, l'appel renvoie 402 avec une invite de mise à niveau.
  • Les plans admin contournent entièrement la barrière.

Les plans qui incluent discover_enabled sont définis par palier ; les quotas actuels figurent sur la page tarifs. Les plans de conversion V1 n'incluent pas les endpoints V2 — un appel discover ne consomme jamais de quota de conversion V1.


Réponses d'erreur

Status Condition
400 Bad Request L'URL n'est pas http(s), porte des identifiants embarqués, n'a aucun nom d'hôte ou se résout vers une adresse privée, de bouclage, link-local ou de métadonnées cloud (protection SSRF).
401 Unauthorized Clé API / jeton JWT manquant ou invalide.
402 Payment Required Discover n'est pas activé sur votre plan actuel.
403 Forbidden /v2/discover ne figure pas dans les endpoints autorisés de la clé API.
422 Unprocessable Entity La validation de la requête a échoué : enum mode incorrect, max_urls hors de 1–1 000, max_depth hors de 1–5, plus de 50 motifs d'inclusion/exclusion, une regex mal formée ou une url de plus de 2 048 caractères.
500 Internal Server Error La découverte d'URL a échoué de façon inattendue. Le client reçoit un message générique ; le détail complet ne va que dans les journaux serveur.

Notez qu'une récupération de sitemap en échec ou une faute de crawl ne produit pas de statut d'erreur — ces cas se dégradent en entrées dans le tableau warnings, et la requête renvoie tout de même 200 avec ce qui a été trouvé. La référence complète des codes de statut figure dans le guide des codes d'erreur.


Limites

Limit Value
Longueur d'URL 2 048 caractères
max_urls 1–1 000 (par défaut 100)
max_depth 1–5 (par défaut 2)
include_patterns 50 motifs max
exclude_patterns 50 motifs max
Pages récupérées en mode crawl 50 (min(max_urls, 50))
Délai de requête 300 secondes
Quota par opération Aucun — pas de compteur mensuel de discover