Skip to main content

API Overview

The FormLeap API allows you to programmatically create forms, manage submissions, and integrate FormLeap with your applications.

Introduction

The FormLeap API is a RESTful API that uses JSON for request and response payloads. It provides access to all core FormLeap functionality:

  • Forms - Create, read, update, and delete form templates
  • Submissions - List, retrieve, and search form submissions
  • Invitations - Manage email invitations for specific forms (optional feature)

Base URL

https://formleap.app/api/v1

All API endpoints are relative to this base URL.

API Version

Current version: v1

The API version is included in the URL path (/api/v1/). Future versions will be introduced as needed while maintaining backward compatibility where possible.


Authentication

API Keys

The FormLeap API uses API keys for authentication. API keys are workspace-scoped, meaning each key has access only to forms and submissions within a specific workspace.

Creating an API Key

  1. Log in to FormLeap
  2. Navigate to Workspace Settings
  3. Scroll to API Keys
  4. Click Generate API Key
  5. Give it a descriptive name (e.g., "Production Integration")
  6. Copy the key immediately (it's only shown once)
  7. Store it securely

Security: API keys grant full access to your workspace data. Never commit them to version control or share them publicly.

Using API Keys

Include your API key in the Authorization header using the Bearer scheme:

Authorization: Bearer fl_your_api_key_here

Example with cURL:

curl https://formleap.app/api/v1/forms \
  -H "Authorization: Bearer fl_your_api_key_here"

Example with

const response = await fetch('https://formleap.app/api/v1/forms', {
  headers: {
    'Authorization': 'Bearer fl_your_api_key_here',
    'Content-Type': 'application/json'
  }
});

Example with Python:

import requests

headers = {
    'Authorization': 'Bearer fl_your_api_key_here',
    'Content-Type': 'application/json'
}

response = requests.get(
    'https://formleap.app/api/v1/forms',
    headers=headers
)

Workspace Scoping

API keys are tied to a specific workspace. All API requests operate within that workspace's context:

  • You can only access forms belonging to that workspace
  • Created forms are added to that workspace
  • Submissions are scoped to that workspace's forms

To access multiple workspaces, generate separate API keys for each.


Rate Limits

To ensure fair usage and system stability, the API enforces rate limits.

Current Limits

Tier Requests per Minute Burst
Free 60 10
Pro 300 30
Business 1000 100
Enterprise Custom Custom

Burst: Short bursts above the per-minute rate are allowed up to the burst limit.

Rate Limit Headers

Every API response includes rate limit information in the headers:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 285
X-RateLimit-Reset: 1642694400
  • X-RateLimit-Limit - Maximum requests per minute
  • X-RateLimit-Remaining - Requests remaining in current window
  • X-RateLimit-Reset - Unix timestamp when the limit resets

Handling Rate Limits

If you exceed the rate limit, you'll receive a 429 Too Many Requests response:

{
  "error": "rate_limit_exceeded",
  "message": "Too many requests. Please try again in 30 seconds.",
  "retry_after": 30
}

Best Practices:

  1. Monitor headers - Check X-RateLimit-Remaining before making requests
  2. Implement backoff - Wait when approaching limits
  3. Use webhooks - For real-time events instead of polling
  4. Cache responses - Avoid redundant API calls
  5. Batch operations - Combine multiple updates when possible

Example: Exponential Backoff

async function fetchWithRetry(url, options, retries = 3) {
  for (let i = 0; i < retries; i++) {
    const response = await fetch(url, options);

    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
      await sleep(retryAfter * 1000);
      continue;
    }

    return response;
  }

  throw new Error('Max retries exceeded');
}

Request Format

HTTP Methods

The API uses standard HTTP methods:

  • GET - Retrieve resources
  • POST - Create resources
  • PUT - Update resources
  • DELETE - Delete resources

Content Type

All requests with a body must include:

Content-Type: application/json

Request Body

Send data as JSON in the request body:

{
  "name": "Customer Feedback Form",
  "description": "Collect customer feedback",
  "structure": {
    "type": "form",
    "attrs": { "name": "Customer Feedback" },
    "children": [...]
  }
}

Response Format

Success Responses

Successful requests return JSON with HTTP status codes:

  • 200 OK - Request succeeded
  • 201 Created - Resource created successfully
  • 204 No Content - Request succeeded with no response body

Example:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Contact Form",
  "status": "published",
  "created_at": "2025-01-20T10:30:00Z"
}

List Responses

List endpoints return paginated results:

{
  "data": [
    { "id": "...", "name": "Form 1" },
    { "id": "...", "name": "Form 2" }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total_count": 45,
    "total_pages": 3
  }
}

Pagination

Use query parameters to paginate:

GET /api/v1/forms?page=2&per_page=50
  • page - Page number (default: 1)
  • per_page - Items per page (default: 20, max: 100)

Error Handling

Error Response Format

Errors return JSON with an error code and message:

{
  "error": "unauthorized",
  "message": "Invalid API key"
}

HTTP Status Codes

Status Meaning
400 Bad Request Invalid request format or parameters
401 Unauthorized Missing or invalid API key
403 Forbidden API key doesn't have required permissions
404 Not Found Resource doesn't exist
422 Unprocessable Entity Validation errors
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Server error

Common Error Codes

Error Code Description
unauthorized Invalid or missing API key
forbidden Insufficient permissions
not_found Resource not found
validation_error Request data failed validation
rate_limit_exceeded Too many requests
server_error Internal server error

Validation Errors

Validation errors (422) include field-specific details:

{
  "error": "validation_error",
  "message": "Validation failed",
  "errors": [
    {
      "field": "name",
      "message": "Name is required"
    },
    {
      "field": "structure",
      "message": "Form must have at least one step"
    }
  ]
}

Error Handling Example

async function createForm(data) {
  try {
    const response = await fetch('https://formleap.app/api/v1/forms', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    });

    if (!response.ok) {
      const error = await response.json();

      switch (response.status) {
        case 401:
          throw new Error('Invalid API key');
        case 422:
          throw new Error(`Validation failed: ${error.errors.map(e => e.message).join(', ')}`);
        case 429:
          throw new Error('Rate limit exceeded. Please try again later.');
        default:
          throw new Error(error.message || 'An error occurred');
      }
    }

    return await response.json();
  } catch (error) {
    console.error('API Error:', error);
    throw error;
  }
}

Getting Started

Step 1: Get an API Key

  1. Log in to FormLeap
  2. Go to Workspace Settings → API Keys
  3. Generate a new key
  4. Copy and store securely

Step 2: Make Your First Request

List all forms in your workspace:

curl https://formleap.app/api/v1/forms \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Contact Form",
      "status": "published",
      "submission_count": 42,
      "created_at": "2025-01-15T10:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 20,
    "total_count": 1,
    "total_pages": 1
  }
}

Step 3: Create a Form

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": "Feedback Form" },
      "children": [
        {
          "type": "step",
          "attrs": { "title": "Your Feedback" },
          "children": [
            {
              "type": "text",
              "attrs": {
                "id": "name",
                "label": "Name",
                "required": true
              },
              "children": []
            },
            {
              "type": "textarea",
              "attrs": {
                "id": "feedback",
                "label": "Feedback",
                "required": true
              },
              "children": []
            }
          ]
        }
      ]
    }
  }'

Step 4: Retrieve Submissions

curl https://formleap.app/api/v1/forms/FORM_ID/submissions \
  -H "Authorization: Bearer YOUR_API_KEY"

Next Steps


API changes are announced via email to API key owners. Subscribe to updates in your account settings.