Fodo Docs
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:

For logged-in users in the browser. Automatic when using wp.apiFetch().

Application passwords

For external applications (WordPress 5.6+):

  1. Go to Users → Your Profile
  2. Scroll to Application Passwords
  3. Create a new password
  4. Use HTTP Basic Auth with username and app password
curl -u "username:app_password" \
  https://example.com/wp-json/fodo-forms/v1/forms

JWT / 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/forms

Response:

[
  {
    "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/entries

Query Parameters:

  • form_id - Filter by form
  • status - Filter by status (read, unread)
  • per_page - Results per page
  • page - 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 entries
  • X-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

CodeStatusDescription
rest_forbidden403Authentication required
not_found404Resource doesn't exist
validation_error400Invalid form data
invalid_nonce403Security 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 CaseRecommended
React to submissionsWebhooks
Build admin interfaceREST API
Mobile appREST API
External integrationsWebhooks
Sync data periodicallyREST API