Docs

Comprehensive guides and references for FiraForm.

API Reference

Complete API documentation for FiraForm

API Reference

Complete technical reference for the FiraForm API.

Base URL

https://a.firaform.com

Form Submission Endpoint

POST /api/f/{form_id}

Submit form data to your form endpoint.

Endpoint Format:

https://a.firaform.com/api/f/{form_id}

Replace {form_id} with your actual form UUID from the dashboard.

Request Methods

HTML Form Submission

Standard HTML form with automatic redirect:

<form action="https://a.firaform.com/api/f/YOUR-FORM-ID" method="POST">
  <input type="text" name="name" required />
  <input type="email" name="email" required />
  <textarea name="message"></textarea>
  <button type="submit">Submit</button>
</form>

Content-Type: application/x-www-form-urlencoded or multipart/form-data (for files)

Response: Redirects to success/error URL or default FiraForm page

JSON Submission

JavaScript/Ajax with JSON response:

fetch('https://a.firaform.com/api/f/YOUR-FORM-ID', {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'John Doe',
    email: 'john@example.com',
    message: 'Hello from the API'
  })
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));

Content-Type: application/json Accept: application/json (required for JSON response)

File Upload

Submit files using FormData:

const formData = new FormData();
formData.append('name', 'John Doe');
formData.append('email', 'john@example.com');
formData.append('resume', fileInput.files[0]);

fetch('https://a.firaform.com/api/f/YOUR-FORM-ID', {
  method: 'POST',
  headers: {
    'Accept': 'application/json'
  },
  body: formData
})
  .then(response => response.json())
  .then(data => console.log(data));

Content-Type: multipart/form-data (automatically set by browser)

Request Headers

HeaderRequiredDescription
Content-TypeNoapplication/json, application/x-www-form-urlencoded, or multipart/form-data
AcceptNoSet to application/json to receive JSON response instead of redirect
RefererYes*Browser automatically sends. Used for domain whitelist validation

*The Referer header is automatically included by browsers and must match your configured allowed domains.

Response Formats

Success Response (JSON)

Status Code: 200 OK

{
  "success": true,
  "message": "Form submitted successfully"
}

Validation Error Response (JSON)

Status Code: 422 Unprocessable Entity

{
  "success": false,
  "message": "The given data was invalid.",
  "errors": {
    "email": [
      "The email field is required."
    ],
    "name": [
      "The name must be at least 2 characters."
    ]
  }
}

Domain Not Allowed Response (JSON)

Status Code: 403 Forbidden

{
  "success": false,
  "message": "Domain not allowed"
}

Form Disabled Response (JSON)

Status Code: 403 Forbidden

{
  "success": false,
  "message": "This form is not accepting submissions"
}

Server Error Response (JSON)

Status Code: 500 Internal Server Error

{
  "success": false,
  "message": "An error occurred processing your submission"
}

HTML Form Redirects

When submitting without Accept: application/json, responses are HTTP redirects:

Success:

  • Redirects to your configured Success Redirect URL
  • Or to FiraForm’s default success page

Validation Error:

  • Redirects to your configured Error Redirect URL with ?errors={json} parameter
  • Or to FiraForm’s default error page

Example Error Redirect:

https://yoursite.com/error?errors={"email":["The email field is required"],"name":["The name must be at least 2 characters"]}

Parse the errors parameter as JSON to display validation messages.

CAPTCHA Verification

When CAPTCHA is enabled, include the CAPTCHA token in your submission.

Adding CAPTCHA to HTML Forms

<form action="https://a.firaform.com/api/f/YOUR-FORM-ID" method="POST">
  <input type="text" name="name" required />
  <input type="email" name="email" required />
  
  <!-- CAPTCHA widget (automatically includes token) -->
  <script src="https://a.firaform.com/captcha/YOUR-FORM-ID"></script>
  
  <button type="submit">Submit</button>
</form>

The CAPTCHA script automatically:

  1. Displays a slider challenge
  2. Generates a token when completed
  3. Includes the token in form submission

CAPTCHA with JavaScript

For Ajax submissions, include the CAPTCHA token:

// Get token from CAPTCHA widget
const captchaToken = document.querySelector('[name="firaform_captcha_token"]').value;

fetch('https://a.firaform.com/api/f/YOUR-FORM-ID', {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'John Doe',
    email: 'john@example.com',
    firaform_captcha_token: captchaToken
  })
});

