Support Log in

5. Submissions API

Developer Guide
Prefer video? Watch the Fillin Forge tutorials 9 short guides covering every feature Watch

Endpoints for form submissions — both public submission and admin retrieval.

POST /formforge/v1/forms/{id}/submit

This route returns HTTP 501 Not Implemented and does not accept submissions.

Submissions go through the AJAX handler (wp_ajax_formforge_submit /

wp_ajax_nopriv_formforge_submit), which enforces nonce verification,

structural anti-spam (honeypot, timing, HMAC token), file uploads, payment

intents, and all integrations — guards a tokenless REST POST cannot satisfy.

Use the AJAX path below.

AJAX Submission (the supported path for frontend forms):
javascript
const formEl = document.querySelector( '.formforge-form' );
const formData = new FormData( formEl );
formData.append( 'action', 'formforge_submit' );

fetch( formforgeFront.ajaxUrl, {
    method: 'POST',
    body: formData
} )
.then( r => r.json() )
.then( data => {
    if ( data.success ) {
        console.log( 'Success:', data.data.message );
        if ( data.data.redirect ) {
            window.location.href = data.data.redirect;
        }
    } else {
        console.error( 'Error:', data.data.message );
        // data.data.errors is a list of messages, data.data.field_id names the first field that failed
    }
} );
AJAX success response:
json
{
  "success": true,
  "data": {
    "message": "Thank you! We will get back to you within 24 hours.",
    "redirect": "",
    "actions": [],
    "submit_action": "message"
  }
}

When the form’s After submit setting is message, the bundled frontend renders a single completion state, hides the completed form controls, and resets non-payment forms after the saved submission succeeds. Payment forms lock the completed controls instead of clearing the captured payment context.

When the setting is redirect, redirect contains a root-relative or same-site URL and the bundled frontend navigates immediately instead of rendering a success-message delay. When the setting is custom_js, Fillin Forge does not return raw JavaScript; it returns a safe structured action list such as:

json
{
  "actions": [
    {
      "type": "add_class",
      "selector": "#modal",
      "value": "is-active"
    }
  ]
}

The frontend runner only supports add_class, remove_class, and toggle_class on ID or class selectors. The server rejects arbitrary script execution, external requests, cookie/storage access, assignments, eval, and markup injection.

AJAX error response (validation failure):
json
{
  "success": false,
  "data": {
    "message": "Email must be a valid email.",
    "errors": [
      "Email must be a valid email."
    ],
    "field_id": "field_2"
  }
}

message joins the messages with <br>. errors is a list of messages, not an object keyed by field. field_id is the id of the first field that failed, when there is one.

Submitting from PHP:

There is no PHP method that takes a form id and values and saves a submission. The handler reads the request and answers in JSON, and it checks the nonce and the anti-spam first. To react to a saved submission, listen to formforge/submission_created (see Submission Hooks).

GET /formforge/v1/submissions/{form_id}

Get submissions for a form. Requires manage_options. Returns up to 100 most recent submissions ordered by date descending. The test submissions sent from the form builder are left out; add ?status=test to get only those. Abandoned drafts of the Pro tracking are in the list with the status abandoned. Each row is the table row as it is stored, so the numbers are strings.

bash
curl -s -u "admin:XXXX XXXX XXXX XXXX" \
  https://example.com/wp-json/formforge/v1/submissions/1
Response (200):
json
[
  {
    "id": "42",
    "form_id": "1",
    "data": {
      "field_1": {
        "label": "Name",
        "value": "John Doe",
        "type": "text"
      },
      "field_2": {
        "label": "Email",
        "value": "[email protected]",
        "type": "email"
      }
    },
    "ip_address": "203.0.113.50",
    "user_agent": "Mozilla/5.0 ...",
    "user_id": "0",
    "status": "new",
    "session_id": "",
    "payment_status": "",
    "created_at": "2025-01-20 14:35:22"
  }
]

Admin AJAX: PDF and Delete Actions

The Submissions screen uses admin AJAX for per-submission PDF download and deletion:

ActionMethodCapabilityNonceResponse
formforge_download_pdfGETmanage_optionsformforge_pdf via nonceapplication/pdf attachment named submission-{id}.pdf
formforge_delete_submissionPOSTmanage_optionsformforge_delete_submission_{id} via _wpnonceJSON success with { "deleted": id }

Delete also removes any private files attached to that submission from uploads/formforge-private/. Public form submission continues to use formforge_submit; File Upload is a Free field, while locked PRO field types are skipped or rejected server-side after a downgrade.

—

Forge AI Assistant Online

Hi! I'm the Fillin Forge AI assistant. Ask me anything about the plugin — setup, features, troubleshooting, or development.

Just now
Powered by Forge AI · Browse docs