Surveys
Surveys are a separate product from forms - multi-screen, conditional logic, scoring, partial-response resume. Same token model: bearer auth, ability gates, team-scoped.
Base URL: https://formspring.io/api/v1
| Method | Path | Ability |
|---|---|---|
| GET | /surveys |
surveys:read |
| POST | /surveys |
surveys:write |
| GET | /surveys/{survey} |
surveys:read |
| PUT | PATCH | /surveys/{survey} |
surveys:write |
| DELETE | /surveys/{survey} |
surveys:write |
| POST | /surveys/{survey}/publish |
surveys:write |
| POST | /surveys/{survey}/unpublish |
surveys:write |
Surveys require a paid plan. Free-plan tokens get 402 Surveys require a paid plan on every mutating call.
The {survey} path parameter accepts the survey's public_id (preferred) or its slug.
List surveys
GET /surveys
Returns up to 100 surveys for the current team, sorted by updated_at desc. Soft-deleted and archived surveys are excluded.
Response 200:
{
"data": [
{
"id": "sv_8XfP2k",
"name": "Customer feedback",
"slug": "customer-feedback",
"public_url": "https://frmsp.io/s/customer-feedback",
"is_published": true,
"published_at": "2026-05-10T14:32:00+00:00",
"submissions_count": 142,
"updated_at": "2026-05-15T09:18:00+00:00"
}
]
}
Create a survey
POST /surveys
Content-Type: application/json
{
"name": "Customer feedback",
"slug": "customer-feedback",
"template": "nps",
"fields": [
{ "type": "email", "label": "Work email", "required": true },
{ "type": "textarea", "label": "What could be better?" }
]
}
Fields:
namerequired - survey name (1-120 chars).slug- URL slug. Auto-generated when omitted.template- key from the survey template registry (nps,csat,lead-qualification, …). Pre-fills fields/theme/settings.fields- explicit field schema. Overrides any template-supplied fields. The API stamps anid(fld_xxxxxxxx), normalizes type aliases (long_text→textarea,dropdown→select), and slugs missing names - so a bare LLM-shaped definition works.
A newly-created survey is draft unless its fields array is empty (an empty-shell survey auto-publishes for quick demos). Call /publish once content is ready.
Response 201: SurveyResource with is_published: false.
Show a survey
GET /surveys/{survey}
Includes the full field array, theme, settings, scoring config, and a submissions_count accessor. Encrypted columns (hcaptcha_secret, recaptcha_secret, akismet_key) are never returned; matching *_set booleans indicate whether a secret is configured.
Update a survey
PATCH /surveys/{survey}
Content-Type: application/json
{
"name": "Customer feedback (Q2)",
"fields": [
{ "type": "rating", "label": "Overall satisfaction", "required": true },
{ "type": "textarea", "label": "Anything else?" }
]
}
PUT and PATCH behave the same - every field is optional, omitted keys stay unchanged. Sending fields replaces the entire field array (and triggers a relational rebuild of survey_screens + survey_questions to keep them in lockstep).
Publish / unpublish
POST /surveys/{survey}/publish
POST /surveys/{survey}/unpublish
Publish sets published_at = now(). Unpublish sets published_at = null. While unpublished, the public /s/{slug} URL serves a 409 with a "not yet published" notice instead of accepting responses.
Delete a survey
DELETE /surveys/{survey}
Soft-deletes the survey AND clears published_at (defense-in-depth - any cached snapshot or MCP read tool sees "not live" immediately). The row stays recoverable from the dashboard's trash for the retention window; permanent purge happens through the admin panel.
Response 200: { "ok": true }
Errors
| Status | When | What to do |
|---|---|---|
| 402 | Team's plan doesn't include surveys | Upgrade in dashboard or use a different team |
| 403 | Token missing surveys:read/surveys:write |
Mint a token with the right ability |
| 404 | Survey doesn't belong to the calling team | Switch active team in the dashboard and mint a fresh token |
| 422 | Validation failure (e.g. unknown template, malformed field) | Check the response errors map |
See also
- Submissions → - surveys reuse the same submission model
- Tokens & abilities → - full ability catalogue
- MCP server → - the same operations available as agent tools