Skip to main content

API Reference

Complete documentation for all FormLeap API endpoints with request and response examples.

Base URL

https://formleap.app/api/v1

All endpoints are relative to this base URL. See API Overview for authentication and error handling.


Forms

List Forms

Get all forms in your workspace.

GET /forms

Query Parameters:

Parameter Type Default Description
page integer 1 Page number
per_page integer 20 Items per page (max: 100)
status string - Filter by status: draft, published, archived

Example Request:

curl "https://formleap.app/api/v1/forms?page=1&per_page=20&status=published" \
  -H "Authorization: Bearer YOUR_API_KEY"
const response = await fetch('https://formleap.app/api/v1/forms?status=published', {
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

const data = await response.json();
console.log(data.data); // Array of forms

Example Response:

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "workspace_id": "660e8400-e29b-41d4-a716-446655440000",
      "name": "Contact Form",
      "description": "Website contact form",
      "status": "published",
      "submission_count": 42,
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-20T14:22:00Z",
      "published_at": "2025-01-15T11:00:00Z"
    },
    {
      "id": "770e8400-e29b-41d4-a716-446655440000",
      "workspace_id": "660e8400-e29b-41d4-a716-446655440000",
      "name": "Customer Feedback",
      "description": "Post-purchase feedback survey",
      "status": "published",
      "submission_count": 128,
      "created_at": "2025-01-10T09:15:00Z",
      "updated_at": "2025-01-18T16:45:00Z",
      "published_at": "2025-01-10T10:00:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total_count": 2,
    "total_pages": 1
  }
}

Get Form

Retrieve a single form with its complete structure.

GET /forms/:id

Path Parameters:

Parameter Type Description
id UUID Form ID

Example Request:

curl "https://formleap.app/api/v1/forms/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer YOUR_API_KEY"
const formId = '550e8400-e29b-41d4-a716-446655440000';
const response = await fetch(`https://formleap.app/api/v1/forms/${formId}`, {
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

const form = await response.json();
console.log(form.structure); // AST structure

Example Response:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "workspace_id": "660e8400-e29b-41d4-a716-446655440000",
  "name": "Contact Form",
  "description": "Website contact form",
  "status": "published",
  "structure": {
    "type": "form",
    "attrs": {
      "name": "Contact Form"
    },
    "children": [
      {
        "type": "step",
        "attrs": {
          "title": "Your Information"
        },
        "children": [
          {
            "type": "text",
            "attrs": {
              "id": "name",
              "label": "Full Name",
              "required": true
            },
            "children": []
          },
          {
            "type": "email",
            "attrs": {
              "id": "email",
              "label": "Email Address",
              "required": true
            },
            "children": []
          },
          {
            "type": "textarea",
            "attrs": {
              "id": "message",
              "label": "Message",
              "required": true
            },
            "children": []
          }
        ]
      }
    ]
  },
  "settings": {
    "access": "public",
    "confirmation_message": "Thank you for your message!",
    "notification_email": "team@example.com"
  },
  "submission_count": 42,
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-20T14:22:00Z",
  "published_at": "2025-01-15T11:00:00Z"
}

Create Form

Create a new form from an AST structure.

POST /forms

Request Body:

Field Type Required Description
structure object Yes Form AST structure
publish boolean No Publish immediately (default: false)

Example Request:

curl -X POST "https://formleap.app/api/v1/forms" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "structure": {
      "type": "form",
      "attrs": {
        "name": "Newsletter Signup",
        "description": "Subscribe to our newsletter"
      },
      "children": [
        {
          "type": "step",
          "attrs": {
            "title": "Subscribe"
          },
          "children": [
            {
              "type": "email",
              "attrs": {
                "id": "email",
                "label": "Email Address",
                "required": true
              },
              "children": []
            },
            {
              "type": "yes_no",
              "attrs": {
                "id": "consent",
                "label": "I agree to receive emails",
                "required": true
              },
              "children": []
            }
          ]
        }
      ]
    },
    "publish": true
  }'
const newForm = {
  structure: {
    type: 'form',
    attrs: {
      name: 'Newsletter Signup',
      description: 'Subscribe to our newsletter'
    },
    children: [
      {
        type: 'step',
        attrs: { title: 'Subscribe' },
        children: [
          {
            type: 'email',
            attrs: {
              id: 'email',
              label: 'Email Address',
              required: true
            },
            children: []
          },
          {
            type: 'yes_no',
            attrs: {
              id: 'consent',
              label: 'I agree to receive emails',
              required: true
            },
            children: []
          }
        ]
      }
    ]
  },
  publish: true
};

