# Exporter les soumissions

> Téléchargez les soumissions en CSV depuis le tableau de bord, ou exportez-les toutes avec l'API REST.

## CSV depuis le tableau de bord

Ouvrez **Submissions**, ou l'onglet des soumissions d'un formulaire, réglez les filtres voulus et choisissez **Export CSV**. Le fichier suit les filtres affichés à l'écran.

| Filtre | Valeurs |
| --- | --- |
| Formulaire | Un formulaire, ou tous |
| Statut | Reçues, spam, ou les deux |
| Période | Dernières 24 heures, 7 derniers jours, 30 derniers jours, ou depuis le début |

- Les colonnes sont `id`, `created_at`, `form`, `status`, puis une colonne par champ. Pour un seul formulaire, ses champs définis viennent en premier, suivis des autres noms de champs trouvés dans les lignes exportées.
- Les tableaux de valeurs simples sont joints par une virgule et une espace. Les objets sont écrits en JSON.
- Les valeurs qui commencent par `=`, `+`, `-`, `@`, une tabulation ou un retour chariot reçoivent un `'` en tête, pour que les tableurs ne les exécutent pas comme des formules.
- Le fichier est en UTF-8 avec BOM, donc Excel affiche correctement les accents.
- Un export contient jusqu'à 100 000 lignes et 500 colonnes de champs. Affinez les filtres pour les espaces de travail plus volumineux, ou utilisez l'API.

## Tout avec l'API REST

Pour une sauvegarde complète, une synchronisation planifiée ou plus de 100 000 lignes, parcourez l'[API REST](https://ikiform.com/fr/docs/api.md#list-submissions) page par page avec une clé secrète qui a `submissions:read`. Les listes commencent par les plus récentes et restent stables pendant l'arrivée de nouvelles soumissions.

**Node** (`export.ts`)

```ts
import { createWriteStream } from "node:fs";
import { createClient } from "@ikiform/sdk";

const ikiform = createClient({ apiKey: process.env.IKIFORM_SECRET_KEY! });
const out = createWriteStream("submissions.jsonl");

for await (const submission of ikiform.submissions.iterate({
  formId: "frm_xxxxxxxxxxxxxxxx",
  status: "received",
  limit: 100,
})) {
  out.write(`${JSON.stringify(submission)}\n`);
}

out.end();
```

**Python** (`export.py`)

```python
import csv
import os

import requests

session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['IKIFORM_SECRET_KEY']}"
params = {"form_id": "frm_xxxxxxxxxxxxxxxx", "status": "received", "limit": 100}

with open("submissions.csv", "w", newline="", encoding="utf-8") as file:
    writer = None
    while True:
        page = session.get("https://ikiform.com/api/v1/submissions", params=params, timeout=30).json()
        for submission in page["data"]:
            row = {"id": submission["id"], "created_at": submission["created_at"], **submission["fields"]}
            if writer is None:
                writer = csv.DictWriter(file, fieldnames=list(row), extrasaction="ignore")
                writer.writeheader()
            writer.writerow(row)
        if not page["has_more"]:
            break
        params["cursor"] = page["next_cursor"]
```

> Chaque clé peut faire 100 requêtes par minute. Avec `limit: 100`, cela fait jusqu'à 10 000 soumissions par minute. L'itérateur du SDK lève une `IkiformError` avec `retryAfter` sur un `429` ; attendez ce nombre de secondes et reprenez depuis le dernier curseur.