CAPTCHA Error Response

Status Code: 422 Unprocessable Entity

{
  "success": false,
  "message": "CAPTCHA verification failed",
  "errors": {
    "firaform_captcha_token": [
      "The CAPTCHA verification failed. Please try again."
    ]
  }
}

Webhook Payloads

When you configure a webhook integration, FiraForm sends POST requests to your endpoint with submission data.

Webhook Request

Method: POST

Headers:

Content-Type: application/json
User-Agent: FiraForm-Webhook/1.0

Body:

{
  "form_id": "550e8400-e29b-41d4-a716-446655440000",
  "form_name": "Contact Form",
  "submission_id": "123456",
  "submitted_at": "2026-01-21T14:30:00Z",
  "data": {
    "name": "John Doe",
    "email": "john@example.com",
    "message": "Hello!"
  },
  "files": [
    {
      "field": "resume",
      "filename": "resume.pdf",
      "url": "https://files.firaform.com/...",
      "size": 245760
    }
  ],
  "metadata": {
    "ip": "192.168.1.1",
    "user_agent": "Mozilla/5.0...",
    "referer": "https://yoursite.com/contact"
  }
}

Webhook Response

Your webhook endpoint should return a 2xx status code to acknowledge receipt:

HTTP/1.1 200 OK

If your endpoint returns an error status (4xx or 5xx), FiraForm will retry the webhook delivery up to 3 times.

Rate Limiting

FiraForm applies rate limiting to prevent abuse:

  • Per Form: 100 submissions per minute
  • Per IP: 10 submissions per minute per form

Exceeding these limits returns:

Status Code: 429 Too Many Requests

{
  "success": false,
  "message": "Too many requests. Please try again later."
}

CORS Support

FiraForm supports Cross-Origin Resource Sharing (CORS) for browser-based Ajax submissions.

Allowed Origins: Any domain configured in your Domain whitelist

Allowed Methods: POST, OPTIONS

Allowed Headers: Content-Type, Accept

Examples

Complete Contact Form

<!DOCTYPE html>
<html>
<head>
  <title>Contact Us</title>
</head>
<body>
  <h1>Contact Us</h1>
  <form action="https://a.firaform.com/api/f/YOUR-FORM-ID" method="POST">
    <label for="name">Name *</label>
    <input type="text" id="name" name="name" required>

    <label for="email">Email *</label>
    <input type="email" id="email" name="email" required>

    <label for="phone">Phone</label>
    <input type="tel" id="phone" name="phone">

    <label for="message">Message *</label>
    <textarea id="message" name="message" required></textarea>

    <!-- Honeypot for spam protection -->
    <input type="text" name="website" style="display:none" tabindex="-1">

    <!-- CAPTCHA -->
    <script src="https://a.firaform.com/captcha/YOUR-FORM-ID"></script>

    <button type="submit">Send Message</button>
  </form>
</body>
</html>

Ajax Form with Error Handling

document.getElementById('contact-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  
  const formData = new FormData(e.target);
  const data = Object.fromEntries(formData);
  
  try {
    const response = await fetch('https://a.firaform.com/api/f/YOUR-FORM-ID', {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    });
    
    const result = await response.json();
    
    if (result.success) {
      alert('Thank you! Your message has been sent.');
      e.target.reset();
    } else {
      // Display validation errors
      const errorMessages = Object.values(result.errors).flat();
      alert('Please fix the following errors:\n' + errorMessages.join('\n'));
    }
  } catch (error) {
    alert('An error occurred. Please try again later.');
    console.error(error);
  }
});

curl Example

curl -X POST "https://a.firaform.com/api/f/YOUR-FORM-ID" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "john@example.com",
    "message": "Test submission from curl"
  }'

Best Practices

  1. Always validate client-side - Don’t rely solely on server validation
  2. Use HTTPS - FiraForm only accepts HTTPS submissions
  3. Configure domain whitelist - Don’t use * in production
  4. Enable CAPTCHA - Protect against spam when needed
  5. Handle errors gracefully - Display user-friendly error messages
  6. Use honeypots - Add invisible fields to catch bots
  7. Test webhooks - Verify your webhook endpoint receives data correctly
  8. Monitor submissions - Check the dashboard regularly for spam

Support

For additional help: