# Campagnes

Les configurations de crawl réutilisables et leur planification.

## Lister les campagnes d’un projet

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

Les configurations de crawl réutilisables et leur planification, de la plus récente à la plus ancienne.

- Scopes requis: `projects: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.

### Exemple de requête (cURL)

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

### Exemple de réponse

```json
{
    "data": [
        {
            "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "name": "Exemple",
            "start_url": "https://exemple.fr/",
            "max_depth": 42,
            "max_urls": 42,
            "javascript_rendering": true,
            "pagespeed": true,
            "check_external_links": true,
            "check_ai_reachability": true,
            "check_accessibility": true,
            "protected_site": true,
            "schedule": {
                "frequency": "manual",
                "day": "string",
                "time": "string",
                "paused": true,
                "next_run_at": "string"
            },
            "created_at": "2026-10-01T09:30:00Z"
        }
    ],
    "meta": {
        "limit": 100,
        "has_more": true,
        "next_cursor": "string"
    }
}
```

## Créer une campagne

`POST /v1/projects/{project}/campaigns`

Même validation et mêmes bornes d’offre que le produit (budget d’URL, rendu JavaScript, fréquences de planification). Un champ inconnu est refusé, jamais ignoré.

- Scopes requis: `projects: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

- `name` (string, requis)
- `start_url` (string, requis)
- `max_depth` (integer, requis)
- `max_urls` (integer, requis)
- `javascript_rendering` (boolean, facultatif)
- `pagespeed` (boolean, facultatif)
- `check_external_links` (boolean, facultatif)
- `check_ai_reachability` (boolean, facultatif)
- `check_accessibility` (boolean, facultatif)
- `check_accessibility_rendered` (boolean, facultatif)
- `include_patterns` (string | null, facultatif)
- `exclude_patterns` (string | null, facultatif)
- `issue_exclusion_patterns` (string | null, facultatif)
- `timeout` (integer | null, facultatif)
- `retries` (integer | null, facultatif)
- `duplication_threshold` (number | null, facultatif)
- `regression_threshold` (string, facultatif) [off, warning, error]
- `protected_site` (boolean, facultatif)
- `http_user` (string | null, facultatif)
- `http_password` (string | null, facultatif)
- `notify` (boolean, facultatif)
- `schedule` (object, facultatif)

### Réponses

- `201`: 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/campaigns" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"name":"Exemple","start_url":"https://exemple.fr/","max_depth":42,"max_urls":42,"javascript_rendering":true,"pagespeed":true,"check_external_links":true,"check_ai_reachability":true,"check_accessibility":true,"check_accessibility_rendered":true,"include_patterns":"string","exclude_patterns":"string","issue_exclusion_patterns":"string","timeout":42,"retries":42,"duplication_threshold":0.5,"regression_threshold":"off","protected_site":true,"http_user":"string","http_password":"string","notify":true,"schedule":{"frequency":"manual","day":"string","time":"string"}}'
```

### Exemple de réponse

```json
{
    "data": {
        "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "name": "Exemple",
        "start_url": "https://exemple.fr/",
        "max_depth": 42,
        "max_urls": 42,
        "javascript_rendering": true,
        "pagespeed": true,
        "check_external_links": true,
        "check_ai_reachability": true,
        "check_accessibility": true,
        "protected_site": true,
        "schedule": {
            "frequency": "manual",
            "day": "string",
            "time": "string",
            "paused": true,
            "next_run_at": "string"
        },
        "created_at": "2026-10-01T09:30:00Z"
    }
}
```

## Lire une campagne

`GET /v1/campaigns/{campaign}`

Une configuration de crawl et sa planification. Les identifiants HTTP ne sont jamais rendus.

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

### Paramètres

- `campaign` (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.

### Exemple de requête (cURL)

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

### Exemple de réponse

```json
{
    "data": {
        "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "name": "Exemple",
        "start_url": "https://exemple.fr/",
        "max_depth": 42,
        "max_urls": 42,
        "javascript_rendering": true,
        "pagespeed": true,
        "check_external_links": true,
        "check_ai_reachability": true,
        "check_accessibility": true,
        "protected_site": true,
        "schedule": {
            "frequency": "manual",
            "day": "string",
            "time": "string",
            "paused": true,
            "next_run_at": "string"
        },
        "created_at": "2026-10-01T09:30:00Z"
    }
}
```

## Modifier une campagne

`PATCH /v1/campaigns/{campaign}`

Mise à jour partielle : un champ absent garde sa valeur. Le mot de passe HTTP reste inchangé s’il est absent.

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

### Paramètres

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

### Corps de la requête

- `name` (string, facultatif)
- `start_url` (string, facultatif)
- `max_depth` (integer, facultatif)
- `max_urls` (integer, facultatif)
- `javascript_rendering` (boolean, facultatif)
- `pagespeed` (boolean, facultatif)
- `check_external_links` (boolean, facultatif)
- `check_ai_reachability` (boolean, facultatif)
- `check_accessibility` (boolean, facultatif)
- `check_accessibility_rendered` (boolean, facultatif)
- `include_patterns` (string | null, facultatif)
- `exclude_patterns` (string | null, facultatif)
- `issue_exclusion_patterns` (string | null, facultatif)
- `timeout` (integer | null, facultatif)
- `retries` (integer | null, facultatif)
- `duplication_threshold` (number | null, facultatif)
- `regression_threshold` (string, facultatif) [off, warning, error]
- `protected_site` (boolean, facultatif)
- `http_user` (string | null, facultatif)
- `http_password` (string | null, facultatif)
- `notify` (boolean, facultatif)
- `schedule` (object, 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 -X PATCH "https://api.nessflow.com/v1/campaigns/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Exemple","start_url":"https://exemple.fr/","max_depth":42,"max_urls":42,"javascript_rendering":true,"pagespeed":true,"check_external_links":true,"check_ai_reachability":true,"check_accessibility":true,"check_accessibility_rendered":true,"include_patterns":"string","exclude_patterns":"string","issue_exclusion_patterns":"string","timeout":42,"retries":42,"duplication_threshold":0.5,"regression_threshold":"off","protected_site":true,"http_user":"string","http_password":"string","notify":true,"schedule":{"frequency":"manual","day":"string","time":"string"}}'
```

### Exemple de réponse

```json
{
    "data": {
        "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "name": "Exemple",
        "start_url": "https://exemple.fr/",
        "max_depth": 42,
        "max_urls": 42,
        "javascript_rendering": true,
        "pagespeed": true,
        "check_external_links": true,
        "check_ai_reachability": true,
        "check_accessibility": true,
        "protected_site": true,
        "schedule": {
            "frequency": "manual",
            "day": "string",
            "time": "string",
            "paused": true,
            "next_run_at": "string"
        },
        "created_at": "2026-10-01T09:30:00Z"
    }
}
```

## Supprimer une campagne

`DELETE /v1/campaigns/{campaign}`

Supprime la campagne et ses crawls. Un crawl en cours de la campagne est d’abord arrêté.

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

### Paramètres

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

### Réponses

- `204`: Deleted.
- `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.

### Exemple de requête (cURL)

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