All docs
4 min read

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

http
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:

json
{
  "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

http
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:

  • name required - 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 an id (fld_xxxxxxxx), normalizes type aliases (long_texttextarea, dropdownselect), 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

http
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

http
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

http
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

http
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