Aller au contenu
NessFlow
Menu
    Sommaire de la documentation

    Crawls

    Les crawls exécutés et leurs résultats : anomalies, pages, rapports.

    Lister les crawls d’un projet

    GET /v1/projects/{project}/crawls

    Les crawls exécutés d’un projet, du plus récent au plus ancien.

    Scopes requis
    crawls:read
    Coût en débit
    1 unité(s)

    Paramètres

    • project path · string (uuid) · requis

    • cursor query · string · facultatif

      Opaque cursor from `meta.next_cursor`. It is bound to the request that issued it; reusing it with other filters returns `400 pagination.invalid_cursor`.

    • limit query · integer · facultatif

      Items per page, 1 to 100 (default 25).

    Réponses

    • 200 OK.
    • 400 Malformed request, such as an invalid pagination cursor (`pagination.invalid_cursor`).
    • 422 Invalid query or body values (`validation_failed`), with `errors` by field.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/crawls" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/crawls', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/crawls', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/crawls",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": [
            {
                "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
                "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
                "campaign_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
                "status": "queued",
                "stage": "string",
                "active": true,
                "stage_plan": {
                    "current_step": 42,
                    "step_count": 42,
                    "settled": true,
                    "steps": [
                        {
                            "stage": "string",
                            "state": "pending",
                            "skip_reason": "string"
                        }
                    ]
                },
                "pages": {
                    "crawled": 42,
                    "discovered": 42,
                    "budget": 42
                },
                "issue_counts": {
                    "error": 42,
                    "warning": 42,
                    "info": 42
                },
                "truncated": true,
                "blocked": true,
                "blocked_reason": "string",
                "comparable": true,
                "error": "string",
                "trigger": "manual",
                "started_at": "2026-10-01T09:30:00Z",
                "finished_at": "2026-10-01T09:30:00Z",
                "created_at": "2026-10-01T09:30:00Z"
            }
        ],
        "meta": {
            "limit": 100,
            "has_more": true,
            "next_cursor": "string"
        }
    }

    Lire un crawl

    GET /v1/crawls/{crawl}

    L’état d’un crawl. Sondez cette ressource tant que active vaut true. status: completed est posé avant la fin du post-traitement : attendez que stage_plan.settled vaille true avant de lire les rapports.

    Scopes requis
    crawls:read
    Coût en débit
    1 unité(s)

    Paramètres

    • crawl path · string (uuid) · requis

    Réponses

    • 200 OK.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": {
            "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "campaign_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "status": "queued",
            "stage": "string",
            "active": true,
            "stage_plan": {
                "current_step": 42,
                "step_count": 42,
                "settled": true,
                "steps": [
                    {
                        "stage": "string",
                        "state": "pending",
                        "skip_reason": "string"
                    }
                ]
            },
            "pages": {
                "crawled": 42,
                "discovered": 42,
                "budget": 42
            },
            "issue_counts": {
                "error": 42,
                "warning": 42,
                "info": 42
            },
            "truncated": true,
            "blocked": true,
            "blocked_reason": "string",
            "comparable": true,
            "error": "string",
            "trigger": "manual",
            "started_at": "2026-10-01T09:30:00Z",
            "finished_at": "2026-10-01T09:30:00Z",
            "created_at": "2026-10-01T09:30:00Z"
        }
    }

    Lister les occurrences d’anomalies

    GET /v1/crawls/{crawl}/issues

    Une ligne par occurrence (une anomalie sur une URL), dans un ordre stable. Les constats qui décrivent une page de pare-feu ou d’interstitiel plutôt que le site sont exclus ; le résumé en donne le nombre à part.

    Scopes requis
    crawls:read
    Coût en débit
    1 unité(s)

    Paramètres

    • crawl path · string (uuid) · requis

    • cursor query · string · facultatif

      Opaque cursor from `meta.next_cursor`. It is bound to the request that issued it; reusing it with other filters returns `400 pagination.invalid_cursor`.

    • limit query · integer · facultatif

      Items per page, 1 to 100 (default 25).

    • severity query · string · facultatif

    • category query · string · facultatif

    • name query · string · facultatif

      Exact issue name, as returned by the summary.

    Réponses

    • 200 OK.
    • 400 Malformed request, such as an invalid pagination cursor (`pagination.invalid_cursor`).
    • 422 Invalid query or body values (`validation_failed`), with `errors` by field.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/issues" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/issues', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/issues', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/issues",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": [
            {
                "name": "Exemple",
                "severity": "error",
                "category": "string",
                "url": "https://exemple.fr/",
                "details": "string"
            }
        ],
        "meta": {
            "limit": 100,
            "has_more": true,
            "next_cursor": "string"
        }
    }

    Résumer les anomalies

    GET /v1/crawls/{crawl}/issues/summary

    Les familles d’anomalies avec leur nombre d’occurrences, et les totaux par gravité.

    Scopes requis
    crawls:read
    Coût en débit
    5 unité(s)

    Paramètres

    • crawl path · string (uuid) · requis

    Réponses

    • 200 OK.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/issues/summary" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/issues/summary', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/issues/summary', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/issues/summary",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": {
            "crawl_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "totals": {
                "error": 42,
                "warning": 42,
                "info": 42
            },
            "protection_occurrences": 42,
            "groups": [
                {
                    "name": "Exemple",
                    "severity": "error",
                    "category": "string",
                    "occurrences": 42
                }
            ]
        }
    }

    Lister les pages crawlées

    GET /v1/crawls/{crawl}/pages

    Les pages découvertes par le crawl, dans un ordre stable.

    Scopes requis
    crawls:read
    Coût en débit
    1 unité(s)

    Paramètres

    • crawl path · string (uuid) · requis

    • cursor query · string · facultatif

      Opaque cursor from `meta.next_cursor`. It is bound to the request that issued it; reusing it with other filters returns `400 pagination.invalid_cursor`.

    • limit query · integer · facultatif

      Items per page, 1 to 100 (default 25).

    • status query · string · facultatif

      HTTP status class; `unreachable` means no HTTP response at all.

    • internal query · string · facultatif

    Réponses

    • 200 OK.
    • 400 Malformed request, such as an invalid pagination cursor (`pagination.invalid_cursor`).
    • 422 Invalid query or body values (`validation_failed`), with `errors` by field.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pages" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pages', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pages', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pages",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": [
            {
                "url": "https://exemple.fr/",
                "status_code": 200,
                "error_type": "string",
                "content_type": "string",
                "is_internal": true,
                "depth": 42,
                "title": "string",
                "meta_description": "string",
                "h1": "string",
                "word_count": 42,
                "canonical_url": "https://exemple.fr/",
                "response_time_ms": 0.5,
                "size_bytes": 42,
                "internal_links": 42,
                "external_links": 42,
                "images": 42,
                "images_without_alt": 42
            }
        ],
        "meta": {
            "limit": 100,
            "has_more": true,
            "next_cursor": "string"
        }
    }

    Lire une page par son URL

    GET /v1/crawls/{crawl}/pages/by-url

    Une page crawlée et ses anomalies, les erreurs d’abord.

    Scopes requis
    crawls:read
    Coût en débit
    1 unité(s)

    Paramètres

    • crawl path · string (uuid) · requis

    • url query · string · requis

      Page URL; matched on its normalised form.

    Réponses

    • 200 OK.
    • 422 Invalid query or body values (`validation_failed`), with `errors` by field.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pages/by-url?url=https%3A%2F%2Fexemple.fr%2F" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pages/by-url', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
        'query' => [
            'url' => 'https://exemple.fr/',
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pages/by-url?url=https%3A%2F%2Fexemple.fr%2F', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pages/by-url?url=https%3A%2F%2Fexemple.fr%2F",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": {
            "url": "https://exemple.fr/",
            "status_code": 200,
            "error_type": "string",
            "content_type": "string",
            "is_internal": true,
            "depth": 42,
            "title": "string",
            "meta_description": "string",
            "h1": "string",
            "word_count": 42,
            "canonical_url": "https://exemple.fr/",
            "response_time_ms": 0.5,
            "size_bytes": 42,
            "internal_links": 42,
            "external_links": 42,
            "images": 42,
            "images_without_alt": 42,
            "issues": [
                {
                    "name": "Exemple",
                    "severity": "error",
                    "category": "string",
                    "url": "https://exemple.fr/",
                    "details": "string"
                }
            ]
        }
    }

    Lire les résultats PageSpeed

    GET /v1/crawls/{crawl}/pagespeed

    La performance Lighthouse de l’échantillon PageSpeed (page d’accueil et pages catégorie), sur mobile et sur ordinateur. Une stratégie qui n’a abouti sur aucune page vaut null, jamais 0 ; chaque moyenne voyage avec le nombre de pages mesurées. combined est la moyenne des stratégies mesurées, celle du score de santé. failed signifie que toutes les mesures ont été refusées.

    Scopes requis
    crawls:read
    Coût en débit
    1 unité(s)

    Paramètres

    • crawl path · string (uuid) · requis

    Réponses

    • 200 OK.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pagespeed" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pagespeed', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pagespeed', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/pagespeed",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": {
            "crawl_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "status": "ready",
            "average": {
                "mobile": 42,
                "desktop": 42,
                "combined": 42,
                "pages_measured_mobile": 42,
                "pages_measured_desktop": 42,
                "pages_sampled": 42
            },
            "results": [
                {
                    "url": "https://exemple.fr/",
                    "mobile": {
                        "score": 42,
                        "metrics": {
                            "fcp": 0.5,
                            "lcp": 0.5,
                            "cls": 0.5,
                            "fid": 0.5,
                            "speed_index": 0.5,
                            "tti": 0.5
                        }
                    },
                    "desktop": {
                        "score": 42,
                        "metrics": {
                            "fcp": 0.5,
                            "lcp": 0.5,
                            "cls": 0.5,
                            "fid": 0.5,
                            "speed_index": 0.5,
                            "tti": 0.5
                        }
                    },
                    "analysis_date": "string",
                    "error": "string"
                }
            ]
        }
    }

    Lire le rapport de préparation GEO

    GET /v1/crawls/{crawl}/geo

    La préparation à la recherche IA, figée à la fin du crawl : accès des robots IA (robots.txt), llms.txt, inventaire schema.org, signaux éditoriaux et score GEO avec ses axes. Les sections de détail suivent la version du barème qui les a produites (score_version).

    Scopes requis
    crawls:read
    Coût en débit
    5 unité(s)

    Paramètres

    • crawl path · string (uuid) · requis

    Réponses

    • 200 OK.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/geo" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/geo', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/geo', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/geo",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": {
            "crawl_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "status": "ready",
            "score": 42,
            "score_version": 42,
            "score_axes": [
                {
                    "key": "string",
                    "points": 0.5,
                    "max": 42,
                    "applicable": true
                }
            ],
            "origin": "string",
            "access": {},
            "llms_txt": {},
            "structured_data": {},
            "editorial": {},
            "hints": [
                {
                    "key": "string",
                    "priority": "high"
                }
            ]
        }
    }

    Lire le rapport d’accessibilité

    GET /v1/crawls/{crawl}/accessibility

    L’audit d’accessibilité automatisé du crawl (WCAG, taux RGAA), figé à la fin du crawl, avec les pages sur lesquelles il a été mesuré. Exige l’option accessibilité de la campagne, sinon unavailable. Les vérifications manuelles listent ce qu’aucun outil automatique ne peut vérifier.

    Scopes requis
    crawls:read
    Coût en débit
    5 unité(s)

    Paramètres

    • crawl path · string (uuid) · requis

    Réponses

    • 200 OK.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/accessibility" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/accessibility', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/accessibility', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/accessibility",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": {
            "crawl_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "status": "ready",
            "score": 42,
            "score_version": 42,
            "standard": "string",
            "origin": "string",
            "rgaa_compliance_rate": 42,
            "pages_analyzed": 42,
            "pages_total": 42,
            "rendered_pages_analyzed": 42,
            "rendered_pages_total": 42,
            "render_mode": "string",
            "is_protected": true,
            "contrast_status": "string",
            "contrast_incomplete_count": 42,
            "axes": [
                {}
            ],
            "conformance": {},
            "rules": [
                {}
            ],
            "by_principle": [],
            "contrast_pairs": [
                {}
            ],
            "hints": [
                {
                    "key": "string",
                    "priority": "high"
                }
            ],
            "manual_checks": [
                "string"
            ]
        }
    }

    Lire le socle de confiance

    GET /v1/crawls/{crawl}/eeat

    Le socle de confiance E-E-A-T : le score, les axes attendus pour le modèle d’affaires et le secteur déclarés, et les signaux d’attribution. Un axe qui ne s’applique pas vaut non_applicable et sort du dénominateur ; il ne compte jamais comme un échec. previous_score vaut null quand le relevé précédent a été produit par un autre barème.

    Scopes requis
    crawls:read
    Coût en débit
    5 unité(s)

    Paramètres

    • crawl path · string (uuid) · requis

    Réponses

    • 200 OK.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/eeat" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/eeat', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/eeat', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/eeat",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": {
            "crawl_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "status": "ready",
            "score": 42,
            "bareme_version": 42,
            "business_model": "string",
            "business_model_source": "string",
            "declared_sector": "string",
            "declared_fulfilment": [
                "string"
            ],
            "merchant_measured": true,
            "ships_refuted": true,
            "contradiction": "string",
            "pages_analyzed": 42,
            "truncated": true,
            "axes": [
                {
                    "key": "string",
                    "state": "string",
                    "points": 0.5,
                    "max": 42
                }
            ],
            "attribution": {},
            "trust_pages": {},
            "predicate_ranks": {},
            "citations": {},
            "previous_score": 42,
            "comparable_to_previous": true
        }
    }

    Lire le rapport de maillage interne

    GET /v1/crawls/{crawl}/structure

    Le maillage interne du crawl : profondeur, liens entrants, Link Scores (des rangs, pas des notes), pages orphelines, ancres et fuites. Hors score de santé. coverage dit si le JavaScript a été rendu et si des arêtes ont été tronquées : sans cela, un faible nombre de liens se lirait comme un défaut de maillage là où il n’y a qu’une limite de mesure.

    Scopes requis
    crawls:read
    Coût en débit
    10 unité(s)

    Paramètres

    • crawl path · string (uuid) · requis

    Réponses

    • 200 OK.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/structure" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/structure', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/structure', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/structure",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": {
            "crawl_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "status": "measured",
            "error_reason": "string",
            "pages_measured": 42,
            "coverage": {},
            "totals": {},
            "leaks": {},
            "anchors": {},
            "boilerplate": {},
            "pagerank": {},
            "classification": {},
            "depth": {},
            "inlinks": {},
            "score_depth": {},
            "score_spread": {},
            "top_authority": {},
            "top_content": {},
            "orphans": {},
            "deepest": {},
            "no_content_inlinks": {}
        }
    }

    Comparer à un crawl de référence

    GET /v1/crawls/{crawl}/compare

    Les écarts avec un crawl de référence du même projet : santé, pages, anomalies par gravité, codes HTTP, anomalies et pages apparues ou résolues. Sans baseline, le crawl comparable précédent sert de référence ; un crawl tronqué n’en est jamais une (crawl.no_baseline quand il n’y en a aucune).

    Scopes requis
    crawls:read
    Coût en débit
    10 unité(s)

    Paramètres

    • crawl path · string (uuid) · requis

    • baseline query · string (uuid) · facultatif

      The baseline crawl identifier.

    Réponses

    • 200 OK.
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 422 Invalid query or body values (`validation_failed`), with `errors` by field.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/compare" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('GET', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/compare', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/compare', {
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
      },
    });
    
    const data = await response.json();

    Python

    import os
    
    import requests
    
    response = requests.get(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/compare",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": {
            "crawl_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "baseline_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "summary": {},
            "status_codes": {},
            "issues": {},
            "pages": {}
        }
    }

    Lancer un crawl

    POST /v1/campaigns/{campaign}/crawls

    Met en file un crawl de la campagne et répond 202 avec le crawl à sonder (Location). Consomme un crawl du quota mensuel de l’offre, d’où l’Idempotency-Key exigée : une relance après un délai dépassé rend la première réponse au lieu de lancer un second crawl. Un seul crawl tourne à la fois par équipe (409 crawl.already_running, avec l’identifiant du crawl en cours).

    Scopes requis
    crawls:write
    Coût en débit
    1 unité(s)
    Idempotency-Key
    Idempotency-Key exigée
    Coût en débit
    Consomme un quota de l’offre

    Paramètres

    • campaign path · string (uuid) · requis

    Réponses

    • 202 OK.
    • 400 Malformed request, such as an invalid pagination cursor (`pagination.invalid_cursor`).
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 409 The request conflicts with the current state (a crawl already running, an idempotency key in use, a project not ready).
    • 422 Invalid query or body values (`validation_failed`), with `errors` by field.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl -X POST "https://api.nessflow.com/v1/campaigns/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/crawls" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN" \
      -H "Idempotency-Key: $(uuidgen)"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('POST', 'campaigns/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/crawls', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
            'Idempotency-Key' => bin2hex(random_bytes(16)),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/campaigns/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/crawls', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
        'Idempotency-Key': crypto.randomUUID(),
      },
    });
    
    const data = await response.json();

    Python

    import os
    import uuid
    
    import requests
    
    response = requests.post(
        "https://api.nessflow.com/v1/campaigns/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/crawls",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
            "Idempotency-Key": str(uuid.uuid4()),
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": {
            "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "campaign_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "status": "queued",
            "stage": "string",
            "active": true,
            "stage_plan": {
                "current_step": 42,
                "step_count": 42,
                "settled": true,
                "steps": [
                    {
                        "stage": "string",
                        "state": "pending",
                        "skip_reason": "string"
                    }
                ]
            },
            "pages": {
                "crawled": 42,
                "discovered": 42,
                "budget": 42
            },
            "issue_counts": {
                "error": 42,
                "warning": 42,
                "info": 42
            },
            "truncated": true,
            "blocked": true,
            "blocked_reason": "string",
            "comparable": true,
            "error": "string",
            "trigger": "manual",
            "started_at": "2026-10-01T09:30:00Z",
            "finished_at": "2026-10-01T09:30:00Z",
            "created_at": "2026-10-01T09:30:00Z"
        }
    }

    Arrêter un crawl

    POST /v1/crawls/{crawl}/stop

    Arrête un crawl en cours, de façon synchrone. Jamais refusé pour une raison de facturation.

    Scopes requis
    crawls:write
    Coût en débit
    1 unité(s)
    Idempotency-Key
    Idempotency-Key acceptée

    Paramètres

    • crawl path · string (uuid) · requis

    Réponses

    • 200 OK.
    • 400 Malformed request, such as an invalid pagination cursor (`pagination.invalid_cursor`).
    • 401 Missing, invalid or expired token, or a member who left the team.
    • 403 The plan does not include the API (`api.not_in_plan`) or this verb (`api.write_not_in_plan`), or the token lacks a scope (`token.missing_scope`).
    • 404 No such resource for the token's team. Resources of another team answer 404 as well, never 403.
    • 409 The request conflicts with the current state (a crawl already running, an idempotency key in use, a project not ready).
    • 422 Invalid query or body values (`validation_failed`), with `errors` by field.
    • 429 The plan rate limit is exhausted for one window.

    cURL

    curl -X POST "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/stop" \
      -H "Authorization: Bearer $NESSFLOW_TOKEN" \
      -H "Idempotency-Key: $(uuidgen)"

    PHP

    $client = new GuzzleHttp\Client(['base_uri' => 'https://api.nessflow.com/v1/']);
    
    $response = $client->request('POST', 'crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/stop', [
        'headers' => [
            'Authorization' => 'Bearer '.getenv('NESSFLOW_TOKEN'),
            'Idempotency-Key' => bin2hex(random_bytes(16)),
        ],
    ]);
    
    $data = json_decode((string) $response->getBody(), true);

    JavaScript

    const response = await fetch('https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/stop', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.NESSFLOW_TOKEN}`,
        'Idempotency-Key': crypto.randomUUID(),
      },
    });
    
    const data = await response.json();

    Python

    import os
    import uuid
    
    import requests
    
    response = requests.post(
        "https://api.nessflow.com/v1/crawls/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/stop",
        headers={
            "Authorization": f"Bearer {os.environ['NESSFLOW_TOKEN']}",
            "Idempotency-Key": str(uuid.uuid4()),
        },
        timeout=30,
    )
    response.raise_for_status()
    data = response.json()

    Exemple de réponse

    {
        "data": {
            "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "campaign_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "status": "queued",
            "stage": "string",
            "active": true,
            "stage_plan": {
                "current_step": 42,
                "step_count": 42,
                "settled": true,
                "steps": [
                    {
                        "stage": "string",
                        "state": "pending",
                        "skip_reason": "string"
                    }
                ]
            },
            "pages": {
                "crawled": 42,
                "discovered": 42,
                "budget": 42
            },
            "issue_counts": {
                "error": 42,
                "warning": 42,
                "info": 42
            },
            "truncated": true,
            "blocked": true,
            "blocked_reason": "string",
            "comparable": true,
            "error": "string",
            "trigger": "manual",
            "started_at": "2026-10-01T09:30:00Z",
            "finished_at": "2026-10-01T09:30:00Z",
            "created_at": "2026-10-01T09:30:00Z"
        }
    }

    Référence de l’API Codes d’erreur Documentation de l’API

    Cette page en Markdown