Skip to main content
All authenticated endpoints require Authorization: Bearer <api_key>.

List forms

GET /api/v2/form/
Returns a paginated list of all forms owned by the authenticated user. Response
{
  "count": 3,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "uuid",
      "title": "Customer feedback",
      "slug": "a1b2c3d4e5f6",
      "is_active": true,
      "has_published_version": true,
      "is_accepting_responses": true,
      "created": "2026-01-15T08:00:00Z",
      "modified": "2026-03-15T14:30:00Z"
    }
  ]
}

Create a form

POST /api/v2/form/
Request body
{
  "title": "Product survey"
}
A slug is auto-generated. Returns the created form object.

Get a form

GET /api/v2/form/{slug}/
Returns full form details including theme and response count. Response
{
  "id": "uuid",
  "title": "Product survey",
  "slug": "a1b2c3d4e5f6",
  "theme": { "id": "uuid", "name": "Default", ... },
  "published_version": 3,
  "is_active": true,
  "is_accepting_responses": true,
  "response_limit": null,
  "total_sessions": 142,
  "created": "2026-01-15T08:00:00Z",
  "modified": "2026-03-15T14:30:00Z"
}

Update a form

PATCH /api/v2/form/{slug}/
Updates form metadata. Accepts any subset of writable fields. Request body
{
  "title": "Updated title",
  "is_accepting_responses": false,
  "response_limit": 500
}

Delete a form

DELETE /api/v2/form/{slug}/
Soft-deletes the form (sets is_active = false). Returns 204 No Content.

Save a draft

PUT /api/v2/form/{slug}/draft/
Overwrites the form’s current draft with a new graph. Only one draft exists per form at any time. Request body
{
  "title": "Customer feedback",
  "graph": {
    "schema_version": "2.0",
    "entry_node_id": "node_welcome",
    "fallback_end_node_id": "node_end",
    "nodes": [
      {
        "id": "node_welcome",
        "question_type": "welcome_screen",
        "data": {
          "title": "Welcome!",
          "description": "This takes 2 minutes.",
          "is_required": false,
          "config": {}
        }
      },
      {
        "id": "node_q1",
        "question_type": "short_text",
        "data": {
          "title": "What is your name?",
          "is_required": true,
          "config": { "max_length": 100 }
        }
      },
      {
        "id": "node_end",
        "question_type": "end_screen",
        "data": {
          "title": "Thank you!",
          "is_required": false,
          "config": {}
        }
      }
    ],
    "edges": [
      { "from": "node_welcome", "to": "node_q1", "condition": null },
      { "from": "node_q1", "to": "node_end", "condition": null }
    ]
  }
}
Response
{
  "graph": { ... },
  "last_saved_at": "2026-03-17T10:05:30Z"
}

Publish a form

POST /api/v2/form/{slug}/publish/
Validates the current draft and creates an immutable FormVersion. Returns the new version number. Response
{
  "version_number": 4,
  "published_at": "2026-03-17T10:10:00Z"
}
Returns 400 if the draft fails validation (e.g. disconnected nodes, missing entry node).

List versions

GET /api/v2/form/{slug}/versions/
Response
{
  "count": 4,
  "results": [
    {
      "id": "uuid",
      "version_number": 4,
      "status": "published",
      "is_valid": true,
      "published_at": "2026-03-17T10:10:00Z",
      "node_count": 8,
      "edge_count": 7,
      "is_current": true
    }
  ]
}

Get a version

GET /api/v2/form/{slug}/versions/{version_number}/
Returns the immutable graph snapshot for a specific published version. Published versions are never modified.

Next steps

Sessions

Read respondent sessions and their traversal paths.

Responses

Read individual question answers.