const response = await fetch('https://formleap.app/api/v1/forms', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(newForm)
});

const form = await response.json();
console.log('Form created:', form.id);
console.log('Public URL:', form.public_url);

Example Response:

{
  "id": "880e8400-e29b-41d4-a716-446655440000",
  "workspace_id": "660e8400-e29b-41d4-a716-446655440000",
  "name": "Newsletter Signup",
  "description": "Subscribe to our newsletter",
  "status": "published",
  "structure": { ... },
  "public_url": "https://formleap.app/f/880e8400-e29b-41d4-a716-446655440000",
  "builder_url": "https://formleap.app/forms/880e8400-e29b-41d4-a716-446655440000",
  "created_at": "2025-01-21T10:00:00Z",
  "updated_at": "2025-01-21T10:00:00Z",
  "published_at": "2025-01-21T10:00:00Z"
}

Validation Errors:

If the AST structure is invalid, you'll receive a 422 Unprocessable Entity response:

{
  "error": "validation_error",
  "message": "Form structure validation failed",
  "errors": [
    {
      "message": "Missing required attribute: label",
      "path": [0, 1]
    },
    {
      "message": "Element IDs must be unique",
      "path": [0, 2]
    }
  ]
}

Update Form

Update an existing form's structure.

PUT /forms/:id

Path Parameters:

Parameter Type Description
id UUID Form ID

Request Body:

Field Type Required Description
structure object Yes Updated form AST structure

Example Request:

curl -X PUT "https://formleap.app/api/v1/forms/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "structure": {
      "type": "form",
      "attrs": {
        "name": "Updated Contact Form"
      },
      "children": [ ... ]
    }
  }'
const formId = '550e8400-e29b-41d4-a716-446655440000';
const updatedStructure = {
  structure: {
    type: 'form',
    attrs: { name: 'Updated Contact Form' },
    children: [ /* updated fields */ ]
  }
};

const response = await fetch(`https://formleap.app/api/v1/forms/${formId}`, {
  method: 'PUT',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(updatedStructure)
});

const updatedForm = await response.json();

Example Response:

Same as Get Form response with updated data.


Delete Form

Delete a form permanently.

DELETE /forms/:id

Path Parameters:

Parameter Type Description
id UUID Form ID

Example Request:

curl -X DELETE "https://formleap.app/api/v1/forms/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer YOUR_API_KEY"
const formId = '550e8400-e29b-41d4-a716-446655440000';

const response = await fetch(`https://formleap.app/api/v1/forms/${formId}`, {
  method: 'DELETE',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

if (response.status === 204) {
  console.log('Form deleted successfully');
}

Example Response:

204 No Content

Note: Deleting a form also deletes all associated submissions. This action cannot be undone.


Submissions

List Submissions

Get all submissions for a specific form.

GET /forms/:form_id/submissions

Path Parameters:

Parameter Type Description
form_id UUID Form ID

Query Parameters:

Parameter Type Default Description
page integer 1 Page number
per_page integer 20 Items per page (max: 100)
status string - Filter by status: completed, incomplete

Example Request:

curl "https://formleap.app/api/v1/forms/550e8400-e29b-41d4-a716-446655440000/submissions?status=completed" \
  -H "Authorization: Bearer YOUR_API_KEY"
const formId = '550e8400-e29b-41d4-a716-446655440000';
const response = await fetch(
  `https://formleap.app/api/v1/forms/${formId}/submissions?status=completed`,
  {
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    }
  }
);

const data = await response.json();
console.log(`${data.pagination.total_count} submissions`);

Example Response:

{
  "data": [
    {
      "id": "990e8400-e29b-41d4-a716-446655440000",
      "form_id": "550e8400-e29b-41d4-a716-446655440000",
      "status": "completed",
      "answers": {
        "name": "John Doe",
        "email": "john@example.com",
        "message": "I love your product!"
      },
      "metadata": {
        "fields": {
          "name": {
            "label": "Full Name",
            "type": "text",
            "required": true
          },
          "email": {
            "label": "Email Address",
            "type": "email",
            "required": true
          },
          "message": {
            "label": "Message",
            "type": "textarea",
            "required": true
          }
        },
        "form_name": "Contact Form",
        "reference": {
          "source": "website",
          "page": "/contact"
        }
      },
      "completed_at": "2025-01-20T14:30:00Z",
      "created_at": "2025-01-20T14:28:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total_count": 42,
    "total_pages": 3
  }
}

Get Submission

Retrieve a single submission with full details.

GET /submissions/:id

Path Parameters:

Parameter Type Description
id UUID Submission ID

Example Request:

curl "https://formleap.app/api/v1/submissions/990e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer YOUR_API_KEY"
const submissionId = '990e8400-e29b-41d4-a716-446655440000';
const response = await fetch(`https://formleap.app/api/v1/submissions/${submissionId}`, {
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY'
  }
});

const submission = await response.json();
console.log(submission.answers);

Example Response:

Same structure as individual submission in List Submissions.


Search Submissions

Search submissions across all forms using full-text search.

GET /submissions/search

Query Parameters:

Parameter Type Required Description
q string Yes Search query
form_id UUID No Limit to specific form
page integer No Page number (default: 1)
per_page integer No Items per page (default: 20)

Example Request:

curl "https://formleap.app/api/v1/submissions/search?q=urgent&form_id=550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer YOUR_API_KEY"
const searchQuery = 'urgent customer';
const formId = '550e8400-e29b-41d4-a716-446655440000';

const response = await fetch(
  `https://formleap.app/api/v1/submissions/search?q=${encodeURIComponent(searchQuery)}&form_id=${formId}`,
  {
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    }
  }
);

