# Projets

Les projets (sites suivis dans le temps) et leur bilan de santé.

## Lister les projets

`GET /v1/projects`

Tous les projets de l’équipe du jeton, du plus récent au plus ancien.

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

### Paramètres

- `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" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN"
```

### Exemple de réponse

```json
{
    "data": [
        {
            "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "name": "Exemple",
            "slug": "string",
            "url": "https://exemple.fr/",
            "domain": "string",
            "locked": true,
            "created_at": "2026-10-01T09:30:00Z",
            "latest_completed_crawl": {
                "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
                "finished_at": "string"
            }
        }
    ],
    "meta": {
        "limit": 100,
        "has_more": true,
        "next_cursor": "string"
    }
}
```

## Créer un projet

`POST /v1/projects`

Crée un projet et sa campagne par défaut, aux mêmes règles que le produit : l’URL doit désigner un site public, et le plafond de projets de l’offre s’applique.

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

### Corps de la requête

- `url` (string, requis): Public site URL.
- `name` (string | null, facultatif): Defaults to the host name.

### 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" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"url":"https://exemple.fr/","name":"Exemple"}'
```

### Exemple de réponse

```json
{
    "data": {
        "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "name": "Exemple",
        "slug": "string",
        "url": "https://exemple.fr/",
        "domain": "string",
        "locked": true,
        "created_at": "2026-10-01T09:30:00Z",
        "latest_completed_crawl": {
            "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "finished_at": "string"
        }
    }
}
```

## Lire un projet

`GET /v1/projects/{project}`

Un projet et son dernier crawl terminé.

- Scopes requis: `projects: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.
- `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" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN"
```

### Exemple de réponse

```json
{
    "data": {
        "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "name": "Exemple",
        "slug": "string",
        "url": "https://exemple.fr/",
        "domain": "string",
        "locked": true,
        "created_at": "2026-10-01T09:30:00Z",
        "latest_completed_crawl": {
            "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "finished_at": "string"
        }
    }
}
```

## Modifier un projet

`PATCH /v1/projects/{project}`

Change le nom ou l’URL. Changer l’URL efface ce qui décrivait le site précédent (profil, URL prioritaires). Un projet en lecture seule répond `403 project.locked`.

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

### Paramètres

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

### Corps de la requête

- `name` (string, facultatif)
- `url` (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 -X PATCH "https://api.nessflow.com/v1/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Exemple","url":"https://exemple.fr/"}'
```

### Exemple de réponse

```json
{
    "data": {
        "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "name": "Exemple",
        "slug": "string",
        "url": "https://exemple.fr/",
        "domain": "string",
        "locked": true,
        "created_at": "2026-10-01T09:30:00Z",
        "latest_completed_crawl": {
            "id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
            "finished_at": "string"
        }
    }
}
```

## Supprimer un projet

`DELETE /v1/projects/{project}`

Supprime le projet et tout ce qu’il porte, définitivement. Permis sur un projet en lecture seule.

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

### Paramètres

- `project` (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/projects/0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN"
```

## Lire le bilan de santé

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

Les cinq piliers du score de santé (technique, contenu et GEO, accessibilité, acquisition Search Console, exploration des journaux), comme sur l’écran du projet. Il n’y a pas de moyenne globale, par conception : des piliers de natures différentes ne s’additionnent pas. Un pilier non mesurable a `score: null`, jamais `0`.

- Scopes requis: `projects: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.
- `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/scorecard" \
  -H "Authorization: Bearer $NESSFLOW_TOKEN"
```

### Exemple de réponse

```json
{
    "data": {
        "project_id": "0190f5a2-7c4e-7b1a-9d3e-2f6b8c1a4e57",
        "pillars": [
            {
                "key": "technique",
                "score": 42,
                "status": "good",
                "available": true,
                "version": 42,
                "as_of": "string",
                "blocked_reason": "string",
                "axes": [
                    {}
                ]
            }
        ]
    }
}
```
