# Modules

Les modules hors score de santé (positions, Search Console, backlinks, sécurité, journaux). Ils portent une tendance, jamais une note.

## Lire le suivi de positions

`GET /v1/projects/{project}/positions`

Les mots-clés suivis et leur dernière position pour le domaine du projet, avec le résumé de la période. Un mot-clé à `measured: false` n’a jamais été relevé ; un mot-clé à `measured: true` et `position: null` a été relevé et se trouve hors du top 100. Exige une offre qui inclut le module.

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

### Paramètres

- `project` (path, string (uuid), requis)
- `period` (query, string, facultatif)

### 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.

### Exemple de requête (cURL)

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

### Exemple de réponse

```json
{
    "data": {
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "status": "unconfigured",
        "tracker": {
            "location": "string",
            "country": "string",
            "language": "string",
            "device": "string",
            "active": true,
            "last_tracked_on": "2026-10-01"
        },
        "period": {
            "preset": "string",
            "from": "2026-10-01",
            "to": "2026-10-01"
        },
        "summary": {
            "average_position": 0.5,
            "ranking_keywords": 42,
            "measured_keywords": 42,
            "tracked_keywords": 42,
            "top3": 42,
            "top10": 42,
            "visibility_percent": 0.5,
            "improved": 42,
            "declined": 42,
            "entered": 42,
            "exited": 42
        },
        "keywords": [
            {
                "keyword": "string",
                "active": true,
                "measured": true,
                "position": 42,
                "url": "https://exemple.fr/",
                "delta_1d": 42,
                "delta_7d": 42,
                "delta_30d": 42,
                "search_volume": 42,
                "keyword_difficulty": 42,
                "search_intent": "string",
                "serp_features": [
                    "string"
                ]
            }
        ],
        "quota": {
            "used": 42,
            "limit": 100,
            "remaining": 100
        }
    }
}
```

## Suivre des mots-clés

`POST /v1/projects/{project}/tracked-keywords`

Met des mots-clés sous suivi quotidien (100 au plus par requête). Un mot-clé s’identifie par sa forme canonique (minuscules, espaces simples), que la réponse rend. Un mot-clé déjà connu du projet comme candidat est adopté. Cela ouvre une dépense quotidienne récurrente : elle compte dans le pool de l’offre `positions.tracked_keywords` (`plan_limit.positions.tracked_keywords`) et dans le plafond par projet (`keywords.project_limit`), d’où l’`Idempotency-Key` exigée.

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

### Paramètres

- `project` (path, string (uuid), requis)

### Corps de la requête

