# 送信データのエクスポート

> ダッシュボードから送信データを CSV でダウンロードするか、REST API ですべての送信データをエクスポートします。

## ダッシュボードから CSV

**Submissions** またはフォームの送信データタブを開き、必要なフィルターを設定して **Export CSV** を選びます。ファイルには画面のフィルターが反映されます。

| フィルター | 値 |
| --- | --- |
| フォーム | 1 つのフォーム、またはすべてのフォーム |
| ステータス | 受信済み、スパム、またはその両方 |
| 期間 | 過去 24 時間、過去 7 日間、過去 30 日間、全期間 |

- 列は `id`、`created_at`、`form`、`status` で、その後にフィールドごとの列が続きます。1 つのフォームの場合は定義済みのフィールドが先に来て、その後にエクスポートした行に含まれるその他のフィールド名が続きます。
- 単純な値の配列は、カンマとスペースで連結されます。オブジェクトは JSON として書き出されます。
- `=`、`+`、`-`、`@`、タブ、復帰文字で始まる値には先頭に `'` が付くので、表計算アプリが数式として実行することはありません。
- ファイルは BOM 付きの UTF-8 なので、Excel でもアクセント記号が正しく表示されます。
- 1 回のエクスポートは最大 100,000 行、500 個のフィールド列までです。大きなワークスペースではフィルターを絞り込むか、API を使ってください。

## REST API ですべてを

完全なバックアップ、定期的な同期、100,000 行を超えるデータには、`submissions:read` を持つシークレットキーで [REST API](https://ikiform.com/ja/docs/api.md#list-submissions) をページ送りしてください。一覧は新しい順で、新しい送信データが届いても順番は安定しています。

**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"]
```

> 各キーは 1 分あたり 100 リクエストまで送れます。`limit: 100` なら、1 分あたり最大 10,000 件の送信データになります。SDK のイテレーターは `429` のときに `retryAfter` 付きの `IkiformError` を投げます。その秒数だけ待ち、最後のカーソルから再開してください。