const results = await response.json();
console.log(`Found ${results.data.length} matching submissions`);

Example Response:

Same structure as List Submissions, but results are ranked by relevance.

Search Features:

  • Weighted Results - Subject field matches rank highest
  • Stemming - "running" matches "run"
  • Multiple Terms - All terms must be present

AST Structure Reference

Forms are represented as Abstract Syntax Trees (AST) using nested tuples. The API accepts and returns this structure as JSON.

Form Node

{
  "type": "form",
  "attrs": {
    "name": "Form Name",
    "description": "Optional description"
  },
  "children": [ /* step nodes */ ]
}

Step Node

{
  "type": "step",
  "attrs": {
    "title": "Step Title",
    "description": "Optional step description",
    "layout": "stack"
  },
  "children": [ /* element nodes */ ]
}

Input Element Node

{
  "type": "text",
  "attrs": {
    "id": "unique_id",
    "label": "Field Label",
    "placeholder": "Optional placeholder",
    "help_text": "Optional help text",
    "required": true,
    "col_span": 1
  },
  "children": []
}

Supported Element Types

Input Types:

  • text - Single-line text
  • textarea - Multi-line text
  • email - Email address
  • phone - Phone number
  • url - Website URL
  • number - Numeric input
  • date - Date picker
  • time - Time picker
  • datetime - Date and time
  • dropdown - Single select
  • radio - Radio buttons
  • multiple_choice - Checkboxes
  • yes_no - Boolean toggle
  • file_upload - File upload

Content Types:

  • heading - Section heading
  • paragraph - Text content
  • divider - Visual separator

Composite Type:

  • composite - Grouped fields (can contain children)

Selection Elements

For dropdown, radio, and multiple_choice, include options:

{
  "type": "dropdown",
  "attrs": {
    "id": "country",
    "label": "Country",
    "required": true,
    "options": ["United States", "Canada", "United Kingdom"]
  },
  "children": []
}

Composite Elements

Composite elements group related fields:

{
  "type": "composite",
  "attrs": {
    "id": "address",
    "label": "Mailing Address",
    "layout": "grid_2",
    "repeatable": false
  },
  "children": [
    {
      "type": "text",
      "attrs": { "id": "street", "label": "Street", "col_span": 2 },
      "children": []
    },
    {
      "type": "text",
      "attrs": { "id": "city", "label": "City" },
      "children": []
    },
    {
      "type": "text",
      "attrs": { "id": "postal", "label": "Postal Code" },
      "children": []
    }
  ]
}

Composite Layouts:

  • stack - Vertical (default)
  • row - Horizontal
  • grid_2 - 2-column grid
  • grid_3 - 3-column grid
  • grid_4 - 4-column grid

Rate Limiting

See API Overview for rate limit details.

All responses include rate limit headers:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 285
X-RateLimit-Reset: 1642694400

Error Responses

See API Overview for complete error handling documentation.

Common Errors:

Status Error Code Description
400 bad_request Invalid request format
401 unauthorized Invalid API key
404 not_found Resource doesn't exist
422 validation_error Data validation failed
429 rate_limit_exceeded Too many requests

Next Steps


Questions? Contact support@formleap.app