- `keywords` (string[], 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.

### Exemple de requête (cURL)

```bash
curl -X POST "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"keywords":["string"]}'
```

### Exemple de réponse

```json
{
    "data": {
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "tracked": [
            "string"
        ],
        "already_tracked": [
            "string"
        ]
    }
}
```

## Arrêter le suivi de mots-clés

`POST /v1/projects/{project}/tracked-keywords/untrack`

Retire des mots-clés du suivi sans les supprimer : leur historique payé reste, et leurs emplacements sont libérés. Jamais refusé par la facturation. Les mots-clés inconnus ou non suivis sont ignorés ; `untracked` liste ceux qui ont changé.

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

### Paramètres

- `project` (path, string (uuid), requis)

### Corps de la requête

- `keywords` (string[], 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.

### Exemple de requête (cURL)

```bash
curl -X POST "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/untrack" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"keywords":["string"]}'
```

### Exemple de réponse

```json
{
    "data": {
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "untracked": [
            "string"
        ]
    }
}
```

## Suspendre des mots-clés suivis

`POST /v1/projects/{project}/tracked-keywords/pause`

Suspend le relevé quotidien de mots-clés suivis, ce qui libère leurs emplacements dans le pool de l’offre. `keywords.not_tracked` si l’un d’eux n’est pas suivi.

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

### Paramètres

- `project` (path, string (uuid), requis)

### Corps de la requête

- `keywords` (string[], 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.

### Exemple de requête (cURL)

```bash
curl -X POST "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/pause" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"keywords":["string"]}'
```

### Exemple de réponse

```json
{
    "data": {
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "active": true,
        "changed": [
            "string"
        ]
    }
}
```

## Reprendre des mots-clés suivis

`POST /v1/projects/{project}/tracked-keywords/resume`

Reprend le relevé quotidien de mots-clés suspendus. Reprendre reprend un emplacement dans le pool de l’offre (`plan_limit.positions.tracked_keywords`), d’où l’`Idempotency-Key` exigée.

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

### Paramètres

- `project` (path, string (uuid), requis)

### Corps de la requête

- `keywords` (string[], 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.

### Exemple de requête (cURL)

```bash
curl -X POST "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/resume" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"keywords":["string"]}'
```

### Exemple de réponse

```json
{
    "data": {
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "active": true,
        "changed": [
            "string"
        ]
    }
}
```

## Vérifier un mot-clé maintenant

`POST /v1/projects/{project}/tracked-keywords/check`

Met en file un relevé immédiat d’un mot-clé suivi (`202`) ; la position apparaît dans le suivi de positions une fois mesurée. Une vérification immédiate par mot-clé et par jour (`keywords.already_checked_today`), dans le quota journalier de l’offre (`plan_limit.positions.live_checks_per_day`) et le plafond de dépense mensuel.

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

### Paramètres

- `project` (path, string (uuid), requis)

### Corps de la requête

- `keyword` (string, 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.

### Exemple de requête (cURL)

```bash
curl -X POST "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57/tracked-keywords/check" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"keyword":"string"}'
```

### Exemple de réponse

```json
{
    "data": {
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "keyword": "string",
        "status": "queued",
        "date": "2026-10-01"
    }
}
```

## Lire les données Search Console

`GET /v1/projects/{project}/search-console`

Les totaux de performance et la série quotidienne (de la propriété reliée), et les totaux d’inspection d’indexation. `unconfigured` signifie qu’aucune propriété n’est reliée, `pending` qu’elle l’est mais pas encore synchronisée.

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

### Paramètres

- `project` (path, string (uuid), requis)
- `period` (query, string, facultatif)

### 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.

### Exemple de requête (cURL)

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

### Exemple de réponse

```json
{
    "data": {
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "status": "unconfigured",
        "property": "string",
        "performance": {
            "period": {
                "preset": "string",
                "from": "2026-10-01",
                "to": "2026-10-01"
            },
            "totals": {
                "clicks": 42,
                "impressions": 42,
                "ctr_percent": 0.5,
                "average_position": 0.5
            },
            "daily": [
                {
                    "date": "2026-10-01",
                    "clicks": 42,
                    "impressions": 42,
                    "average_position": 0.5
                }
            ]
        },
        "indexation": {
            "inspected": 42,
            "indexed": 42,
            "excluded": 42,
            "canonical_conflicts": 42,
            "last_inspected_at": "2026-10-01T09:30:00Z"
        }
    }
}
```

## Lire le résumé du profil de liens

`GET /v1/projects/{project}/backlinks`

Le dernier relevé quotidien de la cible courante. Les compteurs quotidiens de liens gagnés et perdus se recouvrent et ne s’additionnent pas.

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

### Paramètres

- `project` (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.
- `422`: Invalid query or body values (`validation_failed`), with `errors` by field.
- `429`: The plan rate limit is exhausted for one window.

### Exemple de requête (cURL)

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

### Exemple de réponse

```json
{
    "data": {
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "status": "unconfigured",
        "target": "string",
        "latest": {
            "date": "2026-10-01",
            "rank": 42,
            "backlinks": 42,
            "referring_domains": 42,
            "referring_main_domains": 42,
            "referring_pages": 42,
            "broken_backlinks": 42,
            "broken_pages": 42,
            "spam_score": 42,
            "new_backlinks": 42,
            "lost_backlinks": 42,
            "new_referring_domains": 42,
            "lost_referring_domains": 42
        }
    }
}
```

## Lire les signaux de sécurité

`GET /v1/projects/{project}/security`

Les signaux de sécurité passifs du site du projet, avec leur statut. Un passage incomplet (`scan.complete: false`) ne veut pas dire que rien n’a été trouvé ; `score: null` signifie inconnu, jamais zéro. Les textes suivent `Accept-Language`.

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

### Paramètres

- `project` (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.
- `422`: Invalid query or body values (`validation_failed`), with `errors` by field.
- `429`: The plan rate limit is exhausted for one window.

### Exemple de requête (cURL)

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

### Exemple de réponse

```json
{
    "data": {
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "status": "string",
        "target": "string",
        "scan": {
            "status": "string",
            "running": true,
            "complete": true,
            "results_truncated": true,
            "started_at": "2026-10-01T09:30:00Z",
            "finished_at": "2026-10-01T09:30:00Z"
        },
        "score": 42,
        "counts": {
            "problems": 42,
            "informational": 42,
            "fixed": 42,
            "masked": 42,
            "ignored": 42,
            "falsePositive": 42
        },
        "findings": [
            {
                "key": "string",
                "severity": "critical",
                "status": "string",
                "location": "string",
                "title": "string",
                "explanation": "string",
                "action": "string",
                "first_seen_at": "2026-10-01T09:30:00Z",
                "last_seen_at": "2026-10-01T09:30:00Z",
                "fixed_at": "2026-10-01T09:30:00Z"
            }
        ]
    }
}
```

## Lire l’analyse des journaux serveur

`GET /v1/projects/{project}/logs`

Les requêtes par audience (humains, robots de recherche, robots IA, autres) sur la période, avec les jours réellement couverts par des journaux.

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

### Paramètres

- `project` (path, string (uuid), requis)
- `period` (query, string, facultatif)

### 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.

### Exemple de requête (cURL)

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

### Exemple de réponse

```json
{
    "data": {
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "status": "pending",
        "period": {
            "preset": "string",
            "from": "2026-10-01",
            "to": "2026-10-01",
            "days": 42,
            "days_with_logs": 42
        },
        "totals": {
            "hits": 42,
            "bot_hits": 42,
            "human_hits": 42,
            "bytes": 42
        },
        "daily": [
            {
                "date": "2026-10-01",
                "humans": 42,
                "search": 42,
                "ai": 42,
                "others": 42
            }
        ],
        "gaps": [
            {
                "from": "2026-10-01",
                "to": "2026-10-01",
                "days": 42
            }
        ]
    }
}
```
