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
- Log in to FormLeap
- Navigate to Workspace Settings
- Scroll to API Keys
- Click Generate API Key
- Give it a descriptive name (e.g., "Production Integration")
- Copy the key immediately (it's only shown once)
- 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:
-
Monitor headers - Check
X-RateLimit-Remainingbefore making requests - Implement backoff - Wait when approaching limits
- Use webhooks - For real-time events instead of polling
- Cache responses - Avoid redundant API calls
- 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
- Log in to FormLeap
- Go to Workspace Settings → API Keys
- Generate a new key
- 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 Reference - Complete endpoint documentation
- MCP Integration - AI-powered form creation
- Webhooks - Real-time event notifications
API changes are announced via email to API key owners. Subscribe to updates in your account settings.