API Reference

API Reference

Complete documentation for the Formigo submission API.

Form Submission Endpoint

Submit form data to your unique form endpoint.

POST /f/:slug

Replace :slug with your form's unique identifier.

Example

https://formigo.com/f/contact-form-abc123

Request Format

Formigo accepts both form data and JSON payloads.

Form Data (application/x-www-form-urlencoded)

<form action="https://formigo.com/f/contact-form-abc123" method="POST">
  <input type="text" name="name" value="John Doe">
  <input type="email" name="email" value="[email protected]">
  <textarea name="message">Hello, world!</textarea>
  <button type="submit">Submit</button>
</form>

JSON (application/json)

fetch("https://formigo.com/f/contact-form-abc123", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "John Doe",
    email: "[email protected]",
    message: "Hello, world!"
  })
});

cURL Example

curl -X POST https://formigo.com/f/contact-form-abc123 \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "[email protected]",
    "message": "Hello, world!"
  }'

Spam Protection Fields

Include these special fields to enable spam protection:

_formigo_hp - Honeypot

A hidden field that should remain empty. Bots typically fill all fields, triggering spam detection.

<input type="text" name="_formigo_hp" value=""
       style="display:none" tabindex="-1" autocomplete="off">

_formigo_t - Timestamp

Unix timestamp (in seconds) of when the form was loaded. Submissions under 2 seconds are flagged.

<input type="hidden" name="_formigo_t" value="">

<script>
  // Set when form loads
  document.querySelector('input[name="_formigo_t"]').value =
    Math.floor(Date.now() / 1000);
</script>

_formigo_captcha - CAPTCHA Token

Required if CAPTCHA is enabled on your form. Token from hCaptcha or Cloudflare Turnstile.

See Spam Protection guide for CAPTCHA setup.

Response Codes

The API returns standard HTTP status codes:

200

Success

Submission received and processed successfully.

{
  "success": true,
  "message": "Submission received"
}
422

Unprocessable Entity

Validation errors or spam detected.

{
  "error": "Validation failed",
  "details": {
    "email": ["is invalid"],
    "message": ["can't be blank"]
  }
}
429

Too Many Requests

Rate limit exceeded.

{
  "error": "Rate limit exceeded",
  "retry_after": 600
}

retry_after is in seconds.

404

Not Found

Form with the specified slug doesn't exist.

Rate Limiting

To prevent abuse, Formigo implements rate limiting:

Per Form Limit

5 submissions

Per IP address, per form, every 10 minutes

Global Limit

20 submissions

Per IP address, across all forms, per hour

Note on Rate Limits

These limits are designed to prevent abuse while allowing legitimate use. If you need higher limits for your use case, contact us.

CORS Support

Formigo supports Cross-Origin Resource Sharing (CORS), allowing you to submit forms from any domain using AJAX/fetch.

// Works from any domain
fetch("https://formigo.com/f/your-form", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "John Doe",
    email: "[email protected]"
  })
})
.then(response => response.json())
.then(data => {
  console.log("Success:", data);
})
.catch(error => {
  console.error("Error:", error);
});

Error Handling

Always handle errors gracefully in your forms. Here's a complete example with error handling:

const form = document.querySelector("form");

form.addEventListener("submit", async (e) => {
  e.preventDefault();

  const formData = new FormData(form);
  const data = Object.fromEntries(formData);

  try {
    const response = await fetch("https://formigo.com/f/your-form", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(data)
    });

    const result = await response.json();

    if (response.ok) {
      // Success!
      alert("Thank you! Your submission has been received.");
      form.reset();
    } else if (response.status === 429) {
      // Rate limited
      alert(`Please wait ${result.retry_after} seconds before submitting again.`);
    } else {
      // Other errors
      alert("There was an error. Please try again.");
      console.error(result);
    }
  } catch (error) {
    alert("Network error. Please check your connection.");
    console.error(error);
  }
});