I want my answers in a spreadsheet. One request gives me a CSV file. The dashboard has a CSV button too.
One line
You need your API key and form id. See the quickstart.
export AIFORMAPI_KEY="afk_your_key_here"
curl -sS "https://aiformapi.com/v1/forms/FORM_ID/responses?format=csv" \
-H "Authorization: Bearer $AIFORMAPI_KEY" \
-o responses.csvSwap FORM_ID for your form's id.
JavaScript
Needs Node 18 or newer.
import { writeFile } from "node:fs/promises";
const key = process.env.AIFORMAPI_KEY;
const formId = process.env.AIFORMAPI_FORM_ID;
const res = await fetch(
`https://aiformapi.com/v1/forms/${formId}/responses?format=csv`,
{ headers: { Authorization: `Bearer ${key}` } }
);
if (!res.ok) {
const body = await res.json();
throw new Error(`${res.status} ${body.error.code}: ${body.error.message}`);
}
await writeFile("responses.csv", await res.text());
console.log("Saved responses.csv");Python
import os
import requests
key = os.environ["AIFORMAPI_KEY"]
form_id = os.environ["AIFORMAPI_FORM_ID"]
res = requests.get(
f"https://aiformapi.com/v1/forms/{form_id}/responses",
params={"format": "csv"},
headers={"Authorization": f"Bearer {key}"},
timeout=30,
)
if not res.ok:
error = res.json()["error"]
raise SystemExit(f"{res.status_code} {error['code']}: {error['message']}")
with open("responses.csv", "wb") as f:
f.write(res.content)
print("Saved responses.csv")Errors come back as JSON: {"error": {"code", "message"}}. See errors.
Only new answers
Add since with a UTC ISO 8601 time. Save the time of each pull. Use it on the next one.
curl -sS "https://aiformapi.com/v1/forms/FORM_ID/responses?format=csv&since=2026-10-01T00:00:00Z" \
-H "Authorization: Bearer $AIFORMAPI_KEY" \
-o october.csvMany rows
limit sets rows per call. A CSV holds up to 10,000 rows. Use cursor to go on. See the responses guide.
What is in the file
| Column | What it holds |
|---|---|
| One per field id | The answer. The header is the field id |
response_id | The id of the stored response |
source | human, paste, agent_api or agent_mcp. See agent-fillable forms |
submitted_at | When it was stored |
full_name,attending,guests,response_id,source,submitted_at
Ada Lovelace,Yes,1,RESPONSE_ID_1,human,2026-10-30T09:14:02Z
Grace Hopper,Maybe,0,RESPONSE_ID_2,paste,2026-10-30T09:20:41ZOpen the file
Excel. File, Open, then pick Text Files. Or Data, From Text/CSV, then Load. See form to Excel.
Google Sheets. File, Import, pick the file. See form to Google Sheets.
Numbers. Drag the file onto the Numbers icon.
Careful with strangers' answers. A cell can start with =, +, - or @. A spreadsheet may read it as a formula. Our CSV puts an apostrophe in front, so it stays text.
Browser links and IMPORTDATA fail
A browser bar and IMPORTDATA(url) cannot send the Authorization header. They get 401 unauthorized. Never put your key in a link. For a sheet that fills itself, use the Apps Script on form to Google Sheets.
Limits
Free plan: 30 requests a minute, 1,000 a day per key. See rate limits. Want a push? Add a webhook. More: forms API.
Sources, read 2026-10-30: Microsoft, Google Sheets, IMPORTDATA, Apple.
Questions
How do I export form responses to CSV?
GET /v1/forms/{id}/responses with format=csv and your API key in the Authorization header. Save the body as a .csv file. The dashboard has a CSV button too.
Can I get only the new responses?
Yes. Add since with a UTC ISO 8601 time. You get the responses after that time. Save the time of each pull and use it next time.
Why does my browser link or IMPORTDATA formula fail?
The API reads your key from the Authorization header. A browser bar and IMPORTDATA send only a URL, so you get 401 unauthorized. Use curl, a script or the dashboard.