Forms
REST API
Programmatic access to forms, entries, and submissions
REST API
Fodo Forms provides a REST API for programmatic access to forms and entries. Build custom integrations, mobile apps, or headless WordPress implementations.
Authentication
The API uses WordPress REST API authentication:
Cookie authentication
For logged-in users in the browser. Automatic when using wp.apiFetch().
Application passwords
For external applications (WordPress 5.6+):
- Go to Users → Your Profile
- Scroll to Application Passwords
- Create a new password
- Use HTTP Basic Auth with username and app password
curl -u "username:app_password" \
https://example.com/wp-json/fodo-forms/v1/formsJWT / OAuth
Use plugins like JWT Authentication for headless setups.
Base URL
https://your-site.com/wp-json/fodo-forms/v1/Endpoints
Forms
List all forms
GET /fodo-forms/v1/formsResponse:
[
{
"id": 1,
"title": "Contact Form",
"slug": "contact-form",
"status": "publish",
"fields": [...],
"settings": {...},
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T14:20:00Z"
}
]Query Parameters:
status- Filter by status (publish, draft)per_page- Results per page (default: 20)page- Page number
Get single form
GET /fodo-forms/v1/forms/{id}Response:
{
"id": 1,
"title": "Contact Form",
"slug": "contact-form",
"status": "publish",
"fields": [
{
"id": "name",
"type": "text",
"label": "Your Name",
"required": true
},
{
"id": "email",
"type": "email",
"label": "Email Address",
"required": true
}
],
"settings": {
"notification_email": "admin@example.com",
"success_message": "Thank you!"
}
}Create form
POST /fodo-forms/v1/forms
Content-Type: application/json
{
"title": "New Form",
"fields": [
{
"id": "name",
"type": "text",
"label": "Name",
"required": true
}
],
"settings": {
"notification_email": "admin@example.com"
}
}Update form
PUT /fodo-forms/v1/forms/{id}
Content-Type: application/json
{
"title": "Updated Form Title",
"settings": {
"notification_email": "new@example.com"
}
}Delete form
DELETE /fodo-forms/v1/forms/{id}Entries
List entries
GET /fodo-forms/v1/entriesQuery Parameters:
form_id- Filter by formstatus- Filter by status (read, unread)per_page- Results per pagepage- Page number
Response:
[
{
"id": 456,
"form_id": 1,
"status": "unread",
"fields": {
"name": {"label": "Your Name", "value": "John Smith"},
"email": {"label": "Email", "value": "john@example.com"}
},
"created_at": "2024-01-15T14:30:00Z"
}
]Headers:
X-WP-Total- Total entriesX-WP-TotalPages- Total pages
Get single entry
GET /fodo-forms/v1/entries/{id}Response:
{
"id": 456,
"form_id": 1,
"status": "read",
"fields": {
"name": {"label": "Your Name", "value": "John Smith"},
"email": {"label": "Email", "value": "john@example.com"},
"message": {"label": "Message", "value": "Hello..."}
},
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0...",
"page_url": "https://example.com/contact/",
"created_at": "2024-01-15T14:30:00Z"
}Delete entry
DELETE /fodo-forms/v1/entries/{id}Submissions
Submit form (public)
POST /fodo-forms/v1/submit
Content-Type: application/json
{
"form_id": 1,
"nonce": "abc123",
"fields": {
"name": "John Smith",
"email": "john@example.com",
"message": "Hello, I'm interested in..."
}
}Response (Success):
{
"success": true,
"message": "Thank you! Your submission has been received.",
"entry_id": 457
}Response (Validation Error):
{
"success": false,
"error": "Email is required.",
"field": "email"
}JavaScript examples
Using wp.apiFetch (WordPress)
// Fetch all forms
wp.apiFetch({ path: '/fodo-forms/v1/forms' })
.then(forms => console.log(forms));
// Submit form
wp.apiFetch({
path: '/fodo-forms/v1/submit',
method: 'POST',
data: {
form_id: 1,
nonce: fodoFormsConfig.nonce,
fields: {
name: 'John',
email: 'john@example.com'
}
}
}).then(response => {
if (response.success) {
alert(response.message);
}
});Using Fetch API
async function getEntries(formId) {
const response = await fetch(
`/wp-json/fodo-forms/v1/entries?form_id=${formId}`,
{
headers: {
'X-WP-Nonce': wpApiSettings.nonce
}
}
);
return response.json();
}
async function submitForm(formId, data) {
const response = await fetch('/wp-json/fodo-forms/v1/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
form_id: formId,
nonce: getNonce(),
fields: data
})
});
return response.json();
}PHP examples
Using wp_remote_get
// Get all forms
$response = wp_remote_get(
rest_url('fodo-forms/v1/forms'),
[
'headers' => [
'X-WP-Nonce' => wp_create_nonce('wp_rest')
]
]
);
$forms = json_decode(wp_remote_retrieve_body($response), true);Internal request
// Create internal REST request
$request = new WP_REST_Request('GET', '/fodo-forms/v1/entries');
$request->set_param('form_id', 1);
$request->set_param('per_page', 100);
$response = rest_do_request($request);
$entries = $response->get_data();Error handling
Error response format
{
"code": "error_code",
"message": "Human readable message",
"data": {
"status": 400
}
}Common error codes
| Code | Status | Description |
|---|---|---|
rest_forbidden | 403 | Authentication required |
not_found | 404 | Resource doesn't exist |
validation_error | 400 | Invalid form data |
invalid_nonce | 403 | Security check failed |
Handling errors
try {
const result = await wp.apiFetch({
path: '/fodo-forms/v1/submit',
method: 'POST',
data: formData
});
} catch (error) {
if (error.code === 'validation_error') {
showFieldError(error.data.field, error.message);
} else {
showGenericError(error.message);
}
}Rate limiting
The API follows WordPress defaults:
- Authenticated: No specific limit
- Unauthenticated submissions: Apply your own rate limiting
Consider using a rate limiting plugin for public endpoints.
Webhooks vs API
| Use Case | Recommended |
|---|---|
| React to submissions | Webhooks |
| Build admin interface | REST API |
| Mobile app | REST API |
| External integrations | Webhooks |
| Sync data periodically | REST API |